Skip to content

Commit

Permalink
lightningd: expand exit codes for various failures.
Browse files Browse the repository at this point in the history
Most unexpected ones are still 1, but there are a few recognizable error codes
worth documenting.

Rename the HSM ones to put ERRCODE_ at the front, since we have non-HSM ones
too now.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Jul 20, 2022
1 parent e96eb07 commit 5979a77
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 39 deletions.
17 changes: 12 additions & 5 deletions common/errcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,18 @@ typedef s32 errcode_t;

#define PRIerrcode PRId32

// Setup errors
#define EXITCODE_SUBDAEMON_FAIL 10
#define EXITCODE_PIDFILE_LOCK 11

// HSM errors code
#define HSM_GENERIC_ERROR 20
#define HSM_ERROR_IS_ENCRYPT 21
#define HSM_BAD_PASSWORD 22
#define HSM_PASSWORD_INPUT_ERR 23
#define ERROR_HSM_FILE 24
#define EXITCODE_HSM_GENERIC_ERROR 20
#define EXITCODE_HSM_ERROR_IS_ENCRYPT 21
#define EXITCODE_HSM_BAD_PASSWORD 22
#define EXITCODE_HSM_PASSWORD_INPUT_ERR 23
#define EXITCODE_ERROR_HSM_FILE 24

// Wallet error
#define EXITCODE_WALLET_DB_MISMATCH 30

#endif /* LIGHTNING_COMMON_ERRCODE_H */
18 changes: 9 additions & 9 deletions common/hsm_encryption.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ int hsm_secret_encryption_key_with_exitcode(const char *pass, struct secret *key
/* Don't swap the encryption key ! */
if (sodium_mlock(key->data, sizeof(key->data)) != 0) {
*err_msg = "Could not lock hsm_secret encryption key memory.";
return HSM_GENERIC_ERROR;
return EXITCODE_HSM_GENERIC_ERROR;
}

/* Check bounds. */
if (strlen(pass) < crypto_pwhash_argon2id_PASSWD_MIN) {
*err_msg = "Password too short to be able to derive a key from it.";
return HSM_BAD_PASSWORD;
return EXITCODE_HSM_BAD_PASSWORD;
} else if (strlen(pass) > crypto_pwhash_argon2id_PASSWD_MAX) {
*err_msg = "Password too long to be able to derive a key from it.";
return HSM_BAD_PASSWORD;
return EXITCODE_HSM_BAD_PASSWORD;
}

/* Now derive the key. */
Expand All @@ -34,7 +34,7 @@ int hsm_secret_encryption_key_with_exitcode(const char *pass, struct secret *key
crypto_pwhash_argon2id_MEMLIMIT_MODERATE,
crypto_pwhash_ALG_ARGON2ID13) != 0) {
*err_msg = "Could not derive a key from the password.";
return HSM_BAD_PASSWORD;
return EXITCODE_HSM_BAD_PASSWORD;
}

return 0;
Expand Down Expand Up @@ -122,33 +122,33 @@ char *read_stdin_pass_with_exit_code(char **reason, int *exit_code)
/* Set a temporary term, same as current but with ECHO disabled. */
if (tcgetattr(fileno(stdin), &current_term) != 0) {
*reason = "Could not get current terminal options.";
*exit_code = HSM_PASSWORD_INPUT_ERR;
*exit_code = EXITCODE_HSM_PASSWORD_INPUT_ERR;
return NULL;
}
temp_term = current_term;
temp_term.c_lflag &= ~ECHO;
if (tcsetattr(fileno(stdin), TCSANOW, &temp_term) != 0) {
*reason = "Could not disable pass echoing.";
*exit_code = HSM_PASSWORD_INPUT_ERR;
*exit_code = EXITCODE_HSM_PASSWORD_INPUT_ERR;
return NULL;
}

if (!getline_stdin_pass(&passwd, &passwd_size)) {
*reason = "Could not read pass from stdin.";
*exit_code = HSM_PASSWORD_INPUT_ERR;
*exit_code = EXITCODE_HSM_PASSWORD_INPUT_ERR;
return NULL;
}

