2 protocol_key.c -- handle the meta-protocol, key exchange
3 Copyright (C) 1999-2005 Ivo Timmermans,
4 2000-2014 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"
36 static bool mykeyused = false;
38 void send_key_changed(void) {
39 #ifndef DISABLE_LEGACY
40 send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), 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);
49 /* Force key exchange for connections using SPTPS */
52 for splay_each(node_t, n, node_tree)
53 if(n->status.reachable && n->status.validkey && n->status.sptps)
54 sptps_force_kex(&n->sptps);
58 bool key_changed_h(connection_t *c, const char *request) {
59 char name[MAX_STRING_SIZE];
62 if(sscanf(request, "%*d %*x " MAX_STRING, name) != 1) {
63 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED",
64 c->name, c->hostname);
68 if(seen_request(request))
71 n = lookup_node(name);
74 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
75 "KEY_CHANGED", c->name, c->hostname, name);
79 if(!n->status.sptps) {
80 n->status.validkey = false;
87 forward_request(c, request);
92 static bool send_sptps_data_myself(void *handle, uint8_t type, const void *data, size_t len) {
93 return send_sptps_data(handle, myself, type, data, len);
96 static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
98 to->sptps.send_data = send_sptps_data_myself;
99 char buf[len * 4 / 3 + 5];
100 b64encode(data, buf, len);
101 return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
104 bool send_req_key(node_t *to) {
105 if(to->status.sptps) {
106 if(!node_read_ecdsa_public_key(to)) {
107 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", to->name, to->hostname);
108 send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY);
112 char label[25 + strlen(myself->name) + strlen(to->name)];
113 snprintf(label, sizeof label, "tinc UDP key expansion %s %s", myself->name, to->name);
114 sptps_stop(&to->sptps);
115 to->status.validkey = false;
116 to->status.waitingforkey = true;
117 to->last_req_key = now.tv_sec;
118 to->incompression = myself->incompression;
119 return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof label, send_initial_sptps_data, receive_sptps_record);
122 return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
125 /* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
127 static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
128 /* If this is a SPTPS packet, see if sending UDP info helps.
129 Note that we only do this if we're the destination or the static relay;
130 otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
131 if((reqno == REQ_KEY || reqno == SPTPS_PACKET) && to->via == myself)
132 send_udp_info(myself, from);
134 if(reqno == SPTPS_PACKET) {
135 /* This is a SPTPS data packet. */
137 char buf[MAX_STRING_SIZE];
139 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
140 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");
145 /* We don't just forward the request, because we want to use UDP if it's available. */
146 send_sptps_data(to, from, 0, buf, len);
149 /* The packet is for us */
150 if(!sptps_receive_data(&from->sptps, buf, len)) {
151 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
152 so let's restart SPTPS in case that helps. But don't do that too often
153 to prevent storms. */
154 if(from->last_req_key < now.tv_sec - 10) {
155 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
160 send_mtu_info(myself, from, MTU);
166 /* Requests that are not SPTPS data packets are forwarded as-is. */
169 return send_request(to->nexthop->connection, "%s", request);
171 /* The request is for us */
175 if(!node_read_ecdsa_public_key(from)) {
176 /* Request their key *before* we send our key back. Otherwise the first SPTPS packet from them will get dropped. */
177 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Preemptively requesting Ed25519 key for %s (%s)", from->name, from->hostname);
178 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
180 char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
181 send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey);
187 if(node_read_ecdsa_public_key(from)) {
188 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname);
192 char pubkey[MAX_STRING_SIZE];
193 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) {
194 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey");
198 logger(DEBUG_PROTOCOL, LOG_INFO, "Learned Ed25519 public key from %s (%s)", from->name, from->hostname);
199 append_config_file(from->name, "Ed25519PublicKey", pubkey);
204 if(!node_read_ecdsa_public_key(from)) {
205 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", from->name, from->hostname);
206 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
210 if(from->sptps.label)
211 logger(DEBUG_ALWAYS, LOG_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name);
213 char buf[MAX_STRING_SIZE];
216 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
217 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data");
221 char label[25 + strlen(from->name) + strlen(myself->name)];
222 snprintf(label, sizeof label, "tinc UDP key expansion %s %s", from->name, myself->name);
223 sptps_stop(&from->sptps);
224 from->status.validkey = false;
225 from->status.waitingforkey = true;
226 from->last_req_key = now.tv_sec;
227 sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data_myself, receive_sptps_record);
228 sptps_receive_data(&from->sptps, buf, len);
229 send_mtu_info(myself, from, MTU);
234 logger(DEBUG_ALWAYS, LOG_ERR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request);
239 bool req_key_h(connection_t *c, const char *request) {
240 char from_name[MAX_STRING_SIZE];
241 char to_name[MAX_STRING_SIZE];
245 if(sscanf(request, "%*d " MAX_STRING " " MAX_STRING " %d", from_name, to_name, &reqno) < 2) {
246 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name,
251 if(!check_id(from_name) || !check_id(to_name)) {
252 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name");
256 from = lookup_node(from_name);
259 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
260 "REQ_KEY", c->name, c->hostname, from_name);
264 to = lookup_node(to_name);
267 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
268 "REQ_KEY", c->name, c->hostname, to_name);
272 /* Check if this key request is for us */
274 if(to == myself) { /* Yes */
275 /* Is this an extended REQ_KEY message? */
276 if(experimental && reqno)
277 return req_key_ext_h(c, request, from, to, reqno);
279 /* No, just send our key back */
285 if(!to->status.reachable) {
286 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
287 "REQ_KEY", c->name, c->hostname, to_name);
291 /* Is this an extended REQ_KEY message? */
292 if(experimental && reqno)
293 return req_key_ext_h(c, request, from, to, reqno);
295 send_request(to->nexthop->connection, "%s", request);
301 bool send_ans_key(node_t *to) {
305 #ifdef DISABLE_LEGACY
308 size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
309 char key[keylen * 2 + 1];
311 randomize(key, keylen);
313 cipher_close(to->incipher);
314 digest_close(to->indigest);
316 if(myself->incipher) {
317 to->incipher = cipher_open_by_nid(cipher_get_nid(myself->incipher));
320 if(!cipher_set_key(to->incipher, key, false))
324 if(myself->indigest) {
325 to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest));
328 if(!digest_set_key(to->indigest, key, keylen))
332 to->incompression = myself->incompression;
334 bin2hex(key, key, keylen);
336 // Reset sequence number and late packet window
338 to->received_seqno = 0;
340 if(replaywin) memset(to->late, 0, replaywin);
342 to->status.validkey_in = true;
344 return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY,
345 myself->name, to->name, key,
346 cipher_get_nid(to->incipher),
347 digest_get_nid(to->indigest),
348 (int)digest_length(to->indigest),
353 bool ans_key_h(connection_t *c, const char *request) {
354 char from_name[MAX_STRING_SIZE];
355 char to_name[MAX_STRING_SIZE];
356 char key[MAX_STRING_SIZE];
357 char address[MAX_STRING_SIZE] = "";
358 char port[MAX_STRING_SIZE] = "";
359 int cipher, digest, maclength, compression;
362 if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING,
363 from_name, to_name, key, &cipher, &digest, &maclength,
364 &compression, address, port) < 7) {
365 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
370 if(!check_id(from_name) || !check_id(to_name)) {
371 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
375 from = lookup_node(from_name);
378 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
379 "ANS_KEY", c->name, c->hostname, from_name);
383 to = lookup_node(to_name);
386 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
387 "ANS_KEY", c->name, c->hostname, to_name);
391 /* Forward it if necessary */
397 if(!to->status.reachable) {
398 logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
399 "ANS_KEY", c->name, c->hostname, to_name);
403 if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
404 char *address, *port;
405 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
406 sockaddr2str(&from->address, &address, &port);
407 send_request(to->nexthop->connection, "%s %s %s", request, address, port);
413 return send_request(to->nexthop->connection, "%s", request);
416 #ifndef DISABLE_LEGACY
417 /* Don't use key material until every check has passed. */
418 cipher_close(from->outcipher);
419 digest_close(from->outdigest);
421 if (!from->status.sptps) from->status.validkey = false;
423 if(compression < 0 || compression > 11) {
424 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
428 from->outcompression = compression;
430 /* SPTPS or old-style key exchange? */
432 if(from->status.sptps) {
433 char buf[strlen(key)];
434 int len = b64decode(key, buf, strlen(key));
435 if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
436 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
437 so let's restart SPTPS in case that helps. But don't do that too often
439 Note that simply relying on handshake timeout is not enough, because
440 that doesn't apply to key regeneration. */
441 if(from->last_req_key < now.tv_sec - 10) {
442 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
448 if(from->status.validkey) {
449 if(*address && *port) {
450 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
451 sockaddr_t sa = str2sockaddr(address, port);
452 update_node_udp(from, &sa);
456 send_mtu_info(myself, from, MTU);
461 #ifdef DISABLE_LEGACY
462 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
465 /* Check and lookup cipher and digest algorithms */
468 if(!(from->outcipher = cipher_open_by_nid(cipher))) {
469 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
473 from->outcipher = NULL;
477 if(!(from->outdigest = digest_open_by_nid(digest, maclength))) {
478 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
482 from->outdigest = NULL;
485 if(maclength != digest_length(from->outdigest)) {
486 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
492 int keylen = hex2bin(key, key, sizeof key);
494 if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
495 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
499 /* Update our copy of the origin's packet key */
501 if(from->outcipher && !cipher_set_key(from->outcipher, key, true))
503 if(from->outdigest && !digest_set_key(from->outdigest, key, keylen))
506 from->status.validkey = true;
507 from->sent_seqno = 0;
509 if(*address && *port) {
510 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
511 sockaddr_t sa = str2sockaddr(address, port);
512 update_node_udp(from, &sa);