diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2012-03-31 21:18:07 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2012-03-31 21:18:07 +0200 |
commit | 4f0cfe26bf5445fc06a59a6db47cb2fa3158b87b (patch) | |
tree | 05396b7c13482ab27beb4593236b260c4bdf06c3 | |
parent | f25c92359e57b1e97c86174067485acf6a9445de (diff) | |
download | fastd-4f0cfe26bf5445fc06a59a6db47cb2fa3158b87b.tar fastd-4f0cfe26bf5445fc06a59a6db47cb2fa3158b87b.zip |
Trigger handshake when unexpected data is received from a floating peer
-rw-r--r-- | src/handshake.c | 4 | ||||
-rw-r--r-- | src/peer.c | 2 | ||||
-rw-r--r-- | src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c | 22 | ||||
-rw-r--r-- | src/queue.c | 10 | ||||
-rw-r--r-- | src/queue.h | 1 | ||||
-rw-r--r-- | src/task.c | 38 | ||||
-rw-r--r-- | src/task.h | 1 |
7 files changed, 72 insertions, 6 deletions
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]); @@ -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_ */ @@ -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; @@ -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); |