/* Restore the original terminal */
if (tcsetattr(fileno(stdin), TCSANOW, &current_term) != 0) {
*reason = "Could not restore terminal options.";
free(passwd);
*exit_code = HSM_PASSWORD_INPUT_ERR;
*exit_code = EXITCODE_HSM_PASSWORD_INPUT_ERR;
return NULL;
}
} else if (!getline_stdin_pass(&passwd, &passwd_size)) {
*reason = "Could not read pass from stdin.";
*exit_code = HSM_PASSWORD_INPUT_ERR;
*exit_code = EXITCODE_HSM_PASSWORD_INPUT_ERR;
return NULL;
}
return passwd;
Expand Down
3 changes: 3 additions & 0 deletions doc/lightningd.8.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,13 @@ ERRORS CODE
---

- 1: Generic lightning-cli error
- 10: Error executing subdaemons
- 11: Error locking pidfile (often another lightningd running)
- 20: Generic error related to HSM secret
- 21: HSM secret is encrypted
- 22: Bad password used to decrypt the HSM secred
- 23: Error caused from the I/O operation during a HSM decryption/encryption operation
- 30: Wallet database does not match (network or hsm secret)


BUGS
Expand Down
12 changes: 6 additions & 6 deletions lightningd/hsm_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,21 +83,21 @@ struct ext_key *hsm_init(struct lightningd *ld)

/* We actually send requests synchronously: only status is async. */
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0)
err(HSM_GENERIC_ERROR, "Could not create hsm socketpair");
err(EXITCODE_HSM_GENERIC_ERROR, "Could not create hsm socketpair");

ld->hsm = new_global_subd(ld, "lightning_hsmd",
hsmd_wire_name,
hsm_msg,
take(&fds[1]), NULL);
if (!ld->hsm)
err(HSM_GENERIC_ERROR, "Could not subd hsm");
err(EXITCODE_HSM_GENERIC_ERROR, "Could not subd hsm");

/* If hsm_secret is encrypted and the --encrypted-hsm startup option is
* not passed, don't let hsmd use the first 32 bytes of the cypher as the
* actual secret. */
if (!ld->config.keypass) {
if (is_hsm_secret_encrypted("hsm_secret") == 1)
errx(HSM_ERROR_IS_ENCRYPT, "hsm_secret is encrypted, you need to pass the "
errx(EXITCODE_HSM_ERROR_IS_ENCRYPT, "hsm_secret is encrypted, you need to pass the "
"--encrypted-hsm startup option.");
}

Expand All @@ -110,7 +110,7 @@ struct ext_key *hsm_init(struct lightningd *ld)
IFDEV(ld->dev_force_bip32_seed, NULL),
IFDEV(ld->dev_force_channel_secrets, NULL),
IFDEV(ld->dev_force_channel_secrets_shaseed, NULL))))
err(HSM_GENERIC_ERROR, "Writing init msg to hsm");
err(EXITCODE_HSM_GENERIC_ERROR, "Writing init msg to hsm");

bip32_base = tal(ld, struct ext_key);
msg = wire_sync_read(tmpctx, ld->hsm_fd);
Expand All @@ -119,8 +119,8 @@ struct ext_key *hsm_init(struct lightningd *ld)
&ld->bolt12_base,
&ld->onion_reply_secret)) {
if (ld->config.keypass)
errx(HSM_BAD_PASSWORD, "Wrong password for encrypted hsm_secret.");
errx(HSM_GENERIC_ERROR, "HSM did not give init reply");
errx(EXITCODE_HSM_BAD_PASSWORD, "Wrong password for encrypted hsm_secret.");
errx(EXITCODE_HSM_GENERIC_ERROR, "HSM did not give init reply");
}

return bip32_base;
Expand Down
12 changes: 6 additions & 6 deletions lightningd/lightningd.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,10 +400,10 @@ void test_subdaemons(const struct lightningd *ld)

