From 8c91443808ce376947ff387eaffca6e8cfbe9251 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 19 Apr 2012 17:42:56 +0200 Subject: Don't regenerate session handshake keypair for every handshake so a global state can be used; remove the concept of temporary peers These changes will fix the possibility of a TCP-SYN-Flood-like DoS attack, at the cost of another protocol change: as we can't count request IDs when we don't know have temporary peers, request IDs are removed completely. --- src/config.c | 3 +- src/fastd.c | 89 +++------ src/fastd.h | 12 +- src/handshake.c | 49 +++-- src/handshake.h | 7 +- src/method_xsalsa20_poly1305.c | 2 +- src/packet.h | 4 +- src/peer.c | 116 ++++------- src/peer.h | 26 +-- src/printf.c | 81 ++++---- src/protocol_ec25519_fhmqvc.c | 434 +++++++++++++++++++---------------------- src/types.h | 8 +- 12 files changed, 348 insertions(+), 483 deletions(-) diff --git a/src/config.c b/src/config.c index 3e42f38..c5c4c65 100644 --- a/src/config.c +++ b/src/config.c @@ -55,7 +55,6 @@ static void default_config(fastd_config *conf) { conf->keepalive_interval = 60; conf->peer_stale_time = 300; - conf->peer_stale_time_temp = 30; conf->eth_addr_stale_time = 300; conf->ifname = NULL; @@ -668,7 +667,7 @@ static void reconfigure_handle_old_peers(fastd_context *ctx, fastd_peer_config * static void reconfigure_reset_waiting(fastd_context *ctx) { fastd_peer *peer; for (peer = ctx->peers; peer; peer = peer->next) { - if (fastd_peer_is_waiting(peer)) + if (!fastd_peer_is_established(peer)) fastd_peer_reset(ctx, peer); } } diff --git a/src/fastd.c b/src/fastd.c index 89b764d..0c7e6f5 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -202,20 +202,20 @@ static void close_sockets(fastd_context *ctx) { } } -static void fastd_send_type(fastd_context *ctx, fastd_peer *peer, uint8_t packet_type, fastd_buffer buffer) { +static void fastd_send_type(fastd_context *ctx, const fastd_peer_address *address, uint8_t packet_type, fastd_buffer buffer) { int sockfd; struct msghdr msg; memset(&msg, 0, sizeof(msg)); - switch (peer->address.sa.sa_family) { + switch (address->sa.sa_family) { case AF_INET: - msg.msg_name = &peer->address.in; + msg.msg_name = (void*)&address->in; msg.msg_namelen = sizeof(struct sockaddr_in); sockfd = ctx->sockfd; break; case AF_INET6: - msg.msg_name = &peer->address.in6; + msg.msg_name = (void*)&address->in6; msg.msg_namelen = sizeof(struct sockaddr_in6); sockfd = ctx->sock6fd; break; @@ -243,12 +243,12 @@ static void fastd_send_type(fastd_context *ctx, fastd_peer *peer, uint8_t packet fastd_buffer_free(buffer); } -void fastd_send(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) { - fastd_send_type(ctx, peer, PACKET_DATA, buffer); +void fastd_send(fastd_context *ctx, const fastd_peer_address *address, fastd_buffer buffer) { + fastd_send_type(ctx, address, PACKET_DATA, buffer); } -void fastd_send_handshake(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) { - fastd_send_type(ctx, peer, PACKET_HANDSHAKE, buffer); +void fastd_send_handshake(fastd_context *ctx, const fastd_peer_address *address, fastd_buffer buffer) { + fastd_send_type(ctx, address, PACKET_HANDSHAKE, buffer); } void fastd_handle_receive(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) { @@ -268,7 +268,7 @@ void fastd_handle_receive(fastd_context *ctx, fastd_peer *peer, fastd_buffer buf if (fastd_eth_addr_is_unicast(dest_addr)) { fastd_peer *dest_peer = fastd_peer_find_by_eth_addr(ctx, dest_addr); - if (dest_peer && dest_peer != peer && dest_peer->state == STATE_ESTABLISHED) { + if (dest_peer && dest_peer != peer && fastd_peer_is_established(dest_peer)) { ctx->conf->protocol->send(ctx, dest_peer, buffer); } else { @@ -278,7 +278,7 @@ void fastd_handle_receive(fastd_context *ctx, fastd_peer *peer, fastd_buffer buf else { fastd_peer *dest_peer; for (dest_peer = ctx->peers; dest_peer; dest_peer = dest_peer->next) { - if (dest_peer != peer && dest_peer->state == STATE_ESTABLISHED) { + if (dest_peer != peer && fastd_peer_is_established(dest_peer)) { fastd_buffer send_buffer = fastd_buffer_alloc(buffer.len, ctx->conf->method->min_encrypt_head_space(ctx), 0); memcpy(send_buffer.data, buffer.data, buffer.len); ctx->conf->protocol->send(ctx, dest_peer, send_buffer); @@ -379,7 +379,7 @@ static inline void update_time(fastd_context *ctx) { static inline void send_handshake(fastd_context *ctx, fastd_peer *peer) { if (peer->address.sa.sa_family != AF_UNSPEC) { pr_debug(ctx, "sending handshake to %P...", peer); - ctx->conf->protocol->handshake_init(ctx, peer); + ctx->conf->protocol->handshake_init(ctx, &peer->address, peer->config); } fastd_task_schedule_handshake(ctx, peer, fastd_rand(ctx, 17500, 22500)); @@ -390,7 +390,7 @@ static void handle_tasks(fastd_context *ctx) { while ((task = fastd_task_get(ctx)) != NULL) { switch (task->type) { case TASK_HANDSHAKE: - if (task->peer->state == STATE_RESOLVE) + if (fastd_peer_is_dynamic(task->peer)) fastd_resolve_peer(ctx, task->peer->config); else send_handshake(ctx, task->peer); @@ -437,7 +437,7 @@ static void handle_tun(fastd_context *ctx) { return; } - if (peer->state == STATE_ESTABLISHED) { + if (fastd_peer_is_established(peer)) { ctx->conf->protocol->send(ctx, peer, buffer); } else { @@ -447,7 +447,7 @@ static void handle_tun(fastd_context *ctx) { } if (peer == NULL) { for (peer = ctx->peers; peer; peer = peer->next) { - if (peer->state == STATE_ESTABLISHED) { + if (fastd_peer_is_established(peer)) { fastd_buffer send_buffer = fastd_buffer_alloc(len, ctx->conf->method->min_encrypt_head_space(ctx), 0); memcpy(send_buffer.data, buffer.data, len); ctx->conf->protocol->send(ctx, peer, send_buffer); @@ -490,28 +490,8 @@ static void handle_socket(fastd_context *ctx, int sockfd) { fastd_peer *peer; for (peer = ctx->peers; peer; peer = peer->next) { - if (peer->address.sa.sa_family != recvaddr.sa.sa_family) - continue; - - if (recvaddr.sa.sa_family == AF_INET) { - if (peer->address.in.sin_addr.s_addr != recvaddr.in.sin_addr.s_addr) - continue; - if (peer->address.in.sin_port != recvaddr.in.sin_port) - continue; - + if (fastd_peer_address_equal(&peer->address, &recvaddr)) break; - } - else if (recvaddr.sa.sa_family == AF_INET6) { - if (!IN6_ARE_ADDR_EQUAL(&peer->address.in6.sin6_addr, &recvaddr.in6.sin6_addr)) - continue; - if (peer->address.in6.sin6_port != recvaddr.in6.sin6_port) - continue; - - break; - } - else { - exit_bug(ctx, "unsupported address family"); - } } if (peer) { @@ -521,7 +501,7 @@ static void handle_socket(fastd_context *ctx, int sockfd) { break; case PACKET_HANDSHAKE: - fastd_handshake_handle(ctx, peer, buffer); + fastd_handshake_handle(ctx, &recvaddr, peer->config, buffer); break; default: @@ -533,13 +513,11 @@ static void handle_socket(fastd_context *ctx, int sockfd) { (recvaddr.sa.sa_family == AF_INET6 && ctx->conf->n_dynamic_v6)) { switch (packet_type) { case PACKET_DATA: - peer = fastd_peer_add_temp(ctx, (fastd_peer_address*)&recvaddr); - ctx->conf->protocol->handle_recv(ctx, peer, buffer); + ctx->conf->protocol->handshake_init(ctx, &recvaddr, NULL); break; case PACKET_HANDSHAKE: - peer = fastd_peer_add_temp(ctx, (fastd_peer_address*)&recvaddr); - fastd_handshake_handle(ctx, peer, buffer); + fastd_handshake_handle(ctx, &recvaddr, NULL, buffer); break; default: @@ -547,7 +525,7 @@ static void handle_socket(fastd_context *ctx, int sockfd) { } } else { - pr_debug(ctx, "received packet from unknown peer"); + pr_debug(ctx, "received packet from unknown peer %I", &recvaddr); fastd_buffer_free(buffer); } } @@ -590,26 +568,13 @@ static void cleanup_peers(fastd_context *ctx) { for (peer = ctx->peers; peer; peer = next) { next = peer->next; - if (fastd_peer_is_temporary(peer)) { - if (timespec_diff(&ctx->now, &peer->seen) > ctx->conf->peer_stale_time_temp*1000) - fastd_peer_reset(ctx, peer); - } - else if (fastd_peer_is_established(peer)) { + if (fastd_peer_is_established(peer)) { if (timespec_diff(&ctx->now, &peer->seen) > ctx->conf->peer_stale_time*1000) fastd_peer_reset(ctx, peer); } } } -static void cleanup_peer_with_address(fastd_context *ctx, const fastd_peer_address *addr) { - fastd_peer *peer; - for (peer = ctx->peers; peer; peer = peer->next) { - if (fastd_peer_is_temporary(peer) && fastd_peer_addr_equal(&peer->address, addr)) { - fastd_peer_reset(ctx, peer); - return; - } - } -} static void handle_resolv_returns(fastd_context *ctx) { while (ctx->resolve_returns) { @@ -624,11 +589,13 @@ static void handle_resolv_returns(fastd_context *ctx) { if (!fastd_peer_config_matches_dynamic(peer->config, &ctx->resolve_returns->constraints)) continue; - cleanup_peer_with_address(ctx, &ctx->resolve_returns->addr); - peer->address = ctx->resolve_returns->addr; - - if (peer->state == STATE_RESOLVE) - send_handshake(ctx, peer); + if (fastd_peer_claim_address(ctx, peer, &ctx->resolve_returns->addr)) { + if (!fastd_peer_is_established(peer)) + send_handshake(ctx, peer); + } + else { + pr_warn(ctx, "hostname `%s' resolved to address %I which is used by a fixed peer", ctx->resolve_returns->hostname, ctx->resolve_returns->addr); + } break; } @@ -696,6 +663,8 @@ int main(int argc, char *argv[]) { close_sockets(&ctx); close_tuntap(&ctx); + free(ctx.protocol_state); + fastd_config_release(&ctx, &conf); return 0; diff --git a/src/fastd.h b/src/fastd.h index c681d34..08ef666 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -64,10 +64,9 @@ struct _fastd_protocol { fastd_protocol_config* (*init)(fastd_context *ctx); void (*peer_configure)(fastd_context *ctx, fastd_peer_config *peer_conf); - void (*peer_config_purged)(fastd_context *ctx, fastd_peer_config *peer_conf); - void (*handshake_init)(fastd_context *ctx, fastd_peer *peer); - void (*handshake_handle)(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake); + void (*handshake_init)(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf); + void (*handshake_handle)(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf, const fastd_handshake *handshake); void (*handle_recv)(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer); void (*send)(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer); @@ -116,7 +115,6 @@ struct _fastd_config { unsigned keepalive_interval; unsigned peer_stale_time; - unsigned peer_stale_time_temp; unsigned eth_addr_stale_time; char *ifname; @@ -182,6 +180,8 @@ struct _fastd_context { unsigned int randseed; + fastd_protocol_state *protocol_state; + fastd_resolve_return *resolve_returns; }; @@ -191,8 +191,8 @@ struct _fastd_string_stack { }; -void fastd_send(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer); -void fastd_send_handshake(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer); +void fastd_send(fastd_context *ctx, const fastd_peer_address *address, fastd_buffer buffer); +void fastd_send_handshake(fastd_context *ctx, const fastd_peer_address *address, fastd_buffer buffer); void fastd_handle_receive(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer); void fastd_resolve_peer(fastd_context *ctx, const fastd_peer_config *peer); diff --git a/src/handshake.c b/src/handshake.c index c301e4e..eb33f4f 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -58,7 +58,7 @@ static const char const *REPLY_TYPES[REPLY_MAX] = { #define AS_UINT16(ptr) ((*(uint8_t*)(ptr).data) + (*((uint8_t*)(ptr).data+1) << 8)) -fastd_buffer fastd_handshake_new_init(fastd_context *ctx, fastd_peer *peer, size_t tail_space) { +fastd_buffer fastd_handshake_new_init(fastd_context *ctx, size_t tail_space) { size_t protocol_len = strlen(ctx->conf->protocol->name); size_t method_len = strlen(ctx->conf->method->name); fastd_buffer buffer = fastd_buffer_alloc(sizeof(fastd_packet), 0, @@ -70,8 +70,8 @@ fastd_buffer fastd_handshake_new_init(fastd_context *ctx, fastd_peer *peer, size ); fastd_packet *request = buffer.data; - request->req_id = ++peer->last_req_id; - request->rsv = 0; + request->rsv1 = 0; + request->rsv2 = 0; fastd_handshake_add_uint8(ctx, &buffer, RECORD_HANDSHAKE_TYPE, 1); fastd_handshake_add_uint8(ctx, &buffer, RECORD_MODE, ctx->conf->mode); @@ -83,7 +83,7 @@ fastd_buffer fastd_handshake_new_init(fastd_context *ctx, fastd_peer *peer, size return buffer; } -fastd_buffer fastd_handshake_new_reply(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake, size_t tail_space) { +fastd_buffer fastd_handshake_new_reply(fastd_context *ctx, const fastd_handshake *handshake, size_t tail_space) { bool first = (AS_UINT8(handshake->records[RECORD_HANDSHAKE_TYPE]) == 1); size_t mtu_size = 0; @@ -97,8 +97,8 @@ fastd_buffer fastd_handshake_new_reply(fastd_context *ctx, fastd_peer *peer, con ); fastd_packet *request = buffer.data; - request->req_id = handshake->req_id; - request->rsv = 0; + request->rsv1 = 0; + request->rsv2 = 0; fastd_handshake_add_uint8(ctx, &buffer, RECORD_HANDSHAKE_TYPE, AS_UINT8(handshake->records[RECORD_HANDSHAKE_TYPE])+1); fastd_handshake_add_uint8(ctx, &buffer, RECORD_REPLY_CODE, 0); @@ -109,10 +109,9 @@ fastd_buffer fastd_handshake_new_reply(fastd_context *ctx, fastd_peer *peer, con return buffer; } - -void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) { +void fastd_handshake_handle(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf, fastd_buffer buffer) { if (buffer.len < sizeof(fastd_packet)) { - pr_warn(ctx, "received a short handshake from %P", peer); + pr_warn(ctx, "received a short handshake from %I", address); goto end_free; } @@ -140,10 +139,8 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b ptr += 4+len; } - handshake.req_id = packet->req_id; - if (handshake.records[RECORD_HANDSHAKE_TYPE].length != 1) { - pr_debug(ctx, "received handshake without handshake type from %P", peer); + pr_debug(ctx, "received handshake without handshake type from %I", address); goto end_free; } @@ -151,8 +148,8 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b if (handshake.records[RECORD_MTU].length == 2) { if (AS_UINT16(handshake.records[RECORD_MTU]) != ctx->conf->mtu) { - pr_warn(ctx, "MTU configuration differs with peer %P: local MTU is %u, remote MTU is %u", - peer, ctx->conf->mtu, AS_UINT16(handshake.records[RECORD_MTU])); + pr_warn(ctx, "MTU configuration differs with peer %I: local MTU is %u, remote MTU is %u", + address, ctx->conf->mtu, AS_UINT16(handshake.records[RECORD_MTU])); } } @@ -203,47 +200,47 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b fastd_buffer reply_buffer = fastd_buffer_alloc(sizeof(fastd_packet), 0, 3*5 /* enough space for handshake type, reply code and error detail */); fastd_packet *reply = reply_buffer.data; - reply->req_id = packet->req_id; - reply->rsv = 0; + reply->rsv1 = 0; + reply->rsv2 = 0; fastd_handshake_add_uint8(ctx, &reply_buffer, RECORD_HANDSHAKE_TYPE, 2); fastd_handshake_add_uint8(ctx, &reply_buffer, RECORD_REPLY_CODE, reply_code); fastd_handshake_add_uint8(ctx, &reply_buffer, RECORD_ERROR_DETAIL, error_detail); - fastd_send_handshake(ctx, peer, reply_buffer); + fastd_send_handshake(ctx, address, reply_buffer); } else { - ctx->conf->protocol->handshake_handle(ctx, peer, &handshake); + ctx->conf->protocol->handshake_handle(ctx, address, peer_conf, &handshake); } } else { if ((handshake.type & 1) == 0) { - if (packet->req_id != peer->last_req_id) { + /*if (packet->req_id != peer->last_req_id) { pr_warn(ctx, "received handshake reply with request ID %u from %P while %u was expected", packet->req_id, peer, peer->last_req_id); goto end_free; - } + }*/ } if (handshake.records[RECORD_REPLY_CODE].length != 1) { - pr_warn(ctx, "received handshake reply without reply code from %P", peer); + pr_warn(ctx, "received handshake reply without reply code from %I", address); goto end_free; } uint8_t reply_code = AS_UINT8(handshake.records[RECORD_REPLY_CODE]); if (reply_code == REPLY_SUCCESS) { - ctx->conf->protocol->handshake_handle(ctx, peer, &handshake); + ctx->conf->protocol->handshake_handle(ctx, address, peer_conf, &handshake); } else { const char *error_field_str; if (reply_code >= REPLY_MAX) { - pr_warn(ctx, "Handshake with %P failed with unknown code %i", peer, reply_code); + pr_warn(ctx, "Handshake with %I failed with unknown code %I", address, reply_code); goto end_free; } if (handshake.records[RECORD_ERROR_DETAIL].length != 1) { - pr_warn(ctx, "Handshake with %P failed with code %s", peer, REPLY_TYPES[reply_code]); + pr_warn(ctx, "Handshake with %I failed with code %s", address, REPLY_TYPES[reply_code]); goto end_free; } @@ -255,11 +252,11 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b switch (reply_code) { case REPLY_MANDATORY_MISSING: - pr_warn(ctx, "Handshake with %P failed: mandatory field `%s' missing", peer, error_field_str); + pr_warn(ctx, "Handshake with %I failed: mandatory field `%s' missing", address, error_field_str); break; case REPLY_UNACCEPTABLE_VALUE: - pr_warn(ctx, "Handshake with %P failed: unacceptable value for field `%s'", peer, error_field_str); + pr_warn(ctx, "Handshake with %I failed: unacceptable value for field `%s'", address, error_field_str); break; default: /* just to silence the warning */ diff --git a/src/handshake.h b/src/handshake.h index 9bb1a56..5e7ee1d 100644 --- a/src/handshake.h +++ b/src/handshake.h @@ -61,16 +61,15 @@ typedef struct _fastd_handshake_record { } fastd_handshake_record; struct _fastd_handshake { - uint8_t req_id; uint8_t type; fastd_handshake_record records[RECORD_MAX]; }; -fastd_buffer fastd_handshake_new_init(fastd_context *ctx, fastd_peer *peer, size_t tail_space); -fastd_buffer fastd_handshake_new_reply(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake, size_t tail_space); +fastd_buffer fastd_handshake_new_init(fastd_context *ctx, size_t tail_space); +fastd_buffer fastd_handshake_new_reply(fastd_context *ctx, const fastd_handshake *handshake, size_t tail_space); -void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer); +void fastd_handshake_handle(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf, fastd_buffer buffer); static inline void fastd_handshake_add(fastd_context *ctx, fastd_buffer *buffer, fastd_handshake_record_type type, size_t len, const void *data) { diff --git a/src/method_xsalsa20_poly1305.c b/src/method_xsalsa20_poly1305.c index 5194a4d..9331265 100644 --- a/src/method_xsalsa20_poly1305.c +++ b/src/method_xsalsa20_poly1305.c @@ -118,7 +118,7 @@ static bool method_session_is_initiator(fastd_context *ctx, fastd_method_session } static bool method_session_want_refresh(fastd_context *ctx, fastd_method_session_state *session) { - return (method_session_is_initiator(ctx, session) && timespec_after(&ctx->now, &session->refresh_after)); + return timespec_after(&ctx->now, &session->refresh_after); } static void method_session_free(fastd_context *ctx, fastd_method_session_state *session) { diff --git a/src/packet.h b/src/packet.h index 76a64d1..210955d 100644 --- a/src/packet.h +++ b/src/packet.h @@ -37,8 +37,8 @@ typedef enum _fastd_packet_type { } fastd_packet_type; typedef struct __attribute__ ((__packed__)) _fastd_packet { - uint8_t req_id; - uint16_t rsv; + uint8_t rsv1; + uint16_t rsv2; uint8_t tlv_data[]; } fastd_packet; diff --git a/src/peer.c b/src/peer.c index 1ad4c7f..f3d9da8 100644 --- a/src/peer.c +++ b/src/peer.c @@ -152,7 +152,7 @@ static void on_disestablish(fastd_context *ctx, fastd_peer *peer) { } static inline void reset_peer(fastd_context *ctx, fastd_peer *peer) { - if (peer->state == STATE_ESTABLISHED) + if (peer->established) on_disestablish(ctx, peer); ctx->conf->protocol->free_peer_state(ctx, peer); @@ -179,12 +179,9 @@ static inline void setup_peer(fastd_context *ctx, fastd_peer *peer) { else peer->address = peer->config->address; - if (peer->config->hostname) - peer->state = STATE_RESOLVE; - else - peer->state = STATE_WAIT; - + peer->established = false; peer->seen = (struct timespec){0, 0}; + peer->protocol_state = NULL; if (!fastd_peer_is_floating(peer)) fastd_task_schedule_handshake(ctx, peer, 0); @@ -247,11 +244,10 @@ void fastd_peer_config_purge(fastd_context *ctx, fastd_peer_config *conf) { fastd_peer_delete(ctx, peer); } - ctx->conf->protocol->peer_config_purged(ctx, conf); fastd_peer_config_free(conf); } -bool fastd_peer_addr_equal(const fastd_peer_address *addr1, const fastd_peer_address *addr2) { +bool fastd_peer_address_equal(const fastd_peer_address *addr1, const fastd_peer_address *addr2) { if (addr1->sa.sa_family != addr2->sa.sa_family) return false; @@ -262,13 +258,41 @@ bool fastd_peer_addr_equal(const fastd_peer_address *addr1, const fastd_peer_add case AF_INET: if (addr1->in.sin_addr.s_addr != addr2->in.sin_addr.s_addr) return false; + if (addr1->in.sin_port != addr2->in.sin_port) + return false; break; case AF_INET6: if (!IN6_ARE_ADDR_EQUAL(&addr1->in6.sin6_addr, &addr2->in6.sin6_addr)) return false; + if (addr1->in6.sin6_port != addr2->in6.sin6_port) + return false; + } + + return true; +} + +bool fastd_peer_claim_address(fastd_context *ctx, fastd_peer *new_peer, const fastd_peer_address *addr) { + fastd_peer *peer; + for (peer = ctx->peers; peer; peer = peer->next) { + if (fastd_peer_address_equal(&peer->address, addr)) { + if (peer == new_peer) + break; + + if (fastd_peer_is_floating(peer) || fastd_peer_is_dynamic(peer)) { + if (fastd_peer_is_established(peer)) + fastd_peer_reset(ctx, peer); + + memset(&peer->address, 0, sizeof(fastd_peer_address)); + break; + } + else { + return false; + } + } } + new_peer->address = *addr; return true; } @@ -279,7 +303,7 @@ bool fastd_peer_config_equal(const fastd_peer_config *peer1, const fastd_peer_co if (!strequal(peer1->hostname, peer2->hostname)) return false; - if (!fastd_peer_addr_equal(&peer1->address, &peer2->address)) + if (!fastd_peer_address_equal(&peer1->address, &peer2->address)) return false; if (!strequal(peer1->key, peer2->key)) @@ -292,11 +316,7 @@ void fastd_peer_reset(fastd_context *ctx, fastd_peer *peer) { pr_debug(ctx, "resetting peer %P", peer); reset_peer(ctx, peer); - - if (fastd_peer_is_temporary(peer)) - delete_peer(ctx, peer); - else - setup_peer(ctx, peer); + setup_peer(ctx, peer); } void fastd_peer_delete(fastd_context *ctx, fastd_peer *peer) { @@ -304,21 +324,12 @@ void fastd_peer_delete(fastd_context *ctx, fastd_peer *peer) { delete_peer(ctx, peer); } -static fastd_peer* add_peer(fastd_context *ctx) { +fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *peer_conf) { fastd_peer *peer = malloc(sizeof(fastd_peer)); peer->next = ctx->peers; - peer->last_req_id = 0; - peer->protocol_state = NULL; - ctx->peers = peer; - return peer; -} - -fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *peer_conf) { - fastd_peer *peer = add_peer(ctx); - peer->config = peer_conf; setup_peer(ctx, peer); @@ -327,64 +338,11 @@ fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *peer_conf) { return peer; } -fastd_peer* fastd_peer_add_temp(fastd_context *ctx, const fastd_peer_address *address) { - fastd_peer *peer = add_peer(ctx); - - peer->config = NULL; - peer->address = *address; - peer->state = STATE_TEMP; - peer->seen = ctx->now; - - pr_debug(ctx, "added peer %P", peer); - - return peer; -} - -fastd_peer* fastd_peer_set_established_merge(fastd_context *ctx, fastd_peer *perm_peer, fastd_peer *temp_peer) { - pr_debug(ctx, "merging peer %P into %P", temp_peer, perm_peer); - - ctx->conf->protocol->free_peer_state(ctx, perm_peer); - - if (perm_peer->state == STATE_ESTABLISHED) - on_disestablish(ctx, perm_peer); - - perm_peer->address = temp_peer->address; - perm_peer->state = STATE_ESTABLISHED; - perm_peer->seen = temp_peer->seen; - perm_peer->protocol_state = temp_peer->protocol_state; - temp_peer->protocol_state = NULL; - - int i; - for (i = 0; i < ctx->n_eth_addr; i++) { - if (ctx->eth_addr[i].peer == temp_peer) { - ctx->eth_addr[i].peer = perm_peer; - } - } - - fastd_task_replace_peer(ctx, temp_peer, perm_peer); - - fastd_peer_reset(ctx, temp_peer); - - on_establish(ctx, perm_peer); - pr_info(ctx, "Connection with %P established.", perm_peer); - - return perm_peer; -} - void fastd_peer_set_established(fastd_context *ctx, fastd_peer *peer) { - switch(peer->state) { - case STATE_RESOLVE: - case STATE_WAIT: - peer->state = STATE_ESTABLISHED; + if (!peer->established) { + peer->established = true; on_establish(ctx, peer); pr_info(ctx, "Connection with %P established.", peer); - break; - - case STATE_TEMP: - exit_bug(ctx, "tried to set a temporary connection to established"); - - default: - return; } } diff --git a/src/peer.h b/src/peer.h index f8b0f84..cf16629 100644 --- a/src/peer.h +++ b/src/peer.h @@ -37,8 +37,7 @@ struct _fastd_peer { fastd_peer_address address; - fastd_peer_state state; - uint8_t last_req_id; + bool established; struct timespec seen; @@ -67,7 +66,7 @@ struct _fastd_peer_eth_addr { }; -bool fastd_peer_addr_equal(const fastd_peer_address *addr1, const fastd_peer_address *addr2); +bool fastd_peer_address_equal(const fastd_peer_address *addr1, const fastd_peer_address *addr2); fastd_peer_config* fastd_peer_config_new(fastd_context *ctx, fastd_config *conf); void fastd_peer_config_free(fastd_peer_config *peer); @@ -78,9 +77,8 @@ bool fastd_peer_config_equal(const fastd_peer_config *peer1, const fastd_peer_co void fastd_peer_reset(fastd_context *ctx, fastd_peer *peer); void fastd_peer_delete(fastd_context *ctx, fastd_peer *peer); fastd_peer* fastd_peer_add(fastd_context *ctx, fastd_peer_config *conf); -fastd_peer* fastd_peer_add_temp(fastd_context *ctx, const fastd_peer_address *address); -fastd_peer* fastd_peer_set_established_merge(fastd_context *ctx, fastd_peer *perm_peer, fastd_peer *temp_peer); void fastd_peer_set_established(fastd_context *ctx, fastd_peer *peer); +bool fastd_peer_claim_address(fastd_context *ctx, fastd_peer *peer, const fastd_peer_address *addr); const fastd_eth_addr* fastd_get_source_address(const fastd_context *ctx, fastd_buffer buffer); const fastd_eth_addr* fastd_get_dest_address(const fastd_context *ctx, fastd_buffer buffer); @@ -89,26 +87,22 @@ static inline bool fastd_peer_config_is_floating(const fastd_peer_config *config return (config->hostname == NULL && config->address.sa.sa_family == AF_UNSPEC); } +static inline bool fastd_peer_config_is_dynamic(const fastd_peer_config *config) { + return (config->hostname != NULL); +} + bool fastd_peer_config_matches_dynamic(const fastd_peer_config *config, const fastd_peer_address *addr); static inline bool fastd_peer_is_floating(const fastd_peer *peer) { - return (peer->config && fastd_peer_config_is_floating(peer->config)); + return fastd_peer_config_is_floating(peer->config); } static inline bool fastd_peer_is_dynamic(const fastd_peer *peer) { - return (peer->config && peer->config->hostname); -} - -static inline bool fastd_peer_is_waiting(const fastd_peer *peer) { - return (peer->state == STATE_WAIT); -} - -static inline bool fastd_peer_is_temporary(const fastd_peer *peer) { - return (peer->state == STATE_TEMP); + return fastd_peer_config_is_dynamic(peer->config); } static inline bool fastd_peer_is_established(const fastd_peer *peer) { - return (peer->state == STATE_ESTABLISHED); + return peer->established; } static inline void fastd_peer_seen(fastd_context *ctx, fastd_peer *peer) { diff --git a/src/printf.c b/src/printf.c index 7c922c5..cbecbc8 100644 --- a/src/printf.c +++ b/src/printf.c @@ -31,37 +31,35 @@ #include -static void print_peer_str(const fastd_context *ctx, const fastd_peer *peer) { +static void print_peer_address(const fastd_context *ctx, const fastd_peer_address *address) { char addr_buf[INET6_ADDRSTRLEN] = ""; - char pl = '<', pr = '>'; - if (fastd_peer_is_temporary(peer)) { - pl = '{'; - pr = '}'; + switch (address->sa.sa_family) { + case AF_UNSPEC: + fputs("floating", stderr); + return; + + case AF_INET: + if (inet_ntop(AF_INET, &address->in.sin_addr, addr_buf, sizeof(addr_buf))) + fprintf(stderr, "%s:%u", addr_buf, ntohs(address->in.sin_port)); + return; + + case AF_INET6: + if (inet_ntop(AF_INET6, &address->in6.sin6_addr, addr_buf, sizeof(addr_buf))) + fprintf(stderr, "[%s]:%u", addr_buf, ntohs(address->in6.sin6_port)); + break; + + default: + exit_bug(ctx, "unsupported address family"); } +} +static void print_peer_str(const fastd_context *ctx, const fastd_peer *peer) { if (peer->config && peer->config->name) { - fprintf(stderr, "%c%s%c", pl, peer->config->name, pr); + fprintf(stderr, "<%s>", peer->config->name); } else { - switch (peer->address.sa.sa_family) { - case AF_UNSPEC: - fprintf(stderr, "%cfloating%c", pl, pr); - return; - - case AF_INET: - if (inet_ntop(AF_INET, &peer->address.in.sin_addr, addr_buf, sizeof(addr_buf))) - fprintf(stderr, "%c%s:%u%c", pl, addr_buf, ntohs(peer->address.in.sin_port), pr); - return; - - case AF_INET6: - if (inet_ntop(AF_INET6, &peer->address.in6.sin6_addr, addr_buf, sizeof(addr_buf))) - fprintf(stderr, "%c[%s]:%u%c", pl, addr_buf, ntohs(peer->address.in6.sin6_port), pr); - break; - - default: - exit_bug(ctx, "unsupported address family"); - } + fputs("<(null)>", stderr); } } @@ -84,10 +82,8 @@ void fastd_printf(const fastd_context *ctx, const char *format, ...) { for(len = 1; str[len]; len++) { char last; bool finished = true; - char addr_buf[INET6_ADDRSTRLEN]; - void *p; - fastd_peer *peer; - fastd_eth_addr *eth_addr; + const void *p; + const fastd_eth_addr *eth_addr; switch (str[len]) { case 'l': @@ -190,20 +186,8 @@ void fastd_printf(const fastd_context *ctx, const char *format, ...) { str[len+1] = last; break; - case 'I': - p = va_arg(ap, void*); - - if (p) { - if (inet_ntop(flag_l ? AF_INET6 : AF_INET, p, addr_buf, sizeof(addr_buf))) - fputs(addr_buf, stderr); - } - else { - fputs("(null)", stderr); - } - break; - case 'E': - eth_addr = va_arg(ap, fastd_eth_addr*); + eth_addr = va_arg(ap, const fastd_eth_addr*); if (eth_addr) { fprintf(stderr, "%02x:%02x:%02x:%02x:%02x:%02x", @@ -216,10 +200,19 @@ void fastd_printf(const fastd_context *ctx, const char *format, ...) { break; case 'P': - peer = va_arg(ap, void*); + p = va_arg(ap, const fastd_peer*); + + if (p) + print_peer_str(ctx, (const fastd_peer*)p); + else + fputs("(null)", stderr); + break; + + case 'I': + p = va_arg(ap, const fastd_peer_address*); - if (peer) - print_peer_str(ctx, peer); + if (p) + print_peer_address(ctx, (const fastd_peer_address*)p); else fputs("(null)", stderr); break; diff --git a/src/protocol_ec25519_fhmqvc.c b/src/protocol_ec25519_fhmqvc.c index 93fd9c4..e4a0e93 100644 --- a/src/protocol_ec25519_fhmqvc.c +++ b/src/protocol_ec25519_fhmqvc.c @@ -58,26 +58,22 @@ struct _fastd_protocol_config { ecc_public_key_256 public_key; }; -typedef enum _handshake_state { - HANDSHAKE_STATE_INIT, - HANDSHAKE_STATE_RESPONSE, - HANDSHAKE_STATE_ESTABLISHED -} handshake_state; +typedef struct _handshake_key { + struct timespec preferred_till; + struct timespec valid_till; -struct _fastd_protocol_peer_config { + ecc_secret_key_256 secret_key; ecc_public_key_256 public_key; -}; +} handshake_key; -typedef struct _protocol_handshake { - const fastd_peer_config *peer_config; +struct _fastd_protocol_state { + handshake_key prev_handshake_key; + handshake_key handshake_key; +}; - handshake_state state; - ecc_secret_key_256 secret_key; +struct _fastd_protocol_peer_config { ecc_public_key_256 public_key; - ecc_public_key_256 peer_key; - ecc_public_key_256 sigma; - uint8_t shared_handshake_key[HASHBYTES]; -} protocol_handshake; +}; typedef struct _protocol_session { bool handshakes_cleaned; @@ -89,9 +85,6 @@ typedef struct _protocol_session { struct _fastd_protocol_peer_state { protocol_session old_session; protocol_session session; - - protocol_handshake *initiating_handshake; - protocol_handshake *accepting_handshake; }; @@ -116,6 +109,14 @@ static inline bool read_key(uint8_t key[32], const char *hexkey) { return true; } +static inline bool is_handshake_key_valid(fastd_context *ctx, const handshake_key *handshake_key) { + return timespec_after(&handshake_key->valid_till, &ctx->now); +} + +static inline bool is_handshake_key_preferred(fastd_context *ctx, const handshake_key *handshake_key) { + return timespec_after(&handshake_key->preferred_till, &ctx->now); +} + static inline bool is_session_valid(fastd_context *ctx, const protocol_session *session) { return ctx->conf->method->session_is_valid(ctx, session->method_state); } @@ -123,7 +124,7 @@ static inline bool is_session_valid(fastd_context *ctx, const protocol_session * static inline void check_session_refresh(fastd_context *ctx, fastd_peer *peer) { protocol_session *session = &peer->protocol_state->session; - if (!session->refreshing && ctx->conf->method->session_want_refresh(ctx, session->method_state)) { + if (!session->refreshing && ctx->conf->method->session_is_initiator(ctx, session->method_state) && ctx->conf->method->session_want_refresh(ctx, session->method_state)) { pr_debug(ctx, "refreshing session with %P", peer); session->refreshing = true; fastd_task_schedule_handshake(ctx, peer, 0); @@ -173,89 +174,67 @@ static void init_peer_state(fastd_context *ctx, fastd_peer *peer) { memset(peer->protocol_state, 0, sizeof(fastd_protocol_peer_state)); } -static inline void free_handshake(protocol_handshake *handshake) { +static inline void free_handshake_key(handshake_key *handshake) { if (handshake) { - memset(handshake, 0, sizeof(protocol_handshake)); + memset(handshake, 0, sizeof(handshake_key)); free(handshake); } } -static void protocol_peer_config_purged(fastd_context *ctx, fastd_peer_config *peer_conf) { - fastd_peer *peer; - for (peer = ctx->peers; peer; peer = peer->next) { - if (!peer->protocol_state) - continue; - - if (peer->protocol_state->initiating_handshake && - peer->protocol_state->initiating_handshake->peer_config == peer_conf) { - free_handshake(peer->protocol_state->initiating_handshake); - peer->protocol_state->initiating_handshake = NULL; - } - - if (peer->protocol_state->accepting_handshake && - peer->protocol_state->accepting_handshake->peer_config == peer_conf) { - free_handshake(peer->protocol_state->accepting_handshake); - peer->protocol_state->accepting_handshake = NULL; - } +static void maintenance(fastd_context *ctx) { + if (!ctx->protocol_state) { + ctx->protocol_state = malloc(sizeof(fastd_protocol_state)); + memset(ctx->protocol_state, 0, sizeof(fastd_protocol_state)); } -} -static protocol_handshake* new_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_peer_config *peer_config, bool initiate) { - protocol_handshake **handshake; + if (!is_handshake_key_preferred(ctx, &ctx->protocol_state->handshake_key)) { + pr_debug(ctx, "generating new handshake key"); - if (initiate) - handshake = &peer->protocol_state->initiating_handshake; - else - handshake = &peer->protocol_state->accepting_handshake; - - free_handshake(*handshake); - - *handshake = malloc(sizeof(protocol_handshake)); + ctx->protocol_state->prev_handshake_key = ctx->protocol_state->handshake_key; - (*handshake)->peer_config = peer_config; + fastd_random_bytes(ctx, ctx->protocol_state->handshake_key.secret_key.s, 32, false); + ecc_25519_secret_sanitize(&ctx->protocol_state->handshake_key.secret_key, &ctx->protocol_state->handshake_key.secret_key); - (*handshake)->state = HANDSHAKE_STATE_INIT; + ecc_25519_work work; + ecc_25519_scalarmult_base(&work, &ctx->protocol_state->handshake_key.secret_key); + ecc_25519_store(&ctx->protocol_state->handshake_key.public_key, &work); - fastd_random_bytes(ctx, (*handshake)->secret_key.s, 32, false); - ecc_25519_secret_sanitize(&(*handshake)->secret_key, &(*handshake)->secret_key); + ctx->protocol_state->handshake_key.preferred_till = ctx->now; + ctx->protocol_state->handshake_key.preferred_till.tv_sec += 15; - ecc_25519_work work; - ecc_25519_scalarmult_base(&work, &(*handshake)->secret_key); - ecc_25519_store(&(*handshake)->public_key, &work); - - return *handshake; + ctx->protocol_state->handshake_key.valid_till = ctx->now; + ctx->protocol_state->handshake_key.valid_till.tv_sec += 30; + } } -static void protocol_handshake_init(fastd_context *ctx, fastd_peer *peer) { - init_peer_state(ctx, peer); - - fastd_buffer buffer = fastd_handshake_new_init(ctx, peer, 3*(4+PUBLICKEYBYTES) /* sender key, receipient key, handshake key */); +static void protocol_handshake_init(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf) { + maintenance(ctx); - protocol_handshake *handshake = new_handshake(ctx, peer, peer->config, true); + fastd_buffer buffer = fastd_handshake_new_init(ctx, 3*(4+PUBLICKEYBYTES) /* sender key, receipient key, handshake key */); fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p); - if (handshake->peer_config) - fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, handshake->peer_config->protocol_config->public_key.p); + if (peer_conf) + fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer_conf->protocol_config->public_key.p); else - pr_debug(ctx, "sending handshake to unknown peer %P", peer); + pr_debug(ctx, "sending handshake to unknown peer %I", address); - fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, handshake->public_key.p); + fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, ctx->protocol_state->handshake_key.public_key.p); - fastd_send_handshake(ctx, peer, buffer); + fastd_send_handshake(ctx, address, buffer); } -static void respond_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) { - pr_debug(ctx, "responding handshake with %P...", peer); +static void respond_handshake(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf, const handshake_key *handshake_key, const ecc_public_key_256 *peer_handshake_key, const fastd_handshake *handshake) { + pr_debug(ctx, "responding handshake with %I...", address); uint8_t hashinput[5*PUBLICKEYBYTES]; uint8_t hashbuf[HASHBYTES]; uint8_t hmacbuf[HMACBYTES]; - memcpy(hashinput, peer->protocol_state->accepting_handshake->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_key.p, PUBLICKEYBYTES); + memcpy(hashinput, handshake_key->public_key.p, PUBLICKEYBYTES); + memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES); memcpy(hashinput+2*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+3*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES); + memcpy(hashinput+3*PUBLICKEYBYTES, peer_conf->protocol_config->public_key.p, PUBLICKEYBYTES); crypto_hash_sha256(hashbuf, hashinput, 4*PUBLICKEYBYTES); @@ -268,11 +247,11 @@ static void respond_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_ e.s[15] |= 0x80; ecc_25519_secret_mult(&eb, &e, &ctx->conf->protocol_config->secret_key); - ecc_25519_secret_add(&s, &eb, &peer->protocol_state->accepting_handshake->secret_key); + ecc_25519_secret_add(&s, &eb, &handshake_key->secret_key); ecc_25519_work work, workX; - ecc_25519_load(&work, &peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key); - ecc_25519_load(&workX, &peer->protocol_state->accepting_handshake->peer_key); + ecc_25519_load(&work, &peer_conf->protocol_config->public_key); + ecc_25519_load(&workX, peer_handshake_key); ecc_25519_scalarmult(&work, &d, &work); ecc_25519_add(&work, &workX, &work); @@ -281,36 +260,46 @@ static void respond_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_ if (ecc_25519_is_identity(&work)) return; - ecc_25519_store(&peer->protocol_state->accepting_handshake->sigma, &work); + ecc_public_key_256 sigma; + ecc_25519_store(&sigma, &work); - memcpy(hashinput+4*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->sigma.p, PUBLICKEYBYTES); - crypto_hash_sha256(peer->protocol_state->accepting_handshake->shared_handshake_key, hashinput, 5*PUBLICKEYBYTES); + uint8_t shared_handshake_key[HASHBYTES]; + memcpy(hashinput+4*PUBLICKEYBYTES, sigma.p, PUBLICKEYBYTES); + crypto_hash_sha256(shared_handshake_key, hashinput, 5*PUBLICKEYBYTES); memcpy(hashinput, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->public_key.p, PUBLICKEYBYTES); + memcpy(hashinput+PUBLICKEYBYTES, handshake_key->public_key.p, PUBLICKEYBYTES); - crypto_auth_hmacsha256(hmacbuf, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->shared_handshake_key); + crypto_auth_hmacsha256(hmacbuf, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key); - fastd_buffer buffer = fastd_handshake_new_reply(ctx, peer, handshake, 4*(4+PUBLICKEYBYTES) + 4+HMACBYTES); + fastd_buffer buffer = fastd_handshake_new_reply(ctx, handshake, 4*(4+PUBLICKEYBYTES) + 4+HMACBYTES); fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p); - fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key.p); - fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->public_key.p); - fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_key.p); + fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer_conf->protocol_config->public_key.p); + fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, handshake_key->public_key.p); + fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key->p); fastd_handshake_add(ctx, &buffer, RECORD_T, HMACBYTES, hmacbuf); - fastd_send_handshake(ctx, peer, buffer); - - peer->protocol_state->accepting_handshake->state = HANDSHAKE_STATE_RESPONSE; + fastd_send_handshake(ctx, address, buffer); } -static void establish(fastd_context *ctx, fastd_peer *peer, const fastd_peer_config *peer_config, bool initiator, +static void establish(fastd_context *ctx, const fastd_peer_config *peer_conf, const fastd_peer_address *address, bool initiator, const ecc_public_key_256 *A, const ecc_public_key_256 *B, const ecc_public_key_256 *X, const ecc_public_key_256 *Y, const ecc_public_key_256 *sigma) { uint8_t hashinput[5*PUBLICKEYBYTES]; uint8_t hash[HASHBYTES]; - pr_verbose(ctx, "New session with %P established.", peer); + fastd_peer *peer; + for (peer = ctx->peers; peer; peer = peer->next) { + if (peer->config == peer_conf) + break; + } + if (!peer) + exit_bug(ctx, "no peer for config found"); + + pr_verbose(ctx, "%I authorized as %P", address, peer); + + init_peer_state(ctx, peer); if (is_session_valid(ctx, &peer->protocol_state->session) && !is_session_valid(ctx, &peer->protocol_state->old_session)) { ctx->conf->method->session_free(ctx, peer->protocol_state->old_session.method_state); @@ -331,43 +320,34 @@ static void establish(fastd_context *ctx, fastd_peer *peer, const fastd_peer_con peer->protocol_state->session.refreshing = false; peer->protocol_state->session.method_state = ctx->conf->method->session_init(ctx, hash, HASHBYTES, initiator); - free_handshake(peer->protocol_state->initiating_handshake); - peer->protocol_state->initiating_handshake = NULL; - - free_handshake(peer->protocol_state->accepting_handshake); - peer->protocol_state->accepting_handshake = NULL; - fastd_peer_seen(ctx, peer); - if (peer_config != peer->config) { - fastd_peer *perm_peer; - for (perm_peer = ctx->peers; perm_peer; perm_peer = perm_peer->next) { - if (perm_peer->config == peer_config) { - peer = fastd_peer_set_established_merge(ctx, perm_peer, peer); - break; - } - } - } - else { - fastd_peer_set_established(ctx, peer); + if (!fastd_peer_claim_address(ctx, peer, address)) { + pr_warn(ctx, "can't set address %I which is used by a fixed peer", ctx->resolve_returns->addr); + fastd_peer_reset(ctx, peer); + return; } + fastd_peer_set_established(ctx, peer); + + pr_verbose(ctx, "new session with %P established.", peer); + fastd_task_schedule_keepalive(ctx, peer, ctx->conf->keepalive_interval*1000); if (!initiator) protocol_send(ctx, peer, fastd_buffer_alloc(0, ctx->conf->method->min_encrypt_head_space(ctx), 0)); } -static void finish_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) { - pr_debug(ctx, "finishing handshake with %P...", peer); +static void finish_handshake(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf, const handshake_key *handshake_key, const ecc_public_key_256 *peer_handshake_key, const fastd_handshake *handshake) { + pr_debug(ctx, "finishing handshake with %I...", address); uint8_t hashinput[5*PUBLICKEYBYTES]; uint8_t hashbuf[HASHBYTES]; uint8_t hmacbuf[HMACBYTES]; - memcpy(hashinput, peer->protocol_state->initiating_handshake->peer_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+2*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES); + memcpy(hashinput, peer_handshake_key->p, PUBLICKEYBYTES); + memcpy(hashinput+PUBLICKEYBYTES, handshake_key->public_key.p, PUBLICKEYBYTES); + memcpy(hashinput+2*PUBLICKEYBYTES, peer_conf->protocol_config->public_key.p, PUBLICKEYBYTES); memcpy(hashinput+3*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES); crypto_hash_sha256(hashbuf, hashinput, 4*PUBLICKEYBYTES); @@ -381,11 +361,11 @@ static void finish_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_h e.s[15] |= 0x80; ecc_25519_secret_mult(&da, &d, &ctx->conf->protocol_config->secret_key); - ecc_25519_secret_add(&s, &da, &peer->protocol_state->initiating_handshake->secret_key); + ecc_25519_secret_add(&s, &da, &handshake_key->secret_key); ecc_25519_work work, workY; - ecc_25519_load(&work, &peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key); - ecc_25519_load(&workY, &peer->protocol_state->initiating_handshake->peer_key); + ecc_25519_load(&work, &peer_conf->protocol_config->public_key); + ecc_25519_load(&workY, peer_handshake_key); ecc_25519_scalarmult(&work, &e, &work); ecc_25519_add(&work, &workY, &work); @@ -394,72 +374,103 @@ static void finish_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_h if (ecc_25519_is_identity(&work)) return; - ecc_25519_store(&peer->protocol_state->initiating_handshake->sigma, &work); + ecc_public_key_256 sigma; + ecc_25519_store(&sigma, &work); - memcpy(hashinput+4*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->sigma.p, PUBLICKEYBYTES); - crypto_hash_sha256(peer->protocol_state->initiating_handshake->shared_handshake_key, hashinput, 5*PUBLICKEYBYTES); + uint8_t shared_handshake_key[HASHBYTES]; + memcpy(hashinput+4*PUBLICKEYBYTES, sigma.p, PUBLICKEYBYTES); + crypto_hash_sha256(shared_handshake_key, hashinput, 5*PUBLICKEYBYTES); - memcpy(hashinput, peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->peer_key.p, PUBLICKEYBYTES); + memcpy(hashinput, peer_conf->protocol_config->public_key.p, PUBLICKEYBYTES); + memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES); - if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->shared_handshake_key) != 0) { - pr_warn(ctx, "received invalid protocol handshake response from %P", peer); + if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key) != 0) { + pr_warn(ctx, "received invalid protocol handshake response from %I", address); return; } memcpy(hashinput, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->public_key.p, PUBLICKEYBYTES); - crypto_auth_hmacsha256(hmacbuf, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->shared_handshake_key); + memcpy(hashinput+PUBLICKEYBYTES, handshake_key->public_key.p, PUBLICKEYBYTES); + crypto_auth_hmacsha256(hmacbuf, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key); - fastd_buffer buffer = fastd_handshake_new_reply(ctx, peer, handshake, 4*(4+PUBLICKEYBYTES) + 4+HMACBYTES); + fastd_buffer buffer = fastd_handshake_new_reply(ctx, handshake, 4*(4+PUBLICKEYBYTES) + 4+HMACBYTES); fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p); - fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key.p); - fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->public_key.p); - fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer->protocol_state->initiating_handshake->peer_key.p); + fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer_conf->protocol_config->public_key.p); + fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, handshake_key->public_key.p); + fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key->p); fastd_handshake_add(ctx, &buffer, RECORD_T, HMACBYTES, hmacbuf); - fastd_send_handshake(ctx, peer, buffer); + fastd_send_handshake(ctx, address, buffer); - establish(ctx, peer, peer->protocol_state->initiating_handshake->peer_config, true, - &peer->protocol_state->initiating_handshake->public_key, - &peer->protocol_state->initiating_handshake->peer_key, - &ctx->conf->protocol_config->public_key, - &peer->protocol_state->initiating_handshake->peer_config->protocol_config->public_key, - &peer->protocol_state->initiating_handshake->sigma); + establish(ctx, peer_conf, address, true, &handshake_key->public_key, peer_handshake_key, &ctx->conf->protocol_config->public_key, + &peer_conf->protocol_config->public_key, &sigma); } -static void handle_finish_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) { - pr_debug(ctx, "handling handshake finish with %P...", peer); +static void handle_finish_handshake(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf, const handshake_key *handshake_key, const ecc_public_key_256 *peer_handshake_key, const fastd_handshake *handshake) { + pr_debug(ctx, "handling handshake finish with %I...", address); + + uint8_t hashinput[5*PUBLICKEYBYTES]; + uint8_t hashbuf[HASHBYTES]; + + memcpy(hashinput, handshake_key->public_key.p, PUBLICKEYBYTES); + memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES); + memcpy(hashinput+2*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES); + memcpy(hashinput+3*PUBLICKEYBYTES, peer_conf->protocol_config->public_key.p, PUBLICKEYBYTES); + + crypto_hash_sha256(hashbuf, hashinput, 4*PUBLICKEYBYTES); + + ecc_secret_key_256 d = {{0}}, e = {{0}}, eb, s; + + memcpy(d.s, hashbuf, HASHBYTES/2); + memcpy(e.s, hashbuf+HASHBYTES/2, HASHBYTES/2); + + d.s[15] |= 0x80; + e.s[15] |= 0x80; - uint8_t hashinput[2*PUBLICKEYBYTES]; + ecc_25519_secret_mult(&eb, &e, &ctx->conf->protocol_config->secret_key); + ecc_25519_secret_add(&s, &eb, &handshake_key->secret_key); - memcpy(hashinput, peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->peer_key.p, PUBLICKEYBYTES); + ecc_25519_work work, workX; + ecc_25519_load(&work, &peer_conf->protocol_config->public_key); + ecc_25519_load(&workX, peer_handshake_key); - if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, peer->protocol_state->accepting_handshake->shared_handshake_key) != 0) { - pr_warn(ctx, "received invalid protocol handshake finish from %P", peer); + ecc_25519_scalarmult(&work, &d, &work); + ecc_25519_add(&work, &workX, &work); + ecc_25519_scalarmult(&work, &s, &work); + + if (ecc_25519_is_identity(&work)) + return; + + ecc_public_key_256 sigma; + ecc_25519_store(&sigma, &work); + + uint8_t shared_handshake_key[HASHBYTES]; + memcpy(hashinput+4*PUBLICKEYBYTES, sigma.p, PUBLICKEYBYTES); + crypto_hash_sha256(shared_handshake_key, hashinput, 5*PUBLICKEYBYTES); + + memcpy(hashinput, peer_conf->protocol_config->public_key.p, PUBLICKEYBYTES); + memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES); + + if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key) != 0) { + pr_warn(ctx, "received invalid protocol handshake finish from %I", address); return; } - establish(ctx, peer, peer->protocol_state->accepting_handshake->peer_config, false, - &peer->protocol_state->accepting_handshake->peer_key, - &peer->protocol_state->accepting_handshake->public_key, - &peer->protocol_state->accepting_handshake->peer_config->protocol_config->public_key, - &ctx->conf->protocol_config->public_key, - &peer->protocol_state->accepting_handshake->sigma); + establish(ctx, peer_conf, address, false, peer_handshake_key, &handshake_key->public_key, &peer_conf->protocol_config->public_key, + &ctx->conf->protocol_config->public_key, &sigma); } -static inline const fastd_peer_config* match_sender_key(fastd_context *ctx, fastd_peer *peer, const unsigned char key[32]) { - if (peer->config) { - if (memcmp(peer->config->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0) - return peer->config; +static const fastd_peer_config* match_sender_key(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf, const unsigned char key[32]) { + if (peer_conf) { + if (memcmp(peer_conf->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0) + return peer_conf; } - if (fastd_peer_is_temporary(peer) || fastd_peer_is_floating(peer) || fastd_peer_is_dynamic(peer)) { + if (!peer_conf || fastd_peer_config_is_floating(peer_conf) || fastd_peer_config_is_dynamic(peer_conf)) { fastd_peer_config *config; for (config = ctx->conf->peers; config; config = config->next) { - if (!fastd_peer_config_is_floating(config) && !fastd_peer_config_matches_dynamic(config, &peer->address)) + if (!fastd_peer_config_is_floating(config) && !fastd_peer_config_matches_dynamic(config, address)) continue; if (memcmp(config->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0) { @@ -477,129 +488,89 @@ static inline const fastd_peer_config* match_sender_key(fastd_context *ctx, fast return NULL; } -static void kill_handshakes(fastd_context *ctx, fastd_peer *peer) { - pr_debug(ctx, "there is a handshake conflict, retrying in a moment..."); - - free_handshake(peer->protocol_state->initiating_handshake); - peer->protocol_state->initiating_handshake = NULL; - - free_handshake(peer->protocol_state->accepting_handshake); - peer->protocol_state->accepting_handshake = NULL; -} - static inline bool has_field(const fastd_handshake *handshake, uint8_t type, size_t length) { return (handshake->records[type].length == length); } -static void protocol_handshake_handle(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) { - init_peer_state(ctx, peer); +static void protocol_handshake_handle(fastd_context *ctx, const fastd_peer_address *address, const fastd_peer_config *peer_conf, const fastd_handshake *handshake) { + handshake_key *handshake_key; + + maintenance(ctx); if (!has_field(handshake, RECORD_SENDER_KEY, PUBLICKEYBYTES)) { - pr_debug(ctx, "received handshake without sender key from %P", peer); + pr_debug(ctx, "received handshake without sender key from %I", address); return; } - const fastd_peer_config *peer_config = match_sender_key(ctx, peer, handshake->records[RECORD_SENDER_KEY].data); - if (!peer_config) { - pr_debug(ctx, "ignoring handshake from %P (unknown key or unresolved host)", peer); + peer_conf = match_sender_key(ctx, address, peer_conf, handshake->records[RECORD_SENDER_KEY].data); + if (!peer_conf) { + pr_debug(ctx, "ignoring handshake from %I (unknown key or unresolved host)", address); return; } if (handshake->type > 1 && !has_field(handshake, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES)) { - pr_debug(ctx, "received handshake reply without receipient key from %P", peer); + pr_debug(ctx, "received handshake reply without receipient key from %I", address); return; } else if(has_field(handshake, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES)) { if (memcmp(ctx->conf->protocol_config->public_key.p, handshake->records[RECORD_RECEIPIENT_KEY].data, PUBLICKEYBYTES) != 0) { - pr_debug(ctx, "received protocol handshake with wrong receipient key from %P", peer); + pr_debug(ctx, "received protocol handshake with wrong receipient key from %I", address); return; } } if (!has_field(handshake, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES)) { - pr_debug(ctx, "received handshake without sender handshake key from %P", peer); + pr_debug(ctx, "received handshake without sender handshake key from %I", address); return; } if (handshake->type > 1 && !has_field(handshake, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES)) { - pr_debug(ctx, "received handshake reply without receipient handshake key from %P", peer); + pr_debug(ctx, "received handshake reply without receipient handshake key from %I", address); return; } if (handshake->type > 1 && !has_field(handshake, RECORD_T, HMACBYTES)) { - pr_debug(ctx, "received handshake reply without HMAC from %P", peer); + pr_debug(ctx, "received handshake reply without HMAC from %I", address); return; } switch(handshake->type) { case 1: - new_handshake(ctx, peer, peer_config, false); - memcpy(peer->protocol_state->accepting_handshake->peer_key.p, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, PUBLICKEYBYTES); - respond_handshake(ctx, peer, handshake); + respond_handshake(ctx, address, peer_conf, &ctx->protocol_state->handshake_key, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, handshake); break; case 2: - if (!peer->protocol_state->initiating_handshake || peer->protocol_state->initiating_handshake->state != HANDSHAKE_STATE_INIT) { - pr_debug(ctx, "received unexpected handshake response from %P", peer); - return; - } - - if (peer->protocol_state->initiating_handshake->peer_config != peer_config) { - if (peer->protocol_state->initiating_handshake->peer_config) { - pr_debug(ctx, "received handshake response with wrong sender key from %P", peer); - return; - } - else { - peer->protocol_state->initiating_handshake->peer_config = peer_config; - } + if (is_handshake_key_valid(ctx, &ctx->protocol_state->handshake_key) && memcmp(ctx->protocol_state->handshake_key.public_key.p, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) { + handshake_key = &ctx->protocol_state->handshake_key; } - - if (memcmp(peer->protocol_state->initiating_handshake->public_key.p, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) != 0) { - pr_debug(ctx, "received handshake response with unexpected receipient handshake key from %P", peer); - return; + else if (is_handshake_key_valid(ctx, &ctx->protocol_state->prev_handshake_key) && memcmp(ctx->protocol_state->prev_handshake_key.public_key.p, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) { + handshake_key = &ctx->protocol_state->prev_handshake_key; } - - pr_debug(ctx, "received handshake response from %P", peer); - - if (peer->protocol_state->accepting_handshake) { - kill_handshakes(ctx, peer); + else { + pr_debug(ctx, "received handshake response with unexpected receipient handshake key from %I", address); return; } - memcpy(peer->protocol_state->initiating_handshake->peer_key.p, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, PUBLICKEYBYTES); + pr_debug(ctx, "received handshake response from %I", address); - finish_handshake(ctx, peer, handshake); + finish_handshake(ctx, address, peer_conf, handshake_key, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, handshake); break; case 3: - if (!peer->protocol_state->accepting_handshake || peer->protocol_state->accepting_handshake->state != HANDSHAKE_STATE_RESPONSE) { - pr_debug(ctx, "received unexpected protocol handshake finish from %P", peer); - return; + if (is_handshake_key_valid(ctx, &ctx->protocol_state->handshake_key) && memcmp(ctx->protocol_state->handshake_key.public_key.p, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) { + handshake_key = &ctx->protocol_state->handshake_key; } - - if (peer->protocol_state->accepting_handshake->peer_config != peer_config) { - pr_debug(ctx, "received protocol handshake finish with wrong sender key from %P", peer); - return; + else if (is_handshake_key_valid(ctx, &ctx->protocol_state->prev_handshake_key) && memcmp(ctx->protocol_state->prev_handshake_key.public_key.p, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) { + handshake_key = &ctx->protocol_state->prev_handshake_key; } - - if (memcmp(peer->protocol_state->accepting_handshake->public_key.p, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) != 0) { - pr_debug(ctx, "received handshake response with unexpected receipient handshake key from %P", peer); + else { + pr_debug(ctx, "received handshake response with unexpected receipient handshake key from %I", address); return; } - if (memcmp(peer->protocol_state->accepting_handshake->peer_key.p, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, PUBLICKEYBYTES) != 0) { - pr_debug(ctx, "received handshake response with unexpected sender handshake key from %P", peer); - return; - } + pr_debug(ctx, "received handshake finish from %I", address); - pr_debug(ctx, "received handshake finish from %P", peer); - - if (peer->protocol_state->initiating_handshake && peer->protocol_state->initiating_handshake->state != HANDSHAKE_STATE_INIT) { - kill_handshakes(ctx, peer); - return; - } - - handle_finish_handshake(ctx, peer, handshake); + handle_finish_handshake(ctx, address, peer_conf, handshake_key, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, handshake); break; default: @@ -609,12 +580,8 @@ static void protocol_handshake_handle(fastd_context *ctx, fastd_peer *peer, cons static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) { if (!fastd_peer_is_established(peer)) { - pr_debug(ctx, "received unexpected packet from %P", peer); - - if (fastd_peer_is_temporary(peer)) { - pr_debug(ctx, "sending handshake to temporary peer %P", peer); - fastd_task_schedule_handshake(ctx, peer, 0); - } + pr_debug(ctx, "received unexpected packet from %P, scheduling handshake", peer); + fastd_task_schedule_handshake(ctx, peer, 0); goto fail; } @@ -690,7 +657,7 @@ static void protocol_send(fastd_context *ctx, fastd_peer *peer, fastd_buffer buf if (!ctx->conf->method->encrypt(ctx, session->method_state, &send_buffer, buffer)) goto fail; - fastd_send(ctx, peer, send_buffer); + fastd_send(ctx, &peer->address, send_buffer); fastd_task_delete_peer_keepalives(ctx, peer); fastd_task_schedule_keepalive(ctx, peer, ctx->conf->keepalive_interval*1000); @@ -702,9 +669,6 @@ static void protocol_send(fastd_context *ctx, fastd_peer *peer, fastd_buffer buf static void protocol_free_peer_state(fastd_context *ctx, fastd_peer *peer) { if (peer->protocol_state) { - free_handshake(peer->protocol_state->initiating_handshake); - free_handshake(peer->protocol_state->accepting_handshake); - ctx->conf->method->session_free(ctx, peer->protocol_state->old_session.method_state); ctx->conf->method->session_free(ctx, peer->protocol_state->session.method_state); @@ -712,7 +676,6 @@ static void protocol_free_peer_state(fastd_context *ctx, fastd_peer *peer) { } } - static void hexdump(const char *desc, unsigned char d[32]) { printf("%s", desc); @@ -746,7 +709,6 @@ const fastd_protocol fastd_protocol_ec25519_fhmqvc = { .init = protocol_init, .peer_configure = protocol_peer_configure, - .peer_config_purged = protocol_peer_config_purged, .handshake_init = protocol_handshake_init, .handshake_handle = protocol_handshake_handle, diff --git a/src/types.h b/src/types.h index c48cf59..6efd224 100644 --- a/src/types.h +++ b/src/types.h @@ -47,13 +47,6 @@ typedef enum _fastd_mode { MODE_TUN, } fastd_mode; -typedef enum _fastd_peer_state { - STATE_RESOLVE, - STATE_WAIT, - STATE_TEMP, - STATE_ESTABLISHED, -} fastd_peer_state; - typedef struct _fastd_buffer fastd_buffer; @@ -78,6 +71,7 @@ typedef struct _fastd_resolve_return fastd_resolve_return; /* May be defined by the protocol/method however it likes */ typedef struct _fastd_protocol_config fastd_protocol_config; +typedef struct _fastd_protocol_state fastd_protocol_state; typedef struct _fastd_protocol_peer_config fastd_protocol_peer_config; typedef struct _fastd_protocol_peer_state fastd_protocol_peer_state; typedef struct _fastd_method_session_state fastd_method_session_state; -- cgit v1.2.3