summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-03-31 21:18:07 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-03-31 21:18:07 +0200
commit4f0cfe26bf5445fc06a59a6db47cb2fa3158b87b (patch)
tree05396b7c13482ab27beb4593236b260c4bdf06c3
parentf25c92359e57b1e97c86174067485acf6a9445de (diff)
downloadfastd-4f0cfe26bf5445fc06a59a6db47cb2fa3158b87b.tar
fastd-4f0cfe26bf5445fc06a59a6db47cb2fa3158b87b.zip
Trigger handshake when unexpected data is received from a floating peer
-rw-r--r--src/handshake.c4
-rw-r--r--src/peer.c2
-rw-r--r--src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c22
-rw-r--r--src/queue.c10
-rw-r--r--src/queue.h1
-rw-r--r--src/task.c38
-rw-r--r--src/task.h1
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]);
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);