mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
lightningd: regroup hsm_secret password input logic
Signed-off-by: Antoine Poinsot <darosior@protonmail.com>
This commit is contained in:
committed by
Christian Decker
parent
917f78a4f8
commit
a441485a35
@@ -1,6 +1,8 @@
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/hsm_encryption.h>
|
||||
#include <sodium.h>
|
||||
#include <sodium/utils.h>
|
||||
#include <termios.h>
|
||||
|
||||
|
||||
char *hsm_secret_encryption_key(const char *pass, struct secret *key)
|
||||
@@ -36,3 +38,39 @@ void discard_key(struct secret *key TAKES)
|
||||
if (taken(key))
|
||||
tal_free(key);
|
||||
}
|
||||
|
||||
char *read_stdin_pass(char **reason)
|
||||
{
|
||||
struct termios current_term, temp_term;
|
||||
char *passwd = NULL;
|
||||
size_t passwd_size = 0;
|
||||
|
||||
/* Set a temporary term, same as current but with ECHO disabled. */
|
||||
if (tcgetattr(fileno(stdin), ¤t_term) != 0) {
|
||||
*reason = "Could not get current terminal options.";
|
||||
return NULL;
|
||||
}
|
||||
temp_term = current_term;
|
||||
temp_term.c_lflag &= ~ECHO;
|
||||
if (tcsetattr(fileno(stdin), TCSAFLUSH, &temp_term) != 0) {
|
||||
*reason = "Could not disable pass echoing.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read the password, do not take the newline character into account. */
|
||||
if (getline(&passwd, &passwd_size, stdin) < 0) {
|
||||
*reason = "Could not read pass from stdin.";
|
||||
return NULL;
|
||||
}
|
||||
if (passwd[strlen(passwd) - 1] == '\n')
|
||||
passwd[strlen(passwd) - 1] = '\0';
|
||||
|
||||
/* Restore the original terminal */
|
||||
if (tcsetattr(fileno(stdin), TCSAFLUSH, ¤t_term) != 0) {
|
||||
*reason = "Could not restore terminal options.";
|
||||
free(passwd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return passwd;
|
||||
}
|
||||
|
||||
@@ -19,4 +19,11 @@ char *hsm_secret_encryption_key(const char *pass, struct secret *encryption_key)
|
||||
*/
|
||||
void discard_key(struct secret *key TAKES);
|
||||
|
||||
/** Read hsm_secret encryption pass from stdin, disabling echoing.
|
||||
* @reason: if NULL is returned, will point to the human-readable error.
|
||||
*
|
||||
* Caller must free the string as it does tal-reallocate getline's output.
|
||||
*/
|
||||
char *read_stdin_pass(char **reason);
|
||||
|
||||
#endif /* LIGHTNING_COMMON_HSM_ENCRYPTION_H */
|
||||
|
||||
@@ -389,8 +389,7 @@ static char *opt_important_plugin(const char *arg, struct lightningd *ld)
|
||||
static char *opt_set_hsm_password(struct lightningd *ld)
|
||||
{
|
||||
struct termios current_term, temp_term;
|
||||
char *passwd = NULL, *passwd_confirmation = NULL, *err;
|
||||
size_t passwd_size = 0;
|
||||
char *passwd, *passwd_confirmation, *err;
|
||||
|
||||
/* Get the password from stdin, but don't echo it. */
|
||||
if (tcgetattr(fileno(stdin), ¤t_term) != 0)
|
||||
@@ -405,18 +404,14 @@ static char *opt_set_hsm_password(struct lightningd *ld)
|
||||
/* If we don't flush we might end up being buffered and we might seem
|
||||
* to hang while we wait for the password. */
|
||||
fflush(stdout);
|
||||
if (getline(&passwd, &passwd_size, stdin) < 0)
|
||||
return "Could not read password from stdin.";
|
||||
passwd = read_stdin_pass(&err);
|
||||
if (!passwd)
|
||||
return err;
|
||||
printf("Confirm hsm_secret password:\n");
|
||||
fflush(stdout);
|
||||
if (getline(&passwd_confirmation, &passwd_size, stdin) < 0)
|
||||
return "Could not read password confirmation from stdin.";
|
||||
if (!streq(passwd, passwd_confirmation))
|
||||
return "Password confirmation mismatch.";
|
||||
if (passwd[strlen(passwd) - 1] == '\n')
|
||||
passwd[strlen(passwd) - 1] = '\0';
|
||||
if (tcsetattr(fileno(stdin), TCSAFLUSH, ¤t_term) != 0)
|
||||
return "Could not restore terminal options.";
|
||||
passwd_confirmation = read_stdin_pass(&err);
|
||||
if (!passwd_confirmation)
|
||||
return err;
|
||||
printf("\n");
|
||||
|
||||
ld->config.keypass = tal(NULL, struct secret);
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <limits.h>
|
||||
#include <sodium.h>
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <wally_bip39.h>
|
||||
|
||||
@@ -168,46 +167,21 @@ static bool hsm_secret_is_encrypted(const char *hsm_secret_path)
|
||||
return st.st_size > 32;
|
||||
}
|
||||
|
||||
/* Read a pass from stdin, disabling echoing as done in lightning/options for the
|
||||
* --encrypted-hsm startup option.
|
||||
* Caller must free the returned string. */
|
||||
static char *read_stdin_pass(void)
|
||||
{
|
||||
struct termios current_term, temp_term;
|
||||
char *passwd = NULL;
|
||||
size_t passwd_size = 0;
|
||||
|
||||
if (tcgetattr(fileno(stdin), ¤t_term) != 0)
|
||||
errx(ERROR_TERM, "Could not get current terminal options.");
|
||||
temp_term = current_term;
|
||||
temp_term.c_lflag &= ~ECHO;
|
||||
if (tcsetattr(fileno(stdin), TCSAFLUSH, &temp_term) != 0)
|
||||
errx(ERROR_TERM, "Could not disable pass echoing.");
|
||||
/* If we don't flush we might end up being buffered and we might seem
|
||||
* to hang while we wait for the password. */
|
||||
fflush(stdout);
|
||||
if (getline(&passwd, &passwd_size, stdin) < 0)
|
||||
errx(ERROR_TERM, "Could not read pass from stdin.");
|
||||
if (passwd[strlen(passwd) - 1] == '\n')
|
||||
passwd[strlen(passwd) - 1] = '\0';
|
||||
if (tcsetattr(fileno(stdin), TCSAFLUSH, ¤t_term) != 0)
|
||||
errx(ERROR_TERM, "Could not restore terminal options.");
|
||||
|
||||
return passwd;
|
||||
}
|
||||
|
||||
static int decrypt_hsm(const char *hsm_secret_path)
|
||||
{
|
||||
int fd;
|
||||
struct secret hsm_secret;
|
||||
char *passwd;
|
||||
char *passwd, *err;
|
||||
const char *dir, *backup;
|
||||
|
||||
/* This checks the file existence, too. */
|
||||
if (!hsm_secret_is_encrypted(hsm_secret_path))
|
||||
errx(ERROR_USAGE, "hsm_secret is not encrypted");
|
||||
printf("Enter hsm_secret password:\n");
|
||||
passwd = read_stdin_pass();
|
||||
fflush(stdout);
|
||||
passwd = read_stdin_pass(&err);
|
||||
if (!passwd)
|
||||
errx(ERROR_TERM, "%s", err);
|
||||
|
||||
if (sodium_init() == -1)
|
||||
errx(ERROR_LIBSODIUM,
|
||||
@@ -265,9 +239,15 @@ static int encrypt_hsm(const char *hsm_secret_path)
|
||||
errx(ERROR_USAGE, "hsm_secret is already encrypted");
|
||||
|
||||
printf("Enter hsm_secret password:\n");
|
||||
passwd = read_stdin_pass();
|
||||
fflush(stdout);
|
||||
passwd = read_stdin_pass(&err);
|
||||
if (!passwd)
|
||||
errx(ERROR_TERM, "%s", err);
|
||||
printf("Confirm hsm_secret password:\n");
|
||||
passwd_confirmation = read_stdin_pass();
|
||||
fflush(stdout);
|
||||
passwd_confirmation = read_stdin_pass(&err);
|
||||
if (!passwd_confirmation)
|
||||
errx(ERROR_TERM, "%s", err);
|
||||
if (!streq(passwd, passwd_confirmation))
|
||||
errx(ERROR_USAGE, "Passwords confirmation mismatch.");
|
||||
get_hsm_secret(&hsm_secret, hsm_secret_path);
|
||||
@@ -295,10 +275,8 @@ static int encrypt_hsm(const char *hsm_secret_path)
|
||||
errx(ERROR_LIBSODIUM, "Could not encrypt the seed.");
|
||||
|
||||
/* Once the encryption key derived, we don't need it anymore. */
|
||||
if (passwd)
|
||||
free(passwd);
|
||||
if (passwd_confirmation)
|
||||
free(passwd_confirmation);
|
||||
free(passwd);
|
||||
free(passwd_confirmation);
|
||||
|
||||
/* Create a backup file, "just in case". */
|
||||
rename(hsm_secret_path, backup);
|
||||
@@ -335,7 +313,7 @@ static int dump_commitments_infos(struct node_id *node_id, u64 channel_id,
|
||||
struct sha256 shaseed;
|
||||
struct secret hsm_secret, channel_seed, per_commitment_secret;
|
||||
struct pubkey per_commitment_point;
|
||||
char *passwd;
|
||||
char *passwd, *err;
|
||||
|
||||
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
|
||||
| SECP256K1_CONTEXT_SIGN);
|
||||
@@ -343,7 +321,10 @@ static int dump_commitments_infos(struct node_id *node_id, u64 channel_id,
|
||||
/* This checks the file existence, too. */
|
||||
if (hsm_secret_is_encrypted(hsm_secret_path)) {
|
||||
printf("Enter hsm_secret password:\n");
|
||||
passwd = read_stdin_pass();
|
||||
fflush(stdout);
|
||||
passwd = read_stdin_pass(&err);
|
||||
if (!passwd)
|
||||
errx(ERROR_TERM, "%s", err);
|
||||
get_encrypted_hsm_secret(&hsm_secret, hsm_secret_path, passwd);
|
||||
free(passwd);
|
||||
} else
|
||||
@@ -388,7 +369,7 @@ static int guess_to_remote(const char *address, struct node_id *node_id,
|
||||
u64 tries, char *hsm_secret_path)
|
||||
{
|
||||
struct secret hsm_secret, channel_seed, basepoint_secret;
|
||||
char *passwd;
|
||||
char *passwd, *err;
|
||||
struct pubkey basepoint;
|
||||
struct ripemd160 pubkeyhash;
|
||||
/* We only support P2WPKH, hence 20. */
|
||||
@@ -410,7 +391,10 @@ static int guess_to_remote(const char *address, struct node_id *node_id,
|
||||
/* This checks the file existence, too. */
|
||||
if (hsm_secret_is_encrypted(hsm_secret_path)) {
|
||||
printf("Enter hsm_secret password:\n");
|
||||
passwd = read_stdin_pass();
|
||||
fflush(stdout);
|
||||
passwd = read_stdin_pass(&err);
|
||||
if (!passwd)
|
||||
errx(ERROR_TERM, "%s", err);
|
||||
get_encrypted_hsm_secret(&hsm_secret, hsm_secret_path, passwd);
|
||||
free(passwd);
|
||||
} else
|
||||
@@ -512,14 +496,17 @@ static void read_mnemonic(char *mnemonic) {
|
||||
static int generate_hsm(const char *hsm_secret_path)
|
||||
{
|
||||
char mnemonic[BIP39_WORDLIST_LEN];
|
||||
char *passphrase;
|
||||
char *passphrase, *err;
|
||||
|
||||
read_mnemonic(mnemonic);
|
||||
printf("Warning: remember that different passphrases yield different "
|
||||
"bitcoin wallets.\n");
|
||||
printf("If left empty, no password is used (echo is disabled).\n");
|
||||
printf("Enter your passphrase: \n");
|
||||
passphrase = read_stdin_pass();
|
||||
fflush(stdout);
|
||||
passphrase = read_stdin_pass(&err);
|
||||
if (!passphrase)
|
||||
errx(ERROR_TERM, "%s", err);
|
||||
if (strlen(passphrase) == 0) {
|
||||
free(passphrase);
|
||||
passphrase = NULL;
|
||||
@@ -558,7 +545,7 @@ static int dumponchaindescriptors(const char *hsm_secret_path, const char *old_p
|
||||
const bool is_testnet)
|
||||
{
|
||||
struct secret hsm_secret;
|
||||
char *passwd;
|
||||
char *passwd, *err;
|
||||
u8 bip32_seed[BIP32_ENTROPY_LEN_256];
|
||||
u32 salt = 0;
|
||||
u32 version = is_testnet ?
|
||||
@@ -570,7 +557,10 @@ static int dumponchaindescriptors(const char *hsm_secret_path, const char *old_p
|
||||
/* This checks the file existence, too. */
|
||||
if (hsm_secret_is_encrypted(hsm_secret_path)) {
|
||||
printf("Enter hsm_secret password:\n");
|
||||
passwd = read_stdin_pass();
|
||||
fflush(stdout);
|
||||
passwd = read_stdin_pass(&err);
|
||||
if (!passwd)
|
||||
errx(ERROR_TERM, "%s", err);
|
||||
get_encrypted_hsm_secret(&hsm_secret, hsm_secret_path, passwd);
|
||||
free(passwd);
|
||||
} else
|
||||
|
||||
Reference in New Issue
Block a user