Upgrade Tapir / Fix Token Acquisition
continuous-integration/drone/pr Build is failing Details

cached_tokens
Sarah Jamie Lewis 4 months ago committed by Gitea
parent c66561d84f
commit f2b879a9c4

@ -145,11 +145,14 @@ func (app *application) DeletePeer(onion string, password string) {
defer app.appmutex.Unlock()
if app.peers[onion].CheckPassword(password) {
app.shutdownPeer(onion)
// soft-shutdown
app.peers[onion].Shutdown()
// delete the underlying storage
app.peers[onion].Delete()
// hard shutdown / remove from app
app.shutdownPeer(onion)
// Shutdown and Remove the Engine
log.Debugf("Delete peer for %v Done\n", onion)
app.appBus.Publish(event.NewEventList(event.PeerDeleted, event.Identity, onion))
return

@ -3,7 +3,7 @@ module cwtch.im/cwtch
go 1.17
require (
git.openprivacy.ca/cwtch.im/tapir v0.5.5
git.openprivacy.ca/cwtch.im/tapir v0.6.0
git.openprivacy.ca/openprivacy/connectivity v1.8.6
git.openprivacy.ca/openprivacy/log v1.0.3
github.com/gtank/ristretto255 v0.1.3-0.20210930101514-6bb39798585c

@ -1,8 +1,8 @@
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
git.openprivacy.ca/cwtch.im/tapir v0.5.5 h1:km6UDrLYH/GCEn2s+S299/TiRHhxKCIAipYr9GbG3Hk=
git.openprivacy.ca/cwtch.im/tapir v0.5.5/go.mod h1:bWWHrDYBtHvxMri59RwIB/w7Eg1aC0BrQ/ycKlnbB5k=
git.openprivacy.ca/cwtch.im/tapir v0.6.0 h1:TtnKjxitkIDMM7Qn0n/u+mOHRLJzuQUYjYRu5n0/QFY=
git.openprivacy.ca/cwtch.im/tapir v0.6.0/go.mod h1:iQIq4y7N+DuP3CxyG66WNEC/d6vzh+wXvvOmelB+KoY=
git.openprivacy.ca/openprivacy/bine v0.0.4 h1:CO7EkGyz+jegZ4ap8g5NWRuDHA/56KKvGySR6OBPW+c=
git.openprivacy.ca/openprivacy/bine v0.0.4/go.mod h1:13ZqhKyqakDsN/ZkQkIGNULsmLyqtXc46XBcnuXm/mU=
git.openprivacy.ca/openprivacy/connectivity v1.8.6 h1:g74PyDGvpMZ3+K0dXy3mlTJh+e0rcwNk0XF8owzkmOA=

@ -99,42 +99,54 @@ func (cp *cwtchPeer) Delete() {
cp.storage.Delete()
}
// CheckPassword returns true if the given password can be used to derive the key that encrypts the underlying
// cwtch storage database. Returns false otherwise.
func (cp *cwtchPeer) CheckPassword(password string) bool {
// this lock is not really needed, but because we directly access cp.storage.ProfileDirectory
// we keep it here.
cp.mutex.Lock()
defer cp.mutex.Unlock()
// open *our* database with the given password (set createIfNotExists to false)
db, err := openEncryptedDatabase(cp.storage.ProfileDirectory, password, false)
if db == nil || err != nil {
// this will only fail in the rare cases that ProfileDirectory has been moved or deleted
// it is actually a critical error, but far beyond the scope of Cwtch to deal with.
return false
}
// check that the storage object is valid (this will fail if the DB key is incorrect)
cps, err := NewCwtchProfileStorage(db, cp.storage.ProfileDirectory)
if err != nil {
// this will error if any SQL queries fail, which will be the case if the profile is invalid.
return false
}
db.Close()
// we have a valid database, close the storage (but don't purge as we may be using those conversations...)
cps.Close(false)
// success!
return true
}
func (cp *cwtchPeer) ChangePassword(password string, newpassword string, newpasswordAgain string) error {
cp.mutex.Lock()
defer cp.mutex.Unlock()
db, err := openEncryptedDatabase(cp.storage.ProfileDirectory, password, false)
if db == nil || err != nil {
return errors.New(constants.InvalidPasswordError)
}
cps, err := NewCwtchProfileStorage(db, cp.storage.ProfileDirectory)
if err != nil {
return errors.New(constants.InvalidPasswordError)
}
cps.Close()
if cp.CheckPassword(password) {
cp.mutex.Lock()
defer cp.mutex.Unlock()
salt, err := os.ReadFile(path.Join(cp.storage.ProfileDirectory, saltFile))
if err != nil {
return err
}
salt, err := os.ReadFile(path.Join(cp.storage.ProfileDirectory, saltFile))
if err != nil {
return err
}
// probably redundant but we like api safety
if newpassword == newpasswordAgain {
rekey := createKey(newpassword, salt)
log.Infof("rekeying database...")
return cp.storage.Rekey(rekey)
// probably redundant but we like api safety
if newpassword == newpasswordAgain {
rekey := createKey(newpassword, salt)
log.Infof("rekeying database...")
return cp.storage.Rekey(rekey)
}
return errors.New(constants.PasswordsDoNotMatchError)
}
return errors.New(constants.PasswordsDoNotMatchError)
return errors.New(constants.InvalidPasswordError)
}
// GenerateProtocolEngine
@ -1027,7 +1039,7 @@ func (cp *cwtchPeer) Shutdown() {
cp.shutdown = true
cp.queue.Shutdown()
if cp.storage != nil {
cp.storage.Close()
cp.storage.Close(true)
}
}

@ -771,12 +771,13 @@ func (cps *CwtchProfileStorage) PurgeNonSavedMessages() {
}
// Close closes the underlying database and prepared statements
func (cps *CwtchProfileStorage) Close() {
func (cps *CwtchProfileStorage) Close(purgeAllNonSavedMessages bool) {
cps.mutex.Lock()
defer cps.mutex.Unlock()
if cps.db != nil {
cps.PurgeNonSavedMessages()
if purgeAllNonSavedMessages {
cps.PurgeNonSavedMessages()
}
cps.insertProfileKeyValueStmt.Close()
cps.selectProfileKeyValueStmt.Close()

@ -490,14 +490,14 @@ func (e *engine) peerAuthed(onion string) {
func (e *engine) peerConnecting(onion string) {
e.eventManager.Publish(event.NewEvent(event.PeerStateChange, map[event.Field]string{
event.RemotePeer: string(onion),
event.RemotePeer: onion,
event.ConnectionState: ConnectionStateName[CONNECTING],
}))
}
func (e *engine) serverConnecting(onion string) {
e.eventManager.Publish(event.NewEvent(event.ServerStateChange, map[event.Field]string{
event.GroupServer: string(onion),
event.GroupServer: onion,
event.ConnectionState: ConnectionStateName[CONNECTING],
}))
}

@ -4,18 +4,19 @@ import (
"encoding/json"
"errors"
"git.openprivacy.ca/cwtch.im/tapir/primitives/privacypass"
"git.openprivacy.ca/openprivacy/log"
"sync"
)
// TokenManager maintains a list of tokens associated with a single TokenServer
type TokenManager struct {
lock sync.Mutex
tokens map[string]bool
tokens map[string]*privacypass.Token
}
func NewTokenManager() *TokenManager {
tm := new(TokenManager)
tm.tokens = make(map[string]bool)
tm.tokens = make(map[string]*privacypass.Token)
return tm
}
@ -23,9 +24,10 @@ func NewTokenManager() *TokenManager {
func (tm *TokenManager) NewTokens(tokens []*privacypass.Token) {
tm.lock.Lock()
defer tm.lock.Unlock()
log.Debugf("acquired %v new tokens", tokens)
for _, token := range tokens {
serialized, _ := json.Marshal(token)
tm.tokens[string(serialized)] = true
tm.tokens[string(serialized)] = token
}
}
@ -44,10 +46,8 @@ func (tm *TokenManager) FetchToken() (*privacypass.Token, int, error) {
if len(tm.tokens) == 0 {
return nil, 0, errors.New("no more tokens")
}
for serializedToken := range tm.tokens {
for serializedToken, token := range tm.tokens {
delete(tm.tokens, serializedToken)
token := new(privacypass.Token)
json.Unmarshal([]byte(serializedToken), token)
return token, len(tm.tokens), nil
}
return nil, 0, errors.New("no more tokens")

@ -66,17 +66,22 @@ func (ta *TokenBoardClient) NewInstance() tapir.Application {
// Init initializes the cryptographic TokenBoardApp
func (ta *TokenBoardClient) Init(connection tapir.Connection) {
// connection.Hostname is always valid because we are ALWAYS the initiating party
log.Debugf("connecting to server: %v", connection.Hostname())
ta.AuthApp.Init(connection)
log.Debugf("server protocol complete: %v", connection.Hostname())
if connection.HasCapability(applications.AuthCapability) {
ta.connection = connection
ta.tokenBoardHandler.ServerAuthedHandler(ta.connection.Hostname())
log.Debugf("Successfully Initialized Connection to %v", connection.Hostname())
ta.connection = connection
ta.tokenBoardHandler.ServerAuthedHandler(connection.Hostname())
go ta.Listen()
// Optimistically acquire many tokens for this server...
go ta.PurchaseTokens()
go ta.PurchaseTokens()
ta.Replay()
} else {
log.Debugf("Error Connecting to %v", connection.Hostname())
ta.tokenBoardHandler.ServerClosedHandler(connection.Hostname())
connection.Close()
}
}
@ -117,10 +122,12 @@ func (ta *TokenBoardClient) Listen() {
ta.postQueue = ta.postQueue[1:]
ta.postLock.Unlock()
if !message.PostResult.Success {
log.Debugf("post result message: %v", message.PostResult)
// Retry using another token
posted, _ := ta.Post(egm.Group, egm.Ciphertext, egm.Signature)
// if posting failed...
if !posted {
log.Errorf("error posting message")
ta.tokenBoardHandler.PostingFailed(egm.Group, egm.Signature)
}
}

Loading…
Cancel
Save