summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fastd.c8
-rw-r--r--src/handshake.c98
-rw-r--r--src/handshake.h1
-rw-r--r--src/packet.h24
-rw-r--r--src/peer.c2
-rw-r--r--src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c21
-rw-r--r--src/protocol_null.c3
-rw-r--r--src/task.c3
-rw-r--r--src/task.h7
9 files changed, 106 insertions, 61 deletions
diff --git a/src/fastd.c b/src/fastd.c
index d2e0881..70f4248 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -180,14 +180,14 @@ static void handle_tasks(fastd_context *ctx) {
break;
case TASK_HANDSHAKE:
- if (task->peer->state != STATE_WAIT && task->peer->state != STATE_TEMP)
+ if (task->peer->state != STATE_WAIT && task->peer->state != STATE_TEMP && !task->handshake.force)
break;
pr_debug(ctx, "Sending handshake to %P...", task->peer);
fastd_handshake_send(ctx, task->peer);
if (task->peer->state == STATE_WAIT)
- fastd_task_schedule_handshake(ctx, task->peer, 20000);
+ fastd_task_schedule_handshake(ctx, task->peer, 20000, false);
break;
default:
@@ -314,7 +314,9 @@ static void handle_socket(fastd_context *ctx, int sockfd) {
fastd_buffer_free(buffer);
peer = fastd_peer_add_temp(ctx, (fastd_peer_address*)&recvaddr);
- fastd_task_schedule_handshake(ctx, peer, 0);
+ ctx->conf->protocol->handle_recv(ctx, peer, buffer);
+ pr_debug(ctx, "Requesting re-handshake from %P", peer);
+ fastd_handshake_rehandshake(ctx, peer);
break;
case PACKET_HANDSHAKE:
diff --git a/src/handshake.c b/src/handshake.c
index 97ddde4..29ed692 100644
--- a/src/handshake.c
+++ b/src/handshake.c
@@ -34,6 +34,7 @@
static const char const *RECORD_TYPES[RECORD_MAX] = {
+ "handshake type",
"reply code",
"error detail",
"flags",
@@ -47,6 +48,7 @@ static const char const *REPLY_TYPES[REPLY_MAX] = {
"unacceptable value",
};
+#define AS_UINT8(ptr) (*(uint8_t*)(ptr))
static inline void handshake_add(fastd_context *ctx, fastd_buffer *buffer, fastd_handshake_record_type type, size_t len, const void *data) {
if ((uint8_t*)buffer->data + buffer->len + 2 + len > (uint8_t*)buffer->base + buffer->base_len)
@@ -61,32 +63,54 @@ static inline void handshake_add(fastd_context *ctx, fastd_buffer *buffer, fastd
buffer->len += 2 + len;
}
+static inline void handshake_add_uint8(fastd_context *ctx, fastd_buffer *buffer, fastd_handshake_record_type type, uint8_t value) {
+ if ((uint8_t*)buffer->data + buffer->len + 3 > (uint8_t*)buffer->base + buffer->base_len)
+ exit_bug(ctx, "not enough buffer allocated for handshake");
+
+ uint8_t *dst = (uint8_t*)buffer->data + buffer->len;
+
+ dst[0] = type;
+ dst[1] = 1;
+ dst[2] = value;
+
+ buffer->len += 3;
+}
+
void fastd_handshake_send(fastd_context *ctx, fastd_peer *peer) {
size_t protocol_len = strlen(ctx->conf->protocol->name);
fastd_buffer buffer = fastd_buffer_alloc(sizeof(fastd_packet), 0,
- 2+1 + /* mode */
+ 2*3 + /* handshake type, mode */
2+protocol_len /* protocol name */
);
fastd_packet *request = buffer.data;
- request->reply = 0;
- request->cp = 0;
request->req_id = ++peer->last_req_id;
request->rsv = 0;
- uint8_t mode = ctx->conf->mode;
- handshake_add(ctx, &buffer, RECORD_MODE, 1, &mode);
+ handshake_add_uint8(ctx, &buffer, RECORD_HANDSHAKE_TYPE, HANDSHAKE_REQUEST);
+ handshake_add_uint8(ctx, &buffer, RECORD_MODE, ctx->conf->mode);
handshake_add(ctx, &buffer, RECORD_PROTOCOL_NAME, protocol_len, ctx->conf->protocol->name);
fastd_task_put_send_handshake(ctx, peer, buffer);
}
+void fastd_handshake_rehandshake(fastd_context *ctx, fastd_peer *peer) {
+ size_t protocol_len = strlen(ctx->conf->protocol->name);
+ fastd_buffer buffer = fastd_buffer_alloc(sizeof(fastd_packet), 0, 3 /* handshake type */);
+ fastd_packet *request = buffer.data;
+
+ request->req_id = ++peer->last_req_id;
+ request->rsv = 0;
+
+ handshake_add_uint8(ctx, &buffer, RECORD_HANDSHAKE_TYPE, HANDSHAKE_REHANDSHAKE_REQUEST);
+ fastd_task_put_send_handshake(ctx, peer, buffer);
+}
void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) {
if (buffer.len < sizeof(fastd_packet)) {
- pr_warn(ctx, "received an invalid handshake from %P", peer);
+ pr_warn(ctx, "received a short handshake from %P", peer);
goto end_free;
}
@@ -112,12 +136,22 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b
ptr += 2+len;
}
- if (!packet->reply) {
- fastd_buffer reply_buffer;
- fastd_packet *reply;
+ if (!records[RECORD_HANDSHAKE_TYPE]) {
+ pr_warn(ctx, "received a handshake without type from %P", peer);
+ goto end_free;
+ }
- uint8_t reply_code = REPLY_SUCCESS;
- uint8_t error_detail = 0;
+ fastd_buffer reply_buffer;
+ fastd_packet *reply;
+
+ uint8_t reply_code;
+ uint8_t error_detail;
+ const char *error_field_str;
+
+ switch (AS_UINT8(records[RECORD_HANDSHAKE_TYPE])) {
+ case HANDSHAKE_REQUEST:
+ reply_code = REPLY_SUCCESS;
+ error_detail = 0;
if (!records[RECORD_MODE]) {
reply_code = REPLY_MANDATORY_MISSING;
@@ -125,7 +159,7 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b
goto send_reply;
}
- if (lengths[RECORD_MODE] != 1 || *(uint8_t*)records[RECORD_MODE] != ctx->conf->mode) {
+ if (lengths[RECORD_MODE] != 1 || AS_UINT8(records[RECORD_MODE]) != ctx->conf->mode) {
reply_code = REPLY_UNACCEPTABLE_VALUE;
error_detail = RECORD_MODE;
goto send_reply;
@@ -145,30 +179,26 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b
}
send_reply:
- reply_buffer = fastd_buffer_alloc(sizeof(fastd_packet), 0, 6 /* enough space for reply code and error detail */);
+ reply_buffer = fastd_buffer_alloc(sizeof(fastd_packet), 0, 3*3 /* enough space for handshake type, reply code and error detail */);
reply = reply_buffer.data;
- reply->reply = 1;
- reply->cp = packet->cp;
reply->req_id = packet->req_id;
reply->rsv = 0;
- handshake_add(ctx, &reply_buffer, RECORD_REPLY_CODE, 1, &reply_code);
+ handshake_add_uint8(ctx, &reply_buffer, RECORD_HANDSHAKE_TYPE, HANDSHAKE_REPLY);
+ handshake_add_uint8(ctx, &reply_buffer, RECORD_REPLY_CODE, reply_code);
if (reply_code)
- handshake_add(ctx, &reply_buffer, RECORD_ERROR_DETAIL, 1, &error_detail);
+ handshake_add_uint8(ctx, &reply_buffer, RECORD_ERROR_DETAIL, error_detail);
fastd_task_put_send_handshake(ctx, peer, reply_buffer);
- }
- else {
- if (!packet->cp) {
- 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;
- }
- }
- else {
- goto end_free; /* TODO */
+
+ break;
+
+ case HANDSHAKE_REPLY:
+ 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 (!records[RECORD_REPLY_CODE] || lengths[RECORD_REPLY_CODE] != 1) {
@@ -176,9 +206,7 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b
goto end_free;
}
- uint8_t reply_code = *(uint8_t*)records[RECORD_REPLY_CODE];
- uint8_t error_detail;
- const char *error_field_str;
+ reply_code = AS_UINT8(records[RECORD_REPLY_CODE]);
switch (reply_code) {
case REPLY_SUCCESS:
@@ -198,7 +226,7 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b
break;
}
- error_detail = *(uint8_t*)records[RECORD_ERROR_DETAIL];
+ error_detail = AS_UINT8(records[RECORD_ERROR_DETAIL]);
if (error_detail >= RECORD_MAX)
error_field_str = "<unknown>";
else
@@ -217,6 +245,14 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b
break;
}
}
+ break;
+
+ case HANDSHAKE_REHANDSHAKE_REQUEST:
+ fastd_task_schedule_handshake(ctx, peer, 0, true);
+ break;
+
+ default:
+ pr_warn(ctx, "received a handshake with unknown type from %P", peer);
}
end_free:
diff --git a/src/handshake.h b/src/handshake.h
index 3457a0e..c485576 100644
--- a/src/handshake.h
+++ b/src/handshake.h
@@ -31,6 +31,7 @@
#include "fastd.h"
void fastd_handshake_send(fastd_context *ctx, fastd_peer *peer);
+void fastd_handshake_rehandshake(fastd_context *ctx, fastd_peer *peer);
void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer);
#endif /* _FASTD_HANDSHAKE_H_ */
diff --git a/src/packet.h b/src/packet.h
index 0960cce..b99f7de 100644
--- a/src/packet.h
+++ b/src/packet.h
@@ -28,7 +28,6 @@
#ifndef _FASTD_PACKET_H_
#define _FASTD_PACKET_H_
-#include <asm/byteorder.h>
#include <stdint.h>
@@ -39,7 +38,8 @@ typedef enum _fastd_packet_type {
} fastd_packet_type;
typedef enum _fastd_handshake_record_type {
- RECORD_REPLY_CODE = 0,
+ RECORD_HANDSHAKE_TYPE = 0,
+ RECORD_REPLY_CODE,
RECORD_ERROR_DETAIL,
RECORD_FLAGS,
RECORD_MODE,
@@ -47,6 +47,13 @@ typedef enum _fastd_handshake_record_type {
RECORD_MAX,
} fastd_handshake_record_type;
+typedef enum _fastd_handshake_type {
+ HANDSHAKE_REQUEST = 0,
+ HANDSHAKE_REPLY,
+ HANDSHAKE_REHANDSHAKE_REQUEST,
+ HANDSHAKE_MAX,
+} fastd_handshake_type;
+
typedef enum _fastd_reply_code {
REPLY_SUCCESS = 0,
REPLY_MANDATORY_MISSING,
@@ -56,18 +63,7 @@ typedef enum _fastd_reply_code {
typedef struct __attribute__ ((__packed__)) _fastd_packet {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned req_id : 6;
- unsigned cp : 1;
- unsigned reply : 1;
-#elif defined (__BIG_ENDIAN_BITFIELD)
- unsigned reply : 1;
- unsigned cp : 1;
- unsigned req_id : 6;
-#else
-#error "Bitfield endianess not defined."
-#endif
-
+ uint8_t req_id;
uint16_t rsv;
uint8_t tlv_data[];
} fastd_packet;
diff --git a/src/peer.c b/src/peer.c
index cae108f..f2f79dd 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -60,7 +60,7 @@ static inline void setup_peer(fastd_context *ctx, fastd_peer *peer) {
peer->seen = (struct timespec){0, 0};
if (!fastd_peer_is_floating(peer))
- fastd_task_schedule_handshake(ctx, peer, 0);
+ fastd_task_schedule_handshake(ctx, peer, 0, false);
}
diff --git a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
index 6f59323..8ef0efb 100644
--- a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
+++ b/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
@@ -281,18 +281,21 @@ static void protocol_init_peer(fastd_context *ctx, fastd_peer *peer) {
}
create_peer_state(ctx, peer);
- new_handshake(ctx, peer, true);
- fastd_buffer buffer = fastd_buffer_alloc(sizeof(protocol_handshake_init_packet), 0, 0);
- protocol_handshake_init_packet *packet = buffer.data;
+ if (!fastd_peer_is_temporary(peer)) {
+ new_handshake(ctx, peer, true);
- memset(packet->common.noncepad, 0, NONCEBYTES);
- packet->common.type = HANDSHAKE_PACKET_INIT;
- memcpy(packet->common.sender_key, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->common.receipient_key, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(packet->handshake_key, peer->protocol_state->initiating_handshake->public_key.p, PUBLICKEYBYTES);
+ fastd_buffer buffer = fastd_buffer_alloc(sizeof(protocol_handshake_init_packet), 0, 0);
+ protocol_handshake_init_packet *packet = buffer.data;
- fastd_task_put_send(ctx, peer, buffer);
+ memset(packet->common.noncepad, 0, NONCEBYTES);
+ packet->common.type = HANDSHAKE_PACKET_INIT;
+ memcpy(packet->common.sender_key, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(packet->common.receipient_key, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(packet->handshake_key, peer->protocol_state->initiating_handshake->public_key.p, PUBLICKEYBYTES);
+
+ fastd_task_put_send(ctx, peer, buffer);
+ }
}
static void respond_handshake(fastd_context *ctx, fastd_peer *peer) {
diff --git a/src/protocol_null.c b/src/protocol_null.c
index b22e03e..24cb58b 100644
--- a/src/protocol_null.c
+++ b/src/protocol_null.c
@@ -50,7 +50,8 @@ static size_t protocol_min_head_space(fastd_context *ctx) {
static void protocol_init_peer(fastd_context *ctx, fastd_peer *peer) {
pr_info(ctx, "Connection with %P established.", peer);
- fastd_task_put_send(ctx, peer, fastd_buffer_alloc(0, 0, 0));
+ if (!fastd_peer_is_temporary(peer))
+ fastd_task_put_send(ctx, peer, fastd_buffer_alloc(0, 0, 0));
}
static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) {
diff --git a/src/task.c b/src/task.c
index 2726ced..472d491 100644
--- a/src/task.c
+++ b/src/task.c
@@ -61,11 +61,12 @@ void fastd_task_put_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buff
fastd_queue_put(ctx, &ctx->task_queue, &task->entry, 0);
}
-void fastd_task_schedule_handshake(fastd_context *ctx, fastd_peer *peer, int timeout) {
+void fastd_task_schedule_handshake(fastd_context *ctx, fastd_peer *peer, int timeout, bool force) {
fastd_task *task = malloc(sizeof(fastd_task));
task->type = TASK_HANDSHAKE;
task->peer = peer;
+ task->handshake.force = force;
fastd_queue_put(ctx, &ctx->task_queue, &task->entry, timeout);
}
diff --git a/src/task.h b/src/task.h
index 367502e..80c6852 100644
--- a/src/task.h
+++ b/src/task.h
@@ -52,6 +52,10 @@ typedef struct _fastd_task_handle_recv {
fastd_buffer buffer;
} fastd_task_handle_recv;
+typedef struct _fastd_task_handshake {
+ bool force;
+} fastd_task_handshake;
+
typedef struct _fastd_task {
fastd_queue_entry entry;
@@ -61,6 +65,7 @@ typedef struct _fastd_task {
union {
fastd_task_send send;
fastd_task_handle_recv handle_recv;
+ fastd_task_handshake handshake;
};
} fastd_task;
@@ -77,7 +82,7 @@ void fastd_task_put_send_handshake(fastd_context *ctx, fastd_peer *peer, fastd_b
void fastd_task_put_send(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer);
void fastd_task_put_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer);
-void fastd_task_schedule_handshake(fastd_context *ctx, fastd_peer *peer, int timeout);
+void fastd_task_schedule_handshake(fastd_context *ctx, fastd_peer *peer, int timeout, bool force);
void fastd_task_delete_peer(fastd_context *ctx, fastd_peer *peer);