diff --git a/common/errcode.h b/common/errcode.h index d9784e962..eb4da10c7 100644 --- a/common/errcode.h +++ b/common/errcode.h @@ -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 */ diff --git a/common/hsm_encryption.c b/common/hsm_encryption.c index b2f7c813f..796fc33cc 100644 --- a/common/hsm_encryption.c +++ b/common/hsm_encryption.c @@ -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. */ @@ -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; @@ -122,20 +122,20 @@ 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), ¤t_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; } @@ -143,12 +143,12 @@ char *read_stdin_pass_with_exit_code(char **reason, int *exit_code) if (tcsetattr(fileno(stdin), TCSANOW, ¤t_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; diff --git a/doc/lightningd.8.md b/doc/lightningd.8.md index 2f3a68a7f..552c8c303 100644 --- a/doc/lightningd.8.md +++ b/doc/lightningd.8.md @@ -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 diff --git a/lightningd/hsm_control.c b/lightningd/hsm_control.c index c4b2a0690..c5252fc3b 100644 --- a/lightningd/hsm_control.c +++ b/lightningd/hsm_control.c @@ -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."); } @@ -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); @@ -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; diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 07d79128f..e15a0309a 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -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 */ @@ -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. */ @@ -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. */ @@ -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); @@ -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); diff --git a/lightningd/options.c b/lightningd/options.c index 9333d21da..7fc77e26b 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -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); diff --git a/tools/hsmtool.c b/tools/hsmtool.c index 41eb514ab..e6ae1e36c 100644 --- a/tools/hsmtool.c +++ b/tools/hsmtool.c @@ -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); } @@ -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) @@ -148,7 +148,7 @@ 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: { @@ -156,7 +156,7 @@ static bool hsm_secret_is_encrypted(const char *hsm_secret_path) 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; @@ -198,13 +198,13 @@ 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."); } @@ -212,7 +212,7 @@ static int decrypt_hsm(const char *hsm_secret_path) 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); @@ -272,7 +272,7 @@ 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, @@ -280,14 +280,14 @@ static int encrypt_hsm(const char *hsm_secret_path) 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);