From 4f0cfe26bf5445fc06a59a6db47cb2fa3158b87b Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 31 Mar 2012 21:18:07 +0200 Subject: Trigger handshake when unexpected data is received from a floating peer --- src/handshake.c | 4 ++- src/peer.c | 2 ++ src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c | 22 ++++++++++---- src/queue.c | 10 +++++++ src/queue.h | 1 + src/task.c | 38 +++++++++++++++++++++++++ src/task.h | 1 + 7 files changed, 72 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/handshake.c b/src/handshake.c index ce8895d..839951b 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -122,8 +122,10 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b handshake.req_id = packet->req_id; - if (handshake.records[RECORD_HANDSHAKE_TYPE].length != 1) + if (handshake.records[RECORD_HANDSHAKE_TYPE].length != 1) { + pr_debug(ctx, "received handshake without handshake type from %P", peer); goto end_free; + } handshake.type = AS_UINT8(handshake.records[RECORD_HANDSHAKE_TYPE]); diff --git a/src/peer.c b/src/peer.c index 7fe8c0e..74f5649 100644 --- a/src/peer.c +++ b/src/peer.c @@ -169,6 +169,8 @@ fastd_peer* fastd_peer_set_established_merge(fastd_context *ctx, fastd_peer *per } } + fastd_task_replace_peer(ctx, temp_peer, perm_peer); + fastd_peer_reset(ctx, temp_peer); pr_info(ctx, "Connection with %P established.", perm_peer); diff --git a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c index a7a635c..32c459a 100644 --- a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c +++ b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c @@ -561,8 +561,13 @@ static void protocol_handshake_handle(fastd_context *ctx, fastd_peer *peer, cons } if (peer->protocol_state->initiating_handshake->peer_config != peer_config) { - pr_debug(ctx, "received handshake response with wrong sender key from %P", peer); - return; + 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 (memcmp(peer->protocol_state->initiating_handshake->public_key.p, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) != 0) { @@ -606,14 +611,21 @@ 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)) + 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); + } + goto end; + } if (buffer.len < NONCEBYTES) goto end; if (!peer->protocol_state || !is_session_valid(ctx, &peer->protocol_state->session)) { - pr_debug(ctx, "received unexpected packet from %P", peer); goto end; } @@ -644,7 +656,7 @@ static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buf if (!is_nonce_valid(nonce, session->receive_nonce)) { pr_debug(ctx, "received packet with invalid nonce from %P", peer); - + fastd_buffer_free(recv_buffer); goto end; } diff --git a/src/queue.c b/src/queue.c index 2509538..70ee54b 100644 --- a/src/queue.c +++ b/src/queue.c @@ -85,3 +85,13 @@ void fastd_queue_filter(fastd_context *ctx, fastd_queue *queue, bool (*pred)(fas entry = &(*entry)->next; } } + +bool fastd_queue_has_entry(fastd_context *ctx, fastd_queue *queue, bool (*pred)(fastd_queue_entry*, void*), void *extra) { + fastd_queue_entry *entry; + for (entry = queue->head; entry; entry = entry->next) { + if (pred(entry, extra)) + return true; + } + + return false; +} diff --git a/src/queue.h b/src/queue.h index 50456ee..8e93e0e 100644 --- a/src/queue.h +++ b/src/queue.h @@ -50,5 +50,6 @@ void fastd_queue_put(fastd_context *ctx, fastd_queue *queue, fastd_queue_entry * fastd_queue_entry* fastd_queue_get(fastd_context *ctx, fastd_queue *queue); int fastd_queue_timeout(fastd_context *ctx, fastd_queue *queue); void fastd_queue_filter(fastd_context *ctx, fastd_queue *queue, bool (*pred)(fastd_queue_entry*, void*), void *extra); +bool fastd_queue_has_entry(fastd_context *ctx, fastd_queue *queue, bool (*pred)(fastd_queue_entry*, void*), void *extra); #endif /* _FASTD_QUEUE_H_ */ diff --git a/src/task.c b/src/task.c index b4004ef..9526508 100644 --- a/src/task.c +++ b/src/task.c @@ -60,7 +60,22 @@ void fastd_task_put_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buff fastd_queue_put(ctx, &ctx->task_queue, &task->entry, 0); } +static bool is_handshake(fastd_queue_entry *data, void *extra) { + fastd_task *task = container_of(data, fastd_task, entry); + fastd_peer *peer = extra; + + if (task->peer != peer) + return true; + + return (task->type == TASK_HANDSHAKE); +} + void fastd_task_schedule_handshake(fastd_context *ctx, fastd_peer *peer, int timeout) { + if (fastd_queue_has_entry(ctx, &ctx->task_queue, is_handshake, peer)) { + pr_debug(ctx, "not sending a handshake to %P, there still is one queued", peer); + return; + } + fastd_task *task = malloc(sizeof(fastd_task)); task->type = TASK_HANDSHAKE; @@ -69,6 +84,29 @@ void fastd_task_schedule_handshake(fastd_context *ctx, fastd_peer *peer, int tim fastd_queue_put(ctx, &ctx->task_queue, &task->entry, timeout); } +typedef struct _replace_peer_extra { + fastd_peer *old_peer; + fastd_peer *new_peer; +} replace_peer_extra; + + +static bool replace_peer(fastd_queue_entry *data, void *extra) { + replace_peer_extra *e = extra; + fastd_task *task = container_of(data, fastd_task, entry); + fastd_peer *old_peer = e->old_peer; + fastd_peer *new_peer = e->new_peer; + + if (task->peer == old_peer) + task->peer = new_peer; + + return true; +} + +void fastd_task_replace_peer(fastd_context *ctx, fastd_peer *old_peer, fastd_peer *new_peer) { + replace_peer_extra extra = {old_peer, new_peer}; + fastd_queue_filter(ctx, &ctx->task_queue, replace_peer, &extra); +} + typedef struct _delete_task_extra { fastd_peer *peer; bool handshake_only; diff --git a/src/task.h b/src/task.h index f5634d9..312c8f9 100644 --- a/src/task.h +++ b/src/task.h @@ -78,6 +78,7 @@ void fastd_task_put_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buff void fastd_task_schedule_handshake(fastd_context *ctx, fastd_peer *peer, int timeout); +void fastd_task_replace_peer(fastd_context *ctx, fastd_peer *old_peer, fastd_peer *new_peer); void fastd_task_delete_peer(fastd_context *ctx, fastd_peer *peer); void fastd_task_delete_peer_handshakes(fastd_context *ctx, fastd_peer *peer); -- cgit v1.2.3