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 send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), 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);
47 /* Force key exchange for connections using SPTPS */
50 for splay_each(node_t, n, node_tree)
51 if(n->status.reachable && n->status.validkey && n->status.sptps)
52 sptps_force_kex(&n->sptps);
56 bool key_changed_h(connection_t *c, const char *request) {
57 char name[MAX_STRING_SIZE];
60 if(sscanf(request, "%*d %*x " MAX_STRING, name) != 1) {
61 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED",
62 c->name, c->hostname);
66 if(seen_request(request))
69 n = lookup_node(name);
72 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
73 "KEY_CHANGED", c->name, c->hostname, name);
77 if(!n->status.sptps) {
78 n->status.validkey = false;
85 forward_request(c, request);
90 static bool send_sptps_data_myself(void *handle, uint8_t type, const void *data, size_t len) {
91 return send_sptps_data(handle, myself, type, data, len);
94 static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
96 to->sptps.send_data = send_sptps_data_myself;
97 char buf[len * 4 / 3 + 5];
98 b64encode(data, buf, len);
99 return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
102 bool send_req_key(node_t *to) {
103 if(to->status.sptps) {
104 if(!node_read_ecdsa_public_key(to)) {
105 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", to->name, to->hostname);
106 send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY);
110 char label[25 + strlen(myself->name) + strlen(to->name)];
111 snprintf(label, sizeof label, "tinc UDP key expansion %s %s", myself->name, to->name);
112 sptps_stop(&to->sptps);
113 to->status.validkey = false;
114 to->status.waitingforkey = true;
115 to->last_req_key = now.tv_sec;
116 to->incompression = myself->incompression;
117 return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof label, send_initial_sptps_data, receive_sptps_record);
120 return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
123 /* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
125 static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
126 /* If this is a SPTPS packet, see if sending UDP info helps.
127 Note that we only do this if we're the destination or the static relay;
128 otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
129 if((reqno == REQ_KEY || reqno == SPTPS_PACKET) && to->via == myself)
130 send_udp_info(myself, from);
132 if(reqno == SPTPS_PACKET) {
133 /* This is a SPTPS data packet. */
135 char buf[MAX_STRING_SIZE];
137 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
138 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");
143 /* We don't just forward the request, because we want to use UDP if it's available. */
144 send_sptps_data(to, from, 0, buf, len);
147 /* The packet is for us */
148 if(!sptps_receive_data(&from->sptps, buf, len)) {
149 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
150 so let's restart SPTPS in case that helps. But don't do that too often
151 to prevent storms. */
152 if(from->last_req_key < now.tv_sec - 10) {
153 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
158 send_mtu_info(myself, from, MTU);
164 /* Requests that are not SPTPS data packets are forwarded as-is. */
167 return send_request(to->nexthop->connection, "%s", request);
169 /* The request is for us */
173 if(!node_read_ecdsa_public_key(from)) {
174 /* Request their key *before* we send our key back. Otherwise the first SPTPS packet from them will get dropped. */
175 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Preemptively requesting Ed25519 key for %s (%s)", from->name, from->hostname);
176 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
178 char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
179 send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey);
185 if(node_read_ecdsa_public_key(from)) {
186 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname);
190 char pubkey[MAX_STRING_SIZE];
191 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) {
192 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey");
196 logger(DEBUG_PROTOCOL, LOG_INFO, "Learned Ed25519 public key from %s (%s)", from->name, from->hostname);
197 append_config_file(from->name, "Ed25519PublicKey", pubkey);
202 if(!node_read_ecdsa_public_key(from)) {
203 logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", from->name, from->hostname);
204 send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
208 if(from->sptps.label)
209 logger(DEBUG_ALWAYS, LOG_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name);
211 char buf[MAX_STRING_SIZE];
214 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
215 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data");
219 char label[25 + strlen(from->name) + strlen(myself->name)];
220 snprintf(label, sizeof label, "tinc UDP key expansion %s %s", from->name, myself->name);
221 sptps_stop(&from->sptps);
222 from->status.validkey = false;
223 from->status.waitingforkey = true;
224 from->last_req_key = now.tv_sec;
225 sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data_myself, receive_sptps_record);
226 sptps_receive_data(&from->sptps, buf, len);
227 send_mtu_info(myself, from, MTU);
232 logger(DEBUG_ALWAYS, LOG_ERR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request);
237 bool req_key_h(connection_t *c, const char *request) {
238 char from_name[MAX_STRING_SIZE];
239 char to_name[MAX_STRING_SIZE];
243 if(sscanf(request, "%*d " MAX_STRING " " MAX_STRING " %d", from_name, to_name, &reqno) < 2) {
244 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name,
249 if(!check_id(from_name) || !check_id(to_name)) {
250 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name");
254 from = lookup_node(from_name);
257 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
258 "REQ_KEY", c->name, c->hostname, from_name);
262 to = lookup_node(to_name);
265 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
266 "REQ_KEY", c->name, c->hostname, to_name);
270 /* Check if this key request is for us */
272 if(to == myself) { /* Yes */
273 /* Is this an extended REQ_KEY message? */
274 if(experimental && reqno)
275 return req_key_ext_h(c, request, from, to, reqno);
277 /* No, just send our key back */
283 if(!to->status.reachable) {
284 logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
285 "REQ_KEY", c->name, c->hostname, to_name);
289 /* Is this an extended REQ_KEY message? */
290 if(experimental && reqno)
291 return req_key_ext_h(c, request, from, to, reqno);
293 send_request(to->nexthop->connection, "%s", request);
299 bool send_ans_key(node_t *to) {
303 #ifdef DISABLE_LEGACY
306 size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
307 char key[keylen * 2 + 1];
309 randomize(key, keylen);
311 cipher_close(to->incipher);
312 digest_close(to->indigest);
314 if(myself->incipher) {
315 to->incipher = cipher_open_by_nid(cipher_get_nid(myself->incipher));
318 if(!cipher_set_key(to->incipher, key, false))
322 if(myself->indigest) {
323 to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest));
326 if(!digest_set_key(to->indigest, key, keylen))
330 to->incompression = myself->incompression;
332 bin2hex(key, key, keylen);
334 // Reset sequence number and late packet window
336 to->received_seqno = 0;
338 if(replaywin) memset(to->late, 0, replaywin);
340 to->status.validkey_in = true;
342 return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY,
343 myself->name, to->name, key,
344 cipher_get_nid(to->incipher),
345 digest_get_nid(to->indigest),
346 (int)digest_length(to->indigest),
351 bool ans_key_h(connection_t *c, const char *request) {
352 char from_name[MAX_STRING_SIZE];
353 char to_name[MAX_STRING_SIZE];
354 char key[MAX_STRING_SIZE];
355 char address[MAX_STRING_SIZE] = "";
356 char port[MAX_STRING_SIZE] = "";
357 int cipher, digest, maclength, compression, keylen;
360 if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING,
361 from_name, to_name, key, &cipher, &digest, &maclength,
362 &compression, address, port) < 7) {
363 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
368 if(!check_id(from_name) || !check_id(to_name)) {
369 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
373 from = lookup_node(from_name);
376 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
377 "ANS_KEY", c->name, c->hostname, from_name);
381 to = lookup_node(to_name);
384 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
385 "ANS_KEY", c->name, c->hostname, to_name);
389 /* Forward it if necessary */
395 if(!to->status.reachable) {
396 logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
397 "ANS_KEY", c->name, c->hostname, to_name);
401 if(!*address && from->address.sa.sa_family != AF_UNSPEC) {
402 char *address, *port;
403 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
404 sockaddr2str(&from->address, &address, &port);
405 send_request(to->nexthop->connection, "%s %s %s", request, address, port);
411 return send_request(to->nexthop->connection, "%s", request);
414 #ifndef DISABLE_LEGACY
415 /* Don't use key material until every check has passed. */
416 cipher_close(from->outcipher);
417 digest_close(from->outdigest);
419 from->status.validkey = false;
421 if(compression < 0 || compression > 11) {
422 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
426 from->outcompression = compression;
428 /* SPTPS or old-style key exchange? */
430 if(from->status.sptps) {
431 char buf[strlen(key)];
432 int len = b64decode(key, buf, strlen(key));
433 if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
434 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
435 so let's restart SPTPS in case that helps. But don't do that too often
437 Note that simply relying on handshake timeout is not enough, because
438 that doesn't apply to key regeneration. */
439 if(from->last_req_key < now.tv_sec - 10) {
440 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
446 if(from->status.validkey) {
447 if(*address && *port) {
448 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
449 sockaddr_t sa = str2sockaddr(address, port);
450 update_node_udp(from, &sa);
454 send_mtu_info(myself, from, MTU);
459 #ifdef DISABLE_LEGACY
460 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
463 /* Check and lookup cipher and digest algorithms */
466 if(!(from->outcipher = cipher_open_by_nid(cipher))) {
467 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
471 from->outcipher = NULL;
475 if(!(from->outdigest = digest_open_by_nid(digest, maclength))) {
476 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
480 from->outdigest = NULL;
483 if(maclength != digest_length(from->outdigest)) {
484 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
490 keylen = hex2bin(key, key, sizeof key);
492 if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
493 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
497 /* Update our copy of the origin's packet key */
499 if(from->outcipher && !cipher_set_key(from->outcipher, key, true))
501 if(from->outdigest && !digest_set_key(from->outdigest, key, keylen))
504 from->status.validkey = true;
505 from->sent_seqno = 0;
507 if(*address && *port) {
508 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
509 sockaddr_t sa = str2sockaddr(address, port);
510 update_node_udp(from, &sa);