From 483991603836a803200161d4b3e48fd7f55fe606 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 1 Apr 2017 20:55:59 +1030 Subject: [PATCH] lightningd/cryptomsg: discard unknown odd messages internally. This saves all callers having to handle it. Signed-off-by: Rusty Russell --- lightningd/cryptomsg.c | 11 +++++++++ lightningd/cryptomsg.h | 4 ++-- lightningd/test/run-cryptomsg.c | 4 ++++ wire/Makefile | 4 +++- wire/peer_wire.c | 42 +++++++++++++++++++++++++++++++++ wire/peer_wire.h | 20 ++++++++++++++++ 6 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 wire/peer_wire.c create mode 100644 wire/peer_wire.h diff --git a/lightningd/cryptomsg.c b/lightningd/cryptomsg.c index 59dd9fe71..df1948cf0 100644 --- a/lightningd/cryptomsg.c +++ b/lightningd/cryptomsg.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -132,6 +133,16 @@ static struct io_plan *peer_decrypt_body(struct io_conn *conn, if (!decrypted) return io_close(conn); + /* BOLT #1: + * + * A node MUST ignore a received message of unknown type, if that type + * is odd. + */ + if (unlikely(unknown_msg_discardable(decrypted))) { + pcs->in = tal_free(pcs->in); + return peer_read_message(conn, pcs, pcs->next_in); + } + /* Steal cs->in: we free it after, and decrypted too unless * they steal but be careful not to touch anything after * next_in (could free itself) */ diff --git a/lightningd/cryptomsg.h b/lightningd/cryptomsg.h index df6a0fa8d..2028fcecb 100644 --- a/lightningd/cryptomsg.h +++ b/lightningd/cryptomsg.h @@ -32,7 +32,7 @@ struct peer_crypto_state { /* Initializes peer->cs (still need to read in cs->cs) */ void init_peer_crypto_state(struct peer *peer, struct peer_crypto_state *pcs); -/* Get decrypted message */ +/* Get decrypted message: ignores unknown odd messages. */ struct io_plan *peer_read_message(struct io_conn *conn, struct peer_crypto_state *cs, struct io_plan *(*next)(struct io_conn *, @@ -49,7 +49,7 @@ struct io_plan *peer_write_message(struct io_conn *conn, void towire_crypto_state(u8 **pptr, const struct crypto_state *cs); void fromwire_crypto_state(const u8 **ptr, size_t *max, struct crypto_state *cs); -/* Low-level functions for sync comms. */ +/* Low-level functions for sync comms: doesn't discard unknowns! */ u8 *cryptomsg_encrypt_msg(const tal_t *ctx, struct crypto_state *cs, const u8 *msg); diff --git a/lightningd/test/run-cryptomsg.c b/lightningd/test/run-cryptomsg.c index 1414e4007..75759e556 100644 --- a/lightningd/test/run-cryptomsg.c +++ b/lightningd/test/run-cryptomsg.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #undef io_read @@ -37,6 +38,9 @@ static void do_write(const void *buf, size_t len) #define status_trace(fmt, ...) \ printf(fmt "\n", __VA_ARGS__) +/* We test what look like unknown messages. */ +#define unknown_msg_discardable(x) 0 + #include "../cryptomsg.c" const void *trc; diff --git a/wire/Makefile b/wire/Makefile index ebab67749..055ceb873 100644 --- a/wire/Makefile +++ b/wire/Makefile @@ -4,7 +4,8 @@ wire-wrongdir: $(MAKE) -C .. wire-all -WIRE_HEADERS := wire/wire.h \ +WIRE_HEADERS := wire/peer_wire.h \ + wire/wire.h \ wire/wire_sync.h \ wire/wire_io.h WIRE_GEN_HEADERS := wire/gen_peer_wire.h wire/gen_onion_wire.h @@ -13,6 +14,7 @@ WIRE_GEN_ONION_SRC := wire/gen_onion_wire.c WIRE_SRC := wire/wire_sync.c \ wire/wire_io.c \ wire/fromwire.c \ + wire/peer_wire.c \ wire/towire.c WIRE_OBJS := $(WIRE_SRC:.c=.o) $(WIRE_GEN_SRC:.c=.o) diff --git a/wire/peer_wire.c b/wire/peer_wire.c new file mode 100644 index 000000000..17a37e6cb --- /dev/null +++ b/wire/peer_wire.c @@ -0,0 +1,42 @@ +#include + +static bool unknown_type(enum wire_type t) +{ + switch (t) { + case WIRE_INIT: + case WIRE_ERROR: + case WIRE_OPEN_CHANNEL: + case WIRE_ACCEPT_CHANNEL: + case WIRE_FUNDING_CREATED: + case WIRE_FUNDING_SIGNED: + case WIRE_FUNDING_LOCKED: + case WIRE_SHUTDOWN: + case WIRE_CLOSING_SIGNED: + case WIRE_UPDATE_ADD_HTLC: + case WIRE_UPDATE_FULFILL_HTLC: + case WIRE_UPDATE_FAIL_HTLC: + case WIRE_UPDATE_FAIL_MALFORMED_HTLC: + case WIRE_COMMITMENT_SIGNED: + case WIRE_REVOKE_AND_ACK: + case WIRE_UPDATE_FEE: + case WIRE_ANNOUNCEMENT_SIGNATURES: + case WIRE_CHANNEL_ANNOUNCEMENT: + case WIRE_NODE_ANNOUNCEMENT: + case WIRE_CHANNEL_UPDATE: + return false; + } + return true; +} + +/* Return true if it's an unknown message. cursor is a tal ptr. */ +bool unknown_msg(const u8 *cursor) +{ + return unknown_type(fromwire_peektype(cursor)); +} + +/* Return true if it's an unknown ODD message. cursor is a tal ptr. */ +bool unknown_msg_discardable(const u8 *cursor) +{ + enum wire_type t = fromwire_peektype(cursor); + return unknown_type(t) && (t & 1); +} diff --git a/wire/peer_wire.h b/wire/peer_wire.h new file mode 100644 index 000000000..b3a95c392 --- /dev/null +++ b/wire/peer_wire.h @@ -0,0 +1,20 @@ +#ifndef LIGHTNING_WIRE_PEER_WIRE_H +#define LIGHTNING_WIRE_PEER_WIRE_H +#include "config.h" +#include +#include + +/* BOLT #1: + * + * A node MUST ignore a received message of unknown type, if that type is odd. + * + * A node MUST fail the channels if it receives a message of unknown type, if + * that type is even. + */ + +/* Return true if it's an unknown message. cursor is a tal ptr. */ +bool unknown_msg(const u8 *cursor); +/* Return true if it's an unknown ODD message. cursor is a tal ptr. */ +bool unknown_msg_discardable(const u8 *cursor); + +#endif /* LIGHTNING_WIRE_PEER_WIRE_H */