From 5871d08a3a519dbc54261c8a18e649ec9cc8bd7f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 26 Apr 2014 23:22:12 +0200 Subject: Make on-verify support optional --- cmake/config.cmake | 2 + src/async.c | 7 ++ src/config.c | 4 ++ src/config.y | 5 ++ src/fastd.h | 16 ++++- src/fastd_config.h.in | 1 + src/options.c | 4 ++ src/options.def.h | 2 + src/peer.c | 6 ++ src/peer.h | 4 ++ src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c | 2 + src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h | 3 + src/protocols/ec25519_fhmqvc/handshake.c | 92 +++++++++++++++------------ src/receive.c | 2 +- src/verify.c | 6 ++ src/verify.h | 4 +- 16 files changed, 116 insertions(+), 44 deletions(-) diff --git a/cmake/config.cmake b/cmake/config.cmake index dbd5668..765f608 100644 --- a/cmake/config.cmake +++ b/cmake/config.cmake @@ -29,6 +29,8 @@ set(WITH_CMDLINE_LOGGING TRUE CACHE BOOL "Include support for setting logging re set(WITH_CMDLINE_OPERATION TRUE CACHE BOOL "Include support for setting options related to the VPN operation (like mode, interface, encryption method) on the command line") set(WITH_CMDLINE_COMMANDS TRUE CACHE BOOL "Include support for setting handler scripts (e.g. --on-up) on the command line") +set(WITH_VERIFY TRUE CACHE BOOL "Include support for on-verify handlers") + set(MAX_CONFIG_DEPTH 10 CACHE STRING "Maximum config include depth") diff --git a/src/async.c b/src/async.c index 982543d..ed8370f 100644 --- a/src/async.c +++ b/src/async.c @@ -53,6 +53,8 @@ static void handle_resolve_return(const fastd_async_resolve_return_t *resolve_re fastd_peer_handle_resolve(peer, remote, resolve_return->n_addr, resolve_return->addr); } +#ifdef WITH_VERIFY + static void handle_verify_return(const fastd_async_verify_return_t *verify_return) { fastd_peer_t *peer = fastd_peer_find_by_id(verify_return->peer_id); if (!peer) @@ -67,6 +69,9 @@ static void handle_verify_return(const fastd_async_verify_return_t *verify_retur verify_return->method, verify_return->protocol_data, verify_return->ok); } +#endif + + void fastd_async_handle(void) { fastd_async_hdr_t header; struct iovec vec[2] = { @@ -97,9 +102,11 @@ void fastd_async_handle(void) { handle_resolve_return((const fastd_async_resolve_return_t *)buf); break; +#ifdef WITH_VERIFY case ASYNC_TYPE_VERIFY_RETURN: handle_verify_return((const fastd_async_verify_return_t *)buf); break; +#endif default: exit_bug("fastd_async_handle: unknown type"); diff --git a/src/config.c b/src/config.c index 7d826d4..e7a69c3 100644 --- a/src/config.c +++ b/src/config.c @@ -76,8 +76,10 @@ static void default_config(void) { conf.key_refresh = 3300; /* 55 minutes */ conf.key_refresh_splay = 300; /* 5 minutes */ +#ifdef WITH_VERIFY conf.min_verify_interval = 10; conf.verify_valid_time = 60; /* 1 minute */ +#endif conf.peer_group = calloc(1, sizeof(fastd_peer_group_config_t)); conf.peer_group->name = strdup("default"); @@ -706,7 +708,9 @@ void fastd_config_release(void) { fastd_shell_command_unset(&conf.on_connect); fastd_shell_command_unset(&conf.on_establish); fastd_shell_command_unset(&conf.on_disestablish); +#ifdef WITH_VERIFY fastd_shell_command_unset(&conf.on_verify); +#endif free(conf.user); free(conf.group); diff --git a/src/config.y b/src/config.y index 5ef2d1b..8c53b07 100644 --- a/src/config.y +++ b/src/config.y @@ -413,7 +413,12 @@ on_disestablish: sync_def_async TOK_STRING { ; on_verify: sync_def_async TOK_STRING { +#ifdef WITH_VERIFY fastd_shell_command_set(&conf.on_verify, $2->str, $1); +#else + fastd_config_error(&@$, filename, depth, "`on verify' is not supported by this version of fastd"); + YYERROR; +#endif } ; diff --git a/src/fastd.h b/src/fastd.h index 2f9f12a..6666d70 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -60,7 +60,9 @@ struct fastd_protocol { void (*handshake_init)(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer); void (*handshake_handle)(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, const fastd_method_info_t *method); +#ifdef WITH_VERIFY void (*handle_verify_return)(fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, const fastd_method_info_t *method, const void *protocol_data, bool ok); +#endif void (*handle_recv)(fastd_peer_t *peer, fastd_buffer_t buffer); void (*send)(fastd_peer_t *peer, fastd_buffer_t buffer); @@ -154,8 +156,10 @@ struct fastd_config { unsigned min_handshake_interval; unsigned min_resolve_interval; +#ifdef WITH_VERIFY unsigned min_verify_interval; unsigned verify_valid_time; +#endif char *ifname; @@ -216,7 +220,9 @@ struct fastd_config { fastd_shell_command_t on_connect; fastd_shell_command_t on_establish; fastd_shell_command_t on_disestablish; +#ifdef WITH_VERIFY fastd_shell_command_t on_verify; +#endif bool daemon; char *pid_file; @@ -411,7 +417,7 @@ static inline fastd_string_stack_t* fastd_string_stack_push(fastd_string_stack_t } static inline void fastd_string_stack_free(fastd_string_stack_t *str) { - while(str) { + while (str) { fastd_string_stack_t *next = str->next; free(str); str = next; @@ -442,6 +448,14 @@ static inline void fastd_update_time(void) { clock_gettime(CLOCK_MONOTONIC, &ctx.now); } +static inline bool fastd_allow_verify(void) { +#ifdef WITH_VERIFY + return fastd_shell_command_isset(&conf.on_verify); +#else + return false; +#endif +} + static inline bool strequal(const char *str1, const char *str2) { if (str1 && str2) return (!strcmp(str1, str2)); diff --git a/src/fastd_config.h.in b/src/fastd_config.h.in index 0f9522b..8a3255f 100644 --- a/src/fastd_config.h.in +++ b/src/fastd_config.h.in @@ -47,6 +47,7 @@ #cmakedefine WITH_CMDLINE_OPERATION #cmakedefine WITH_CMDLINE_COMMANDS +#cmakedefine WITH_VERIFY #cmakedefine HAVE_LIBSODIUM #cmakedefine ENABLE_OPENSSL diff --git a/src/options.c b/src/options.c index fef7cc1..2a84a06 100644 --- a/src/options.c +++ b/src/options.c @@ -297,12 +297,16 @@ static void option_on_disestablish(const char *arg) { fastd_shell_command_set(&conf.on_disestablish, arg, false); } +#ifdef WITH_VERIFY + static void option_on_verify(const char *arg) { fastd_shell_command_set(&conf.on_verify, arg, false); } #endif +#endif + static void option_verify_config(void) { conf.verify_config = true; } diff --git a/src/options.def.h b/src/options.def.h index cb4480f..0f4c108 100644 --- a/src/options.def.h +++ b/src/options.def.h @@ -43,7 +43,9 @@ OPTION_ARG(option_on_post_down, "--on-post-down", "", "Sets a shell com OPTION_ARG(option_on_connect, "--on-connect", "", "Sets a shell command to execute when a handshake is sent to establish a new connection"); OPTION_ARG(option_on_establish, "--on-establish", "", "Sets a shell command to execute when a new connection is established"); OPTION_ARG(option_on_disestablish, "--on-disestablish", "", "Sets a shell command to execute when a connection is lost"); +#ifdef WITH_VERIFY OPTION_ARG(option_on_verify, "--on-verify", "", "Sets a shell command to execute to check a connection attempt by an unknown peer"); +#endif SEPARATOR; #endif diff --git a/src/peer.c b/src/peer.c index eef7d0f..662504d 100644 --- a/src/peer.c +++ b/src/peer.c @@ -683,6 +683,7 @@ fastd_peer_t* fastd_peer_add(fastd_peer_config_t *peer_conf) { pr_verbose("adding peer %P (group `%s')", peer, peer->group->conf->name); } else { +#ifdef WITH_VERIFY if (!fastd_shell_command_isset(&conf.on_verify)) exit_bug("tried to add temporary peer without on-verify command"); @@ -692,6 +693,9 @@ fastd_peer_t* fastd_peer_add(fastd_peer_config_t *peer_conf) { peer->verify_valid_timeout = ctx.now; pr_debug("adding temporary peer"); +#else + exit_bug("temporary peers not supported"); +#endif } setup_peer(peer); @@ -867,12 +871,14 @@ static bool maintain_peer(fastd_peer_t *peer) { if (fastd_peer_is_temporary(peer) || fastd_peer_is_established(peer)) { /* check for peer timeout */ if (fastd_timed_out(&peer->timeout)) { +#ifdef WITH_VERIFY if (fastd_peer_is_temporary(peer) && fastd_timed_out(&peer->verify_timeout) && fastd_timed_out(&peer->verify_valid_timeout)) { fastd_peer_delete(peer); return false; } +#endif if (fastd_peer_is_established(peer)) fastd_peer_reset(peer); diff --git a/src/peer.h b/src/peer.h index 8cd23c0..74b1074 100644 --- a/src/peer.h +++ b/src/peer.h @@ -57,8 +57,10 @@ struct fastd_peer { struct timespec establish_handshake_timeout; +#ifdef WITH_VERIFY struct timespec verify_timeout; struct timespec verify_valid_timeout; +#endif fastd_protocol_peer_config_t *protocol_config; fastd_protocol_peer_state_t *protocol_state; @@ -151,6 +153,7 @@ static inline void fastd_peer_unschedule_handshake(fastd_peer_t *peer) { fastd_dlist_remove(&peer->handshake_entry); } +#ifdef WITH_VERIFY static inline void fastd_peer_set_verifying(fastd_peer_t *peer) { peer->verify_timeout = fastd_in_seconds(conf.min_verify_interval); } @@ -161,6 +164,7 @@ static inline void fastd_peer_set_verified(fastd_peer_t *peer, bool ok) { else peer->verify_valid_timeout = ctx.now; } +#endif static inline bool fastd_peer_handshake_scheduled(fastd_peer_t *peer) { return fastd_dlist_linked(&peer->handshake_entry); diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c index 777e731..eca1cd1 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c @@ -205,7 +205,9 @@ const fastd_protocol_t fastd_protocol_ec25519_fhmqvc = { .handshake_init = fastd_protocol_ec25519_fhmqvc_handshake_init, .handshake_handle = fastd_protocol_ec25519_fhmqvc_handshake_handle, +#ifdef WITH_VERIFY .handle_verify_return = fastd_protocol_ec25519_fhmqvc_handle_verify_return, +#endif .handle_recv = protocol_handle_recv, .send = protocol_send, diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h index c301822..6dcc149 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h @@ -90,7 +90,10 @@ void fastd_protocol_ec25519_fhmqvc_free_peer_state(fastd_peer_t *peer); void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer); void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, const fastd_method_info_t *method); + +#ifdef WITH_VERIFY void fastd_protocol_ec25519_fhmqvc_handle_verify_return(fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, const fastd_method_info_t *method, const void *protocol_data, bool ok); +#endif void fastd_protocol_ec25519_fhmqvc_send_empty(fastd_peer_t *peer, protocol_session_t *session); diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c index 237732d..725a827 100644 --- a/src/protocols/ec25519_fhmqvc/handshake.c +++ b/src/protocols/ec25519_fhmqvc/handshake.c @@ -474,6 +474,26 @@ bool fastd_protocol_ec25519_fhmqvc_peer_check(fastd_peer_config_t *peer_conf) { return true; } +void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer) { + fastd_protocol_ec25519_fhmqvc_maintenance(); + + fastd_buffer_t buffer = fastd_handshake_new_init(3*(4+PUBLICKEYBYTES) /* sender key, receipient key, handshake key */); + + fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public); + + if (peer) + fastd_handshake_add(&buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, &peer->protocol_config->public_key); + else + pr_debug("sending handshake to unknown peer %I", remote_addr); + + fastd_handshake_add(&buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, &ctx.protocol_state->handshake_key.key.public); + + if (!peer || !fastd_peer_is_established(peer)) + fastd_peer_exec_shell_command(&conf.on_connect, peer, (local_addr && local_addr->sa.sa_family) ? local_addr : sock->bound_addr, remote_addr); + + fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer); +} + bool fastd_protocol_ec25519_fhmqvc_peer_check_temporary(fastd_peer_t *peer) { if (key_count(peer->protocol_config->public_key.u8)) { char buf[65]; @@ -485,12 +505,15 @@ bool fastd_protocol_ec25519_fhmqvc_peer_check_temporary(fastd_peer_t *peer) { return true; } -static inline bool allow_unknown(void) { - return fastd_shell_command_isset(&conf.on_verify); -} + +#ifdef WITH_VERIFY + +typedef struct verify_data { + aligned_int256_t peer_handshake_key; +} verify_data_t; static fastd_peer_t * add_temporary(fastd_socket_t *sock, const fastd_peer_address_t *addr, const unsigned char key[PUBLICKEYBYTES]) { - if (!allow_unknown()) { + if (!fastd_allow_verify()) { pr_debug("ignoring handshake from %I (unknown key)", addr); return NULL; } @@ -517,31 +540,6 @@ static fastd_peer_t * add_temporary(fastd_socket_t *sock, const fastd_peer_addre return peer; } - -void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer) { - fastd_protocol_ec25519_fhmqvc_maintenance(); - - fastd_buffer_t buffer = fastd_handshake_new_init(3*(4+PUBLICKEYBYTES) /* sender key, receipient key, handshake key */); - - fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public); - - if (peer) - fastd_handshake_add(&buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, &peer->protocol_config->public_key); - else - pr_debug("sending handshake to unknown peer %I", remote_addr); - - fastd_handshake_add(&buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, &ctx.protocol_state->handshake_key.key.public); - - if (!peer || !fastd_peer_is_established(peer)) - fastd_peer_exec_shell_command(&conf.on_connect, peer, (local_addr && local_addr->sa.sa_family) ? local_addr : sock->bound_addr, remote_addr); - - fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer); -} - -typedef struct verify_data { - aligned_int256_t peer_handshake_key; -} verify_data_t; - static bool handle_temporary(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, const fastd_method_info_t *method) { if (handshake->type != 1 || !fastd_timed_out(&peer->verify_timeout)) @@ -566,6 +564,28 @@ static bool handle_temporary(fastd_socket_t *sock, const fastd_peer_address_t *l return true; } +void fastd_protocol_ec25519_fhmqvc_handle_verify_return(fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, + const fastd_method_info_t *method, const void *protocol_data, bool ok) { + if (!ok) + return; + + const verify_data_t *data = protocol_data; + + peer->last_handshake_response_timeout = fastd_in_seconds(conf.min_handshake_interval); + peer->last_handshake_response_address = *remote_addr; + respond_handshake(sock, local_addr, remote_addr, peer, &data->peer_handshake_key, method); +} + +#else + +static inline fastd_peer_t * add_temporary(fastd_socket_t *sock UNUSED, const fastd_peer_address_t *addr, const unsigned char key[PUBLICKEYBYTES] UNUSED) { + pr_debug("ignoring handshake from %I (unknown key)", addr); + return NULL; +} + +#endif /* WITH_VERIFY */ + + void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, const fastd_method_info_t *method) { fastd_protocol_ec25519_fhmqvc_maintenance(); @@ -616,10 +636,12 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const } } +#ifdef WITH_VERIFY if (fastd_peer_is_temporary(peer)) { if (!handle_temporary(sock, local_addr, remote_addr, peer, handshake, method)) return; } +#endif aligned_int256_t peer_handshake_key; memcpy(&peer_handshake_key, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, PUBLICKEYBYTES); @@ -687,15 +709,3 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const pr_debug("received handshake reply with unknown type %u from %P[%I]", handshake->type, peer, remote_addr); } } - -void fastd_protocol_ec25519_fhmqvc_handle_verify_return(fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, - const fastd_method_info_t *method, const void *protocol_data, bool ok) { - if (!ok) - return; - - const verify_data_t *data = protocol_data; - - peer->last_handshake_response_timeout = fastd_in_seconds(conf.min_handshake_interval); - peer->last_handshake_response_address = *remote_addr; - respond_handshake(sock, local_addr, remote_addr, peer, &data->peer_handshake_key, method); -} diff --git a/src/receive.c b/src/receive.c index a8ec1ce..4ebd185 100644 --- a/src/receive.c +++ b/src/receive.c @@ -132,7 +132,7 @@ static inline void handle_socket_receive_known(fastd_socket_t *sock, const fastd } static inline bool allow_unknown_peers(void) { - return conf.has_floating || fastd_shell_command_isset(&conf.on_verify); + return conf.has_floating || fastd_allow_verify(); } static inline void handle_socket_receive_unknown(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer) { diff --git a/src/verify.c b/src/verify.c index fb592bd..876e133 100644 --- a/src/verify.c +++ b/src/verify.c @@ -25,6 +25,10 @@ #include "verify.h" + + +#ifdef WITH_VERIFY + #include "async.h" #include "shell.h" @@ -109,3 +113,5 @@ fastd_tristate_t fastd_verify_peer(fastd_peer_t *peer, fastd_socket_t *sock, con return (fastd_tristate_t){.set = false}; } } + +#endif /* WITH_VERIFY */ diff --git a/src/verify.h b/src/verify.h index 6f1b525..7f0d5c0 100644 --- a/src/verify.h +++ b/src/verify.h @@ -26,8 +26,10 @@ #pragma once - #include "types.h" +#ifdef WITH_VERIFY fastd_tristate_t fastd_verify_peer(fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, const fastd_method_info_t *method, const void *data, size_t data_len); + +#endif /* WITH_VERIFY */ -- cgit v1.2.3