Skip to content

Commit

Permalink
json: Add two param functions to parse string arrs and outpoint arrs
Browse files Browse the repository at this point in the history
In a couple of places we accept arrays of strings and don't validate
them. If we forward them, e.g., call a JSON-RPC method from the
plugin, we end up embedding the unverified string in the JSON-RPC
call without escaping, which then leads to invalid JSON being passed
on.

This at least partially causes ElementsProject#4238
  • Loading branch information
cdecker authored and vibhaa committed Mar 24, 2021
1 parent f45ee82 commit 8f16a52
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 0 deletions.
6 changes: 6 additions & 0 deletions bitcoin/tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ struct wally_psbt;
struct bitcoin_txid {
struct sha256_double shad;
};

struct bitcoin_outpoint {
struct bitcoin_txid txid;
u16 n;
};

/* Define bitcoin_txid_eq */
STRUCTEQ_DEF(bitcoin_txid, 0, shad.sha.u);

Expand Down
25 changes: 25 additions & 0 deletions common/json_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,31 @@ bool json_to_txid(const char *buffer, const jsmntok_t *tok,
tok->end - tok->start, txid);
}

bool json_to_outpoint(const char *buffer, const jsmntok_t *tok,
struct bitcoin_outpoint *op)
{
size_t len = tok->end - tok->start;
char str[len + 1];

if (len < 66)
return NULL;

memcpy(str, buffer+tok->start, len);
str[len] = 0x00;

if (str[64] != ':')
return NULL;

if (!bitcoin_txid_from_hex(str, 64, &op->txid))
return false;

op->n = atoi(str + 65);
if (op->n < 0)
return false;

return true;
}

bool json_to_channel_id(const char *buffer, const jsmntok_t *tok,
struct channel_id *cid)
{
Expand Down
4 changes: 4 additions & 0 deletions common/json_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ bool json_to_msat(const char *buffer, const jsmntok_t *tok,
bool json_to_txid(const char *buffer, const jsmntok_t *tok,
struct bitcoin_txid *txid);

/* Extract a bitcoin outpoint from this */
bool json_to_outpoint(const char *buffer, const jsmntok_t *tok,
struct bitcoin_outpoint *op);

/* Extract a channel id from this */
bool json_to_channel_id(const char *buffer, const jsmntok_t *tok,
struct channel_id *cid);
Expand Down
29 changes: 29 additions & 0 deletions common/json_tok.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,32 @@ struct command_result *param_psbt(struct command *cmd,
return command_fail_badparam(cmd, name, buffer, tok,
"Expected a PSBT");
}

struct command_result *param_outpoint_arr(struct command *cmd,
const char *name,
const char *buffer,
const jsmntok_t *tok,
struct bitcoin_outpoint **outpoints)
{
size_t i;
const jsmntok_t *curr;
if (tok->type != JSMN_ARRAY) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Could not decode the outpoint array for %s: "
"\"%s\" is not a valid outpoint array.",
name, json_strdup(tmpctx, buffer, tok));
}

*outpoints = tal_arr(cmd, struct bitcoin_outpoint, tok->size);

json_for_each_arr(i, curr, tok) {
struct bitcoin_outpoint op;
if (!json_to_outpoint(buffer, curr, &op))
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Could not decode outpoint \"%.*s\", "
"expected format: txid:output",
json_tok_full_len(curr), json_tok_full(buffer, curr));
(*outpoints)[i] = op;
}
return NULL;
}
10 changes: 10 additions & 0 deletions common/json_tok.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
struct amount_msat;
struct amount_sat;
struct bitcoin_txid;
struct bitcoin_outpoint;
struct channel_id;
struct command;
struct command_result;
Expand Down Expand Up @@ -172,4 +173,13 @@ struct command_result *param_psbt(struct command *cmd,
const char *buffer,
const jsmntok_t *tok,
struct wally_psbt **psbt);

/**
* Parse a list of `txid:output` outpoints.
*/
struct command_result *param_outpoint_arr(struct command *cmd,
const char *name,
const char *buffer,
const jsmntok_t *tok,
struct bitcoin_outpoint **outpoints);
#endif /* LIGHTNING_COMMON_JSON_TOK_H */
4 changes: 4 additions & 0 deletions common/test/run-param.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ bool json_to_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEED
bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct node_id *id UNNEEDED)
{ fprintf(stderr, "json_to_node_id called!\n"); abort(); }
/* Generated stub for json_to_outpoint */
bool json_to_outpoint(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct bitcoin_outpoint *op UNNEEDED)
{ fprintf(stderr, "json_to_outpoint called!\n"); abort(); }
/* Generated stub for json_to_pubkey */
bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct pubkey *pubkey UNNEEDED)
Expand Down

0 comments on commit 8f16a52

Please sign in to comment.