From a04bcf247f4be7e3da4fe3895200f0b9709fc0bb Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 24 Aug 2014 01:00:45 +0200 Subject: Merge peer config into peer structure With this refactoring, the structure fastd_peer_config_t is merged into fastd_peer_t, and fastd_remote_config_t into fastd_remote_t. This also means we now create peers directly when reading their configurations, which significantly simplifies the whole reload process, and prepares for some future optimizations like a key hash table. Note: This commit is too big, but I couldn't come up with a nice way to split it into smaller pieces... --- src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c | 51 +++++-------- src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h | 12 +-- src/protocols/ec25519_fhmqvc/handshake.c | 104 ++++++++++---------------- src/protocols/ec25519_fhmqvc/util.c | 20 +++-- 4 files changed, 73 insertions(+), 114 deletions(-) (limited to 'src/protocols') diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c index d952a5e..080c555 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c @@ -74,37 +74,26 @@ static fastd_protocol_config_t* protocol_init(void) { return protocol_config; } -/** Checks if a peer configuration is valid */ -static void protocol_peer_verify(fastd_peer_config_t *peer_conf) { - if (!peer_conf->key) - exit_error("no key configured for peer `%s'", peer_conf->name); - - aligned_int256_t key; - if (!read_key(key.u8, peer_conf->key)) - exit_error("invalid key configured for peer `%s'", peer_conf->name); -} - -/** Initializes the protocol-specific peer configuration */ -static void protocol_peer_configure(fastd_peer_config_t *peer_conf) { - if (peer_conf->protocol_config) - return; +/** Parses a peer's key */ +static fastd_protocol_key_t * protocol_read_key(const char *key) { + fastd_protocol_key_t *ret = fastd_new(fastd_protocol_key_t); - if (!peer_conf->key) { - pr_warn("no key configured for `%s', disabling peer", peer_conf->name); - return; + if (!read_key(ret->key.u8, key)) { + free(ret); + return NULL; } - aligned_int256_t key; - if (!read_key(key.u8, peer_conf->key)) { - pr_warn("invalid key configured for `%s', disabling peer", peer_conf->name); - return; - } + return ret; +} - peer_conf->protocol_config = fastd_new(fastd_protocol_peer_config_t); - peer_conf->protocol_config->public_key = key; +/** Checks if a peer is configured using our own key */ +static bool protocol_check_peer(const fastd_peer_t *peer) { + if (memcmp(conf.protocol_config->key.public.u8, peer->key->key.u8, PUBLICKEYBYTES) == 0) { + pr_verbose("found own key as %P, ignoring peer", peer); + return false; + } - if (memcmp(&peer_conf->protocol_config->public_key, &conf.protocol_config->key.public, PUBLICKEYBYTES) == 0) - pr_debug("found own key as `%s', ignoring peer", peer_conf->name); + return true; } /** Checks if the current session with a peer is valid and resets the connection if not */ @@ -215,11 +204,6 @@ const fastd_protocol_t fastd_protocol_ec25519_fhmqvc = { .name = "ec25519-fhmqvc", .init = protocol_init, - .peer_verify = protocol_peer_verify, - .peer_configure = protocol_peer_configure, - - .peer_check = fastd_protocol_ec25519_fhmqvc_peer_check, - .peer_check_dynamic = fastd_protocol_ec25519_fhmqvc_peer_check_dynamic, .handshake_init = fastd_protocol_ec25519_fhmqvc_handshake_init, .handshake_handle = fastd_protocol_ec25519_fhmqvc_handshake_handle, @@ -234,8 +218,13 @@ const fastd_protocol_t fastd_protocol_ec25519_fhmqvc = { .reset_peer_state = fastd_protocol_ec25519_fhmqvc_reset_peer_state, .free_peer_state = fastd_protocol_ec25519_fhmqvc_free_peer_state, + .read_key = protocol_read_key, + .check_peer = protocol_check_peer, + .find_peer = fastd_protocol_ec25519_fhmqvc_find_peer, + .generate_key = fastd_protocol_ec25519_fhmqvc_generate_key, .show_key = fastd_protocol_ec25519_fhmqvc_show_key, + .set_shell_env = fastd_protocol_ec25519_fhmqvc_set_shell_env, .describe_peer = fastd_protocol_ec25519_fhmqvc_describe_peer, }; diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h index 529dd15..55696c1 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h @@ -65,9 +65,9 @@ struct fastd_protocol_config { keypair_t key; /**< The own keypair */ }; -/** The protocol-specific peer configuration */ -struct fastd_protocol_peer_config { - aligned_int256_t public_key; /**< The peer's public key */ +/** A peer's public key */ +struct fastd_protocol_key { + aligned_int256_t key; /**< The peer's public key */ }; /** Session state */ @@ -101,9 +101,6 @@ struct fastd_protocol_peer_state { }; -bool fastd_protocol_ec25519_fhmqvc_peer_check(fastd_peer_config_t *peer_conf); -bool fastd_protocol_ec25519_fhmqvc_peer_check_dynamic(fastd_peer_t *peer); - void fastd_protocol_ec25519_fhmqvc_maintenance(void); void fastd_protocol_ec25519_fhmqvc_init_peer_state(fastd_peer_t *peer); void fastd_protocol_ec25519_fhmqvc_reset_peer_state(fastd_peer_t *peer); @@ -118,8 +115,11 @@ void fastd_protocol_ec25519_fhmqvc_handle_verify_return(fastd_peer_t *peer, fast void fastd_protocol_ec25519_fhmqvc_send_empty(fastd_peer_t *peer, protocol_session_t *session); +fastd_peer_t * fastd_protocol_ec25519_fhmqvc_find_peer(const fastd_protocol_key_t *key); + void fastd_protocol_ec25519_fhmqvc_generate_key(void); void fastd_protocol_ec25519_fhmqvc_show_key(void); + void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const fastd_peer_t *peer); bool fastd_protocol_ec25519_fhmqvc_describe_peer(const fastd_peer_t *peer, char *buf, size_t len); diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c index 86f9f9e..8f468cd 100644 --- a/src/protocols/ec25519_fhmqvc/handshake.c +++ b/src/protocols/ec25519_fhmqvc/handshake.c @@ -277,7 +277,7 @@ static bool update_shared_handshake_key(const fastd_peer_t *peer, const handshak bool compat = !conf.secure_handshakes; if (!make_shared_handshake_key(&handshake_key->key.secret, false, - &peer->config->protocol_config->public_key, + &peer->key->key, &conf.protocol_config->key.public, peer_handshake_key, &handshake_key->key.public, @@ -315,7 +315,7 @@ static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_addre fastd_buffer_t buffer = fastd_handshake_new_reply(2, method, true, 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->config->protocol_config->public_key); + fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key); fastd_handshake_add(&buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, &handshake_key->key.public); fastd_handshake_add(&buffer, RECORD_RECIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key); @@ -344,7 +344,7 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l fastd_sha256_t shared_handshake_key, shared_handshake_key_compat; if (!make_shared_handshake_key(&handshake_key->key.secret, true, &conf.protocol_config->key.public, - &peer->config->protocol_config->public_key, + &peer->key->key, &handshake_key->key.public, peer_handshake_key, &sigma, @@ -361,7 +361,7 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l valid = fastd_hmacsha256_verify(mac, shared_handshake_key.w, handshake->tlv_data, handshake->tlv_len); } else { - valid = fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, shared_handshake_key_compat.w, peer->config->protocol_config->public_key.u32, peer_handshake_key->u32, NULL); + valid = fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, shared_handshake_key_compat.w, peer->key->key.u32, peer_handshake_key->u32, NULL); } if (!valid) { @@ -370,13 +370,13 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l } if (!establish(peer, method, sock, local_addr, remote_addr, true, &handshake_key->key.public, peer_handshake_key, &conf.protocol_config->key.public, - &peer->config->protocol_config->public_key, &sigma, compat ? NULL : shared_handshake_key.w, handshake_key->serial)) + &peer->key->key, &sigma, compat ? NULL : shared_handshake_key.w, handshake_key->serial)) return; fastd_buffer_t buffer = fastd_handshake_new_reply(3, method, false, 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->config->protocol_config->public_key); + fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key); fastd_handshake_add(&buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, &handshake_key->key.public); fastd_handshake_add(&buffer, RECORD_RECIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key); @@ -415,7 +415,7 @@ static void handle_finish_handshake(fastd_socket_t *sock, const fastd_peer_addre valid = fastd_hmacsha256_verify(mac, peer->protocol_state->shared_handshake_key.w, handshake->tlv_data, handshake->tlv_len); } else { - valid = fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, peer->protocol_state->shared_handshake_key_compat.w, peer->config->protocol_config->public_key.u32, peer_handshake_key->u32, NULL); + valid = fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, peer->protocol_state->shared_handshake_key_compat.w, peer->key->key.u32, peer_handshake_key->u32, NULL); } if (!valid) { @@ -423,14 +423,14 @@ static void handle_finish_handshake(fastd_socket_t *sock, const fastd_peer_addre return; } - establish(peer, method, sock, local_addr, remote_addr, false, peer_handshake_key, &handshake_key->key.public, &peer->config->protocol_config->public_key, + establish(peer, method, sock, local_addr, remote_addr, false, peer_handshake_key, &handshake_key->key.public, &peer->key->key, &conf.protocol_config->key.public, &peer->protocol_state->sigma, compat ? NULL : peer->protocol_state->shared_handshake_key.w, handshake_key->serial); clear_shared_handshake_key(peer); } -/** Searches the peer a public key belongs to */ -static fastd_peer_t* find_sender_key(const fastd_peer_address_t *address, const unsigned char key[PUBLICKEYBYTES]) { +/** Searches the peer a public key belongs to, optionally restricting matches to a specific sender address */ +static fastd_peer_t * find_key(const uint8_t key[PUBLICKEYBYTES], const fastd_peer_address_t *address) { errno = 0; fastd_peer_t *ret = NULL; @@ -439,10 +439,13 @@ static fastd_peer_t* find_sender_key(const fastd_peer_address_t *address, const for (i = 0; i < VECTOR_LEN(ctx.peers); i++) { fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i); - if (!fastd_peer_is_enabled(peer)) + if (address && !fastd_peer_is_enabled(peer)) continue; - if (memcmp(&peer->config->protocol_config->public_key, key, PUBLICKEYBYTES) == 0) { + if (memcmp(&peer->key->key, key, PUBLICKEYBYTES) == 0) { + if (!address) + return peer; + if (!fastd_peer_matches_address(peer, address)) { errno = EPERM; return NULL; @@ -464,15 +467,20 @@ static fastd_peer_t* find_sender_key(const fastd_peer_address_t *address, const return ret; } +/** Searches the peer a public key belongs to (including disabled peers) */ +fastd_peer_t * fastd_protocol_ec25519_fhmqvc_find_peer(const fastd_protocol_key_t *key) { + return find_key(key->key.u8, NULL); +} + /** Checks if a key matches a peer and searches the correct peer if it doesn't */ -static fastd_peer_t* match_sender_key(const fastd_socket_t *sock, const fastd_peer_address_t *address, fastd_peer_t *peer, const unsigned char key[PUBLICKEYBYTES]) { +static fastd_peer_t * match_sender_key(const fastd_socket_t *sock, const fastd_peer_address_t *address, fastd_peer_t *peer, const uint8_t key[PUBLICKEYBYTES]) { errno = 0; if (sock->peer && peer != sock->peer) exit_bug("packet without correct peer set on dynamic socket"); if (peer) { - if (memcmp(&peer->config->protocol_config->public_key, key, PUBLICKEYBYTES) == 0) + if (memcmp(&peer->key->key, key, PUBLICKEYBYTES) == 0) return peer; if (fastd_peer_owns_address(peer, address)) { @@ -481,41 +489,7 @@ static fastd_peer_t* match_sender_key(const fastd_socket_t *sock, const fastd_pe } } - return find_sender_key(address, key); -} - -/** Counts how many peers with a key are configured */ -static size_t key_count(const unsigned char key[PUBLICKEYBYTES]) { - size_t ret = 0; - - fastd_peer_config_t *p; - for (p = ctx.peer_configs; p; p = p->next) { - if (!p->protocol_config) - continue; - - if (memcmp(&p->protocol_config->public_key, key, PUBLICKEYBYTES) == 0) - ret++; - } - - return ret; -} - -/** Validates a peer config */ -bool fastd_protocol_ec25519_fhmqvc_peer_check(fastd_peer_config_t *peer_conf) { - if (!peer_conf->protocol_config) - return false; - - if (memcmp(&peer_conf->protocol_config->public_key, &conf.protocol_config->key.public, PUBLICKEYBYTES) == 0) - return false; - - if (key_count(peer_conf->protocol_config->public_key.u8) > 1) { - char buf[65]; - hexdump(buf, peer_conf->protocol_config->public_key.u8); - pr_warn("more than one peer is configured with key %s, disabling %s", buf, peer_conf->name); - return false; - } - - return true; + return find_key(key, address); } /** Sends an initial handshake (type 1) to a peer */ @@ -527,7 +501,7 @@ void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fa fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public); if (peer) { - fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->config->protocol_config->public_key); + fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key); pr_verbose("sending handshake to %P[%I]...", peer, remote_addr); } @@ -543,18 +517,6 @@ void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fa fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer); } -/** Checks if a dynamic peer (added after an on-verify command) can stay after new peers have been configured */ -bool fastd_protocol_ec25519_fhmqvc_peer_check_dynamic(fastd_peer_t *peer) { - if (key_count(peer->config->protocol_config->public_key.u8)) { - char buf[65]; - hexdump(buf, peer->config->protocol_config->public_key.u8); - pr_info("key %s is configured now, deleting dynamic peer.", buf); - return false; - } - - return true; -} - #ifdef WITH_DYNAMIC_PEERS @@ -576,15 +538,25 @@ static fastd_peer_t * add_dynamic(fastd_socket_t *sock, const fastd_peer_address return NULL; } - if (key_count(key)) { + if (memcmp(&conf.protocol_config->key.public, key, PUBLICKEYBYTES) == 0) { + pr_debug("ignoring handshake from %I (used our own key)", addr); + return NULL; + } + + if (find_key(key, NULL)) { pr_debug("ignoring handshake from %I (disabled key)", addr); return NULL; } - fastd_peer_t *peer = fastd_peer_add(NULL); + fastd_peer_t *peer = fastd_new0(fastd_peer_t); + peer->group = conf.peer_group; + peer->config_state = CONFIG_DYNAMIC; + + peer->key = fastd_new(fastd_protocol_key_t); + memcpy(&peer->key->key, key, PUBLICKEYBYTES); - peer->config->protocol_config = fastd_new(fastd_protocol_peer_config_t); - memcpy(&peer->config->protocol_config->public_key, key, PUBLICKEYBYTES); + if (!fastd_peer_add(peer)) + exit_bug("failed to add dynamic peer"); /* Ugly hack */ peer->protocol_state->last_serial--; diff --git a/src/protocols/ec25519_fhmqvc/util.c b/src/protocols/ec25519_fhmqvc/util.c index c716916..f34f709 100644 --- a/src/protocols/ec25519_fhmqvc/util.c +++ b/src/protocols/ec25519_fhmqvc/util.c @@ -80,8 +80,8 @@ void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const f hexdump(buf, conf.protocol_config->key.public.u8); fastd_shell_env_set(env, "LOCAL_KEY", buf); - if (peer && peer->config->protocol_config) { - hexdump(buf, peer->config->protocol_config->public_key.u8); + if (peer) { + hexdump(buf, peer->key->key.u8); fastd_shell_env_set(env, "PEER_KEY", buf); } else { @@ -97,14 +97,12 @@ void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const f public key. */ bool fastd_protocol_ec25519_fhmqvc_describe_peer(const fastd_peer_t *peer, char *buf, size_t len) { - if (peer && peer->config->protocol_config) { - char dumpbuf[65]; - - hexdump(dumpbuf, peer->config->protocol_config->public_key.u8); - snprintf(buf, len, "%.16s", dumpbuf); - return true; - } - else { + if (!peer->key) return false; - } + + char dumpbuf[65]; + hexdump(dumpbuf, peer->key->key.u8); + snprintf(buf, len, "%.16s", dumpbuf); + + return true; } -- cgit v1.2.3