mirror of
https://github.com/neocturne/fastd.git
synced 2025-05-14 12:25:07 +02:00
Allow to configure methods per peer group
This commit is contained in:
parent
7815904f11
commit
51a1da3272
9 changed files with 92 additions and 40 deletions
31
src/config.c
31
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();
|
||||
|
|
|
@ -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);
|
||||
|
|
12
src/config.y
12
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; }
|
||||
;
|
||||
|
||||
|
|
12
src/fastd.h
12
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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
15
src/peer.h
15
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue