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"
37 void send_key_changed(void) {
38 #ifndef DISABLE_LEGACY
39 send_request(everyone, "%d %x %s", KEY_CHANGED, prng(UINT32_MAX), myself->name);
41 /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
43 for list_each(connection_t, c, &connection_list) {
44 if(c->edge && c->node && c->node->status.reachable && !c->node->status.sptps) {
45 send_ans_key(c->node);
51 /* Force key exchange for connections using SPTPS */
54 for splay_each(node_t, n, &node_tree) {
55 if(n->status.reachable && n->status.validkey && n->status.sptps) {
56 sptps_force_kex(&n->sptps);
62 bool key_changed_h(connection_t *c, const char *request) {
63 char name[MAX_STRING_SIZE];
66 if(sscanf(request, "%*d %*x " MAX_STRING, name) != 1) {
67 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED",
68 c->name, c->hostname);
72 if(seen_request(request)) {
76 n = lookup_node(name);
79 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
80 "KEY_CHANGED", c->name, c->hostname, name);
84 if(!n->status.sptps) {
85 n->status.validkey = false;
92 forward_request(c, request);
98 static bool send_sptps_data_myself(void *handle, uint8_t type, const void *data, size_t len) {
99 return send_sptps_data(handle, myself, type, data, len);
102 static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
105 to->sptps.send_data = send_sptps_data_myself;
107 char *buf = alloca(B64_SIZE(len));
108 b64encode_tinc(data, buf, len);
110 return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
113 bool send_req_key(node_t *to) {
114 if(to->status.sptps) {
115 if(!node_read_ecdsa_public_key(to)) {
116 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", to->name, to->hostname);
117 send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY);
121 const size_t labellen = 25 + strlen(myself->name) + strlen(to->name);
122 char *label = alloca(labellen);
123 snprintf(label, labellen, "tinc UDP key expansion %s %s", myself->name, to->name);
125 sptps_stop(&to->sptps);
126 to->status.validkey = false;
127 to->status.waitingforkey = true;
128 to->last_req_key = now.tv_sec;
129 to->incompression = myself->incompression;
130 return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, labellen, send_initial_sptps_data, receive_sptps_record);
133 return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
136 /* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
138 static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
141 /* If this is a SPTPS packet, see if sending UDP info helps.
142 Note that we only do this if we're the destination or the static relay;
143 otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
144 if((reqno == REQ_KEY || reqno == SPTPS_PACKET) && to->via == myself) {
145 send_udp_info(myself, from);
148 if(reqno == SPTPS_PACKET) {
149 /* This is a SPTPS data packet. */
151 char buf[MAX_STRING_SIZE];
154 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode_tinc(buf, buf, strlen(buf)))) {
155 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");
160 /* We don't just forward the request, because we want to use UDP if it's available. */
161 if(forwarding_mode == FMODE_INTERNAL) {
162 send_sptps_data(to, from, 0, buf, len);
166 /* The packet is for us */
167 if(!sptps_receive_data(&from->sptps, buf, len)) {
168 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
169 so let's restart SPTPS in case that helps. But don't do that too often
170 to prevent storms. */
171 if(from->last_req_key < now.tv_sec - 10) {
172 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
179 send_mtu_info(myself, from, MTU);
185 /* Requests that are not SPTPS data packets are forwarded as-is. */
188 return send_request(to->nexthop->connection, "%s", request);
191 /* The request is for us */
195 if(!node_read_ecdsa_public_key(from)) {
196 /* Request their key *before* we send our key back. Otherwise the first SPTPS packet from them will get dropped. */
197 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Preemptively requesting Ed25519 key for %s (%s)", from->name, from->hostname);
198 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
201 char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
202 send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey);
208 if(node_read_ecdsa_public_key(from)) {
209 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname);
213 char pubkey[MAX_STRING_SIZE];
215 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) {
216 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey");
220 logger(DEBUG_PROTOCOL, LOG_INFO, "Learned Ed25519 public key from %s (%s)", from->name, from->hostname);
221 append_config_file(from->name, "Ed25519PublicKey", pubkey);
226 if(!node_read_ecdsa_public_key(from)) {
227 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", from->name, from->hostname);
228 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
232 if(from->sptps.label) {
233 logger(DEBUG_ALWAYS, LOG_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name);
236 char buf[MAX_STRING_SIZE];
239 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode_tinc(buf, buf, strlen(buf)))) {
240 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data");
244 const size_t labellen = 25 + strlen(from->name) + strlen(myself->name);
245 char *label = alloca(labellen);
246 snprintf(label, labellen, "tinc UDP key expansion %s %s", from->name, myself->name);
247 sptps_stop(&from->sptps);
248 from->status.validkey = false;
249 from->status.waitingforkey = true;
250 from->last_req_key = now.tv_sec;
251 sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, labellen, send_sptps_data_myself, receive_sptps_record);
252 sptps_receive_data(&from->sptps, buf, len);
253 send_mtu_info(myself, from, MTU);
258 logger(DEBUG_ALWAYS, LOG_ERR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request);
263 bool req_key_h(connection_t *c, const char *request) {
264 char from_name[MAX_STRING_SIZE];
265 char to_name[MAX_STRING_SIZE];
269 if(sscanf(request, "%*d " MAX_STRING " " MAX_STRING " %d", from_name, to_name, &reqno) < 2) {
270 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name,
275 if(!check_id(from_name) || !check_id(to_name)) {
276 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name");
280 from = lookup_node(from_name);
283 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
284 "REQ_KEY", c->name, c->hostname, from_name);
288 to = lookup_node(to_name);
291 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
292 "REQ_KEY", c->name, c->hostname, to_name);
296 /* Check if this key request is for us */
298 if(to == myself) { /* Yes */
299 if(!from->status.reachable) {
300 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which is not reachable",
301 "REQ_KEY", c->name, c->hostname, from_name);
305 /* Is this an extended REQ_KEY message? */
306 if(experimental && reqno) {
307 return req_key_ext_h(c, request, from, to, reqno);
310 /* No, just send our key back */
317 if(!to->status.reachable) {
318 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
319 "REQ_KEY", c->name, c->hostname, to_name);
323 /* Is this an extended REQ_KEY message? */
324 if(experimental && reqno) {
325 return req_key_ext_h(c, request, from, to, reqno);
328 send_request(to->nexthop->connection, "%s", request);
334 bool send_ans_key(node_t *to) {
335 if(to->status.sptps) {
339 #ifdef DISABLE_LEGACY
342 size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
343 char *key = alloca(keylen * 2 + 1);
345 randomize(key, keylen);
347 cipher_free(&to->incipher);
348 digest_free(&to->indigest);
350 if(myself->incipher) {
351 to->incipher = cipher_alloc();
353 if(!cipher_open_by_nid(to->incipher, cipher_get_nid(myself->incipher))) {
357 if(!cipher_set_key(to->incipher, key, false)) {
362 if(myself->indigest) {
363 to->indigest = digest_alloc();
365 if(!digest_open_by_nid(to->indigest,
366 digest_get_nid(myself->indigest),
367 digest_length(myself->indigest))) {
371 if(!digest_set_key(to->indigest, key, keylen)) {
376 to->incompression = myself->incompression;
378 bin2hex(key, key, keylen);
380 // Reset sequence number and late packet window
381 to->received_seqno = 0;
385 memset(to->late, 0, replaywin);
388 to->status.validkey_in = true;
390 return send_request(to->nexthop->connection, "%d %s %s %s %d %d %lu %d", ANS_KEY,
391 myself->name, to->name, key,
392 cipher_get_nid(to->incipher),
393 digest_get_nid(to->indigest),
394 (unsigned long)digest_length(to->indigest),
399 bool ans_key_h(connection_t *c, const char *request) {
400 char from_name[MAX_STRING_SIZE];
401 char to_name[MAX_STRING_SIZE];
402 char key[MAX_STRING_SIZE];
403 char address[MAX_STRING_SIZE] = "";
404 char port[MAX_STRING_SIZE] = "";
406 unsigned long maclength;
410 if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %lu %d "MAX_STRING" "MAX_STRING,
411 from_name, to_name, key, &cipher, &digest, &maclength,
412 &compression, address, port) < 7) {
413 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
418 if(!check_id(from_name) || !check_id(to_name)) {
419 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
423 from = lookup_node(from_name);
426 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
427 "ANS_KEY", c->name, c->hostname, from_name);
431 to = lookup_node(to_name);
434 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
435 "ANS_KEY", c->name, c->hostname, to_name);
439 /* Forward it if necessary */
446 if(!to->status.reachable) {
447 logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
448 "ANS_KEY", c->name, c->hostname, to_name);
452 if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
453 char *address, *port;
454 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
455 sockaddr2str(&from->address, &address, &port);
456 send_request(to->nexthop->connection, "%s %s %s", request, address, port);
462 return send_request(to->nexthop->connection, "%s", request);
465 #ifndef DISABLE_LEGACY
466 /* Don't use key material until every check has passed. */
467 cipher_free(&from->outcipher);
468 digest_free(&from->outdigest);
471 if(!from->status.sptps) {
472 from->status.validkey = false;
475 switch(compression) {
480 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
481 logger(DEBUG_ALWAYS, LOG_ERR, "LZ4 compression is unavailable on this node.");
485 case COMPRESS_LZO_HI:
486 case COMPRESS_LZO_LO:
490 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
491 logger(DEBUG_ALWAYS, LOG_ERR, "LZO compression is unavailable on this node.");
495 case COMPRESS_ZLIB_9:
496 case COMPRESS_ZLIB_8:
497 case COMPRESS_ZLIB_7:
498 case COMPRESS_ZLIB_6:
499 case COMPRESS_ZLIB_5:
500 case COMPRESS_ZLIB_4:
501 case COMPRESS_ZLIB_3:
502 case COMPRESS_ZLIB_2:
503 case COMPRESS_ZLIB_1:
507 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
508 logger(DEBUG_ALWAYS, LOG_ERR, "ZLIB compression is unavailable on this node.");
516 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
517 logger(DEBUG_ALWAYS, LOG_ERR, "Compression level %i is unrecognized by this node.", compression);
521 from->outcompression = compression;
523 /* SPTPS or old-style key exchange? */
525 if(from->status.sptps) {
526 const size_t buflen = strlen(key);
527 uint8_t *buf = alloca(buflen);
528 size_t len = b64decode_tinc(key, buf, buflen);
530 if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
531 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
532 so let's restart SPTPS in case that helps. But don't do that too often
534 Note that simply relying on handshake timeout is not enough, because
535 that doesn't apply to key regeneration. */
536 if(from->last_req_key < now.tv_sec - 10) {
537 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
544 if(from->status.validkey) {
545 if(*address && *port) {
546 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
547 sockaddr_t sa = str2sockaddr(address, port);
548 update_node_udp(from, &sa);
552 send_mtu_info(myself, from, MTU);
557 #ifdef DISABLE_LEGACY
558 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
561 /* Check and lookup cipher and digest algorithms */
564 from->outcipher = cipher_alloc();
566 if(!cipher_open_by_nid(from->outcipher, cipher)) {
567 cipher_free(&from->outcipher);
568 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
572 from->outcipher = NULL;
576 from->outdigest = digest_alloc();
578 if(!digest_open_by_nid(from->outdigest, digest, maclength)) {
579 digest_free(&from->outdigest);
580 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
584 from->outdigest = NULL;
587 if(maclength != digest_length(from->outdigest)) {
588 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
594 size_t keylen = hex2bin(key, key, sizeof(key));
596 if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
597 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
601 /* Update our copy of the origin's packet key */
603 if(from->outcipher && !cipher_set_key(from->outcipher, key, true)) {
607 if(from->outdigest && !digest_set_key(from->outdigest, key, keylen)) {
611 from->status.validkey = true;
612 from->sent_seqno = 0;
614 if(*address && *port) {
615 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
616 sockaddr_t sa = str2sockaddr(address, port);
617 update_node_udp(from, &sa);