summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.c31
-rw-r--r--src/config.h2
-rw-r--r--src/config.y12
-rw-r--r--src/fastd.h12
-rw-r--r--src/handshake.c52
-rw-r--r--src/handshake.h2
-rw-r--r--src/options.c2
-rw-r--r--src/peer.h15
-rw-r--r--src/protocols/ec25519_fhmqvc/handshake.c4
9 files changed, 92 insertions, 40 deletions
diff --git a/src/config.c b/src/config.c
index 7b87dcf..7a0cb4e 100644
--- a/src/config.c
+++ b/src/config.c
@@ -80,10 +80,10 @@ void fastd_config_protocol(const char *name) {
}
/** Handles the configuration of a crypto method */
-void fastd_config_method(const char *name) {
+void fastd_config_method(fastd_peer_group_t *group, const char *name) {
fastd_string_stack_t **method;
- for (method = &conf.method_list; *method; method = &(*method)->next) {
+ for (method = &group->methods; *method; method = &(*method)->next) {
if (!strcmp((*method)->str, name)) {
pr_debug("duplicate method name `%s', ignoring", name);
return;
@@ -168,6 +168,7 @@ static void free_peer_group(fastd_peer_group_t *group) {
}
fastd_string_stack_free(group->peer_dirs);
+ fastd_string_stack_free(group->methods);
free(group->name);
free(group);
}
@@ -467,12 +468,30 @@ static void configure_method_parameters(void) {
conf.min_decrypt_head_space = alignto(conf.min_decrypt_head_space, 16) + 8;
}
+
+/** Collects a list of the configured methods of all peer groups */
+static void collect_methods(const fastd_peer_group_t *group, size_t *count) {
+ const fastd_string_stack_t *method;
+
+ for (method = group->methods; method; method = method->next) {
+ if (!fastd_string_stack_contains(conf.method_list, method->str)) {
+ conf.method_list = fastd_string_stack_push(conf.method_list, method->str);
+ (*count)++;
+ }
+ }
+
+ const fastd_peer_group_t *sub;
+ for (sub = group->children; sub; sub = sub->next)
+ collect_methods(sub, count);
+}
+
+
/** Handles the initialization of the configured methods */
static void configure_methods(void) {
size_t n_methods = 0, i;
fastd_string_stack_t *method_name;
- for (method_name = conf.method_list; method_name; method_name = method_name->next)
- n_methods++;
+
+ collect_methods(conf.peer_group, &n_methods);
conf.methods = fastd_new0_array(n_methods+1, fastd_method_info_t);
@@ -546,9 +565,9 @@ void fastd_config_check(void) {
if (!VECTOR_LEN(ctx.peers) && !has_peer_group_peer_dirs(conf.peer_group))
exit_error("config error: neither fixed peers nor peer dirs have been configured");
- if (!conf.method_list) {
+ if (!conf.peer_group->methods) {
pr_warn("no encryption method configured, falling back to method `null' (unencrypted)");
- fastd_config_method("null");
+ fastd_config_method(conf.peer_group, "null");
}
configure_user();
diff --git a/src/config.h b/src/config.h
index b076266..b8ef95d 100644
--- a/src/config.h
+++ b/src/config.h
@@ -46,7 +46,7 @@ struct fastd_parser_state {
void fastd_config_protocol(const char *name);
-void fastd_config_method(const char *name);
+void fastd_config_method(fastd_peer_group_t *group, const char *name);
void fastd_config_cipher(const char *name, const char *impl);
void fastd_config_mac(const char *name, const char *impl);
void fastd_config_bind_address(const fastd_peer_address_t *address, const char *bindtodev, bool default_v4, bool default_v6);
diff --git a/src/config.y b/src/config.y
index bd106e7..c4d7eaa 100644
--- a/src/config.y
+++ b/src/config.y
@@ -191,7 +191,6 @@ statement: peer_group_statement
| TOK_PMTU pmtu ';'
| TOK_MODE mode ';'
| TOK_PROTOCOL protocol ';'
- | TOK_METHOD method ';'
| TOK_SECRET secret ';'
| TOK_ON TOK_PRE_UP on_pre_up ';'
| TOK_ON TOK_UP on_up ';'
@@ -209,6 +208,7 @@ peer_group_statement:
TOK_PEER peer '{' peer_conf '}' peer_after
| TOK_PEER TOK_GROUP peer_group '{' peer_group_config '}' peer_group_after
| TOK_PEER TOK_LIMIT peer_limit ';'
+ | TOK_METHOD method ';'
| TOK_INCLUDE include ';'
;
@@ -371,11 +371,6 @@ protocol: TOK_STRING {
}
;
-method: TOK_STRING {
- fastd_config_method($1->str);
- }
- ;
-
secret: TOK_STRING { free(conf.secret); conf.secret = fastd_strdup($1->str); }
;
@@ -546,6 +541,11 @@ peer_limit: TOK_UINT {
}
;
+method: TOK_STRING {
+ fastd_config_method(state->peer_group, $1->str);
+ }
+ ;
+
forward: boolean { conf.forward = $1; }
;
diff --git a/src/fastd.h b/src/fastd.h
index 8af0556..6e4cda6 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -450,6 +450,18 @@ static inline const char * fastd_string_stack_get(const fastd_string_stack_t *st
return stack ? stack->str : NULL;
}
+/** */
+static inline bool fastd_string_stack_contains(const fastd_string_stack_t *stack, const char *str) {
+ while (stack) {
+ if (strcmp(stack->str, str) == 0)
+ return true;
+
+ stack = stack->next;
+ }
+
+ return false;
+}
+
/** Frees a whole string stack */
static inline void fastd_string_stack_free(fastd_string_stack_t *str) {
while (str) {
diff --git a/src/handshake.c b/src/handshake.c
index 2c22655..1bb18a1 100644
--- a/src/handshake.c
+++ b/src/handshake.c
@@ -105,16 +105,17 @@ static inline uint32_t as_uint(const fastd_handshake_record_t *record) {
/** Generates a zero-separated list of supported methods */
-static uint8_t * create_method_list(size_t *len) {
- size_t n, i;
- for (n = 0; conf.methods[n].name; n++) {
- }
+static uint8_t * create_method_list(const fastd_string_stack_t *methods, size_t *len) {
+ size_t n = 0, i;
+ const fastd_string_stack_t *method;
+ for (method = methods; method; method = method->next)
+ n++;
*len = 0;
size_t lens[n];
- for (i = 0; i < n; i++) {
- lens[i] = strlen(conf.methods[i].name) + 1;
+ for (method = methods, i = 0; method; method = method->next, i++) {
+ lens[i] = strlen(method->str) + 1;
*len += lens[i];
}
@@ -123,8 +124,8 @@ static uint8_t * create_method_list(size_t *len) {
uint8_t *ptr = ret;
- for (i = 0; i < n; i++) {
- memcpy(ptr, conf.methods[i].name, lens[i]);
+ for (method = methods, i = 0; method; method = method->next, i++) {
+ memcpy(ptr, method->str, lens[i]);
ptr += lens[i];
}
@@ -160,7 +161,7 @@ static fastd_string_stack_t * parse_string_list(const uint8_t *data, size_t len)
}
/** Allocates and initializes a new handshake packet */
-static fastd_handshake_buffer_t new_handshake(uint8_t type, bool little_endian, const fastd_method_info_t *method, bool with_method_list, size_t tail_space) {
+static fastd_handshake_buffer_t new_handshake(uint8_t type, bool little_endian, const fastd_method_info_t *method, const fastd_string_stack_t *methods, size_t tail_space) {
size_t version_len = strlen(FASTD_VERSION);
size_t protocol_len = strlen(conf.protocol->name);
size_t method_len = method ? strlen(method->name) : 0;
@@ -168,8 +169,8 @@ static fastd_handshake_buffer_t new_handshake(uint8_t type, bool little_endian,
size_t method_list_len = 0;
uint8_t *method_list = NULL;
- if (with_method_list)
- method_list = create_method_list(&method_list_len);
+ if (methods)
+ method_list = create_method_list(methods, &method_list_len);
fastd_handshake_buffer_t buffer = {
.buffer = fastd_buffer_alloc(sizeof(fastd_handshake_packet_t), 1,
@@ -193,10 +194,10 @@ static fastd_handshake_buffer_t new_handshake(uint8_t type, bool little_endian,
fastd_handshake_add(&buffer, RECORD_VERSION_NAME, version_len, FASTD_VERSION);
fastd_handshake_add(&buffer, RECORD_PROTOCOL_NAME, protocol_len, conf.protocol->name);
- if (method && (!with_method_list || !conf.secure_handshakes))
+ if (method && (!methods || !conf.secure_handshakes))
fastd_handshake_add(&buffer, RECORD_METHOD_NAME, method_len, method->name);
- if (with_method_list) {
+ if (methods) {
fastd_handshake_add(&buffer, RECORD_METHOD_LIST, method_list_len, method_list);
free(method_list);
}
@@ -206,12 +207,12 @@ static fastd_handshake_buffer_t new_handshake(uint8_t type, bool little_endian,
/** Allocates and initializes a new initial handshake packet */
fastd_handshake_buffer_t fastd_handshake_new_init(size_t tail_space) {
- return new_handshake(1, true, NULL, !conf.secure_handshakes, tail_space);
+ return new_handshake(1, true, NULL, conf.secure_handshakes ? NULL : conf.peer_group->methods, tail_space);
}
/** Allocates and initializes a new reply handshake packet */
-fastd_handshake_buffer_t fastd_handshake_new_reply(uint8_t type, bool little_endian, const fastd_method_info_t *method, bool with_method_list, size_t tail_space) {
- fastd_handshake_buffer_t buffer = new_handshake(type, little_endian, method, with_method_list, tail_space);
+fastd_handshake_buffer_t fastd_handshake_new_reply(uint8_t type, bool little_endian, const fastd_method_info_t *method, const fastd_string_stack_t *methods, size_t tail_space) {
+ fastd_handshake_buffer_t buffer = new_handshake(type, little_endian, method, methods, tail_space);
fastd_handshake_add_uint8(&buffer, RECORD_REPLY_CODE, 0);
return buffer;
}
@@ -390,16 +391,19 @@ static inline bool check_records(fastd_socket_t *sock, const fastd_peer_address_
}
/** Returns the method info with a specified name and length */
-static inline const fastd_method_info_t * get_method_by_name(const char *name, size_t n) {
+static inline const fastd_method_info_t * get_method_by_name(const fastd_string_stack_t *methods, const char *name, size_t n) {
char name0[n+1];
memcpy(name0, name, n);
name0[n] = 0;
+ if (!fastd_string_stack_contains(methods, name0))
+ return NULL;
+
return fastd_method_get_by_name(name0);
}
/** Returns the most appropriate method to negotiate with a peer a handshake was received from */
-static inline const fastd_method_info_t * get_method(const fastd_handshake_t *handshake) {
+static inline const fastd_method_info_t * get_method(const fastd_string_stack_t *methods, const fastd_handshake_t *handshake) {
if (handshake->records[RECORD_METHOD_LIST].data && handshake->records[RECORD_METHOD_LIST].length) {
fastd_string_stack_t *method_list = parse_string_list(handshake->records[RECORD_METHOD_LIST].data, handshake->records[RECORD_METHOD_LIST].length);
@@ -407,10 +411,12 @@ static inline const fastd_method_info_t * get_method(const fastd_handshake_t *ha
fastd_string_stack_t *method_name;
for (method_name = method_list; method_name; method_name = method_name->next) {
- const fastd_method_info_t *cur_method = fastd_method_get_by_name(method_name->str);
+ if (!fastd_string_stack_contains(methods, method_name->str))
+ continue;
- if (cur_method)
- method = cur_method;
+ method = fastd_method_get_by_name(method_name->str);
+ if (!method)
+ exit_bug("get_method: can't find configured method");
}
fastd_string_stack_free(method_list);
@@ -421,7 +427,7 @@ static inline const fastd_method_info_t * get_method(const fastd_handshake_t *ha
if (!handshake->records[RECORD_METHOD_NAME].data)
return NULL;
- return get_method_by_name((const char *)handshake->records[RECORD_METHOD_NAME].data, handshake->records[RECORD_METHOD_NAME].length);
+ return get_method_by_name(methods, (const char *)handshake->records[RECORD_METHOD_NAME].data, handshake->records[RECORD_METHOD_NAME].length);
}
/** Handles a handshake packet */
@@ -447,7 +453,7 @@ void fastd_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *lo
goto end_free;
if (!conf.secure_handshakes || handshake.type > 1) {
- method = get_method(&handshake);
+ method = get_method(fastd_peer_get_methods(peer), &handshake);
if (handshake.records[RECORD_VERSION_NAME].data)
handshake.peer_version = peer_version = fastd_strndup((const char *)handshake.records[RECORD_VERSION_NAME].data, handshake.records[RECORD_VERSION_NAME].length);
diff --git a/src/handshake.h b/src/handshake.h
index f432f64..70d7a16 100644
--- a/src/handshake.h
+++ b/src/handshake.h
@@ -100,7 +100,7 @@ struct fastd_handshake_buffer {
fastd_handshake_buffer_t fastd_handshake_new_init(size_t tail_space);
-fastd_handshake_buffer_t fastd_handshake_new_reply(uint8_t type, bool little_endian, const fastd_method_info_t *method, bool with_method_list, size_t tail_space);
+fastd_handshake_buffer_t fastd_handshake_new_reply(uint8_t type, bool little_endian, const fastd_method_info_t *method, const fastd_string_stack_t *methods, size_t tail_space);
void fastd_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, fastd_buffer_t buffer);
diff --git a/src/options.c b/src/options.c
index 2a67f13..b54c086 100644
--- a/src/options.c
+++ b/src/options.c
@@ -315,7 +315,7 @@ static void option_protocol(const char *arg) {
/** Handles the --method option */
static void option_method(const char *arg) {
- fastd_config_method(arg);
+ fastd_config_method(conf.peer_group, arg);
}
/** Handles the --forward option */
diff --git a/src/peer.h b/src/peer.h
index ca03e2f..3181544 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -121,6 +121,7 @@ struct fastd_peer_group {
/* constraints */
int max_connections; /**< The maximum number of connections to allow in this group; -1 for no limit */
+ fastd_string_stack_t *methods; /**< The list of configured method names */
};
/** An entry for a MAC address seen at another peer */
@@ -265,6 +266,20 @@ static inline bool fastd_peer_is_socket_dynamic(const fastd_peer_t *peer) {
return (!peer->sock || !peer->sock->addr);
}
+/** Returns the configured methods for a peer's group */
+static inline const fastd_string_stack_t * fastd_peer_get_methods(const fastd_peer_t *peer) {
+ if (!peer)
+ return conf.peer_group->methods;
+
+ const fastd_peer_group_t *group;
+ for (group = peer->group; group; group = group->parent) {
+ if (group->methods)
+ return group->methods;
+ }
+
+ return NULL;
+}
+
/** Checks if a MAC address is a normal unicast address */
static inline bool fastd_eth_addr_is_unicast(fastd_eth_addr_t addr) {
return ((addr.data[0] & 1) == 0);
diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c
index 2daa709..a6dfc67 100644
--- a/src/protocols/ec25519_fhmqvc/handshake.c
+++ b/src/protocols/ec25519_fhmqvc/handshake.c
@@ -306,7 +306,7 @@ static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_addre
if (!update_shared_handshake_key(peer, handshake_key, peer_handshake_key))
return;
- fastd_handshake_buffer_t buffer = fastd_handshake_new_reply(2, little_endian, method, true, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
+ fastd_handshake_buffer_t buffer = fastd_handshake_new_reply(2, little_endian, method, fastd_peer_get_methods(peer), 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key);
@@ -365,7 +365,7 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l
&peer->key->key, &sigma, compat ? NULL : shared_handshake_key.w, handshake_key->serial))
return;
- fastd_handshake_buffer_t buffer = fastd_handshake_new_reply(3, handshake->little_endian, method, false, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
+ fastd_handshake_buffer_t buffer = fastd_handshake_new_reply(3, handshake->little_endian, method, NULL, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key);