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 size_t keyhexlen = HEX_SIZE(keylen);
345 char *key = alloca(keyhexlen);
347 randomize(key, keylen);
349 cipher_free(to->incipher);
352 digest_free(to->indigest);
355 if(myself->incipher) {
356 to->incipher = cipher_alloc();
358 if(!cipher_open_by_nid(to->incipher, cipher_get_nid(myself->incipher))) {
362 if(!cipher_set_key(to->incipher, key, false)) {
367 if(myself->indigest) {
368 to->indigest = digest_alloc();
370 if(!digest_open_by_nid(to->indigest,
371 digest_get_nid(myself->indigest),
372 digest_length(myself->indigest))) {
376 if(!digest_set_key(to->indigest, key, keylen)) {
381 to->incompression = myself->incompression;
383 bin2hex(key, key, keylen);
385 // Reset sequence number and late packet window
386 to->received_seqno = 0;
390 memset(to->late, 0, replaywin);
393 to->status.validkey_in = true;
395 bool sent = send_request(to->nexthop->connection, "%d %s %s %s %d %d %lu %d", ANS_KEY,
396 myself->name, to->name, key,
397 cipher_get_nid(to->incipher),
398 digest_get_nid(to->indigest),
399 (unsigned long)digest_length(to->indigest),
402 memzero(key, keyhexlen);
408 bool ans_key_h(connection_t *c, const char *request) {
409 char from_name[MAX_STRING_SIZE];
410 char to_name[MAX_STRING_SIZE];
411 char key[MAX_STRING_SIZE];
412 char address[MAX_STRING_SIZE] = "";
413 char port[MAX_STRING_SIZE] = "";
415 unsigned long maclength;
419 if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %lu %d "MAX_STRING" "MAX_STRING,
420 from_name, to_name, key, &cipher, &digest, &maclength,
421 &compression, address, port) < 7) {
422 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
427 if(!check_id(from_name) || !check_id(to_name)) {
428 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
432 from = lookup_node(from_name);
435 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
436 "ANS_KEY", c->name, c->hostname, from_name);
440 to = lookup_node(to_name);
443 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
444 "ANS_KEY", c->name, c->hostname, to_name);
448 /* Forward it if necessary */
455 if(!to->status.reachable) {
456 logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
457 "ANS_KEY", c->name, c->hostname, to_name);
461 if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
462 char *address, *port;
463 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
464 sockaddr2str(&from->address, &address, &port);
465 send_request(to->nexthop->connection, "%s %s %s", request, address, port);
471 return send_request(to->nexthop->connection, "%s", request);
474 #ifndef DISABLE_LEGACY
475 /* Don't use key material until every check has passed. */
476 cipher_free(from->outcipher);
477 from->outcipher = NULL;
479 digest_free(from->outdigest);
480 from->outdigest = NULL;
483 if(!from->status.sptps) {
484 from->status.validkey = false;
487 switch(compression) {
492 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
493 logger(DEBUG_ALWAYS, LOG_ERR, "LZ4 compression is unavailable on this node.");
497 case COMPRESS_LZO_HI:
498 case COMPRESS_LZO_LO:
502 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
503 logger(DEBUG_ALWAYS, LOG_ERR, "LZO compression is unavailable on this node.");
507 case COMPRESS_ZLIB_9:
508 case COMPRESS_ZLIB_8:
509 case COMPRESS_ZLIB_7:
510 case COMPRESS_ZLIB_6:
511 case COMPRESS_ZLIB_5:
512 case COMPRESS_ZLIB_4:
513 case COMPRESS_ZLIB_3:
514 case COMPRESS_ZLIB_2:
515 case COMPRESS_ZLIB_1:
519 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
520 logger(DEBUG_ALWAYS, LOG_ERR, "ZLIB compression is unavailable on this node.");
528 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
529 logger(DEBUG_ALWAYS, LOG_ERR, "Compression level %i is unrecognized by this node.", compression);
533 from->outcompression = compression;
535 /* SPTPS or old-style key exchange? */
537 if(from->status.sptps) {
538 const size_t buflen = strlen(key);
539 uint8_t *buf = alloca(buflen);
540 size_t len = b64decode_tinc(key, buf, buflen);
542 if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
543 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
544 so let's restart SPTPS in case that helps. But don't do that too often
546 Note that simply relying on handshake timeout is not enough, because
547 that doesn't apply to key regeneration. */
548 if(from->last_req_key < now.tv_sec - 10) {
549 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
556 if(from->status.validkey) {
557 if(*address && *port) {
558 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
559 sockaddr_t sa = str2sockaddr(address, port);
560 update_node_udp(from, &sa);
564 send_mtu_info(myself, from, MTU);
569 #ifdef DISABLE_LEGACY
570 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
573 /* Check and lookup cipher and digest algorithms */
576 from->outcipher = cipher_alloc();
578 if(!cipher_open_by_nid(from->outcipher, cipher)) {
579 cipher_free(from->outcipher);
580 from->outcipher = NULL;
581 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
585 from->outcipher = NULL;
589 from->outdigest = digest_alloc();
591 if(!digest_open_by_nid(from->outdigest, digest, maclength)) {
592 digest_free(from->outdigest);
593 from->outdigest = NULL;
594 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
598 from->outdigest = NULL;
601 if(maclength != digest_length(from->outdigest)) {
602 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
608 size_t keylen = hex2bin(key, key, sizeof(key));
610 if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
611 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
615 /* Update our copy of the origin's packet key */
617 if(from->outcipher && !cipher_set_key(from->outcipher, key, true)) {
621 if(from->outdigest && !digest_set_key(from->outdigest, key, keylen)) {
625 from->status.validkey = true;
626 from->sent_seqno = 0;
628 if(*address && *port) {
629 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
630 sockaddr_t sa = str2sockaddr(address, port);
631 update_node_udp(from, &sa);