From e922fc40d5307c688448e043f7e847ec0050c5d7 Mon Sep 17 00:00:00 2001 From: Ivan Belyakov Date: Tue, 22 Aug 2023 16:36:51 +0200 Subject: [PATCH] fix(wallet): do not create databases on verifyDatabasePassword call. Fixed wallet database having uppercase password in some cases which does not match lowercase password of app db. --- api/backend_test.go | 8 +++- api/geth_backend.go | 107 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 93 insertions(+), 22 deletions(-) diff --git a/api/backend_test.go b/api/backend_test.go index 8648c394d..a9c3a18ec 100644 --- a/api/backend_test.go +++ b/api/backend_test.go @@ -1234,11 +1234,15 @@ func TestChangeDatabasePassword(t *testing.T) { require.NoError(t, err) // Test that DBs can be opened with new password - appDb, err := sqlite.OpenDB(backend.getAppDBPath(account.KeyUID), newPassword, account.KDFIterations) + appDbPath, err := backend.getAppDBPath(account.KeyUID) + require.NoError(t, err) + appDb, err := sqlite.OpenDB(appDbPath, newPassword, account.KDFIterations) require.NoError(t, err) appDb.Close() - walletDb, err := sqlite.OpenDB(backend.getWalletDBPath(account.KeyUID), newPassword, account.KDFIterations) + walletDbPath, err := backend.getWalletDBPath(account.KeyUID) + require.NoError(t, err) + walletDb, err := sqlite.OpenDB(walletDbPath, newPassword, account.KDFIterations) require.NoError(t, err) walletDb.Close() diff --git a/api/geth_backend.go b/api/geth_backend.go index 3303d5feb..e89c6047e 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -248,7 +248,16 @@ func (b *GethStatusBackend) DeleteMultiaccount(keyUID string, keyStoreDir string return err } - appDbPath := b.getAppDBPath(keyUID) + appDbPath, err := b.getAppDBPath(keyUID) + if err != nil { + return err + } + + walletDbPath, err := b.getWalletDBPath(keyUID) + if err != nil { + return err + } + dbFiles := []string{ filepath.Join(b.rootDataDir, fmt.Sprintf("app-%x.sql", keyUID)), filepath.Join(b.rootDataDir, fmt.Sprintf("app-%x.sql-shm", keyUID)), @@ -259,6 +268,9 @@ func (b *GethStatusBackend) DeleteMultiaccount(keyUID string, keyStoreDir string appDbPath, appDbPath + "-shm", appDbPath + "-wal", + walletDbPath, + walletDbPath + "-shm", + walletDbPath + "-wal", } for _, path := range dbFiles { if _, err := os.Stat(path); err == nil { @@ -304,9 +316,12 @@ func (b *GethStatusBackend) runDBFileMigrations(account multiaccounts.Account, p // Migrate file path to fix issue https://github.com/status-im/status-go/issues/2027 unsupportedPath := filepath.Join(b.rootDataDir, fmt.Sprintf("app-%x.sql", account.KeyUID)) v3Path := filepath.Join(b.rootDataDir, fmt.Sprintf("%s.db", account.KeyUID)) - v4Path := b.getAppDBPath(account.KeyUID) + v4Path, err := b.getAppDBPath(account.KeyUID) + if err != nil { + return "", err + } - _, err := os.Stat(unsupportedPath) + _, err = os.Stat(unsupportedPath) if err == nil { err := os.Rename(unsupportedPath, v3Path) if err != nil { @@ -364,27 +379,54 @@ func (b *GethStatusBackend) ensureAppDBOpened(account multiaccounts.Account, pas b.appDB, err = appdatabase.InitializeDB(dbFilePath, password, account.KDFIterations) if err != nil { - b.log.Error("failed to initialize db", "err", err) + b.log.Error("failed to initialize db", "err", err.Error()) return err } b.statusNode.SetAppDB(b.appDB) return nil } +func fileExists(path string) bool { + if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { + return false + } + + return true +} + +func (b *GethStatusBackend) walletDBExists(keyUID string) bool { + path, err := b.getWalletDBPath(keyUID) + if err != nil { + return false + } + + return fileExists(path) +} + +func (b *GethStatusBackend) appDBExists(keyUID string) bool { + path, err := b.getAppDBPath(keyUID) + if err != nil { + return false + } + + return fileExists(path) +} + func (b *GethStatusBackend) ensureWalletDBOpened(account multiaccounts.Account, password string) (err error) { b.mu.Lock() defer b.mu.Unlock() if b.walletDB != nil { return nil } - if len(b.rootDataDir) == 0 { - return errors.New("root datadir wasn't provided") + + dbWalletPath, err := b.getWalletDBPath(account.KeyUID) + if err != nil { + return err } - dbWalletPath := b.getWalletDBPath(account.KeyUID) b.walletDB, err = walletdatabase.InitializeDB(dbWalletPath, password, account.KDFIterations) if err != nil { - b.log.Error("failed to initialize wallet db", "err", err) + b.log.Error("failed to initialize wallet db", "err", err.Error()) return err } b.statusNode.SetWalletDB(b.walletDB) @@ -815,13 +857,13 @@ func (b *GethStatusBackend) ImportUnencryptedDatabase(acc multiaccounts.Account, if b.appDB != nil { return nil } - if len(b.rootDataDir) == 0 { - return errors.New("root datadir wasn't provided") + + path, err := b.getAppDBPath(acc.KeyUID) + if err != nil { + return err } - path := b.getAppDBPath(acc.KeyUID) - - err := dbsetup.EncryptDatabase(databasePath, path, password, acc.KDFIterations, signal.SendReEncryptionStarted, signal.SendReEncryptionFinished) + err = dbsetup.EncryptDatabase(databasePath, path, password, acc.KDFIterations, signal.SendReEncryptionStarted, signal.SendReEncryptionFinished) if err != nil { b.log.Error("failed to initialize db", "err", err) return err @@ -858,7 +900,12 @@ func (b *GethStatusBackend) ChangeDatabasePassword(keyUID string, password strin return fmt.Errorf("failed to get database file name, %w", err) } - isCurrentAccount := b.getAppDBPath(keyUID) == internalDbPath + appDBPath, err := b.getAppDBPath(keyUID) + if err != nil { + return err + } + + isCurrentAccount := appDBPath == internalDbPath restartNode := func() { if isCurrentAccount { @@ -913,7 +960,11 @@ func (b *GethStatusBackend) changeAppDBPassword(account *multiaccounts.Account, } defer cleanup() - dbPath := b.getAppDBPath(account.KeyUID) + dbPath, err := b.getAppDBPath(account.KeyUID) + if err != nil { + return err + } + // Exporting database to a temporary file with a new password err = dbsetup.ExportDB(dbPath, password, account.KDFIterations, tmpDbPath, newPassword, signal.SendReEncryptionStarted, signal.SendReEncryptionFinished) if err != nil { @@ -951,7 +1002,11 @@ func (b *GethStatusBackend) changeWalletDBPassword(account *multiaccounts.Accoun } defer cleanup() - dbPath := b.getWalletDBPath(account.KeyUID) + dbPath, err := b.getWalletDBPath(account.KeyUID) + if err != nil { + return err + } + // Exporting database to a temporary file with a new password err = dbsetup.ExportDB(dbPath, password, account.KDFIterations, tmpDbPath, newPassword, signal.SendReEncryptionStarted, signal.SendReEncryptionFinished) if err != nil { @@ -1363,6 +1418,10 @@ func (b *GethStatusBackend) VerifyDatabasePassword(keyUID string, password strin return err } + if !b.appDBExists(keyUID) || !b.walletDBExists(keyUID) { + return errors.New("One or more databases not created") + } + err = b.ensureDBsOpened(multiaccounts.Account{KeyUID: keyUID, KDFIterations: kdfIterations}, password) if err != nil { return err @@ -2268,10 +2327,18 @@ func (b *GethStatusBackend) SwitchFleet(fleet string, conf *params.NodeConfig) e return nil } -func (b *GethStatusBackend) getAppDBPath(keyUID string) string { - return filepath.Join(b.rootDataDir, fmt.Sprintf("%s-v4.db", keyUID)) +func (b *GethStatusBackend) getAppDBPath(keyUID string) (string, error) { + if len(b.rootDataDir) == 0 { + return "", errors.New("root datadir wasn't provided") + } + + return filepath.Join(b.rootDataDir, fmt.Sprintf("%s-v4.db", keyUID)), nil } -func (b *GethStatusBackend) getWalletDBPath(keyUID string) string { - return filepath.Join(b.rootDataDir, fmt.Sprintf("%s-wallet.db", keyUID)) +func (b *GethStatusBackend) getWalletDBPath(keyUID string) (string, error) { + if len(b.rootDataDir) == 0 { + return "", errors.New("root datadir wasn't provided") + } + + return filepath.Join(b.rootDataDir, fmt.Sprintf("%s-wallet.db", keyUID)), nil }