mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-03 13:14:22 +01:00
lightningd: expand exit codes for various failures.
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 <rusty@rustcorp.com.au>
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user