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"
37 #ifndef DISABLE_LEGACY
38 static bool mykeyused = false;
41 void send_key_changed(void) {
42 #ifndef DISABLE_LEGACY
43 send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), myself->name);
45 /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
47 for list_each(connection_t, c, connection_list)
48 if(c->edge && c->node && c->node->status.reachable && !c->node->status.sptps) {
49 send_ans_key(c->node);
54 /* Force key exchange for connections using SPTPS */
57 for splay_each(node_t, n, node_tree)
58 if(n->status.reachable && n->status.validkey && n->status.sptps) {
59 sptps_force_kex(&n->sptps);
64 bool key_changed_h(connection_t *c, const char *request) {
65 char name[MAX_STRING_SIZE];
68 if(sscanf(request, "%*d %*x " MAX_STRING, name) != 1) {
69 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED",
70 c->name, c->hostname);
74 if(seen_request(request)) {
78 n = lookup_node(name);
81 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
82 "KEY_CHANGED", c->name, c->hostname, name);
86 if(!n->status.sptps) {
87 n->status.validkey = false;
94 forward_request(c, request);
100 static bool send_sptps_data_myself(void *handle, uint8_t type, const void *data, size_t len) {
101 return send_sptps_data(handle, myself, type, data, len);
104 static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
107 to->sptps.send_data = send_sptps_data_myself;
108 char buf[len * 4 / 3 + 5];
110 b64encode(data, buf, len);
112 return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
115 bool send_req_key(node_t *to) {
116 if(to->status.sptps) {
117 if(!node_read_ecdsa_public_key(to)) {
118 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", to->name, to->hostname);
119 send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY);
123 char label[25 + strlen(myself->name) + strlen(to->name)];
124 snprintf(label, sizeof(label), "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, sizeof(label), 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(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(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 char label[25 + strlen(from->name) + strlen(myself->name)];
245 snprintf(label, sizeof(label), "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, sizeof(label), 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 /* Is this an extended REQ_KEY message? */
299 if(experimental && reqno) {
300 return req_key_ext_h(c, request, from, to, reqno);
303 /* No, just send our key back */
310 if(!to->status.reachable) {
311 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
312 "REQ_KEY", c->name, c->hostname, to_name);
316 /* Is this an extended REQ_KEY message? */
317 if(experimental && reqno) {
318 return req_key_ext_h(c, request, from, to, reqno);
321 send_request(to->nexthop->connection, "%s", request);
327 bool send_ans_key(node_t *to) {
328 if(to->status.sptps) {
332 #ifdef DISABLE_LEGACY
335 size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
336 char key[keylen * 2 + 1];
338 randomize(key, keylen);
340 cipher_close(to->incipher);
341 digest_close(to->indigest);
343 if(myself->incipher) {
344 to->incipher = cipher_open_by_nid(cipher_get_nid(myself->incipher));
350 if(!cipher_set_key(to->incipher, key, false)) {
355 if(myself->indigest) {
356 to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest));
362 if(!digest_set_key(to->indigest, key, keylen)) {
367 to->incompression = myself->incompression;
369 bin2hex(key, key, keylen);
371 // Reset sequence number and late packet window
373 to->received_seqno = 0;
377 memset(to->late, 0, replaywin);
380 to->status.validkey_in = true;
382 return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY,
383 myself->name, to->name, key,
384 cipher_get_nid(to->incipher),
385 digest_get_nid(to->indigest),
386 (int)digest_length(to->indigest),
391 bool ans_key_h(connection_t *c, const char *request) {
392 char from_name[MAX_STRING_SIZE];
393 char to_name[MAX_STRING_SIZE];
394 char key[MAX_STRING_SIZE];
395 char address[MAX_STRING_SIZE] = "";
396 char port[MAX_STRING_SIZE] = "";
397 int cipher, digest, maclength, compression;
400 if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING,
401 from_name, to_name, key, &cipher, &digest, &maclength,
402 &compression, address, port) < 7) {
403 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
408 if(!check_id(from_name) || !check_id(to_name)) {
409 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
413 from = lookup_node(from_name);
416 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
417 "ANS_KEY", c->name, c->hostname, from_name);
421 to = lookup_node(to_name);
424 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
425 "ANS_KEY", c->name, c->hostname, to_name);
429 /* Forward it if necessary */
436 if(!to->status.reachable) {
437 logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
438 "ANS_KEY", c->name, c->hostname, to_name);
442 if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
443 char *address, *port;
444 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
445 sockaddr2str(&from->address, &address, &port);
446 send_request(to->nexthop->connection, "%s %s %s", request, address, port);
452 return send_request(to->nexthop->connection, "%s", request);
455 #ifndef DISABLE_LEGACY
456 /* Don't use key material until every check has passed. */
457 cipher_close(from->outcipher);
458 digest_close(from->outdigest);
461 if(!from->status.sptps) {
462 from->status.validkey = false;
465 if(compression < 0 || compression > 11) {
466 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
470 from->outcompression = compression;
472 /* SPTPS or old-style key exchange? */
474 if(from->status.sptps) {
475 char buf[strlen(key)];
476 size_t len = b64decode(key, buf, strlen(key));
478 if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
479 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
480 so let's restart SPTPS in case that helps. But don't do that too often
482 Note that simply relying on handshake timeout is not enough, because
483 that doesn't apply to key regeneration. */
484 if(from->last_req_key < now.tv_sec - 10) {
485 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
492 if(from->status.validkey) {
493 if(*address && *port) {
494 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
495 sockaddr_t sa = str2sockaddr(address, port);
496 update_node_udp(from, &sa);
500 send_mtu_info(myself, from, MTU);
505 #ifdef DISABLE_LEGACY
506 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
509 /* Check and lookup cipher and digest algorithms */
512 if(!(from->outcipher = cipher_open_by_nid(cipher))) {
513 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
517 from->outcipher = NULL;
521 if(!(from->outdigest = digest_open_by_nid(digest, maclength))) {
522 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
526 from->outdigest = NULL;
529 if((size_t)maclength != digest_length(from->outdigest)) {
530 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
536 size_t keylen = hex2bin(key, key, sizeof(key));
538 if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
539 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
543 /* Update our copy of the origin's packet key */
545 if(from->outcipher && !cipher_set_key(from->outcipher, key, true)) {
549 if(from->outdigest && !digest_set_key(from->outdigest, key, keylen)) {
553 from->status.validkey = true;
554 from->sent_seqno = 0;
556 if(*address && *port) {
557 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
558 sockaddr_t sa = str2sockaddr(address, port);
559 update_node_udp(from, &sa);