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 static bool mykeyused = false;
39 void send_key_changed(void) {
40 #ifndef DISABLE_LEGACY
41 send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), myself->name);
43 /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
45 for list_each(connection_t, c, connection_list)
46 if(c->edge && c->node && c->node->status.reachable && !c->node->status.sptps) {
47 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);
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;
106 char buf[len * 4 / 3 + 5];
108 b64encode(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 char label[25 + strlen(myself->name) + strlen(to->name)];
122 snprintf(label, sizeof(label), "tinc UDP key expansion %s %s", myself->name, to->name);
123 sptps_stop(&to->sptps);
124 to->status.validkey = false;
125 to->status.waitingforkey = true;
126 to->last_req_key = now.tv_sec;
127 to->incompression = myself->incompression;
128 return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof(label), send_initial_sptps_data, receive_sptps_record);
131 return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
134 /* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
136 static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
139 /* If this is a SPTPS packet, see if sending UDP info helps.
140 Note that we only do this if we're the destination or the static relay;
141 otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
142 if((reqno == REQ_KEY || reqno == SPTPS_PACKET) && to->via == myself) {
143 send_udp_info(myself, from);
146 if(reqno == SPTPS_PACKET) {
147 /* This is a SPTPS data packet. */
149 char buf[MAX_STRING_SIZE];
152 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
153 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");
158 /* We don't just forward the request, because we want to use UDP if it's available. */
159 if(forwarding_mode == FMODE_INTERNAL) {
160 send_sptps_data(to, from, 0, buf, len);
164 /* The packet is for us */
165 if(!sptps_receive_data(&from->sptps, buf, len)) {
166 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
167 so let's restart SPTPS in case that helps. But don't do that too often
168 to prevent storms. */
169 if(from->last_req_key < now.tv_sec - 10) {
170 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
177 send_mtu_info(myself, from, MTU);
183 /* Requests that are not SPTPS data packets are forwarded as-is. */
186 return send_request(to->nexthop->connection, "%s", request);
189 /* The request is for us */
193 if(!node_read_ecdsa_public_key(from)) {
194 /* Request their key *before* we send our key back. Otherwise the first SPTPS packet from them will get dropped. */
195 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Preemptively requesting Ed25519 key for %s (%s)", from->name, from->hostname);
196 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
199 char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
200 send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey);
206 if(node_read_ecdsa_public_key(from)) {
207 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname);
211 char pubkey[MAX_STRING_SIZE];
213 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) {
214 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey");
218 logger(DEBUG_PROTOCOL, LOG_INFO, "Learned Ed25519 public key from %s (%s)", from->name, from->hostname);
219 append_config_file(from->name, "Ed25519PublicKey", pubkey);
224 if(!node_read_ecdsa_public_key(from)) {
225 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", from->name, from->hostname);
226 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
230 if(from->sptps.label) {
231 logger(DEBUG_ALWAYS, LOG_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name);
234 char buf[MAX_STRING_SIZE];
237 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
238 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data");
242 char label[25 + strlen(from->name) + strlen(myself->name)];
243 snprintf(label, sizeof(label), "tinc UDP key expansion %s %s", from->name, myself->name);
244 sptps_stop(&from->sptps);
245 from->status.validkey = false;
246 from->status.waitingforkey = true;
247 from->last_req_key = now.tv_sec;
248 sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof(label), send_sptps_data_myself, receive_sptps_record);
249 sptps_receive_data(&from->sptps, buf, len);
250 send_mtu_info(myself, from, MTU);
255 logger(DEBUG_ALWAYS, LOG_ERR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request);
260 bool req_key_h(connection_t *c, const char *request) {
261 char from_name[MAX_STRING_SIZE];
262 char to_name[MAX_STRING_SIZE];
266 if(sscanf(request, "%*d " MAX_STRING " " MAX_STRING " %d", from_name, to_name, &reqno) < 2) {
267 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name,
272 if(!check_id(from_name) || !check_id(to_name)) {
273 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name");
277 from = lookup_node(from_name);
280 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
281 "REQ_KEY", c->name, c->hostname, from_name);
285 to = lookup_node(to_name);
288 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
289 "REQ_KEY", c->name, c->hostname, to_name);
293 /* Check if this key request is for us */
295 if(to == myself) { /* Yes */
296 /* Is this an extended REQ_KEY message? */
297 if(experimental && reqno) {
298 return req_key_ext_h(c, request, from, to, reqno);
301 /* No, just send our key back */
308 if(!to->status.reachable) {
309 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
310 "REQ_KEY", c->name, c->hostname, to_name);
314 /* Is this an extended REQ_KEY message? */
315 if(experimental && reqno) {
316 return req_key_ext_h(c, request, from, to, reqno);
319 send_request(to->nexthop->connection, "%s", request);
325 bool send_ans_key(node_t *to) {
326 if(to->status.sptps) {
330 #ifdef DISABLE_LEGACY
333 size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
334 char key[keylen * 2 + 1];
336 randomize(key, keylen);
338 cipher_close(to->incipher);
339 digest_close(to->indigest);
341 if(myself->incipher) {
342 to->incipher = cipher_open_by_nid(cipher_get_nid(myself->incipher));
348 if(!cipher_set_key(to->incipher, key, false)) {
353 if(myself->indigest) {
354 to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest));
360 if(!digest_set_key(to->indigest, key, keylen)) {
365 to->incompression = myself->incompression;
367 bin2hex(key, key, keylen);
369 // Reset sequence number and late packet window
371 to->received_seqno = 0;
375 memset(to->late, 0, replaywin);
378 to->status.validkey_in = true;
380 return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY,
381 myself->name, to->name, key,
382 cipher_get_nid(to->incipher),
383 digest_get_nid(to->indigest),
384 (int)digest_length(to->indigest),
389 bool ans_key_h(connection_t *c, const char *request) {
390 char from_name[MAX_STRING_SIZE];
391 char to_name[MAX_STRING_SIZE];
392 char key[MAX_STRING_SIZE];
393 char address[MAX_STRING_SIZE] = "";
394 char port[MAX_STRING_SIZE] = "";
395 int cipher, digest, maclength, compression;
398 if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING,
399 from_name, to_name, key, &cipher, &digest, &maclength,
400 &compression, address, port) < 7) {
401 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
406 if(!check_id(from_name) || !check_id(to_name)) {
407 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
411 from = lookup_node(from_name);
414 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
415 "ANS_KEY", c->name, c->hostname, from_name);
419 to = lookup_node(to_name);
422 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
423 "ANS_KEY", c->name, c->hostname, to_name);
427 /* Forward it if necessary */
434 if(!to->status.reachable) {
435 logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
436 "ANS_KEY", c->name, c->hostname, to_name);
440 if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
441 char *address, *port;
442 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
443 sockaddr2str(&from->address, &address, &port);
444 send_request(to->nexthop->connection, "%s %s %s", request, address, port);
450 return send_request(to->nexthop->connection, "%s", request);
453 #ifndef DISABLE_LEGACY
454 /* Don't use key material until every check has passed. */
455 cipher_close(from->outcipher);
456 digest_close(from->outdigest);
459 if(!from->status.sptps) {
460 from->status.validkey = false;
463 if(compression < 0 || compression > 11) {
464 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
468 from->outcompression = compression;
470 /* SPTPS or old-style key exchange? */
472 if(from->status.sptps) {
473 char buf[strlen(key)];
474 size_t len = b64decode(key, buf, strlen(key));
476 if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
477 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
478 so let's restart SPTPS in case that helps. But don't do that too often
480 Note that simply relying on handshake timeout is not enough, because
481 that doesn't apply to key regeneration. */
482 if(from->last_req_key < now.tv_sec - 10) {
483 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
490 if(from->status.validkey) {
491 if(*address && *port) {
492 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
493 sockaddr_t sa = str2sockaddr(address, port);
494 update_node_udp(from, &sa);
498 send_mtu_info(myself, from, MTU);
503 #ifdef DISABLE_LEGACY
504 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
507 /* Check and lookup cipher and digest algorithms */
510 if(!(from->outcipher = cipher_open_by_nid(cipher))) {
511 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
515 from->outcipher = NULL;
519 if(!(from->outdigest = digest_open_by_nid(digest, maclength))) {
520 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
524 from->outdigest = NULL;
527 if((size_t)maclength != digest_length(from->outdigest)) {
528 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
534 size_t keylen = hex2bin(key, key, sizeof(key));
536 if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
537 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
541 /* Update our copy of the origin's packet key */
543 if(from->outcipher && !cipher_set_key(from->outcipher, key, true)) {
547 if(from->outdigest && !digest_set_key(from->outdigest, key, keylen)) {
551 from->status.validkey = true;
552 from->sent_seqno = 0;
554 if(*address && *port) {
555 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
556 sockaddr_t sa = str2sockaddr(address, port);
557 update_node_udp(from, &sa);