From 2b6feba11671a5633c171b6e24985ad0c3302f2b Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Sat, 14 Oct 2023 10:48:48 +0530 Subject: [PATCH] chanbackup: add rpc to verify emergency.recover file's data. --- plugins/chanbackup.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/plugins/chanbackup.c b/plugins/chanbackup.c index 1c145f59cce0..c875eaa21a0c 100644 --- a/plugins/chanbackup.c +++ b/plugins/chanbackup.c @@ -762,6 +762,92 @@ static struct command_result *json_restorefrompeer(struct command *cmd, NULL); } +/* Returns True if the backup data is correct and + * returns false with the reason in `fail` if it's incorrect. + * Instead of using `decrypt_scb()` we're using this because + * it shuts down the node in case of any discrepancy and that + * is not what we want to happen when someone runs `verifybackup`. */ +static bool verify_bkp(struct command *cmd, + u8 *filedata, + char **fail) { + + bk_crypto_state crypto_state; + u64 version; + u32 timestamp; + struct scb_chan **scb; + + if (tal_bytelen(filedata) < + ABYTES + HEADER_LEN) { + *fail = "data is corrupted!"; + return false; + } + + u8 *decrypt_scb = tal_arr(tmpctx, u8, tal_bytelen(filedata) - + ABYTES - + HEADER_LEN); + + /* The header part */ + if (crypto_secretstream_xchacha20poly1305_init_pull(&crypto_state, + filedata, + (&secret)->data) != 0) { + *fail = "data is corrupted!"; + return false; + } + + if (crypto_secretstream_xchacha20poly1305_pull(&crypto_state, decrypt_scb, + NULL, 0, + filedata + + HEADER_LEN, + tal_bytelen(filedata)- + HEADER_LEN, + NULL, 0) != 0) { + *fail = "data is corrupted!"; + return false; + } + + if (!fromwire_static_chan_backup(cmd, + decrypt_scb, + &version, + ×tamp, + &scb)) { + *fail = "data is corrupted"; + return false; + } + + if (version != VERSION) { + *fail = "Incompatible emergency.recover file version on disk," + "contact the admin or update the file asap!"; + return false; + } + return true; +} + + +static struct command_result *json_verifybackup(struct command *cmd, + const char *buf, + const jsmntok_t *params) +{ + struct json_stream *response; + char *fail; + + if (!param(cmd, buf, params, NULL)) + return command_param_failed(); + + u8 *filedata = get_file_data(tmpctx, cmd->plugin); + + response = jsonrpc_stream_success(cmd); + + if (!verify_bkp(cmd, filedata, &fail)) { + json_add_str_fmt(response, "emergency.recover", "%s, Kindly remove the file and restart the node.", fail); + } + else { + json_add_bool(response, "emergency.recover", true); + } + + return command_finished(cmd, response); + +} + static const char *init(struct plugin *p, const char *buf UNUSED, const jsmntok_t *config UNUSED) @@ -834,6 +920,14 @@ static const struct plugin_command commands[] = { "return channel-id's on completion", json_restorefrompeer, }, + { + "verifybackup", + "recovery", + "Verifies your emergency.recover file and peer storage backup (if exists)." + "Also, gives out the channel IDs of the channels contained in the backup.", + "returns if the file is valid and the channel ID's contained in it", + json_verifybackup, + } }; int main(int argc, char *argv[])