Upgrade Tapir / Fix Token Acquisition
continuous-integration/drone/pr Build is failing
Details
continuous-integration/drone/pr Build is failing
Details
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()
|
defer app.appmutex.Unlock()
|
||||||
|
|
||||||
if app.peers[onion].CheckPassword(password) {
|
if app.peers[onion].CheckPassword(password) {
|
||||||
app.shutdownPeer(onion)
|
// soft-shutdown
|
||||||
|
app.peers[onion].Shutdown()
|
||||||
|
// delete the underlying storage
|
||||||
app.peers[onion].Delete()
|
app.peers[onion].Delete()
|
||||||
|
// hard shutdown / remove from app
|
||||||
|
app.shutdownPeer(onion)
|
||||||
|
|
||||||
// Shutdown and Remove the Engine
|
// Shutdown and Remove the Engine
|
||||||
|
|
||||||
log.Debugf("Delete peer for %v Done\n", onion)
|
log.Debugf("Delete peer for %v Done\n", onion)
|
||||||
app.appBus.Publish(event.NewEventList(event.PeerDeleted, event.Identity, onion))
|
app.appBus.Publish(event.NewEventList(event.PeerDeleted, event.Identity, onion))
|
||||||
return
|
return
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -3,7 +3,7 @@ module cwtch.im/cwtch
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
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/connectivity v1.8.6
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.3
|
git.openprivacy.ca/openprivacy/log v1.0.3
|
||||||
github.com/gtank/ristretto255 v0.1.3-0.20210930101514-6bb39798585c
|
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-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||||
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
|
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
|
||||||
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
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.6.0 h1:TtnKjxitkIDMM7Qn0n/u+mOHRLJzuQUYjYRu5n0/QFY=
|
||||||
git.openprivacy.ca/cwtch.im/tapir v0.5.5/go.mod h1:bWWHrDYBtHvxMri59RwIB/w7Eg1aC0BrQ/ycKlnbB5k=
|
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 h1:CO7EkGyz+jegZ4ap8g5NWRuDHA/56KKvGySR6OBPW+c=
|
||||||
git.openprivacy.ca/openprivacy/bine v0.0.4/go.mod h1:13ZqhKyqakDsN/ZkQkIGNULsmLyqtXc46XBcnuXm/mU=
|
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=
|
git.openprivacy.ca/openprivacy/connectivity v1.8.6 h1:g74PyDGvpMZ3+K0dXy3mlTJh+e0rcwNk0XF8owzkmOA=
|
||||||
|
|
|
@ -99,29 +99,39 @@ func (cp *cwtchPeer) Delete() {
|
||||||
cp.storage.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 {
|
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()
|
cp.mutex.Lock()
|
||||||
defer cp.mutex.Unlock()
|
defer cp.mutex.Unlock()
|
||||||
|
|
||||||
|
// open *our* database with the given password (set createIfNotExists to false)
|
||||||
db, err := openEncryptedDatabase(cp.storage.ProfileDirectory, password, false)
|
db, err := openEncryptedDatabase(cp.storage.ProfileDirectory, password, false)
|
||||||
if db == nil || err != nil {
|
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
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *cwtchPeer) ChangePassword(password string, newpassword string, newpasswordAgain string) error {
|
func (cp *cwtchPeer) ChangePassword(password string, newpassword string, newpasswordAgain string) error {
|
||||||
|
if cp.CheckPassword(password) {
|
||||||
cp.mutex.Lock()
|
cp.mutex.Lock()
|
||||||
defer cp.mutex.Unlock()
|
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))
|
salt, err := os.ReadFile(path.Join(cp.storage.ProfileDirectory, saltFile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -135,6 +145,8 @@ func (cp *cwtchPeer) ChangePassword(password string, newpassword string, newpass
|
||||||
return cp.storage.Rekey(rekey)
|
return cp.storage.Rekey(rekey)
|
||||||
}
|
}
|
||||||
return errors.New(constants.PasswordsDoNotMatchError)
|
return errors.New(constants.PasswordsDoNotMatchError)
|
||||||
|
}
|
||||||
|
return errors.New(constants.InvalidPasswordError)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateProtocolEngine
|
// GenerateProtocolEngine
|
||||||
|
@ -1027,7 +1039,7 @@ func (cp *cwtchPeer) Shutdown() {
|
||||||
cp.shutdown = true
|
cp.shutdown = true
|
||||||
cp.queue.Shutdown()
|
cp.queue.Shutdown()
|
||||||
if cp.storage != nil {
|
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
|
// Close closes the underlying database and prepared statements
|
||||||
func (cps *CwtchProfileStorage) Close() {
|
func (cps *CwtchProfileStorage) Close(purgeAllNonSavedMessages bool) {
|
||||||
cps.mutex.Lock()
|
cps.mutex.Lock()
|
||||||
defer cps.mutex.Unlock()
|
defer cps.mutex.Unlock()
|
||||||
if cps.db != nil {
|
if cps.db != nil {
|
||||||
|
if purgeAllNonSavedMessages {
|
||||||
cps.PurgeNonSavedMessages()
|
cps.PurgeNonSavedMessages()
|
||||||
|
}
|
||||||
|
|
||||||
cps.insertProfileKeyValueStmt.Close()
|
cps.insertProfileKeyValueStmt.Close()
|
||||||
cps.selectProfileKeyValueStmt.Close()
|
cps.selectProfileKeyValueStmt.Close()
|
||||||
|
|
|
@ -490,14 +490,14 @@ func (e *engine) peerAuthed(onion string) {
|
||||||
|
|
||||||
func (e *engine) peerConnecting(onion string) {
|
func (e *engine) peerConnecting(onion string) {
|
||||||
e.eventManager.Publish(event.NewEvent(event.PeerStateChange, map[event.Field]string{
|
e.eventManager.Publish(event.NewEvent(event.PeerStateChange, map[event.Field]string{
|
||||||
event.RemotePeer: string(onion),
|
event.RemotePeer: onion,
|
||||||
event.ConnectionState: ConnectionStateName[CONNECTING],
|
event.ConnectionState: ConnectionStateName[CONNECTING],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *engine) serverConnecting(onion string) {
|
func (e *engine) serverConnecting(onion string) {
|
||||||
e.eventManager.Publish(event.NewEvent(event.ServerStateChange, map[event.Field]string{
|
e.eventManager.Publish(event.NewEvent(event.ServerStateChange, map[event.Field]string{
|
||||||
event.GroupServer: string(onion),
|
event.GroupServer: onion,
|
||||||
event.ConnectionState: ConnectionStateName[CONNECTING],
|
event.ConnectionState: ConnectionStateName[CONNECTING],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,18 +4,19 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"git.openprivacy.ca/cwtch.im/tapir/primitives/privacypass"
|
"git.openprivacy.ca/cwtch.im/tapir/primitives/privacypass"
|
||||||
|
"git.openprivacy.ca/openprivacy/log"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TokenManager maintains a list of tokens associated with a single TokenServer
|
// TokenManager maintains a list of tokens associated with a single TokenServer
|
||||||
type TokenManager struct {
|
type TokenManager struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
tokens map[string]bool
|
tokens map[string]*privacypass.Token
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTokenManager() *TokenManager {
|
func NewTokenManager() *TokenManager {
|
||||||
tm := new(TokenManager)
|
tm := new(TokenManager)
|
||||||
tm.tokens = make(map[string]bool)
|
tm.tokens = make(map[string]*privacypass.Token)
|
||||||
return tm
|
return tm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +24,10 @@ func NewTokenManager() *TokenManager {
|
||||||
func (tm *TokenManager) NewTokens(tokens []*privacypass.Token) {
|
func (tm *TokenManager) NewTokens(tokens []*privacypass.Token) {
|
||||||
tm.lock.Lock()
|
tm.lock.Lock()
|
||||||
defer tm.lock.Unlock()
|
defer tm.lock.Unlock()
|
||||||
|
log.Debugf("acquired %v new tokens", tokens)
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
serialized, _ := json.Marshal(token)
|
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 {
|
if len(tm.tokens) == 0 {
|
||||||
return nil, 0, errors.New("no more tokens")
|
return nil, 0, errors.New("no more tokens")
|
||||||
}
|
}
|
||||||
for serializedToken := range tm.tokens {
|
for serializedToken, token := range tm.tokens {
|
||||||
delete(tm.tokens, serializedToken)
|
delete(tm.tokens, serializedToken)
|
||||||
token := new(privacypass.Token)
|
|
||||||
json.Unmarshal([]byte(serializedToken), token)
|
|
||||||
return token, len(tm.tokens), nil
|
return token, len(tm.tokens), nil
|
||||||
}
|
}
|
||||||
return nil, 0, errors.New("no more tokens")
|
return nil, 0, errors.New("no more tokens")
|
||||||
|
|
|
@ -66,17 +66,22 @@ func (ta *TokenBoardClient) NewInstance() tapir.Application {
|
||||||
|
|
||||||
// Init initializes the cryptographic TokenBoardApp
|
// Init initializes the cryptographic TokenBoardApp
|
||||||
func (ta *TokenBoardClient) Init(connection tapir.Connection) {
|
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)
|
ta.AuthApp.Init(connection)
|
||||||
|
log.Debugf("server protocol complete: %v", connection.Hostname())
|
||||||
if connection.HasCapability(applications.AuthCapability) {
|
if connection.HasCapability(applications.AuthCapability) {
|
||||||
ta.connection = connection
|
|
||||||
ta.tokenBoardHandler.ServerAuthedHandler(ta.connection.Hostname())
|
|
||||||
log.Debugf("Successfully Initialized Connection to %v", connection.Hostname())
|
log.Debugf("Successfully Initialized Connection to %v", connection.Hostname())
|
||||||
|
ta.connection = connection
|
||||||
|
ta.tokenBoardHandler.ServerAuthedHandler(connection.Hostname())
|
||||||
go ta.Listen()
|
go ta.Listen()
|
||||||
// Optimistically acquire many tokens for this server...
|
// Optimistically acquire many tokens for this server...
|
||||||
go ta.PurchaseTokens()
|
go ta.PurchaseTokens()
|
||||||
go ta.PurchaseTokens()
|
go ta.PurchaseTokens()
|
||||||
ta.Replay()
|
ta.Replay()
|
||||||
} else {
|
} else {
|
||||||
|
log.Debugf("Error Connecting to %v", connection.Hostname())
|
||||||
|
ta.tokenBoardHandler.ServerClosedHandler(connection.Hostname())
|
||||||
connection.Close()
|
connection.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,10 +122,12 @@ func (ta *TokenBoardClient) Listen() {
|
||||||
ta.postQueue = ta.postQueue[1:]
|
ta.postQueue = ta.postQueue[1:]
|
||||||
ta.postLock.Unlock()
|
ta.postLock.Unlock()
|
||||||
if !message.PostResult.Success {
|
if !message.PostResult.Success {
|
||||||
|
log.Debugf("post result message: %v", message.PostResult)
|
||||||
// Retry using another token
|
// Retry using another token
|
||||||
posted, _ := ta.Post(egm.Group, egm.Ciphertext, egm.Signature)
|
posted, _ := ta.Post(egm.Group, egm.Ciphertext, egm.Signature)
|
||||||
// if posting failed...
|
// if posting failed...
|
||||||
if !posted {
|
if !posted {
|
||||||
|
log.Errorf("error posting message")
|
||||||
ta.tokenBoardHandler.PostingFailed(egm.Group, egm.Signature)
|
ta.tokenBoardHandler.PostingFailed(egm.Group, egm.Signature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue