From 6ca38bc8150fcd299c633c4f44e187b486c76953 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 1 Jul 2021 11:00:40 +0200 Subject: [PATCH] lnd+config+sample-lnd.conf: add wallet-unlock-allow-create flag As requested by users of node bundle software. They want to use the wallet-unlock-password-file configuration option in their default/template config file. This makes the first-time lnd setup a bit more tricky since lnd will fail with an error if no wallet exists yet while that config option is used. The new wallet-unlock-allow-create option instructs lnd to not fail if no wallet exists yet but instead spin up its unlocker RPC as it would without the wallet-unlock-password-file being present. This is not recommended for auto-provisioned or high-security systems because the wallet creation RPC is unauthenticated and an attacker could inject a seed while lnd is in that state. --- config.go | 8 +++++++- lnd.go | 13 +++++++++---- sample-lnd.conf | 10 +++++++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/config.go b/config.go index 26b109b4..d795feed 100644 --- a/config.go +++ b/config.go @@ -299,7 +299,8 @@ type Config struct { NoNetBootstrap bool `long:"nobootstrap" description:"If true, then automatic network bootstrapping will not be attempted."` NoSeedBackup bool `long:"noseedbackup" description:"If true, NO SEED WILL BE EXPOSED -- EVER, AND THE WALLET WILL BE ENCRYPTED USING THE DEFAULT PASSPHRASE. THIS FLAG IS ONLY FOR TESTING AND SHOULD NEVER BE USED ON MAINNET."` - WalletUnlockPasswordFile string `long:"wallet-unlock-password-file" description:"The full path to a file (or pipe/device) that contains the password for unlocking the wallet; if set, no unlocking through RPC is possible and lnd will exit if no wallet exists or the password is incorrect"` + WalletUnlockPasswordFile string `long:"wallet-unlock-password-file" description:"The full path to a file (or pipe/device) that contains the password for unlocking the wallet; if set, no unlocking through RPC is possible and lnd will exit if no wallet exists or the password is incorrect; if wallet-unlock-allow-create is also set then lnd will ignore this flag if no wallet exists and allow a wallet to be created through RPC."` + WalletUnlockAllowCreate bool `long:"wallet-unlock-allow-create" description:"Don't fail with an error if wallet-unlock-password-file is set but no wallet exists yet."` ResetWalletTransactions bool `long:"reset-wallet-transactions" description:"Removes all transaction history from the on-chain wallet on startup, forcing a full chain rescan starting at the wallet's birthday. Implements the same functionality as btcwallet's dropwtxmgr command. Should be set to false after successful execution to avoid rescanning on every restart of lnd."` @@ -1347,6 +1348,11 @@ func ValidateConfig(cfg Config, usageMessage string, return nil, fmt.Errorf("cannot set noseedbackup and " + "wallet-unlock-password-file at the same time") + // The "allow-create" flag cannot be set without the auto unlock file. + case cfg.WalletUnlockAllowCreate && cfg.WalletUnlockPasswordFile == "": + return nil, fmt.Errorf("cannot set wallet-unlock-allow-create " + + "without wallet-unlock-password-file") + // If a password file was specified, we need it to exist. case cfg.WalletUnlockPasswordFile != "" && !lnrpc.FileExists(cfg.WalletUnlockPasswordFile): diff --git a/lnd.go b/lnd.go index 18e5825c..bd0f2839 100644 --- a/lnd.go +++ b/lnd.go @@ -481,9 +481,14 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error interceptorChain.SetWalletLocked() } - // If we've started in auto unlock mode, then a wallet _must_ already - // exist because we never want to enable the RPC unlocker in that case. - if cfg.WalletUnlockPasswordFile != "" && !walletExists { + // If we've started in auto unlock mode, then a wallet should already + // exist because we don't want to enable the RPC unlocker in that case + // for security reasons (an attacker could inject their seed since the + // RPC is unauthenticated). Only if the user explicitly wants to allow + // wallet creation we don't error out here. + if cfg.WalletUnlockPasswordFile != "" && !walletExists && + !cfg.WalletUnlockAllowCreate { + return fmt.Errorf("wallet unlock password file was specified " + "but wallet does not exist; initialize the wallet " + "before using auto unlocking") @@ -498,7 +503,7 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error // set above. // A password for unlocking is provided in a file. - case cfg.WalletUnlockPasswordFile != "": + case cfg.WalletUnlockPasswordFile != "" && walletExists: ltndLog.Infof("Attempting automatic wallet unlock with " + "password provided in file") pwBytes, err := ioutil.ReadFile(cfg.WalletUnlockPasswordFile) diff --git a/sample-lnd.conf b/sample-lnd.conf index a1e4da0f..865caed7 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -260,9 +260,17 @@ ; The full path to a file (or pipe/device) that contains the password for ; unlocking the wallet; if set, no unlocking through RPC is possible and lnd -; will exit if no wallet exists or the password is incorrect +; will exit if no wallet exists or the password is incorrect; if +; wallet-unlock-allow-create is also set then lnd will ignore this flag if no +; wallet exists and allow a wallet to be created through RPC. ; wallet-unlock-password-file=/tmp/example.password +; Don't fail with an error if wallet-unlock-password-file is set but no wallet +; exists yet. Not recommended for auto-provisioned or high-security systems +; because the wallet creation RPC is unauthenticated and an attacker could +; inject a seed while lnd is in that state. +; wallet-unlock-allow-create=true + ; Removes all transaction history from the on-chain wallet on startup, forcing a ; full chain rescan starting at the wallet's birthday. Implements the same ; functionality as btcwallet's dropwtxmgr command. Should be set to false after