forked from cwtch.im/cwtch
Upgrade Tapir / Fix Token Acquisition
This commit is contained in:
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
|
||||
|
|
2
go.mod
2
go.mod
|
@ -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
|
||||
|
|
4
go.sum
4
go.sum
|
@ -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,29 +99,39 @@ 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
|
||||
}
|
||||
db.Close()
|
||||
// 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
|
||||
}
|
||||
// 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 {
|
||||
if cp.CheckPassword(password) {
|
||||
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()
|
||||
|
||||
salt, err := os.ReadFile(path.Join(cp.storage.ProfileDirectory, saltFile))
|
||||
if err != nil {
|
||||
|
@ -136,6 +146,8 @@ func (cp *cwtchPeer) ChangePassword(password string, newpassword string, newpass
|
|||
}
|
||||
return errors.New(constants.PasswordsDoNotMatchError)
|
||||
}
|
||||
return errors.New(constants.InvalidPasswordError)
|
||||
}
|
||||
|
||||
// GenerateProtocolEngine
|
||||
// Status: New in 1.5
|
||||
|
@ -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 {
|
||||
|
||||
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…
Reference in New Issue