/*~ ccan/err is a wrapper around BSD's err.h, which defines
* the convenience functions err() (error with message
* followed by a string based on errno) and errx() (same,
* followed by a string based on errno) and errx() (same,x
* but no errno string). */
if (pid == -1)
err(1, "Could not run %s", dpath);
err(EXITCODE_SUBDAEMON_FAIL, "Could not run %s", dpath);

/*~ CCAN's grab_file module contains a routine to read into a
* tallocated buffer until EOF */
Expand All @@ -415,7 +415,7 @@ void test_subdaemons(const struct lightningd *ld)
/*~ strstarts is from CCAN/str. */
if (!strstarts(verstring, version())
|| verstring[strlen(version())] != '\n')
errx(1, "%s: bad version '%s'",
errx(EXITCODE_SUBDAEMON_FAIL, "%s: bad version '%s'",
subdaemons[i], verstring);
/*~ The child will be reaped by sigchld_rfd_in, so we don't
* need to waitpid() here. */
Expand Down Expand Up @@ -654,7 +654,7 @@ static void pidfile_create(const struct lightningd *ld)
/* Lock PID file, so future lockf will fail. */
if (lockf(pid_fd, F_TLOCK, 0) < 0)
/* Problem locking file */
err(1, "lightningd already running? Error locking PID file");
err(EXITCODE_PIDFILE_LOCK, "lightningd already running? Error locking PID file");

/*~ As closing the file will remove the lock, we need to keep it open;
* the OS will close it implicitly when we exit for any reason. */
Expand Down Expand Up @@ -959,7 +959,7 @@ int main(int argc, char *argv[])
/* Figure out where our daemons are first. */
ld->daemon_dir = find_daemon_dir(ld, argv[0]);
if (!ld->daemon_dir)
errx(1, "Could not find daemons");
errx(EXITCODE_SUBDAEMON_FAIL, "Could not find daemons");

/* Set up the feature bits for what we support */
ld->our_features = default_features(ld);
Expand Down Expand Up @@ -1053,7 +1053,7 @@ int main(int argc, char *argv[])
* We also check that our node_id is what we expect: otherwise a change
* in hsm_secret will have strange consequences! */
if (!wallet_sanity_check(ld->wallet))
errx(1, "Wallet sanity check failed.");
errx(EXITCODE_WALLET_DB_MISMATCH, "Wallet sanity check failed.");

/*~ Initialize the transaction filter with our pubkeys. */
init_txfilter(ld->wallet, ld->owned_txfilter);
Expand Down
2 changes: 1 addition & 1 deletion lightningd/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ static char *opt_set_hsm_password(struct lightningd *ld)
return err_msg;

if (!streq(passwd, passwd_confirmation)) {
opt_exitcode = HSM_BAD_PASSWORD;
opt_exitcode = EXITCODE_HSM_BAD_PASSWORD;
return "Passwords confirmation mismatch.";
}
free(passwd_confirmation);
Expand Down
24 changes: 12 additions & 12 deletions tools/hsmtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ static void get_hsm_secret(struct secret *hsm_secret,

fd = open(hsm_secret_path, O_RDONLY);
if (fd < 0)
errx(ERROR_HSM_FILE, "Could not open hsm_secret");
errx(EXITCODE_ERROR_HSM_FILE, "Could not open hsm_secret");
if (!read_all(fd, hsm_secret, sizeof(*hsm_secret)))
errx(ERROR_HSM_FILE, "Could not read hsm_secret");
errx(EXITCODE_ERROR_HSM_FILE, "Could not read hsm_secret");
close(fd);
}

Expand All @@ -93,10 +93,10 @@ static void get_encrypted_hsm_secret(struct secret *hsm_secret,

fd = open(hsm_secret_path, O_RDONLY);
if (fd < 0)
errx(ERROR_HSM_FILE, "Could not open hsm_secret");
errx(EXITCODE_ERROR_HSM_FILE, "Could not open hsm_secret");

if (!read_all(fd, encrypted_secret.data, ENCRYPTED_HSM_SECRET_LEN))
errx(ERROR_HSM_FILE, "Could not read encrypted hsm_secret");
errx(EXITCODE_ERROR_HSM_FILE, "Could not read encrypted hsm_secret");

exit_code = hsm_secret_encryption_key_with_exitcode(passwd, &key, &err);
if (exit_code > 0)
Expand Down Expand Up @@ -148,15 +148,15 @@ static bool hsm_secret_is_encrypted(const char *hsm_secret_path)
{
switch (is_hsm_secret_encrypted(hsm_secret_path)) {
case -1:
err(ERROR_HSM_FILE, "Cannot open '%s'", hsm_secret_path);
err(EXITCODE_ERROR_HSM_FILE, "Cannot open '%s'", hsm_secret_path);
case 1:
return true;
case 0: {
/* Extra sanity check on HSM file! */
struct stat st;
stat(hsm_secret_path, &st);
if (st.st_size != 32)
errx(ERROR_HSM_FILE,
errx(EXITCODE_ERROR_HSM_FILE,
"Invalid hsm_secret '%s' (neither plaintext "
"nor encrypted).", hsm_secret_path);
return false;
Expand Down Expand Up @@ -198,21 +198,21 @@ static int decrypt_hsm(const char *hsm_secret_path)
rename(hsm_secret_path, backup);
fd = open(hsm_secret_path, O_CREAT|O_EXCL|O_WRONLY, 0400);
if (fd < 0)
errx(ERROR_HSM_FILE, "Could not open new hsm_secret");
errx(EXITCODE_ERROR_HSM_FILE, "Could not open new hsm_secret");

if (!write_all(fd, &hsm_secret, sizeof(hsm_secret))) {
unlink_noerr(hsm_secret_path);
close(fd);
rename("hsm_secret.backup", hsm_secret_path);
errx(ERROR_HSM_FILE,
errx(EXITCODE_ERROR_HSM_FILE,
"Failure writing plaintext seed to hsm_secret.");
}

/* Be as paranoïd as in hsmd with the file state on disk. */
if (!ensure_hsm_secret_exists(fd, hsm_secret_path)) {
unlink_noerr(hsm_secret_path);
rename(backup, hsm_secret_path);
errx(ERROR_HSM_FILE,
errx(EXITCODE_ERROR_HSM_FILE,
"Could not ensure hsm_secret existence.");
}
unlink_noerr(backup);
Expand Down Expand Up @@ -272,22 +272,22 @@ static int encrypt_hsm(const char *hsm_secret_path)
rename(hsm_secret_path, backup);
fd = open(hsm_secret_path, O_CREAT|O_EXCL|O_WRONLY, 0400);
if (fd < 0)
errx(ERROR_HSM_FILE, "Could not open new hsm_secret");
errx(EXITCODE_ERROR_HSM_FILE, "Could not open new hsm_secret");

/* Write the encrypted hsm_secret. */
if (!write_all(fd, encrypted_hsm_secret.data,
sizeof(encrypted_hsm_secret.data))) {
unlink_noerr(hsm_secret_path);
close(fd);
rename(backup, hsm_secret_path);
errx(ERROR_HSM_FILE, "Failure writing cipher to hsm_secret.");
errx(EXITCODE_ERROR_HSM_FILE, "Failure writing cipher to hsm_secret.");
}

/* Be as paranoïd as in hsmd with the file state on disk. */
if (!ensure_hsm_secret_exists(fd, hsm_secret_path)) {
unlink_noerr(hsm_secret_path);
rename(backup, hsm_secret_path);
errx(ERROR_HSM_FILE, "Could not ensure hsm_secret existence.");
errx(EXITCODE_ERROR_HSM_FILE, "Could not ensure hsm_secret existence.");
}
unlink_noerr(backup);
tal_free(dir);
Expand Down

0 comments on commit 5979a77

Please sign in to comment.