1 /*
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>
5
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.
10
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.
15
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.
19 */
20
21 #include "system.h"
22
23 #include "cipher.h"
24 #include "connection.h"
25 #include "crypto.h"
26 #include "logger.h"
27 #include "net.h"
28 #include "netutl.h"
29 #include "node.h"
30 #include "prf.h"
31 #include "protocol.h"
32 #include "route.h"
33 #include "sptps.h"
34 #include "utils.h"
35 #include "xalloc.h"
36
37 #ifndef DISABLE_LEGACY
38 static bool mykeyused = false;
39 #endif
40
send_key_changed(void)41 void send_key_changed(void) {
42 #ifndef DISABLE_LEGACY
43 send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), myself->name);
44
45 /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
46
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);
50 }
51
52 #endif
53
54 /* Force key exchange for connections using SPTPS */
55
56 if(experimental) {
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);
60 }
61 }
62 }
63
key_changed_h(connection_t * c,const char * request)64 bool key_changed_h(connection_t *c, const char *request) {
65 char name[MAX_STRING_SIZE];
66 node_t *n;
67
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);
71 return false;
72 }
73
74 if(seen_request(request)) {
75 return true;
76 }
77
78 n = lookup_node(name);
79
80 if(!n) {
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);
83 return true;
84 }
85
86 if(!n->status.sptps) {
87 n->status.validkey = false;
88 n->last_req_key = 0;
89 }
90
91 /* Tell the others */
92
93 if(!tunnelserver) {
94 forward_request(c, request);
95 }
96
97 return true;
98 }
99
send_sptps_data_myself(void * handle,uint8_t type,const void * data,size_t len)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);
102 }
103
send_initial_sptps_data(void * handle,uint8_t type,const void * data,size_t len)104 static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
105 (void)type;
106 node_t *to = handle;
107 to->sptps.send_data = send_sptps_data_myself;
108 char buf[len * 4 / 3 + 5];
109
110 b64encode(data, buf, len);
111
112 return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
113 }
114
send_req_key(node_t * to)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);
120 return true;
121 }
122
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);
131 }
132
133 return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
134 }
135
136 /* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
137
req_key_ext_h(connection_t * c,const char * request,node_t * from,node_t * to,int reqno)138 static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
139 (void)c;
140
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);
146 }
147
148 if(reqno == SPTPS_PACKET) {
149 /* This is a SPTPS data packet. */
150
151 char buf[MAX_STRING_SIZE];
152 int len;
153
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");
156 return true;
157 }
158
159 if(to != myself) {
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);
163 try_tx(to, true);
164 }
165 } else {
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);
173 send_req_key(from);
174 }
175
176 return true;
177 }
178
179 send_mtu_info(myself, from, MTU);
180 }
181
182 return true;
183 }
184
185 /* Requests that are not SPTPS data packets are forwarded as-is. */
186
187 if(to != myself) {
188 return send_request(to->nexthop->connection, "%s", request);
189 }
190
191 /* The request is for us */
192
193 switch(reqno) {
194 case REQ_PUBKEY: {
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);
199 }
200
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);
203 free(pubkey);
204 return true;
205 }
206
207 case ANS_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);
210 return true;
211 }
212
213 char pubkey[MAX_STRING_SIZE];
214
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");
217 return true;
218 }
219
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);
222 return true;
223 }
224
225 case REQ_KEY: {
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);
229 return true;
230 }
231
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);
234 }
235
236 char buf[MAX_STRING_SIZE];
237 size_t len;
238
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");
241 return true;
242 }
243
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);
253 return true;
254 }
255
256 default:
257 logger(DEBUG_ALWAYS, LOG_ERR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request);
258 return true;
259 }
260 }
261
req_key_h(connection_t * c,const char * 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];
265 node_t *from, *to;
266 int reqno = 0;
267
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,
270 c->hostname);
271 return false;
272 }
273
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");
276 return false;
277 }
278
279 from = lookup_node(from_name);
280
281 if(!from) {
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);
284 return true;
285 }
286
287 to = lookup_node(to_name);
288
289 if(!to) {
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);
292 return true;
293 }
294
295 /* Check if this key request is for us */
296
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);
301 }
302
303 /* No, just send our key back */
304 send_ans_key(from);
305 } else {
306 if(tunnelserver) {
307 return true;
308 }
309
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);
313 return true;
314 }
315
316 /* Is this an extended REQ_KEY message? */
317 if(experimental && reqno) {
318 return req_key_ext_h(c, request, from, to, reqno);
319 }
320
321 send_request(to->nexthop->connection, "%s", request);
322 }
323
324 return true;
325 }
326
send_ans_key(node_t * to)327 bool send_ans_key(node_t *to) {
328 if(to->status.sptps) {
329 abort();
330 }
331
332 #ifdef DISABLE_LEGACY
333 return false;
334 #else
335 size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
336 char key[keylen * 2 + 1];
337
338 randomize(key, keylen);
339
340 cipher_close(to->incipher);
341 digest_close(to->indigest);
342
343 if(myself->incipher) {
344 to->incipher = cipher_open_by_nid(cipher_get_nid(myself->incipher));
345
346 if(!to->incipher) {
347 abort();
348 }
349
350 if(!cipher_set_key(to->incipher, key, false)) {
351 abort();
352 }
353 }
354
355 if(myself->indigest) {
356 to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest));
357
358 if(!to->indigest) {
359 abort();
360 }
361
362 if(!digest_set_key(to->indigest, key, keylen)) {
363 abort();
364 }
365 }
366
367 to->incompression = myself->incompression;
368
369 bin2hex(key, key, keylen);
370
371 // Reset sequence number and late packet window
372 mykeyused = true;
373 to->received_seqno = 0;
374 to->received = 0;
375
376 if(replaywin) {
377 memset(to->late, 0, replaywin);
378 }
379
380 to->status.validkey_in = true;
381
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),
387 to->incompression);
388 #endif
389 }
390
ans_key_h(connection_t * c,const char * request)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;
398 node_t *from, *to;
399
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,
404 c->hostname);
405 return false;
406 }
407
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");
410 return false;
411 }
412
413 from = lookup_node(from_name);
414
415 if(!from) {
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);
418 return true;
419 }
420
421 to = lookup_node(to_name);
422
423 if(!to) {
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);
426 return true;
427 }
428
429 /* Forward it if necessary */
430
431 if(to != myself) {
432 if(tunnelserver) {
433 return true;
434 }
435
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);
439 return true;
440 }
441
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);
447 free(address);
448 free(port);
449 return true;
450 }
451
452 return send_request(to->nexthop->connection, "%s", request);
453 }
454
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);
459 #endif
460
461 if(!from->status.sptps) {
462 from->status.validkey = false;
463 }
464
465 if(compression < 0 || compression > 11) {
466 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
467 return true;
468 }
469
470 from->outcompression = compression;
471
472 /* SPTPS or old-style key exchange? */
473
474 if(from->status.sptps) {
475 char buf[strlen(key)];
476 size_t len = b64decode(key, buf, strlen(key));
477
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
481 to prevent storms.
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);
486 send_req_key(from);
487 }
488
489 return true;
490 }
491
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);
497 }
498 }
499
500 send_mtu_info(myself, from, MTU);
501
502 return true;
503 }
504
505 #ifdef DISABLE_LEGACY
506 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
507 return false;
508 #else
509 /* Check and lookup cipher and digest algorithms */
510
511 if(cipher) {
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);
514 return false;
515 }
516 } else {
517 from->outcipher = NULL;
518 }
519
520 if(digest) {
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);
523 return false;
524 }
525 } else {
526 from->outdigest = NULL;
527 }
528
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);
531 return false;
532 }
533
534 /* Process key */
535
536 size_t keylen = hex2bin(key, key, sizeof(key));
537
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);
540 return true;
541 }
542
543 /* Update our copy of the origin's packet key */
544
545 if(from->outcipher && !cipher_set_key(from->outcipher, key, true)) {
546 return false;
547 }
548
549 if(from->outdigest && !digest_set_key(from->outdigest, key, keylen)) {
550 return false;
551 }
552
553 from->status.validkey = true;
554 from->sent_seqno = 0;
555
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);
560 }
561
562 return true;
563 #endif
564 }
565