From 68fab88818d716c1ace65c192d33bf072266562b Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Tue, 19 Jul 2022 10:48:35 -0600 Subject: [PATCH 1/2] unlock wallet before other modules startup --- cmd/siad/daemon.go | 18 ++-------------- node/node.go | 54 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/cmd/siad/daemon.go b/cmd/siad/daemon.go index a3525b106..1e232163d 100644 --- a/cmd/siad/daemon.go +++ b/cmd/siad/daemon.go @@ -182,19 +182,6 @@ func installKillSignalHandler() chan os.Signal { return sigChan } -// tryAutoUnlock will try to automatically unlock the server's wallet if the -// environment variable is set. -func tryAutoUnlock(srv *server.Server) { - if password := build.WalletPassword(); password != "" { - fmt.Println("Sia Wallet Password found, attempting to auto-unlock wallet") - if err := srv.Unlock(password); err != nil { - fmt.Println("Auto-unlock failed:", err) - } else { - fmt.Println("Auto-unlock successful.") - } - } -} - // startDaemon uses the config parameters to initialize Sia modules and start // siad. func startDaemon(config Config) (err error) { @@ -218,6 +205,8 @@ func startDaemon(config Config) (err error) { // Create the node params by parsing the modules specified in the config. nodeParams := parseModules(config) + // set the wallet password from the environment variable + nodeParams.WalletPassword = build.WalletPassword() // Start and run the server. srv, err := server.New(config.Siad.APIaddr, config.Siad.RequiredUserAgent, config.APIPassword, nodeParams, loadStart) @@ -225,9 +214,6 @@ func startDaemon(config Config) (err error) { return err } - // Attempt to auto-unlock the wallet using the SIA_WALLET_PASSWORD env variable - tryAutoUnlock(srv) - // listen for kill signals sigChan := installKillSignalHandler() diff --git a/node/node.go b/node/node.go index a79985d6d..e63d5c044 100644 --- a/node/node.go +++ b/node/node.go @@ -11,11 +11,13 @@ import ( "path/filepath" "time" + mnemonics "gitlab.com/NebulousLabs/entropy-mnemonics" "gitlab.com/NebulousLabs/errors" "gitlab.com/NebulousLabs/ratelimit" "gitlab.com/NebulousLabs/siamux" "go.sia.tech/siad/build" + "go.sia.tech/siad/crypto" "go.sia.tech/siad/modules" "go.sia.tech/siad/modules/accounting" "go.sia.tech/siad/modules/consensus" @@ -101,12 +103,13 @@ type NodeParams struct { SiaMuxWSAddress string // Custom settings for modules - Allowance modules.Allowance - Bootstrap bool - UseUPNP bool - HostAddress string - HostStorage uint64 - RPCAddress string + Allowance modules.Allowance + Bootstrap bool + UseUPNP bool + HostAddress string + HostStorage uint64 + RPCAddress string + WalletPassword string // Initialize node from existing seed. PrimarySeed string @@ -236,6 +239,29 @@ func (n *Node) Close() (err error) { return err } +// Unlock unlocks the server's wallet using the provided password. +func tryUnlockWallet(w modules.Wallet, password string) error { + if w == nil { + return errors.New("server doesn't have a wallet") + } + var validKeys []crypto.CipherKey + dicts := []mnemonics.DictionaryID{"english", "german", "japanese"} + for _, dict := range dicts { + seed, err := modules.StringToSeed(password, dict) + if err != nil { + continue + } + validKeys = append(validKeys, crypto.NewWalletKey(crypto.HashObject(seed))) + } + validKeys = append(validKeys, crypto.NewWalletKey(crypto.HashObject(password))) + for _, key := range validKeys { + if err := w.Unlock(key); err == nil { + return nil + } + } + return modules.ErrBadEncryptionKey +} + // New will create a new node. The inputs to the function are the respective // 'New' calls for each module. We need to use this awkward method of // initialization because the siatest package cannot import any of the modules @@ -380,7 +406,21 @@ func New(params NodeParams, loadStartTime time.Time) (*Node, <-chan error) { } i++ printfRelease("(%d/%d) Loading wallet...\n", i, numModules) - return wallet.NewCustomWallet(cs, tp, filepath.Join(dir, modules.WalletDir), walletDeps) + wallet, err := wallet.NewCustomWallet(cs, tp, filepath.Join(dir, modules.WalletDir), walletDeps) + if err != nil { + return nil, err + } + // automatically unlock the wallet if the password is provided + if len(params.WalletPassword) != 0 { + printfRelease(" Wallet password found, attempting to unlock wallet...\n") + unlockErr := tryUnlockWallet(wallet, params.WalletPassword) + if unlockErr != nil { + fmt.Println(" Auto-unlock failed:", unlockErr) + } else { + fmt.Println(" Auto-unlock successful.") + } + } + return wallet, nil }() if err != nil { errChan <- errors.Extend(err, errors.New("unable to create wallet")) From 793a8dafb853af1bdfcc409ba124ba45001f7b42 Mon Sep 17 00:00:00 2001 From: Nate Maninger Date: Tue, 19 Jul 2022 11:02:36 -0600 Subject: [PATCH 2/2] ignore gosec warnings --- .golangci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index 4de60a2ff..c049c9b24 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -95,6 +95,8 @@ linters-settings: - equalFold gosec: excludes: + - G112 # http ReadHeaderTimeout + - G113 # Rat.SetString uncontrolled memory consumption - G307 linters: