2 protocol_key.c -- handle the meta-protocol, key exchange
3 Copyright (C) 1999-2005 Ivo Timmermans,
4 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "connection.h"
34 #include "compression.h"
38 void send_key_changed(void) {
39 #ifndef DISABLE_LEGACY
40 send_request(everyone, "%d %x %s", KEY_CHANGED, prng(UINT32_MAX), myself->name);
42 /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
44 for list_each(connection_t, c, &connection_list) {
45 if(c->edge && c->node && c->node->status.reachable && !c->node->status.sptps) {
46 send_ans_key(c->node);
52 /* Force key exchange for connections using SPTPS */
55 for splay_each(node_t, n, &node_tree) {
56 if(n->status.reachable && n->status.validkey && n->status.sptps) {
57 sptps_force_kex(&n->sptps);
63 bool key_changed_h(connection_t *c, const char *request) {
64 char name[MAX_STRING_SIZE];
67 if(sscanf(request, "%*d %*x " MAX_STRING, name) != 1) {
68 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED",
69 c->name, c->hostname);
73 if(seen_request(request)) {
77 n = lookup_node(name);
80 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
81 "KEY_CHANGED", c->name, c->hostname, name);
85 if(!n->status.sptps) {
86 n->status.validkey = false;
93 forward_request(c, request);
99 static bool send_sptps_data_myself(void *handle, uint8_t type, const void *data, size_t len) {
100 return send_sptps_data(handle, myself, type, data, len);
103 static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
106 to->sptps.send_data = send_sptps_data_myself;
108 char *buf = alloca(B64_SIZE(len));
109 b64encode_tinc(data, buf, len);
111 return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
114 bool send_req_key(node_t *to) {
115 if(to->status.sptps) {
116 if(!node_read_ecdsa_public_key(to)) {
117 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", to->name, to->hostname);
118 send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY);
122 const size_t labellen = 25 + strlen(myself->name) + strlen(to->name);
123 char *label = alloca(labellen);
124 snprintf(label, labellen, "tinc UDP key expansion %s %s", myself->name, to->name);
126 sptps_stop(&to->sptps);
127 to->status.validkey = false;
128 to->status.waitingforkey = true;
129 to->last_req_key = now.tv_sec;
130 to->incompression = myself->incompression;
131 return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, labellen, send_initial_sptps_data, receive_sptps_record);
134 return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
137 /* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
139 static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
142 /* If this is a SPTPS packet, see if sending UDP info helps.
143 Note that we only do this if we're the destination or the static relay;
144 otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
145 if((reqno == REQ_KEY || reqno == SPTPS_PACKET) && to->via == myself) {
146 send_udp_info(myself, from);
149 if(reqno == SPTPS_PACKET) {
150 /* This is a SPTPS data packet. */
152 char buf[MAX_STRING_SIZE];
155 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode_tinc(buf, buf, strlen(buf)))) {
156 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s) to %s (%s): %s", "SPTPS_PACKET", from->name, from->hostname, to->name, to->hostname, "invalid SPTPS data");
161 /* We don't just forward the request, because we want to use UDP if it's available. */
162 if(forwarding_mode == FMODE_INTERNAL) {
163 send_sptps_data(to, from, 0, buf, len);
167 /* The packet is for us */
168 if(!sptps_receive_data(&from->sptps, buf, len)) {
169 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
170 so let's restart SPTPS in case that helps. But don't do that too often
171 to prevent storms. */
172 if(from->last_req_key < now.tv_sec - 10) {
173 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
180 send_mtu_info(myself, from, MTU);
186 /* Requests that are not SPTPS data packets are forwarded as-is. */
189 return send_request(to->nexthop->connection, "%s", request);
192 /* The request is for us */
196 if(!node_read_ecdsa_public_key(from)) {
197 /* Request their key *before* we send our key back. Otherwise the first SPTPS packet from them will get dropped. */
198 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Preemptively requesting Ed25519 key for %s (%s)", from->name, from->hostname);
199 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
202 char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
203 send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey);
209 if(node_read_ecdsa_public_key(from)) {
210 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname);
214 char pubkey[MAX_STRING_SIZE];
216 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) {
217 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey");
221 logger(DEBUG_PROTOCOL, LOG_INFO, "Learned Ed25519 public key from %s (%s)", from->name, from->hostname);
222 append_config_file(from->name, "Ed25519PublicKey", pubkey);
227 if(!node_read_ecdsa_public_key(from)) {
228 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", from->name, from->hostname);
229 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
233 if(from->sptps.label) {
234 logger(DEBUG_ALWAYS, LOG_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name);
237 char buf[MAX_STRING_SIZE];
240 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode_tinc(buf, buf, strlen(buf)))) {
241 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data");
245 const size_t labellen = 25 + strlen(from->name) + strlen(myself->name);
246 char *label = alloca(labellen);
247 snprintf(label, labellen, "tinc UDP key expansion %s %s", from->name, myself->name);
248 sptps_stop(&from->sptps);
249 from->status.validkey = false;
250 from->status.waitingforkey = true;
251 from->last_req_key = now.tv_sec;
252 sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, labellen, send_sptps_data_myself, receive_sptps_record);
253 sptps_receive_data(&from->sptps, buf, len);
254 send_mtu_info(myself, from, MTU);
259 logger(DEBUG_ALWAYS, LOG_ERR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request);
264 bool req_key_h(connection_t *c, const char *request) {
265 char from_name[MAX_STRING_SIZE];
266 char to_name[MAX_STRING_SIZE];
270 if(sscanf(request, "%*d " MAX_STRING " " MAX_STRING " %d", from_name, to_name, &reqno) < 2) {
271 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name,
276 if(!check_id(from_name) || !check_id(to_name)) {
277 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name");
281 from = lookup_node(from_name);
284 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
285 "REQ_KEY", c->name, c->hostname, from_name);
289 to = lookup_node(to_name);
292 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
293 "REQ_KEY", c->name, c->hostname, to_name);
297 /* Check if this key request is for us */
299 if(to == myself) { /* Yes */
300 if(!from->status.reachable) {
301 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which is not reachable",
302 "REQ_KEY", c->name, c->hostname, from_name);
306 /* Is this an extended REQ_KEY message? */
307 if(experimental && reqno) {
308 return req_key_ext_h(c, request, from, to, reqno);
311 /* No, just send our key back */
318 if(!to->status.reachable) {
319 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
320 "REQ_KEY", c->name, c->hostname, to_name);
324 /* Is this an extended REQ_KEY message? */
325 if(experimental && reqno) {
326 return req_key_ext_h(c, request, from, to, reqno);
329 send_request(to->nexthop->connection, "%s", request);
335 bool send_ans_key(node_t *to) {
336 if(to->status.sptps) {
340 #ifdef DISABLE_LEGACY
343 size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
344 char *key = alloca(keylen * 2 + 1);
346 randomize(key, keylen);
348 cipher_free(&to->incipher);
349 digest_free(&to->indigest);
351 if(myself->incipher) {
352 to->incipher = cipher_alloc();
354 if(!cipher_open_by_nid(to->incipher, cipher_get_nid(myself->incipher))) {
358 if(!cipher_set_key(to->incipher, key, false)) {
363 if(myself->indigest) {
364 to->indigest = digest_alloc();
366 if(!digest_open_by_nid(to->indigest,
367 digest_get_nid(myself->indigest),
368 digest_length(myself->indigest))) {
372 if(!digest_set_key(to->indigest, key, keylen)) {
377 to->incompression = myself->incompression;
379 bin2hex(key, key, keylen);
381 // Reset sequence number and late packet window
382 to->received_seqno = 0;
386 memset(to->late, 0, replaywin);
389 to->status.validkey_in = true;
391 return send_request(to->nexthop->connection, "%d %s %s %s %d %d %lu %d", ANS_KEY,
392 myself->name, to->name, key,
393 cipher_get_nid(to->incipher),
394 digest_get_nid(to->indigest),
395 (unsigned long)digest_length(to->indigest),
400 bool ans_key_h(connection_t *c, const char *request) {
401 char from_name[MAX_STRING_SIZE];
402 char to_name[MAX_STRING_SIZE];
403 char key[MAX_STRING_SIZE];
404 char address[MAX_STRING_SIZE] = "";
405 char port[MAX_STRING_SIZE] = "";
407 unsigned long maclength;
411 if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %lu %d "MAX_STRING" "MAX_STRING,
412 from_name, to_name, key, &cipher, &digest, &maclength,
413 &compression, address, port) < 7) {
414 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
419 if(!check_id(from_name) || !check_id(to_name)) {
420 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
424 from = lookup_node(from_name);
427 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
428 "ANS_KEY", c->name, c->hostname, from_name);
432 to = lookup_node(to_name);
435 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
436 "ANS_KEY", c->name, c->hostname, to_name);
440 /* Forward it if necessary */
447 if(!to->status.reachable) {
448 logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
449 "ANS_KEY", c->name, c->hostname, to_name);
453 if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
454 char *address, *port;
455 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
456 sockaddr2str(&from->address, &address, &port);
457 send_request(to->nexthop->connection, "%s %s %s", request, address, port);
463 return send_request(to->nexthop->connection, "%s", request);
466 #ifndef DISABLE_LEGACY
467 /* Don't use key material until every check has passed. */
468 cipher_free(&from->outcipher);
469 digest_free(&from->outdigest);
472 if(!from->status.sptps) {
473 from->status.validkey = false;
476 switch(compression) {
481 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
482 logger(DEBUG_ALWAYS, LOG_ERR, "LZ4 compression is unavailable on this node.");
486 case COMPRESS_LZO_HI:
487 case COMPRESS_LZO_LO:
491 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
492 logger(DEBUG_ALWAYS, LOG_ERR, "LZO compression is unavailable on this node.");
496 case COMPRESS_ZLIB_9:
497 case COMPRESS_ZLIB_8:
498 case COMPRESS_ZLIB_7:
499 case COMPRESS_ZLIB_6:
500 case COMPRESS_ZLIB_5:
501 case COMPRESS_ZLIB_4:
502 case COMPRESS_ZLIB_3:
503 case COMPRESS_ZLIB_2:
504 case COMPRESS_ZLIB_1:
508 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
509 logger(DEBUG_ALWAYS, LOG_ERR, "ZLIB compression is unavailable on this node.");
517 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
518 logger(DEBUG_ALWAYS, LOG_ERR, "Compression level %i is unrecognized by this node.", compression);
522 from->outcompression = compression;
524 /* SPTPS or old-style key exchange? */
526 if(from->status.sptps) {
527 const size_t buflen = strlen(key);
528 uint8_t *buf = alloca(buflen);
529 size_t len = b64decode_tinc(key, buf, buflen);
531 if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
532 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
533 so let's restart SPTPS in case that helps. But don't do that too often
535 Note that simply relying on handshake timeout is not enough, because
536 that doesn't apply to key regeneration. */
537 if(from->last_req_key < now.tv_sec - 10) {
538 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
545 if(from->status.validkey) {
546 if(*address && *port) {
547 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
548 sockaddr_t sa = str2sockaddr(address, port);
549 update_node_udp(from, &sa);
553 send_mtu_info(myself, from, MTU);
558 #ifdef DISABLE_LEGACY
559 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
562 /* Check and lookup cipher and digest algorithms */
565 from->outcipher = cipher_alloc();
567 if(!cipher_open_by_nid(from->outcipher, cipher)) {
568 cipher_free(&from->outcipher);
569 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
573 from->outcipher = NULL;
577 from->outdigest = digest_alloc();
579 if(!digest_open_by_nid(from->outdigest, digest, maclength)) {
580 digest_free(&from->outdigest);
581 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
585 from->outdigest = NULL;
588 if(maclength != digest_length(from->outdigest)) {
589 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
595 size_t keylen = hex2bin(key, key, sizeof(key));
597 if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
598 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
602 /* Update our copy of the origin's packet key */
604 if(from->outcipher && !cipher_set_key(from->outcipher, key, true)) {
608 if(from->outdigest && !digest_set_key(from->outdigest, key, keylen)) {
612 from->status.validkey = true;
613 from->sent_seqno = 0;
615 if(*address && *port) {
616 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
617 sockaddr_t sa = str2sockaddr(address, port);
618 update_node_udp(from, &sa);