gossip: send error messages on grossly malformed node_announcement.
As per BOLT #7. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
39c781aebb
commit
6d72550707
|
@ -450,7 +450,7 @@ static void send_node_announcement(struct daemon *daemon)
|
|||
tal_t *tmpctx = tal_tmpctx(daemon);
|
||||
u32 timestamp = time_now().ts.tv_sec;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
u8 *msg, *nannounce;
|
||||
u8 *msg, *nannounce, *err;
|
||||
|
||||
/* Timestamps must move forward, or announce will be ignored! */
|
||||
if (timestamp <= daemon->last_announce_timestamp)
|
||||
|
@ -470,14 +470,20 @@ static void send_node_announcement(struct daemon *daemon)
|
|||
* from the HSM, create the real announcement and forward it to
|
||||
* gossipd so it can take care of forwarding it. */
|
||||
nannounce = create_node_announcement(tmpctx, daemon, &sig, timestamp);
|
||||
handle_node_announcement(daemon->rstate, take(nannounce));
|
||||
err = handle_node_announcement(daemon->rstate, take(nannounce));
|
||||
if (err)
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"rejected own node announcement: %s",
|
||||
tal_hex(trc, err));
|
||||
tal_free(tmpctx);
|
||||
}
|
||||
|
||||
static void handle_gossip_msg(struct daemon *daemon, u8 *msg)
|
||||
/* Returns error if we should send an error. */
|
||||
static void handle_gossip_msg(struct peer *peer, u8 *msg)
|
||||
{
|
||||
struct routing_state *rstate = daemon->rstate;
|
||||
struct routing_state *rstate = peer->daemon->rstate;
|
||||
int t = fromwire_peektype(msg);
|
||||
u8 *err;
|
||||
|
||||
switch(t) {
|
||||
case WIRE_CHANNEL_ANNOUNCEMENT: {
|
||||
|
@ -485,14 +491,16 @@ static void handle_gossip_msg(struct daemon *daemon, u8 *msg)
|
|||
/* If it's OK, tells us the short_channel_id to lookup */
|
||||
scid = handle_channel_announcement(rstate, msg);
|
||||
if (scid)
|
||||
daemon_conn_send(&daemon->master,
|
||||
take(towire_gossip_get_txout(daemon,
|
||||
daemon_conn_send(&peer->daemon->master,
|
||||
take(towire_gossip_get_txout(NULL,
|
||||
scid)));
|
||||
break;
|
||||
}
|
||||
|
||||
case WIRE_NODE_ANNOUNCEMENT:
|
||||
handle_node_announcement(rstate, msg);
|
||||
err = handle_node_announcement(rstate, msg);
|
||||
if (err)
|
||||
queue_peer_msg(peer, take(err));
|
||||
break;
|
||||
|
||||
case WIRE_CHANNEL_UPDATE:
|
||||
|
@ -595,7 +603,7 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
|
|||
case WIRE_CHANNEL_ANNOUNCEMENT:
|
||||
case WIRE_NODE_ANNOUNCEMENT:
|
||||
case WIRE_CHANNEL_UPDATE:
|
||||
handle_gossip_msg(peer->daemon, msg);
|
||||
handle_gossip_msg(peer, msg);
|
||||
return peer_next_in(conn, peer);
|
||||
|
||||
case WIRE_PING:
|
||||
|
@ -828,7 +836,7 @@ static struct io_plan *owner_msg_in(struct io_conn *conn,
|
|||
int type = fromwire_peektype(msg);
|
||||
if (type == WIRE_CHANNEL_ANNOUNCEMENT || type == WIRE_CHANNEL_UPDATE ||
|
||||
type == WIRE_NODE_ANNOUNCEMENT) {
|
||||
handle_gossip_msg(peer->daemon, dc->msg_in);
|
||||
handle_gossip_msg(peer, dc->msg_in);
|
||||
} else if (type == WIRE_GOSSIP_GET_UPDATE) {
|
||||
handle_get_update(peer, dc->msg_in);
|
||||
} else if (type == WIRE_GOSSIP_LOCAL_ADD_CHANNEL) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <common/pseudorand.h>
|
||||
#include <common/status.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <common/wire_error.h>
|
||||
#include <common/wireaddr.h>
|
||||
#include <inttypes.h>
|
||||
#include <wire/gen_onion_wire.h>
|
||||
|
@ -503,6 +504,7 @@ static void process_pending_node_announcement(struct routing_state *rstate,
|
|||
SUPERVERBOSE(
|
||||
"Processing deferred node_announcement for node %s",
|
||||
type_to_string(pna, struct pubkey, nodeid));
|
||||
/* FIXME: Do something if this is invalid */
|
||||
handle_node_announcement(rstate, pna->node_announcement);
|
||||
}
|
||||
pending_node_map_del(rstate->pending_node_map, pna);
|
||||
|
@ -935,8 +937,7 @@ static struct wireaddr *read_addresses(const tal_t *ctx, const u8 *ser)
|
|||
return wireaddrs;
|
||||
}
|
||||
|
||||
void handle_node_announcement(
|
||||
struct routing_state *rstate, const u8 *node_ann)
|
||||
u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann)
|
||||
{
|
||||
u8 *serialized;
|
||||
struct sha256_double hash;
|
||||
|
@ -957,8 +958,17 @@ void handle_node_announcement(
|
|||
&signature, &features, ×tamp,
|
||||
&node_id, rgb_color, alias,
|
||||
&addresses)) {
|
||||
/* BOLT #7:
|
||||
*
|
||||
* - if `node_id` is NOT a valid compressed public key:
|
||||
* - SHOULD fail the connection.
|
||||
* - MUST NOT process the message further.
|
||||
*/
|
||||
u8 *err = towire_errorfmt(rstate, NULL,
|
||||
"Malformed node_announcement %s",
|
||||
tal_hex(tmpctx, node_ann));
|
||||
tal_free(tmpctx);
|
||||
return;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* BOLT #7:
|
||||
|
@ -972,14 +982,32 @@ void handle_node_announcement(
|
|||
type_to_string(tmpctx, struct pubkey, &node_id),
|
||||
tal_hex(tmpctx, features));
|
||||
tal_free(tmpctx);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sha256_double(&hash, serialized + 66, tal_count(serialized) - 66);
|
||||
if (!check_signed_hash(&hash, &signature, &node_id)) {
|
||||
status_trace("Ignoring node announcement, signature verification failed.");
|
||||
/* BOLT #7:
|
||||
*
|
||||
* - if `signature` is NOT a valid signature (using `node_id`
|
||||
* of the double-SHA256 of the entire message following the
|
||||
* `signature` field, including unknown fields following
|
||||
* `alias`):
|
||||
* - SHOULD fail the connection.
|
||||
* - MUST NOT process the message further.
|
||||
*/
|
||||
u8 *err = towire_errorfmt(rstate, NULL,
|
||||
"Bad signature for %s hash %s"
|
||||
" on node_announcement %s",
|
||||
type_to_string(tmpctx,
|
||||
secp256k1_ecdsa_signature,
|
||||
&signature),
|
||||
type_to_string(tmpctx,
|
||||
struct sha256_double,
|
||||
&hash),
|
||||
tal_hex(tmpctx, node_ann));
|
||||
tal_free(tmpctx);
|
||||
return;
|
||||
return err;
|
||||
}
|
||||
|
||||
node = get_node(rstate, &node_id);
|
||||
|
@ -997,20 +1025,27 @@ void handle_node_announcement(
|
|||
pna->node_announcement = tal_dup_arr(pna, u8, node_ann, tal_len(node_ann), 0);
|
||||
}
|
||||
tal_free(tmpctx);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* - if `node_id` is NOT previously known from a
|
||||
* `channel_announcement` message, OR if `timestamp` is NOT greater
|
||||
* than the last-received `node_announcement` from this `node_id`:
|
||||
* - SHOULD ignore the message.
|
||||
*/
|
||||
if (!node) {
|
||||
SUPERVERBOSE("Node not found, was the node_announcement for "
|
||||
"node %s preceded by at least "
|
||||
"channel_announcement?",
|
||||
type_to_string(tmpctx, struct pubkey, &node_id));
|
||||
tal_free(tmpctx);
|
||||
return;
|
||||
return NULL;
|
||||
} else if (node->last_timestamp >= timestamp) {
|
||||
SUPERVERBOSE("Ignoring node announcement, it's outdated.");
|
||||
tal_free(tmpctx);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status_trace("Received node_announcement for node %s",
|
||||
|
@ -1018,9 +1053,19 @@ void handle_node_announcement(
|
|||
|
||||
wireaddrs = read_addresses(tmpctx, addresses);
|
||||
if (!wireaddrs) {
|
||||
status_trace("Unable to parse addresses.");
|
||||
/* BOLT #7:
|
||||
*
|
||||
* - if `addrlen` is insufficient to hold the address
|
||||
* descriptors of the known types:
|
||||
* - SHOULD fail the connection.
|
||||
*/
|
||||
u8 *err = towire_errorfmt(rstate, NULL,
|
||||
"Malformed wireaddrs %s in %s.",
|
||||
tal_hex(tmpctx, wireaddrs),
|
||||
tal_hex(tmpctx, node_ann));
|
||||
tal_free(serialized);
|
||||
return;
|
||||
tal_free(tmpctx);
|
||||
return err;
|
||||
}
|
||||
tal_free(node->addresses);
|
||||
node->addresses = tal_steal(node, wireaddrs);
|
||||
|
@ -1041,6 +1086,7 @@ void handle_node_announcement(
|
|||
tal_free(node->node_announcement);
|
||||
node->node_announcement = tal_steal(node, serialized);
|
||||
tal_free(tmpctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate,
|
||||
|
|
|
@ -215,7 +215,9 @@ bool handle_pending_cannouncement(struct routing_state *rstate,
|
|||
const u64 satoshis,
|
||||
const u8 *txscript);
|
||||
void handle_channel_update(struct routing_state *rstate, const u8 *update);
|
||||
void handle_node_announcement(struct routing_state *rstate, const u8 *node);
|
||||
|
||||
/* Returns NULL if all OK, otherwise an error for the peer which sent. */
|
||||
u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node);
|
||||
|
||||
/* Set values on the struct node_connection */
|
||||
void set_connection_values(struct chan *chan,
|
||||
|
|
|
@ -87,6 +87,11 @@ bool replace_broadcast(struct broadcast_state *bstate UNNEEDED,
|
|||
void status_failed(enum status_failreason code UNNEEDED,
|
||||
const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "status_failed called!\n"); abort(); }
|
||||
/* Generated stub for towire_errorfmt */
|
||||
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
|
||||
const struct channel_id *channel UNNEEDED,
|
||||
const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "towire_errorfmt called!\n"); abort(); }
|
||||
/* Generated stub for towire_pubkey */
|
||||
void towire_pubkey(u8 **pptr UNNEEDED, const struct pubkey *pubkey UNNEEDED)
|
||||
{ fprintf(stderr, "towire_pubkey called!\n"); abort(); }
|
||||
|
|
|
@ -51,6 +51,11 @@ bool replace_broadcast(struct broadcast_state *bstate UNNEEDED,
|
|||
void status_failed(enum status_failreason code UNNEEDED,
|
||||
const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "status_failed called!\n"); abort(); }
|
||||
/* Generated stub for towire_errorfmt */
|
||||
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
|
||||
const struct channel_id *channel UNNEEDED,
|
||||
const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "towire_errorfmt called!\n"); abort(); }
|
||||
/* Generated stub for towire_pubkey */
|
||||
void towire_pubkey(u8 **pptr UNNEEDED, const struct pubkey *pubkey UNNEEDED)
|
||||
{ fprintf(stderr, "towire_pubkey called!\n"); abort(); }
|
||||
|
|
|
@ -49,6 +49,11 @@ bool replace_broadcast(struct broadcast_state *bstate UNNEEDED,
|
|||
void status_failed(enum status_failreason code UNNEEDED,
|
||||
const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "status_failed called!\n"); abort(); }
|
||||
/* Generated stub for towire_errorfmt */
|
||||
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
|
||||
const struct channel_id *channel UNNEEDED,
|
||||
const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "towire_errorfmt called!\n"); abort(); }
|
||||
/* Generated stub for towire_pubkey */
|
||||
void towire_pubkey(u8 **pptr UNNEEDED, const struct pubkey *pubkey UNNEEDED)
|
||||
{ fprintf(stderr, "towire_pubkey called!\n"); abort(); }
|
||||
|
|
Loading…
Reference in New Issue