From eece4529cbc27eb8266cd9f47cf84c0d0a6b742a Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 20 Jan 2015 23:47:41 +0100 Subject: handshake: delay method parsing until the sender key has been handled Otherwise fastd won't use the correct peer group's method list for handshakes incoming on generic sockets. --- src/fastd.h | 2 +- src/handshake.c | 22 ++++++++-------------- src/handshake.h | 2 ++ src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h | 2 +- src/protocols/ec25519_fhmqvc/handshake.c | 9 ++++++++- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/fastd.h b/src/fastd.h index 60b675a..56a099a 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -78,7 +78,7 @@ struct fastd_protocol { void (*handshake_init)(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer); /** Handles a handshake for the given peer */ - void (*handshake_handle)(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, const fastd_method_info_t *method); + void (*handshake_handle)(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake); #ifdef WITH_DYNAMIC_PEERS /** Handles an asynchronous on-verify command return */ diff --git a/src/handshake.c b/src/handshake.c index 66f9e9a..14de253 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -265,7 +265,7 @@ static void print_error(const char *prefix, const fastd_peer_address_t *remote_a } /** Sends an error reply to a peer */ -static void send_error(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, uint8_t reply_code, uint16_t error_detail) { +void fastd_handshake_send_error(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, uint8_t reply_code, uint16_t error_detail) { print_error("sending", remote_addr, reply_code, error_detail); fastd_handshake_buffer_t buffer = { @@ -354,14 +354,14 @@ static inline void print_error_reply(const fastd_peer_address_t *remote_addr, co static inline bool check_records(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake) { if (handshake->records[RECORD_PROTOCOL_NAME].data) { if (!record_equal(conf.protocol->name, &handshake->records[RECORD_PROTOCOL_NAME])) { - send_error(sock, local_addr, remote_addr, peer, handshake, REPLY_UNACCEPTABLE_VALUE, RECORD_PROTOCOL_NAME); + fastd_handshake_send_error(sock, local_addr, remote_addr, peer, handshake, REPLY_UNACCEPTABLE_VALUE, RECORD_PROTOCOL_NAME); return false; } } if (handshake->records[RECORD_MODE].data) { if (handshake->records[RECORD_MODE].length != 1 || as_uint8(&handshake->records[RECORD_MODE]) != conf.mode) { - send_error(sock, local_addr, remote_addr, peer, handshake, REPLY_UNACCEPTABLE_VALUE, RECORD_MODE); + fastd_handshake_send_error(sock, local_addr, remote_addr, peer, handshake, REPLY_UNACCEPTABLE_VALUE, RECORD_MODE); return false; } } @@ -369,7 +369,7 @@ static inline bool check_records(fastd_socket_t *sock, const fastd_peer_address_ if (!conf.secure_handshakes || handshake->type > 1) { if (handshake->records[RECORD_MTU].length == 2) { if (as_uint16_endian(&handshake->records[RECORD_MTU], handshake->little_endian) != conf.mtu) { - send_error(sock, local_addr, remote_addr, peer, handshake, REPLY_UNACCEPTABLE_VALUE, RECORD_MTU); + fastd_handshake_send_error(sock, local_addr, remote_addr, peer, handshake, REPLY_UNACCEPTABLE_VALUE, RECORD_MTU); return false; } } @@ -403,7 +403,9 @@ static inline const fastd_method_info_t * get_method_by_name(const fastd_string_ } /** Returns the most appropriate method to negotiate with a peer a handshake was received from */ -static inline const fastd_method_info_t * get_method(const fastd_string_stack_t *methods, const fastd_handshake_t *handshake) { +const fastd_method_info_t * fastd_handshake_get_method(const fastd_peer_t *peer, const fastd_handshake_t *handshake) { + const fastd_string_stack_t *methods = fastd_peer_get_methods(peer); + if (handshake->records[RECORD_METHOD_LIST].data && handshake->records[RECORD_METHOD_LIST].length) { fastd_string_stack_t *method_list = parse_string_list(handshake->records[RECORD_METHOD_LIST].data, handshake->records[RECORD_METHOD_LIST].length); @@ -433,7 +435,6 @@ static inline const fastd_method_info_t * get_method(const fastd_string_stack_t /** Handles a handshake packet */ void fastd_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, fastd_buffer_t buffer) { char *peer_version = NULL; - const fastd_method_info_t *method = NULL; fastd_handshake_t handshake = parse_tlvs(&buffer); @@ -453,18 +454,11 @@ void fastd_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *lo goto end_free; if (!conf.secure_handshakes || handshake.type > 1) { - method = get_method(fastd_peer_get_methods(peer), &handshake); - if (handshake.records[RECORD_VERSION_NAME].data) handshake.peer_version = peer_version = fastd_strndup((const char *)handshake.records[RECORD_VERSION_NAME].data, handshake.records[RECORD_VERSION_NAME].length); } - if (handshake.type > 1 && !method) { - send_error(sock, local_addr, remote_addr, peer, &handshake, REPLY_UNACCEPTABLE_VALUE, RECORD_METHOD_LIST); - goto end_free; - } - - conf.protocol->handshake_handle(sock, local_addr, remote_addr, peer, &handshake, method); + conf.protocol->handshake_handle(sock, local_addr, remote_addr, peer, &handshake); end_free: free(peer_version); diff --git a/src/handshake.h b/src/handshake.h index 5ad65a3..ccd1da5 100644 --- a/src/handshake.h +++ b/src/handshake.h @@ -102,6 +102,8 @@ struct fastd_handshake_buffer { fastd_handshake_buffer_t fastd_handshake_new_init(size_t tail_space); fastd_handshake_buffer_t fastd_handshake_new_reply(uint8_t type, bool little_endian, const fastd_method_info_t *method, const fastd_string_stack_t *methods, size_t tail_space); +void fastd_handshake_send_error(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, uint8_t reply_code, uint16_t error_detail); +const fastd_method_info_t * fastd_handshake_get_method(const fastd_peer_t *peer, const fastd_handshake_t *handshake); void fastd_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, fastd_buffer_t buffer); diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h index b24593c..25e7bb3 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h @@ -109,7 +109,7 @@ void fastd_protocol_ec25519_fhmqvc_reset_peer_state(fastd_peer_t *peer); void fastd_protocol_ec25519_fhmqvc_free_peer_state(fastd_peer_t *peer); void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer); -void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, const fastd_method_info_t *method); +void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake); #ifdef WITH_DYNAMIC_PEERS void fastd_protocol_ec25519_fhmqvc_handle_verify_return(fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, const fastd_method_info_t *method, const void *protocol_data, bool ok); diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c index 4d03725..8e3c67a 100644 --- a/src/protocols/ec25519_fhmqvc/handshake.c +++ b/src/protocols/ec25519_fhmqvc/handshake.c @@ -627,7 +627,7 @@ static inline fastd_peer_t * add_dynamic(UNUSED fastd_socket_t *sock, const fast /** Handles a received handshake packet */ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, - fastd_peer_t *peer, const fastd_handshake_t *handshake, const fastd_method_info_t *method) { + fastd_peer_t *peer, const fastd_handshake_t *handshake) { fastd_protocol_ec25519_fhmqvc_maintenance(); if (!has_field(handshake, RECORD_SENDER_KEY, PUBLICKEYBYTES)) { @@ -676,6 +676,8 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const } } + const fastd_method_info_t *method = fastd_handshake_get_method(peer, handshake); + #ifdef WITH_DYNAMIC_PEERS if (fastd_peer_is_dynamic(peer)) { if (!handle_dynamic(sock, local_addr, remote_addr, peer, handshake, method)) @@ -701,6 +703,11 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const return; } + if (!method) { + fastd_handshake_send_error(sock, local_addr, remote_addr, peer, handshake, REPLY_UNACCEPTABLE_VALUE, RECORD_METHOD_LIST); + return; + } + if (!has_field(handshake, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES)) { pr_debug("recived handshake reply without recipient key from %P[%I]", peer, remote_addr); return; -- cgit v1.2.3