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"
36 void send_key_changed(void) {
37 #ifndef DISABLE_LEGACY
38 send_request(everyone, "%d %x %s", KEY_CHANGED, prng(UINT32_MAX), myself->name);
40 /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
42 for list_each(connection_t, c, &connection_list) {
43 if(c->edge && c->node && c->node->status.reachable && !c->node->status.sptps) {
44 send_ans_key(c->node);
50 /* Force key exchange for connections using SPTPS */
53 for splay_each(node_t, n, &node_tree) {
54 if(n->status.reachable && n->status.validkey && n->status.sptps) {
55 sptps_force_kex(&n->sptps);
61 bool key_changed_h(connection_t *c, const char *request) {
62 char name[MAX_STRING_SIZE];
65 if(sscanf(request, "%*d %*x " MAX_STRING, name) != 1) {
66 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED",
67 c->name, c->hostname);
71 if(seen_request(request)) {
75 n = lookup_node(name);
78 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
79 "KEY_CHANGED", c->name, c->hostname, name);
83 if(!n->status.sptps) {
84 n->status.validkey = false;
91 forward_request(c, request);
97 static bool send_sptps_data_myself(void *handle, uint8_t type, const void *data, size_t len) {
98 return send_sptps_data(handle, myself, type, data, len);
101 static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
104 to->sptps.send_data = send_sptps_data_myself;
106 char *buf = alloca(B64_SIZE(len));
107 b64encode_tinc(data, buf, len);
109 return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
112 bool send_req_key(node_t *to) {
113 if(to->status.sptps) {
114 if(!node_read_ecdsa_public_key(to)) {
115 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", to->name, to->hostname);
116 send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY);
120 const size_t labellen = 25 + strlen(myself->name) + strlen(to->name);
121 char *label = alloca(labellen);
122 snprintf(label, labellen, "tinc UDP key expansion %s %s", myself->name, to->name);
124 sptps_stop(&to->sptps);
125 to->status.validkey = false;
126 to->status.waitingforkey = true;
127 to->last_req_key = now.tv_sec;
128 to->incompression = myself->incompression;
129 return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, labellen, send_initial_sptps_data, receive_sptps_record);
132 return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
135 /* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
137 static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
140 /* If this is a SPTPS packet, see if sending UDP info helps.
141 Note that we only do this if we're the destination or the static relay;
142 otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
143 if((reqno == REQ_KEY || reqno == SPTPS_PACKET) && to->via == myself) {
144 send_udp_info(myself, from);
147 if(reqno == SPTPS_PACKET) {
148 /* This is a SPTPS data packet. */
150 char buf[MAX_STRING_SIZE];
153 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode_tinc(buf, buf, strlen(buf)))) {
154 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");
159 /* We don't just forward the request, because we want to use UDP if it's available. */
160 if(forwarding_mode == FMODE_INTERNAL) {
161 send_sptps_data(to, from, 0, buf, len);
165 /* The packet is for us */
166 if(!sptps_receive_data(&from->sptps, buf, len)) {
167 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
168 so let's restart SPTPS in case that helps. But don't do that too often
169 to prevent storms. */
170 if(from->last_req_key < now.tv_sec - 10) {
171 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
178 send_mtu_info(myself, from, MTU);
184 /* Requests that are not SPTPS data packets are forwarded as-is. */
187 return send_request(to->nexthop->connection, "%s", request);
190 /* The request is for us */
194 if(!node_read_ecdsa_public_key(from)) {
195 /* Request their key *before* we send our key back. Otherwise the first SPTPS packet from them will get dropped. */
196 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Preemptively requesting Ed25519 key for %s (%s)", from->name, from->hostname);
197 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
200 char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
201 send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey);
207 if(node_read_ecdsa_public_key(from)) {
208 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname);
212 char pubkey[MAX_STRING_SIZE];
214 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) {
215 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey");
219 logger(DEBUG_PROTOCOL, LOG_INFO, "Learned Ed25519 public key from %s (%s)", from->name, from->hostname);
220 append_config_file(from->name, "Ed25519PublicKey", pubkey);
225 if(!node_read_ecdsa_public_key(from)) {
226 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", from->name, from->hostname);
227 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
231 if(from->sptps.label) {
232 logger(DEBUG_ALWAYS, LOG_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name);
235 char buf[MAX_STRING_SIZE];
238 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode_tinc(buf, buf, strlen(buf)))) {
239 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data");
243 const size_t labellen = 25 + strlen(from->name) + strlen(myself->name);
244 char *label = alloca(labellen);
245 snprintf(label, labellen, "tinc UDP key expansion %s %s", from->name, myself->name);
246 sptps_stop(&from->sptps);
247 from->status.validkey = false;
248 from->status.waitingforkey = true;
249 from->last_req_key = now.tv_sec;
250 sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, labellen, send_sptps_data_myself, receive_sptps_record);
251 sptps_receive_data(&from->sptps, buf, len);
252 send_mtu_info(myself, from, MTU);
257 logger(DEBUG_ALWAYS, LOG_ERR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request);
262 bool req_key_h(connection_t *c, const char *request) {
263 char from_name[MAX_STRING_SIZE];
264 char to_name[MAX_STRING_SIZE];
268 if(sscanf(request, "%*d " MAX_STRING " " MAX_STRING " %d", from_name, to_name, &reqno) < 2) {
269 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name,
274 if(!check_id(from_name) || !check_id(to_name)) {
275 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name");
279 from = lookup_node(from_name);
282 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
283 "REQ_KEY", c->name, c->hostname, from_name);
287 to = lookup_node(to_name);
290 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
291 "REQ_KEY", c->name, c->hostname, to_name);
295 /* Check if this key request is for us */
297 if(to == myself) { /* Yes */
298 if(!from->status.reachable) {
299 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which is not reachable",
300 "REQ_KEY", c->name, c->hostname, from_name);
304 /* Is this an extended REQ_KEY message? */
305 if(experimental && reqno) {
306 return req_key_ext_h(c, request, from, to, reqno);
309 /* No, just send our key back */
316 if(!to->status.reachable) {
317 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
318 "REQ_KEY", c->name, c->hostname, to_name);
322 /* Is this an extended REQ_KEY message? */
323 if(experimental && reqno) {
324 return req_key_ext_h(c, request, from, to, reqno);
327 send_request(to->nexthop->connection, "%s", request);
333 bool send_ans_key(node_t *to) {
334 if(to->status.sptps) {
338 #ifdef DISABLE_LEGACY
341 size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
342 char *key = alloca(keylen * 2 + 1);
344 randomize(key, keylen);
346 cipher_free(&to->incipher);
347 digest_free(&to->indigest);
349 if(myself->incipher) {
350 to->incipher = cipher_alloc();
352 if(!cipher_open_by_nid(to->incipher, cipher_get_nid(myself->incipher))) {
356 if(!cipher_set_key(to->incipher, key, false)) {
361 if(myself->indigest) {
362 to->indigest = digest_alloc();
364 if(!digest_open_by_nid(to->indigest,
365 digest_get_nid(myself->indigest),
366 digest_length(myself->indigest))) {
370 if(!digest_set_key(to->indigest, key, keylen)) {
375 to->incompression = myself->incompression;
377 bin2hex(key, key, keylen);
379 // Reset sequence number and late packet window
380 to->received_seqno = 0;
384 memset(to->late, 0, replaywin);
387 to->status.validkey_in = true;
389 return send_request(to->nexthop->connection, "%d %s %s %s %d %d %lu %d", ANS_KEY,
390 myself->name, to->name, key,
391 cipher_get_nid(to->incipher),
392 digest_get_nid(to->indigest),
393 (unsigned long)digest_length(to->indigest),
398 bool ans_key_h(connection_t *c, const char *request) {
399 char from_name[MAX_STRING_SIZE];
400 char to_name[MAX_STRING_SIZE];
401 char key[MAX_STRING_SIZE];
402 char address[MAX_STRING_SIZE] = "";
403 char port[MAX_STRING_SIZE] = "";
405 unsigned long maclength;
409 if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %lu %d "MAX_STRING" "MAX_STRING,
410 from_name, to_name, key, &cipher, &digest, &maclength,
411 &compression, address, port) < 7) {
412 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
417 if(!check_id(from_name) || !check_id(to_name)) {
418 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
422 from = lookup_node(from_name);
425 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
426 "ANS_KEY", c->name, c->hostname, from_name);
430 to = lookup_node(to_name);
433 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
434 "ANS_KEY", c->name, c->hostname, to_name);
438 /* Forward it if necessary */
445 if(!to->status.reachable) {
446 logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
447 "ANS_KEY", c->name, c->hostname, to_name);
451 if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
452 char *address, *port;
453 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
454 sockaddr2str(&from->address, &address, &port);
455 send_request(to->nexthop->connection, "%s %s %s", request, address, port);
461 return send_request(to->nexthop->connection, "%s", request);
464 #ifndef DISABLE_LEGACY
465 /* Don't use key material until every check has passed. */
466 cipher_free(&from->outcipher);
467 digest_free(&from->outdigest);
470 if(!from->status.sptps) {
471 from->status.validkey = false;
474 switch(compression) {
479 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
480 logger(DEBUG_ALWAYS, LOG_ERR, "LZ4 compression is unavailable on this node.");
484 case COMPRESS_LZO_HI:
485 case COMPRESS_LZO_LO:
489 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
490 logger(DEBUG_ALWAYS, LOG_ERR, "LZO compression is unavailable on this node.");
494 case COMPRESS_ZLIB_9:
495 case COMPRESS_ZLIB_8:
496 case COMPRESS_ZLIB_7:
497 case COMPRESS_ZLIB_6:
498 case COMPRESS_ZLIB_5:
499 case COMPRESS_ZLIB_4:
500 case COMPRESS_ZLIB_3:
501 case COMPRESS_ZLIB_2:
502 case COMPRESS_ZLIB_1:
506 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
507 logger(DEBUG_ALWAYS, LOG_ERR, "ZLIB compression is unavailable on this node.");
515 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
516 logger(DEBUG_ALWAYS, LOG_ERR, "Compression level %i is unrecognized by this node.", compression);
520 from->outcompression = compression;
522 /* SPTPS or old-style key exchange? */
524 if(from->status.sptps) {
525 const size_t buflen = strlen(key);
526 uint8_t *buf = alloca(buflen);
527 size_t len = b64decode_tinc(key, buf, buflen);
529 if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
530 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
531 so let's restart SPTPS in case that helps. But don't do that too often
533 Note that simply relying on handshake timeout is not enough, because
534 that doesn't apply to key regeneration. */
535 if(from->last_req_key < now.tv_sec - 10) {
536 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
543 if(from->status.validkey) {
544 if(*address && *port) {
545 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
546 sockaddr_t sa = str2sockaddr(address, port);
547 update_node_udp(from, &sa);
551 send_mtu_info(myself, from, MTU);
556 #ifdef DISABLE_LEGACY
557 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
560 /* Check and lookup cipher and digest algorithms */
563 from->outcipher = cipher_alloc();
565 if(!cipher_open_by_nid(from->outcipher, cipher)) {
566 cipher_free(&from->outcipher);
567 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
571 from->outcipher = NULL;
575 from->outdigest = digest_alloc();
577 if(!digest_open_by_nid(from->outdigest, digest, maclength)) {
578 digest_free(&from->outdigest);
579 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
583 from->outdigest = NULL;
586 if(maclength != digest_length(from->outdigest)) {
587 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
593 size_t keylen = hex2bin(key, key, sizeof(key));
595 if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
596 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
600 /* Update our copy of the origin's packet key */
602 if(from->outcipher && !cipher_set_key(from->outcipher, key, true)) {
606 if(from->outdigest && !digest_set_key(from->outdigest, key, keylen)) {
610 from->status.validkey = true;
611 from->sent_seqno = 0;
613 if(*address && *port) {
614 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
615 sockaddr_t sa = str2sockaddr(address, port);
616 update_node_udp(from, &sa);