diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2014-04-26 00:46:33 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2014-04-26 22:46:05 +0200 |
commit | 36690c7203f0e46665f328fbe82ae3bd573cc6ff (patch) | |
tree | 761707cbd83e499913277fc931e32d05bf3c32cc /src | |
parent | 64ce1c0f51b4d0c07c124071ea2cd8002eccd45d (diff) | |
download | fastd-36690c7203f0e46665f328fbe82ae3bd573cc6ff.tar fastd-36690c7203f0e46665f328fbe82ae3bd573cc6ff.zip |
Implement async verify
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/async.c | 24 | ||||
-rw-r--r-- | src/async.h | 24 | ||||
-rw-r--r-- | src/config.c | 3 | ||||
-rw-r--r-- | src/fastd.h | 6 | ||||
-rw-r--r-- | src/peer.c | 42 | ||||
-rw-r--r-- | src/peer.h | 16 | ||||
-rw-r--r-- | src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c | 1 | ||||
-rw-r--r-- | src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h | 3 | ||||
-rw-r--r-- | src/protocols/ec25519_fhmqvc/handshake.c | 70 | ||||
-rw-r--r-- | src/types.h | 6 | ||||
-rw-r--r-- | src/verify.c | 111 | ||||
-rw-r--r-- | src/verify.h | 33 |
13 files changed, 279 insertions, 61 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f9143db..9802883 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,6 +39,7 @@ add_executable(fastd socket.c tuntap.c vector.c + verify.c ${BISON_fastd_config_parse_OUTPUTS} ) set_property(TARGET fastd PROPERTY COMPILE_FLAGS "${FASTD_CFLAGS}") diff --git a/src/async.c b/src/async.c index cb9ee14..982543d 100644 --- a/src/async.c +++ b/src/async.c @@ -41,9 +41,7 @@ void fastd_async_init(void) { fastd_setfl(ctx.async_wfd, O_NONBLOCK, 0); } -static void handle_resolve_return(const void *buf) { - const fastd_async_resolve_return_t *resolve_return = buf; - +static void handle_resolve_return(const fastd_async_resolve_return_t *resolve_return) { fastd_peer_t *peer = fastd_peer_find_by_id(resolve_return->peer_id); if (!peer) return; @@ -55,6 +53,20 @@ static void handle_resolve_return(const void *buf) { fastd_peer_handle_resolve(peer, remote, resolve_return->n_addr, resolve_return->addr); } +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) + return; + + if (peer->config) + exit_bug("verify return for permanent peer"); + + fastd_peer_set_verified(peer, verify_return->ok); + + conf.protocol->handle_verify_return(peer, verify_return->sock, &verify_return->local_addr, &verify_return->remote_addr, + verify_return->method, verify_return->protocol_data, verify_return->ok); +} + void fastd_async_handle(void) { fastd_async_hdr_t header; struct iovec vec[2] = { @@ -82,7 +94,11 @@ void fastd_async_handle(void) { switch (header.type) { case ASYNC_TYPE_RESOLVE_RETURN: - handle_resolve_return(buf); + handle_resolve_return((const fastd_async_resolve_return_t *)buf); + break; + + case ASYNC_TYPE_VERIFY_RETURN: + handle_verify_return((const fastd_async_verify_return_t *)buf); break; default: diff --git a/src/async.h b/src/async.h index f2a8f20..fd6ebd5 100644 --- a/src/async.h +++ b/src/async.h @@ -30,13 +30,33 @@ #include "peer.h" -struct fastd_async_resolve_return { +typedef enum fastd_async_type { + ASYNC_TYPE_RESOLVE_RETURN, + ASYNC_TYPE_VERIFY_RETURN, +} fastd_async_type_t; + + +typedef struct fastd_async_resolve_return { uint64_t peer_id; size_t remote; size_t n_addr; fastd_peer_address_t addr[]; -}; +} fastd_async_resolve_return_t; + +typedef struct fastd_async_verify_return { + bool ok; + + uint64_t peer_id; + + const fastd_method_info_t *method; + fastd_socket_t *sock; + + fastd_peer_address_t local_addr; + fastd_peer_address_t remote_addr; + + uint8_t protocol_data[] __attribute__((aligned(8))); +} fastd_async_verify_return_t; void fastd_async_init(void); diff --git a/src/config.c b/src/config.c index e20bc57..7d826d4 100644 --- a/src/config.c +++ b/src/config.c @@ -76,6 +76,9 @@ static void default_config(void) { conf.key_refresh = 3300; /* 55 minutes */ conf.key_refresh_splay = 300; /* 5 minutes */ + conf.min_verify_interval = 10; + conf.verify_valid_time = 60; /* 1 minute */ + conf.peer_group = calloc(1, sizeof(fastd_peer_group_config_t)); conf.peer_group->name = strdup("default"); conf.peer_group->max_connections = -1; diff --git a/src/fastd.h b/src/fastd.h index 838ce94..2f9f12a 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -58,8 +58,9 @@ struct fastd_protocol { bool (*peer_check)(fastd_peer_config_t *peer_conf); bool (*peer_check_temporary)(fastd_peer_t *peer); - void (*handshake_init)(const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer); + 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); + 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); void (*handle_recv)(fastd_peer_t *peer, fastd_buffer_t buffer); void (*send)(fastd_peer_t *peer, fastd_buffer_t buffer); @@ -153,6 +154,9 @@ struct fastd_config { unsigned min_handshake_interval; unsigned min_resolve_interval; + unsigned min_verify_interval; + unsigned verify_valid_time; + char *ifname; size_t n_bind_addrs; @@ -688,7 +688,8 @@ fastd_peer_t* fastd_peer_add(fastd_peer_config_t *peer_conf) { peer->group = ctx.peer_group; - fastd_peer_seen(peer); + peer->verify_timeout = ctx.now; + peer->verify_valid_timeout = ctx.now; pr_debug("adding temporary peer"); } @@ -701,35 +702,6 @@ fastd_peer_t* fastd_peer_add(fastd_peer_config_t *peer_conf) { return peer; } -bool fastd_peer_verify_temporary(fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr) { - if (!fastd_shell_command_isset(&conf.on_verify)) - exit_bug("tried to verify temporary peer without on-verify command"); - - /* TODO: async not supported yet */ - - fastd_shell_env_t *env = fastd_shell_env_alloc(); - fastd_peer_set_shell_env(env, peer, local_addr, peer_addr); - - int ret; - bool ok = fastd_shell_command_exec_sync(&conf.on_verify, env, &ret); - - fastd_shell_env_free(env); - - if (!ok) - return false; - - if (WIFSIGNALED(ret)) { - pr_error("verify command exited with signal %i", WTERMSIG(ret)); - return false; - } - else if (WEXITSTATUS(ret)) { - pr_debug("verify command exited with status %i", WEXITSTATUS(ret)); - return false; - } - - return true; -} - static inline void no_valid_address_debug(const fastd_peer_t *peer) { pr_debug("not sending a handshake to %P (no valid address resolved)", peer); } @@ -895,14 +867,16 @@ 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)) { - if (fastd_peer_is_temporary(peer)) { + 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; } - else { + + if (fastd_peer_is_established(peer)) fastd_peer_reset(peer); - return true; - } + return true; } /* check for keepalive timeout */ @@ -57,6 +57,9 @@ struct fastd_peer { struct timespec establish_handshake_timeout; + struct timespec verify_timeout; + struct timespec verify_valid_timeout; + fastd_protocol_peer_config_t *protocol_config; fastd_protocol_peer_state_t *protocol_state; }; @@ -127,8 +130,6 @@ bool fastd_peer_config_equal(const fastd_peer_config_t *peer1, const fastd_peer_ void fastd_peer_reset(fastd_peer_t *peer); void fastd_peer_delete(fastd_peer_t *peer); fastd_peer_t* fastd_peer_add(fastd_peer_config_t *peer_conf); -bool fastd_peer_verify_temporary(fastd_peer_t *peer, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *peer_addr); -void fastd_peer_enable_temporary(fastd_peer_t *peer); void fastd_peer_set_established(fastd_peer_t *peer); bool fastd_peer_may_connect(fastd_peer_t *peer); void fastd_peer_handle_resolve(fastd_peer_t *peer, fastd_remote_t *remote, size_t n_addresses, const fastd_peer_address_t *addresses); @@ -150,6 +151,17 @@ static inline void fastd_peer_unschedule_handshake(fastd_peer_t *peer) { fastd_dlist_remove(&peer->handshake_entry); } +static inline void fastd_peer_set_verifying(fastd_peer_t *peer) { + peer->verify_timeout = fastd_in_seconds(conf.min_verify_interval); +} + +static inline void fastd_peer_set_verified(fastd_peer_t *peer, bool ok) { + if (ok) + peer->verify_valid_timeout = fastd_in_seconds(conf.verify_valid_time); + else + peer->verify_valid_timeout = ctx.now; +} + 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 ec19da3..777e731 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c @@ -205,6 +205,7 @@ const fastd_protocol_t fastd_protocol_ec25519_fhmqvc = { .handshake_init = fastd_protocol_ec25519_fhmqvc_handshake_init, .handshake_handle = fastd_protocol_ec25519_fhmqvc_handshake_handle, + .handle_verify_return = fastd_protocol_ec25519_fhmqvc_handle_verify_return, .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 fcf9b56..c301822 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h @@ -88,8 +88,9 @@ void fastd_protocol_ec25519_fhmqvc_init_peer_state(fastd_peer_t *peer); void fastd_protocol_ec25519_fhmqvc_reset_peer_state(fastd_peer_t *peer); void fastd_protocol_ec25519_fhmqvc_free_peer_state(fastd_peer_t *peer); -void fastd_protocol_ec25519_fhmqvc_handshake_init(const 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_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); +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); 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 c4177b4..237732d 100644 --- a/src/protocols/ec25519_fhmqvc/handshake.c +++ b/src/protocols/ec25519_fhmqvc/handshake.c @@ -27,6 +27,7 @@ #include "handshake.h" #include "../../handshake.h" #include "../../hkdf_sha256.h" +#include "../../verify.h" #define HASHBYTES FASTD_SHA256_HASH_BYTES @@ -268,9 +269,11 @@ static void clear_shared_handshake_key(const fastd_peer_t *peer) { } static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, - const handshake_key_t *handshake_key, const aligned_int256_t *peer_handshake_key, const fastd_method_info_t *method) { + const aligned_int256_t *peer_handshake_key, const fastd_method_info_t *method) { pr_debug("responding handshake with %P[%I]...", peer, remote_addr); + const handshake_key_t *handshake_key = &ctx.protocol_state->handshake_key; + if (!update_shared_handshake_key(peer, handshake_key, peer_handshake_key)) return; @@ -486,12 +489,18 @@ static inline bool allow_unknown(void) { return fastd_shell_command_isset(&conf.on_verify); } -static inline fastd_peer_t* add_temporary(const fastd_peer_address_t *addr, const unsigned char key[PUBLICKEYBYTES]) { +static fastd_peer_t * add_temporary(fastd_socket_t *sock, const fastd_peer_address_t *addr, const unsigned char key[PUBLICKEYBYTES]) { if (!allow_unknown()) { pr_debug("ignoring handshake from %I (unknown key)", addr); return NULL; } + if (sock->peer) { + /* WTF? */ + pr_debug("ignoring handshake from %I (received on another peer's socket)", addr); + return NULL; + } + if (key_count(key)) { pr_debug("ignoring handshake from %I (disabled key)", addr); return NULL; @@ -509,7 +518,7 @@ static inline fastd_peer_t* add_temporary(const fastd_peer_address_t *addr, cons } -void fastd_protocol_ec25519_fhmqvc_handshake_init(const 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_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 */); @@ -529,6 +538,34 @@ void fastd_protocol_ec25519_fhmqvc_handshake_init(const fastd_socket_t *sock, co 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)) + return !fastd_timed_out(&peer->verify_valid_timeout); + + verify_data_t verify_data; + memset(&verify_data, 0, sizeof(verify_data)); + memcpy(&verify_data.peer_handshake_key, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, PUBLICKEYBYTES); + + fastd_tristate_t verified = fastd_verify_peer(peer, sock, local_addr, remote_addr, method, &verify_data, sizeof(verify_data)); + + if (!verified.set) + /* async verify */ + return false; + + if (!verified.state) { + pr_debug("ignoring handshake from %P[%I] (verification failed)", peer, remote_addr); + fastd_peer_delete(peer); + return false; + } + + return true; +} + 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(); @@ -546,7 +583,7 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const return; case ENOENT: - peer = add_temporary(remote_addr, handshake->records[RECORD_SENDER_KEY].data); + peer = add_temporary(sock, remote_addr, handshake->records[RECORD_SENDER_KEY].data); if (peer) break; @@ -557,9 +594,8 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const } } - if (fastd_peer_is_temporary(peer) && !fastd_peer_verify_temporary(peer, local_addr, remote_addr)) { - pr_debug("ignoring handshake from %P[%I] (verification failed)", peer, remote_addr); - fastd_peer_delete(peer); + if (!has_field(handshake, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES)) { + pr_debug("received handshake without sender handshake key from %P[%I]", peer, remote_addr); return; } @@ -580,9 +616,9 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const } } - if (!has_field(handshake, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES)) { - pr_debug("received handshake without sender handshake key from %P[%I]", peer, remote_addr); - return; + if (fastd_peer_is_temporary(peer)) { + if (!handle_temporary(sock, local_addr, remote_addr, peer, handshake, method)) + return; } aligned_int256_t peer_handshake_key; @@ -599,7 +635,7 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const 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, &ctx.protocol_state->handshake_key, &peer_handshake_key, method); + respond_handshake(sock, local_addr, remote_addr, peer, &peer_handshake_key, method); return; } @@ -651,3 +687,15 @@ 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/types.h b/src/types.h index 8a80d19..4510be2 100644 --- a/src/types.h +++ b/src/types.h @@ -89,10 +89,6 @@ typedef enum fastd_loglevel { LL_DEBUG2, } fastd_loglevel_t; -typedef enum fastd_async_type { - ASYNC_TYPE_RESOLVE_RETURN, -} fastd_async_type_t; - typedef struct fastd_buffer fastd_buffer_t; @@ -134,8 +130,6 @@ typedef struct fastd_string_stack fastd_string_stack_t; typedef struct fastd_shell_command fastd_shell_command_t; typedef struct fastd_shell_env fastd_shell_env_t; -typedef struct fastd_async_resolve_return fastd_async_resolve_return_t; - typedef union fastd_block128 { uint8_t b[16]; diff --git a/src/verify.c b/src/verify.c new file mode 100644 index 0000000..fb592bd --- /dev/null +++ b/src/verify.c @@ -0,0 +1,111 @@ +/* + Copyright (c) 2012-2014, Matthias Schiffer <mschiffer@universe-factory.net> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "verify.h" +#include "async.h" +#include "shell.h" + +#include <pthread.h> + + +static bool do_verify(const fastd_shell_env_t *env) { + int ret; + if (!fastd_shell_command_exec_sync(&conf.on_verify, env, &ret)) + return false; + + if (WIFSIGNALED(ret)) { + pr_error("verify command exited with signal %i", WTERMSIG(ret)); + return false; + } + else if (WEXITSTATUS(ret)) { + pr_debug("verify command exited with status %i", WEXITSTATUS(ret)); + return false; + } + + return true; +} + +typedef struct verify_arg { + fastd_shell_env_t *env; + size_t ret_len; + fastd_async_verify_return_t ret; +} verify_arg_t; + +static void * do_verify_thread(void *p) { + verify_arg_t *arg = p; + + arg->ret.ok = do_verify(arg->env); + fastd_shell_env_free(arg->env); + + fastd_async_enqueue(ASYNC_TYPE_VERIFY_RETURN, &arg->ret, arg->ret_len); + + free(arg); + + return NULL; +} + +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) { + if (!fastd_shell_command_isset(&conf.on_verify)) + exit_bug("tried to verify peer without on-verify command"); + + fastd_peer_set_verifying(peer); + + fastd_shell_env_t *env = fastd_shell_env_alloc(); + fastd_peer_set_shell_env(env, peer, local_addr, remote_addr); + + if (conf.on_verify.sync) { + bool ret = do_verify(env); + fastd_shell_env_free(env); + fastd_peer_set_verified(peer, ret); + return (fastd_tristate_t){.set = true, .state = ret}; + } + else { + verify_arg_t *arg = calloc(1, sizeof(verify_arg_t) + data_len); + + arg->env = env; + arg->ret_len = sizeof(fastd_async_verify_return_t) + data_len; + + arg->ret.peer_id = peer->id; + arg->ret.method = method; + arg->ret.sock = sock; + arg->ret.local_addr = *local_addr; + arg->ret.remote_addr = *remote_addr; + memcpy(arg->ret.protocol_data, data, data_len); + + pthread_t thread; + if ((errno = pthread_create(&thread, NULL, do_verify_thread, arg)) != 0) { + pr_error_errno("unable to create verify thread"); + + fastd_shell_env_free(env); + free(arg); + + return (fastd_tristate_t){.set = true, .state = false}; + } + + pthread_detach(thread); + return (fastd_tristate_t){.set = false}; + } +} diff --git a/src/verify.h b/src/verify.h new file mode 100644 index 0000000..6f1b525 --- /dev/null +++ b/src/verify.h @@ -0,0 +1,33 @@ +/* + Copyright (c) 2012-2014, Matthias Schiffer <mschiffer@universe-factory.net> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#pragma once + + +#include "types.h" + + +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); |