summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.c11
-rw-r--r--src/config.l1
-rw-r--r--src/config.y11
-rw-r--r--src/fastd.c19
-rw-r--r--src/fastd.h4
-rw-r--r--src/peer.c68
-rw-r--r--src/peer.h16
-rw-r--r--src/protocol_ec25519_fhmqvc.c103
-rw-r--r--src/resolve.c3
9 files changed, 196 insertions, 40 deletions
diff --git a/src/config.c b/src/config.c
index c866b14..001cc2e 100644
--- a/src/config.c
+++ b/src/config.c
@@ -549,6 +549,7 @@ static void count_peers(fastd_context_t *ctx, fastd_config_t *conf) {
OPTION_ARG(option_on_down, "--on-down", "<command>", "Sets a shell command to execute before interface destruction") \
OPTION_ARG(option_on_establish, "--on-establish", "<command>", "Sets a shell command to execute when a new connection is established") \
OPTION_ARG(option_on_disestablish, "--on-disestablish", "<command>", "Sets a shell command to execute when a connection is lost") \
+ OPTION_ARG(option_on_verify, "--on-verify", "<command>", "Sets a shell command to execute to check an connection attempt by an unknown peer") \
OPTION(option_generate_key, "--generate-key", "Generates a new keypair") \
OPTION(option_show_key, "--show-key", "Shows the public key corresponding to the configured secret") \
OPTION(option_machine_readable, "--machine-readable", "Suppresses output of explaining text in the --show-key and --generate-key commands")
@@ -781,6 +782,14 @@ static void option_on_disestablish(fastd_context_t *ctx, fastd_config_t *conf, c
conf->on_disestablish_dir = get_current_dir_name();
}
+static void option_on_verify(fastd_context_t *ctx, fastd_config_t *conf, const char *arg) {
+ free(conf->on_verify);
+ free(conf->on_verify_dir);
+
+ conf->on_verify = strdup(arg);
+ conf->on_verify_dir = get_current_dir_name();
+}
+
static void option_daemon(fastd_context_t *ctx, fastd_config_t *conf) {
conf->daemon = true;
}
@@ -1062,6 +1071,8 @@ void fastd_config_release(fastd_context_t *ctx, fastd_config_t *conf) {
free(conf->on_establish_dir);
free(conf->on_disestablish);
free(conf->on_disestablish_dir);
+ free(conf->on_verify);
+ free(conf->on_verify_dir);
free(conf->protocol_config);
free(conf->log_syslog_ident);
}
diff --git a/src/config.l b/src/config.l
index b4e77a0..1ff90c8 100644
--- a/src/config.l
+++ b/src/config.l
@@ -79,6 +79,7 @@ up { TOKEN(TOK_UP); }
down { TOKEN(TOK_DOWN); }
establish { TOKEN(TOK_ESTABLISH); }
disestablish { TOKEN(TOK_DISESTABLISH); }
+verify { TOKEN(TOK_VERIFY); }
peers { TOKEN(TOK_PEERS); }
from { TOKEN(TOK_FROM); }
log { TOKEN(TOK_LOG); }
diff --git a/src/config.y b/src/config.y
index 228ba01..8db6efe 100644
--- a/src/config.y
+++ b/src/config.y
@@ -79,6 +79,7 @@
%token TOK_DOWN
%token TOK_ESTABLISH
%token TOK_DISESTABLISH
+%token TOK_VERIFY
%token TOK_PEERS
%token TOK_FROM
%token TOK_LOG
@@ -167,6 +168,7 @@ statement: peer_group_statement
| TOK_ON TOK_DOWN on_down ';'
| TOK_ON TOK_ESTABLISH on_establish ';'
| TOK_ON TOK_DISESTABLISH on_disestablish ';'
+ | TOK_ON TOK_VERIFY on_verify ';'
| TOK_FORWARD forward ';'
;
@@ -356,6 +358,15 @@ on_disestablish: TOK_STRING {
}
;
+on_verify: TOK_STRING {
+ free(conf->on_verify);
+ free(conf->on_verify_dir);
+
+ conf->on_verify = strdup($1->str);
+ conf->on_verify_dir = get_current_dir_name();
+ }
+ ;
+
peer: TOK_STRING {
fastd_peer_config_new(ctx, conf);
conf->peers->name = strdup($1->str);
diff --git a/src/fastd.c b/src/fastd.c
index ce297f7..89125a9 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -975,14 +975,27 @@ static void cleanup_peers(fastd_context_t *ctx) {
for (peer = ctx->peers; peer; peer = next) {
next = peer->next;
- if (fastd_peer_is_established(peer)) {
- if (timespec_diff(&ctx->now, &peer->seen) > ctx->conf->peer_stale_time*1000)
- fastd_peer_reset(ctx, peer);
+ if (fastd_peer_is_temporary(peer) || fastd_peer_is_established(peer)) {
+ if (timespec_diff(&ctx->now, &peer->seen) > ctx->conf->peer_stale_time*1000) {
+ if (fastd_peer_is_temporary(peer)) {
+ fastd_peer_delete(ctx, peer);
+ }
+ else {
+ fastd_peer_reset(ctx, peer);
+ }
+ }
}
}
}
static void maintenance(fastd_context_t *ctx) {
+ while (ctx->peers_temp) {
+ fastd_peer_t *peer = ctx->peers_temp;
+ ctx->peers_temp = ctx->peers_temp->next;
+
+ fastd_peer_enable_temporary(ctx, peer);
+ }
+
cleanup_peers(ctx);
fastd_peer_eth_addr_cleanup(ctx);
diff --git a/src/fastd.h b/src/fastd.h
index ac27905..3ee445f 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -242,6 +242,9 @@ struct fastd_config {
char *on_disestablish;
char *on_disestablish_dir;
+ char *on_verify;
+ char *on_verify_dir;
+
bool daemon;
char *pid_file;
@@ -262,6 +265,7 @@ struct fastd_context {
unsigned n_peers;
fastd_peer_group_t *peer_group;
fastd_peer_t *peers;
+ fastd_peer_t *peers_temp;
fastd_queue_t task_queue;
int resolverfd;
diff --git a/src/peer.c b/src/peer.c
index 3eeb261..7921b7e 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -151,7 +151,7 @@ static void reset_peer(fastd_context_t *ctx, fastd_peer_t *peer) {
}
static void setup_peer(fastd_context_t *ctx, fastd_peer_t *peer) {
- if (peer->config->hostname)
+ if (!peer->config || peer->config->hostname)
peer->address.sa.sa_family = AF_UNSPEC;
else
peer->address = peer->config->address;
@@ -187,13 +187,25 @@ static void delete_peer(fastd_context_t *ctx, fastd_peer_t *peer) {
for (cur_peer = &ctx->peers; *cur_peer; cur_peer = &(*cur_peer)->next) {
if ((*cur_peer) == peer) {
*cur_peer = peer->next;
+ ctx->n_peers--;
break;
}
}
+ if (!*cur_peer) {
+ for (cur_peer = &ctx->peers_temp; *cur_peer; cur_peer = &(*cur_peer)->next) {
+ if ((*cur_peer) == peer) {
+ *cur_peer = peer->next;
+ break;
+ }
+ }
+ }
ctx->conf->protocol->free_peer_state(ctx, peer);
+
+ if (!peer->config)
+ free(peer->protocol_config);
+
free(peer);
- ctx->n_peers--;
}
@@ -387,6 +399,7 @@ fastd_peer_t* fastd_peer_add(fastd_context_t *ctx, fastd_peer_config_t *peer_con
peer->config = peer_conf;
peer->group = find_peer_group(ctx->peer_group, peer_conf->group);
+ peer->protocol_config = peer_conf->protocol_config;
peer->protocol_state = NULL;
peer->sock = NULL;
setup_peer(ctx, peer);
@@ -397,6 +410,57 @@ fastd_peer_t* fastd_peer_add(fastd_context_t *ctx, fastd_peer_config_t *peer_con
return peer;
}
+fastd_peer_t* fastd_peer_add_temporary(fastd_context_t *ctx, fastd_socket_t *sock, const fastd_peer_address_t *addr) {
+ if (!ctx->conf->on_verify)
+ exit_bug(ctx, "tried to add temporary peer without on-verify command");
+
+ fastd_peer_t *peer = malloc(sizeof(fastd_peer_t));
+
+ peer->next = ctx->peers_temp;
+ ctx->peers_temp = peer;
+
+ peer->config = NULL;
+ peer->group = ctx->peer_group;
+ peer->protocol_state = NULL;
+ peer->sock = sock;
+ setup_peer(ctx, peer);
+
+ peer->address = *addr;
+
+ pr_debug(ctx, "adding temporary peer for %I", addr);
+
+ return peer;
+}
+
+bool fastd_peer_verify_temporary(fastd_context_t *ctx, fastd_peer_t *peer) {
+ if (!ctx->conf->on_verify)
+ exit_bug(ctx, "tried to verify temporary peer without on-verify command");
+
+ int ret;
+ if (!fastd_shell_exec(ctx, peer, ctx->conf->on_verify, ctx->conf->on_verify_dir, &ret))
+ return false;
+
+ if (WIFSIGNALED(ret)) {
+ pr_error(ctx, "verify command exited with signal %i", WTERMSIG(ret));
+ return false;
+ }
+ else if (WEXITSTATUS(ret)) {
+ pr_debug(ctx, "verify command exited with status %i", WEXITSTATUS(ret));
+ return false;
+ }
+
+ return true;
+}
+
+void fastd_peer_enable_temporary(fastd_context_t *ctx, fastd_peer_t *peer) {
+ if (peer->config)
+ exit_bug(ctx, "trying to re-enable non-temporary peer");
+
+ peer->next = ctx->peers;
+ ctx->peers = peer;
+ ctx->n_peers++;
+}
+
void fastd_peer_set_established(fastd_context_t *ctx, fastd_peer_t *peer) {
if (!peer->established) {
peer->established = true;
diff --git a/src/peer.h b/src/peer.h
index 3be2d49..eb72435 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -51,6 +51,7 @@ struct fastd_peer {
struct timespec last_handshake_response;
fastd_peer_address_t last_handshake_response_address;
+ fastd_protocol_peer_config_t *protocol_config;
fastd_protocol_peer_state_t *protocol_state;
};
@@ -90,6 +91,9 @@ bool fastd_peer_config_equal(const fastd_peer_config_t *peer1, const fastd_peer_
void fastd_peer_reset(fastd_context_t *ctx, fastd_peer_t *peer);
void fastd_peer_delete(fastd_context_t *ctx, fastd_peer_t *peer);
fastd_peer_t* fastd_peer_add(fastd_context_t *ctx, fastd_peer_config_t *conf);
+fastd_peer_t* fastd_peer_add_temporary(fastd_context_t *ctx, fastd_socket_t *sock, const fastd_peer_address_t *addr);
+bool fastd_peer_verify_temporary(fastd_context_t *ctx, fastd_peer_t *peer);
+void fastd_peer_enable_temporary(fastd_context_t *ctx, fastd_peer_t *peer);
void fastd_peer_set_established(fastd_context_t *ctx, fastd_peer_t *peer);
bool fastd_peer_may_connect(fastd_context_t *ctx, fastd_peer_t *peer);
bool fastd_peer_claim_address(fastd_context_t *ctx, fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *addr);
@@ -98,6 +102,10 @@ void fastd_peer_reset_socket(fastd_context_t *ctx, fastd_peer_t *peer);
const fastd_eth_addr_t* fastd_get_source_address(const fastd_context_t *ctx, fastd_buffer_t buffer);
const fastd_eth_addr_t* fastd_get_dest_address(const fastd_context_t *ctx, fastd_buffer_t buffer);
+static inline bool fastd_peer_allow_unknown(fastd_context_t *ctx) {
+ return ctx->conf->on_verify;
+}
+
static inline bool fastd_peer_config_is_floating(const fastd_peer_config_t *config) {
return ((config->hostname == NULL && config->address.sa.sa_family == AF_UNSPEC) || config->dynamic_float);
}
@@ -109,11 +117,15 @@ static inline bool fastd_peer_config_is_dynamic(const fastd_peer_config_t *confi
bool fastd_peer_config_matches_dynamic(const fastd_peer_config_t *config, const fastd_peer_address_t *addr);
static inline bool fastd_peer_is_floating(const fastd_peer_t *peer) {
- return fastd_peer_config_is_floating(peer->config);
+ return peer->config ? fastd_peer_config_is_floating(peer->config) : true;
}
static inline bool fastd_peer_is_dynamic(const fastd_peer_t *peer) {
- return fastd_peer_config_is_dynamic(peer->config);
+ return peer->config ? fastd_peer_config_is_dynamic(peer->config) : false;
+}
+
+static inline bool fastd_peer_is_temporary(const fastd_peer_t *peer) {
+ return (!peer->config);
}
static inline bool fastd_peer_is_established(const fastd_peer_t *peer) {
diff --git a/src/protocol_ec25519_fhmqvc.c b/src/protocol_ec25519_fhmqvc.c
index d0b6861..4b0e997 100644
--- a/src/protocol_ec25519_fhmqvc.c
+++ b/src/protocol_ec25519_fhmqvc.c
@@ -222,7 +222,7 @@ static void protocol_handshake_init(fastd_context_t *ctx, const fastd_socket_t *
fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p);
if (peer)
- fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->config->protocol_config->public_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->protocol_config->public_key.p);
else
pr_debug(ctx, "sending handshake to unknown peer %I", address);
@@ -242,7 +242,7 @@ static void respond_handshake(fastd_context_t *ctx, const fastd_socket_t *sock,
memcpy(hashinput, handshake_key->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES);
memcpy(hashinput+2*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+3*PUBLICKEYBYTES, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+3*PUBLICKEYBYTES, peer->protocol_config->public_key.p, PUBLICKEYBYTES);
crypto_hash_sha256(hashbuf, hashinput, 4*PUBLICKEYBYTES);
@@ -265,7 +265,7 @@ static void respond_handshake(fastd_context_t *ctx, const fastd_socket_t *sock,
if (!ecc_25519_is_identity(&work))
return;
- if (!ecc_25519_load_packed(&work, &peer->config->protocol_config->public_key))
+ if (!ecc_25519_load_packed(&work, &peer->protocol_config->public_key))
return;
ecc_25519_scalarmult(&work, &d, &work);
@@ -290,7 +290,7 @@ static void respond_handshake(fastd_context_t *ctx, const fastd_socket_t *sock,
fastd_buffer_t buffer = fastd_handshake_new_reply(ctx, handshake, method, 4*(4+PUBLICKEYBYTES) + 4+HMACBYTES);
fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p);
- fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->config->protocol_config->public_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->protocol_config->public_key.p);
fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, handshake_key->public_key.p);
fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key->p);
fastd_handshake_add(ctx, &buffer, RECORD_T, HMACBYTES, hmacbuf);
@@ -365,7 +365,7 @@ static void finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const f
memcpy(hashinput, peer_handshake_key->p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, handshake_key->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+2*PUBLICKEYBYTES, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+2*PUBLICKEYBYTES, peer->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+3*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
crypto_hash_sha256(hashbuf, hashinput, 4*PUBLICKEYBYTES);
@@ -389,7 +389,7 @@ static void finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const f
if (!ecc_25519_is_identity(&work))
return;
- if (!ecc_25519_load_packed(&work, &peer->config->protocol_config->public_key))
+ if (!ecc_25519_load_packed(&work, &peer->protocol_config->public_key))
return;
ecc_25519_scalarmult(&work, &e, &work);
@@ -406,7 +406,7 @@ static void finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const f
memcpy(hashinput+4*PUBLICKEYBYTES, sigma.p, PUBLICKEYBYTES);
crypto_hash_sha256(shared_handshake_key, hashinput, 5*PUBLICKEYBYTES);
- memcpy(hashinput, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput, peer->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES);
if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key) != 0) {
@@ -419,13 +419,13 @@ static void finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const f
crypto_auth_hmacsha256(hmacbuf, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key);
if (!establish(ctx, peer, method, sock, address, true, &handshake_key->public_key, peer_handshake_key, &ctx->conf->protocol_config->public_key,
- &peer->config->protocol_config->public_key, &sigma, handshake_key->serial))
+ &peer->protocol_config->public_key, &sigma, handshake_key->serial))
return;
fastd_buffer_t buffer = fastd_handshake_new_reply(ctx, handshake, method, 4*(4+PUBLICKEYBYTES) + 4+HMACBYTES);
fastd_handshake_add(ctx, &buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p);
- fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->config->protocol_config->public_key.p);
+ fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, peer->protocol_config->public_key.p);
fastd_handshake_add(ctx, &buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, handshake_key->public_key.p);
fastd_handshake_add(ctx, &buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key->p);
fastd_handshake_add(ctx, &buffer, RECORD_T, HMACBYTES, hmacbuf);
@@ -443,7 +443,7 @@ static void handle_finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock,
memcpy(hashinput, handshake_key->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES);
memcpy(hashinput+2*PUBLICKEYBYTES, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES);
- memcpy(hashinput+3*PUBLICKEYBYTES, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput+3*PUBLICKEYBYTES, peer->protocol_config->public_key.p, PUBLICKEYBYTES);
crypto_hash_sha256(hashbuf, hashinput, 4*PUBLICKEYBYTES);
@@ -466,7 +466,7 @@ static void handle_finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock,
if (!ecc_25519_is_identity(&work))
return;
- if (!ecc_25519_load_packed(&work, &peer->config->protocol_config->public_key))
+ if (!ecc_25519_load_packed(&work, &peer->protocol_config->public_key))
return;
ecc_25519_scalarmult(&work, &d, &work);
@@ -483,7 +483,7 @@ static void handle_finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock,
memcpy(hashinput+4*PUBLICKEYBYTES, sigma.p, PUBLICKEYBYTES);
crypto_hash_sha256(shared_handshake_key, hashinput, 5*PUBLICKEYBYTES);
- memcpy(hashinput, peer->config->protocol_config->public_key.p, PUBLICKEYBYTES);
+ memcpy(hashinput, peer->protocol_config->public_key.p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES);
if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key) != 0) {
@@ -491,10 +491,33 @@ static void handle_finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock,
return;
}
- establish(ctx, peer, method, sock, address, false, peer_handshake_key, &handshake_key->public_key, &peer->config->protocol_config->public_key,
+ establish(ctx, peer, method, sock, address, false, peer_handshake_key, &handshake_key->public_key, &peer->protocol_config->public_key,
&ctx->conf->protocol_config->public_key, &sigma, handshake_key->serial);
}
+static fastd_peer_t* find_sender_key(fastd_context_t *ctx, const fastd_peer_address_t *address, const unsigned char key[32], fastd_peer_t *peers) {
+ fastd_peer_t *peer;
+ for (peer = peers; peer; peer = peer->next) {
+ if (memcmp(peer->protocol_config->public_key.p, key, PUBLICKEYBYTES) != 0)
+ continue;
+
+ if (peer->config && fastd_peer_config_matches_dynamic(peer->config, address)) {
+ fastd_resolve_peer(ctx, peer);
+ errno = EAGAIN;
+ return NULL;
+ }
+
+ if (fastd_peer_is_floating(peer))
+ return peer;
+
+ errno = EPERM;
+ return NULL;
+ }
+
+ errno = ENOENT;
+ return NULL;
+}
+
static fastd_peer_t* match_sender_key(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *address, fastd_peer_t *peer, const unsigned char key[32]) {
errno = 0;
@@ -510,7 +533,7 @@ static fastd_peer_t* match_sender_key(fastd_context_t *ctx, const fastd_socket_t
}
if (peer) {
- if (memcmp(peer->config->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0) {
+ if (memcmp(peer->protocol_config->public_key.p, key, PUBLICKEYBYTES) == 0) {
if (sock->peer && sock->peer != peer) {
errno = EPERM;
return NULL;
@@ -525,31 +548,42 @@ static fastd_peer_t* match_sender_key(fastd_context_t *ctx, const fastd_socket_t
return NULL;
}
- for (peer = ctx->peers; peer; peer = peer->next) {
- if (memcmp(peer->config->protocol_config->public_key.p, key, PUBLICKEYBYTES) != 0)
- continue;
+ peer = find_sender_key(ctx, address, key, ctx->peers);
- if (fastd_peer_config_matches_dynamic(peer->config, address)) {
- fastd_resolve_peer(ctx, peer);
- errno = EAGAIN;
- return NULL;
- }
-
- if (fastd_peer_is_floating(peer))
- return peer;
-
- errno = EPERM;
- return NULL;
+ if (!peer && errno == ENOENT) {
+ errno = 0;
+ peer = find_sender_key(ctx, address, key, ctx->peers_temp);
}
- errno = ENOENT;
- return NULL;
+ return peer;
}
static inline bool has_field(const fastd_handshake_t *handshake, uint8_t type, size_t length) {
return (handshake->records[type].length == length);
}
+static inline fastd_peer_t* add_temporary(fastd_context_t *ctx, fastd_socket_t *sock, const fastd_peer_address_t *address, const unsigned char key[32]) {
+ if (!fastd_peer_allow_unknown(ctx)) {
+ pr_debug(ctx, "ignoring handshake from %I (unknown key)", address);
+ return NULL;
+ }
+
+ fastd_peer_t *peer = fastd_peer_add_temporary(ctx, sock, address);
+
+ peer->protocol_config = malloc(sizeof(fastd_protocol_peer_config_t));
+ memcpy(peer->protocol_config->public_key.p, key, PUBLICKEYBYTES);
+
+ /* Ugly hack */
+ peer->protocol_state->last_serial--;
+
+ if (!fastd_peer_verify_temporary(ctx, peer)) {
+ fastd_peer_delete(ctx, peer);
+ return NULL;
+ }
+
+ return peer;
+}
+
static void protocol_handshake_handle(fastd_context_t *ctx, fastd_socket_t *sock, const fastd_peer_address_t *address, fastd_peer_t *peer, const fastd_handshake_t *handshake, const fastd_method_t *method) {
handshake_key_t *handshake_key;
char *peer_version_name = NULL;
@@ -573,7 +607,10 @@ static void protocol_handshake_handle(fastd_context_t *ctx, fastd_socket_t *sock
return;
case ENOENT:
- pr_debug(ctx, "ignoring handshake from %I (unknown key)", address);
+ peer = add_temporary(ctx, sock, address, handshake->records[RECORD_SENDER_KEY].data);
+ if (peer)
+ break;
+
return;
default:
@@ -855,8 +892,8 @@ static void protocol_set_shell_env(fastd_context_t *ctx, const fastd_peer_t *pee
hexdump(buf, ctx->conf->protocol_config->public_key.p);
setenv("LOCAL_KEY", buf, 1);
- if (peer && peer->config && peer->config->protocol_config) {
- hexdump(buf, peer->config->protocol_config->public_key.p);
+ if (peer && peer->protocol_config) {
+ hexdump(buf, peer->protocol_config->public_key.p);
setenv("PEER_KEY", buf, 1);
}
else {
diff --git a/src/resolve.c b/src/resolve.c
index c01a88f..3b15f57 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -101,6 +101,9 @@ static void* resolve_peer(void *varg) {
}
void fastd_resolve_peer(fastd_context_t *ctx, fastd_peer_t *peer) {
+ if (!peer->config)
+ exit_bug(ctx, "trying to resolve temporary peer");
+
if (timespec_after(&peer->last_resolve, &peer->last_resolve_return)) {
pr_debug(ctx, "not resolving %P as there is already a resolve running", peer);
return;