changePassword #414
|
@ -36,7 +36,6 @@ type Application interface {
|
|||
CreateTaggedPeer(name string, password string, tag string)
|
||||
DeletePeer(onion string, currentPassword string)
|
||||
AddPeerPlugin(onion string, pluginID plugins.PluginID)
|
||||
ChangePeerPassword(onion, oldpass, newpass string)
|
||||
LaunchPeers()
|
||||
|
||||
GetPrimaryBus() event.Manager
|
||||
|
@ -122,10 +121,6 @@ func (app *application) DeletePeer(onion string, password string) {
|
|||
app.appBus.Publish(event.NewEventList(event.AppError, event.Error, event.PasswordMatchError, event.Identity, onion))
|
||||
}
|
||||
|
||||
func (app *application) ChangePeerPassword(onion, oldpass, newpass string) {
|
||||
app.eventBuses[onion].Publish(event.NewEventList(event.ChangePassword, event.Password, oldpass, event.NewPassword, newpass))
|
||||
}
|
||||
|
||||
func (app *application) AddPeerPlugin(onion string, pluginID plugins.PluginID) {
|
||||
app.AddPlugin(onion, pluginID, app.eventBuses[onion], app.acn)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package constants
|
||||
|
||||
// InvalidPasswordError is returned when an incorrect password is provided to a function that requires the current active password
|
||||
const InvalidPasswordError = "invalid_password_error"
|
||||
|
||||
// PasswordsDoNotMatchError is returned when two passwords do not match
|
||||
const PasswordsDoNotMatchError = "passwords_do_not_match"
|
|
@ -13,6 +13,8 @@ import (
|
|||
"git.openprivacy.ca/openprivacy/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"io/ioutil"
|
||||
path "path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -80,6 +82,33 @@ func (cp *cwtchPeer) CheckPassword(password string) bool {
|
|||
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)
|
||||
sarah marked this conversation as resolved
Outdated
|
||||
}
|
||||
cps, err := NewCwtchProfileStorage(db, cp.storage.ProfileDirectory)
|
||||
if err != nil {
|
||||
return errors.New(constants.InvalidPasswordError)
|
||||
}
|
||||
cps.Close()
|
||||
|
||||
salt, err := ioutil.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)
|
||||
}
|
||||
return errors.New(constants.PasswordsDoNotMatchError)
|
||||
sarah marked this conversation as resolved
Outdated
dan
commented
make const so receiver can check against error types make const so receiver can check against error types
|
||||
}
|
||||
|
||||
// GenerateProtocolEngine
|
||||
// Status: New in 1.5
|
||||
func (cp *cwtchPeer) GenerateProtocolEngine(acn connectivity.ACN, bus event.Manager) (connections.Engine, error) {
|
||||
|
@ -1147,7 +1176,6 @@ func (cp *cwtchPeer) eventHandler() {
|
|||
cp.mutex.Lock()
|
||||
cp.state[ev.Data[event.GroupServer]] = connections.ConnectionStateToType()[ev.Data[event.ConnectionState]]
|
||||
cp.mutex.Unlock()
|
||||
|
||||
default:
|
||||
if ev.EventType != "" {
|
||||
log.Errorf("peer event handler received an event it was not subscribed for: %v", ev.EventType)
|
||||
|
|
|
@ -762,3 +762,12 @@ func (cps *CwtchProfileStorage) Delete() {
|
|||
log.Errorf("error deleting profile directory", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Rekey re-encrypts the datastore with the new key.
|
||||
// **note* this is technically a very dangerous API and should only be called after
|
||||
// checks on the current password and the derived new password.
|
||||
func (cps *CwtchProfileStorage) Rekey(newkey [32]byte) error {
|
||||
// PRAGMA queries don't allow subs...
|
||||
_, err := cps.db.Exec(fmt.Sprintf(`PRAGMA rekey="x'%x'";`, newkey))
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -114,5 +114,6 @@ type CwtchPeer interface {
|
|||
|
||||
ShareFile(fileKey string, serializedManifest string)
|
||||
CheckPassword(password string) bool
|
||||
ChangePassword(oldpassword string, newpassword string, newpasswordAgain string) error
|
||||
Delete()
|
||||
}
|
||||
|
|
|
@ -164,6 +164,17 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
alice.PeerWithOnion(bob.GetOnion())
|
||||
alice.PeerWithOnion(carol.GetOnion())
|
||||
|
||||
// Test that we can rekey alice without issues...
|
||||
sarah marked this conversation as resolved
Outdated
dan
commented
this could be a unit test no? this could be a unit test no?
sarah
commented
the point of this test was to prove that rekeying while everything was active wouldn't break any existing flows. the point of this test was to prove that rekeying while everything was active wouldn't break any existing flows.
|
||||
err = alice.ChangePassword("asdfasdf", "password 1 2 3", "password 1 2 3")
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error changing password for Alice: %v", err)
|
||||
}
|
||||
|
||||
if !alice.CheckPassword("password 1 2 3") {
|
||||
t.Fatalf("Alice password did not change...")
|
||||
}
|
||||
|
||||
waitForConnection(t, alice, bob.GetOnion(), connections.AUTHENTICATED)
|
||||
waitForConnection(t, alice, carol.GetOnion(), connections.AUTHENTICATED)
|
||||
waitForConnection(t, bob, alice.GetOnion(), connections.AUTHENTICATED)
|
||||
|
@ -342,7 +353,6 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
|||
if numGoRoutinesStart != numGoRoutinesPostAppShutdown {
|
||||
t.Errorf("Number of GoRoutines at start (%v) does not match number of goRoutines after cleanup of peers and servers (%v), clean up failed, v detected!", numGoRoutinesStart, numGoRoutinesPostAppShutdown)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Utility function for sending a message from a peer to a group
|
||||
|
|
Loading…
Reference in New Issue
const-ify so receiver can check type of error.