GitHub CI: update list of container images
[tinc] / src / protocol_key.c
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 "protocol.h"
31 #include "route.h"
32 #include "sptps.h"
33 #include "utils.h"
34 #include "compression.h"
35 #include "random.h"
36 #include "xalloc.h"
37
38 void send_key_changed(void) {
39 #ifndef DISABLE_LEGACY
40         send_request(everyone, "%d %x %s", KEY_CHANGED, prng(UINT32_MAX), myself->name);
41
42         /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
43
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);
47                 }
48         }
49
50 #endif
51
52         /* Force key exchange for connections using SPTPS */
53
54         if(experimental) {
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);
58                         }
59                 }
60         }
61 }
62
63 bool key_changed_h(connection_t *c, const char *request) {
64         char name[MAX_STRING_SIZE];
65         node_t *n;
66
67         if(sscanf(request, "%*d %*x " MAX_STRING, name) != 1) {
68                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED",
69                        c->name, c->hostname);
70                 return false;
71         }
72
73         if(seen_request(request)) {
74                 return true;
75         }
76
77         n = lookup_node(name);
78
79         if(!n) {
80                 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
81                        "KEY_CHANGED", c->name, c->hostname, name);
82                 return true;
83         }
84
85         if(!n->status.sptps) {
86                 n->status.validkey = false;
87                 n->last_req_key = 0;
88         }
89
90         /* Tell the others */
91
92         if(!tunnelserver) {
93                 forward_request(c, request);
94         }
95
96         return true;
97 }
98
99 static bool send_sptps_data_myself(void *handle, uint8_t type, const void *data, size_t len) {
100         return send_sptps_data(handle, myself, type, data, len);
101 }
102
103 static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
104         (void)type;
105         node_t *to = handle;
106         to->sptps.send_data = send_sptps_data_myself;
107
108         char *buf = alloca(B64_SIZE(len));
109         b64encode_tinc(data, buf, len);
110
111         return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
112 }
113
114 bool send_req_key(node_t *to) {
115         if(to->status.sptps) {
116                 if(!node_read_ecdsa_public_key(to)) {
117                         logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", to->name, to->hostname);
118                         send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY);
119                         return true;
120                 }
121
122                 const size_t labellen = 25 + strlen(myself->name) + strlen(to->name);
123                 char *label = alloca(labellen);
124                 snprintf(label, labellen, "tinc UDP key expansion %s %s", myself->name, to->name);
125
126                 sptps_stop(&to->sptps);
127                 to->status.validkey = false;
128                 to->status.waitingforkey = true;
129                 to->last_req_key = now.tv_sec;
130                 to->incompression = myself->incompression;
131                 return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, labellen, send_initial_sptps_data, receive_sptps_record);
132         }
133
134         return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
135 }
136
137 /* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
138
139 static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
140         (void)c;
141
142         /* If this is a SPTPS packet, see if sending UDP info helps.
143            Note that we only do this if we're the destination or the static relay;
144            otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
145         if((reqno == REQ_KEY || reqno == SPTPS_PACKET) && to->via == myself) {
146                 send_udp_info(myself, from);
147         }
148
149         if(reqno == SPTPS_PACKET) {
150                 /* This is a SPTPS data packet. */
151
152                 char buf[MAX_STRING_SIZE];
153                 size_t len;
154
155                 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode_tinc(buf, buf, strlen(buf)))) {
156                         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");
157                         return true;
158                 }
159
160                 if(to != myself) {
161                         /* We don't just forward the request, because we want to use UDP if it's available. */
162                         if(forwarding_mode == FMODE_INTERNAL) {
163                                 send_sptps_data(to, from, 0, buf, len);
164                                 try_tx(to, true);
165                         }
166                 } else {
167                         /* The packet is for us */
168                         if(!sptps_receive_data(&from->sptps, buf, len)) {
169                                 /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
170                                    so let's restart SPTPS in case that helps. But don't do that too often
171                                    to prevent storms. */
172                                 if(from->last_req_key < now.tv_sec - 10) {
173                                         logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
174                                         send_req_key(from);
175                                 }
176
177                                 return true;
178                         }
179
180                         send_mtu_info(myself, from, MTU);
181                 }
182
183                 return true;
184         }
185
186         /* Requests that are not SPTPS data packets are forwarded as-is. */
187
188         if(to != myself) {
189                 return send_request(to->nexthop->connection, "%s", request);
190         }
191
192         /* The request is for us */
193
194         switch(reqno) {
195         case REQ_PUBKEY: {
196                 if(!node_read_ecdsa_public_key(from)) {
197                         /* Request their key *before* we send our key back. Otherwise the first SPTPS packet from them will get dropped. */
198                         logger(DEBUG_PROTOCOL, LOG_DEBUG, "Preemptively requesting Ed25519 key for %s (%s)", from->name, from->hostname);
199                         send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
200                 }
201
202                 char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
203                 send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey);
204                 free(pubkey);
205                 return true;
206         }
207
208         case ANS_PUBKEY: {
209                 if(node_read_ecdsa_public_key(from)) {
210                         logger(DEBUG_PROTOCOL, LOG_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname);
211                         return true;
212                 }
213
214                 char pubkey[MAX_STRING_SIZE];
215
216                 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) {
217                         logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey");
218                         return true;
219                 }
220
221                 logger(DEBUG_PROTOCOL, LOG_INFO, "Learned Ed25519 public key from %s (%s)", from->name, from->hostname);
222                 append_config_file(from->name, "Ed25519PublicKey", pubkey);
223                 return true;
224         }
225
226         case REQ_KEY: {
227                 if(!node_read_ecdsa_public_key(from)) {
228                         logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", from->name, from->hostname);
229                         send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
230                         return true;
231                 }
232
233                 if(from->sptps.label) {
234                         logger(DEBUG_ALWAYS, LOG_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name);
235                 }
236
237                 char buf[MAX_STRING_SIZE];
238                 size_t len;
239
240                 if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode_tinc(buf, buf, strlen(buf)))) {
241                         logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data");
242                         return true;
243                 }
244
245                 const size_t labellen = 25 + strlen(from->name) + strlen(myself->name);
246                 char *label = alloca(labellen);
247                 snprintf(label, labellen, "tinc UDP key expansion %s %s", from->name, myself->name);
248                 sptps_stop(&from->sptps);
249                 from->status.validkey = false;
250                 from->status.waitingforkey = true;
251                 from->last_req_key = now.tv_sec;
252                 sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, labellen, send_sptps_data_myself, receive_sptps_record);
253                 sptps_receive_data(&from->sptps, buf, len);
254                 send_mtu_info(myself, from, MTU);
255                 return true;
256         }
257
258         default:
259                 logger(DEBUG_ALWAYS, LOG_ERR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request);
260                 return true;
261         }
262 }
263
264 bool req_key_h(connection_t *c, const char *request) {
265         char from_name[MAX_STRING_SIZE];
266         char to_name[MAX_STRING_SIZE];
267         node_t *from, *to;
268         int reqno = 0;
269
270         if(sscanf(request, "%*d " MAX_STRING " " MAX_STRING " %d", from_name, to_name, &reqno) < 2) {
271                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name,
272                        c->hostname);
273                 return false;
274         }
275
276         if(!check_id(from_name) || !check_id(to_name)) {
277                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name");
278                 return false;
279         }
280
281         from = lookup_node(from_name);
282
283         if(!from) {
284                 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
285                        "REQ_KEY", c->name, c->hostname, from_name);
286                 return true;
287         }
288
289         to = lookup_node(to_name);
290
291         if(!to) {
292                 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
293                        "REQ_KEY", c->name, c->hostname, to_name);
294                 return true;
295         }
296
297         /* Check if this key request is for us */
298
299         if(to == myself) {                      /* Yes */
300                 if(!from->status.reachable) {
301                         logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which is not reachable",
302                                "REQ_KEY", c->name, c->hostname, from_name);
303                         return true;
304                 }
305
306                 /* Is this an extended REQ_KEY message? */
307                 if(experimental && reqno) {
308                         return req_key_ext_h(c, request, from, to, reqno);
309                 }
310
311                 /* No, just send our key back */
312                 send_ans_key(from);
313         } else {
314                 if(tunnelserver) {
315                         return true;
316                 }
317
318                 if(!to->status.reachable) {
319                         logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
320                                "REQ_KEY", c->name, c->hostname, to_name);
321                         return true;
322                 }
323
324                 /* Is this an extended REQ_KEY message? */
325                 if(experimental && reqno) {
326                         return req_key_ext_h(c, request, from, to, reqno);
327                 }
328
329                 send_request(to->nexthop->connection, "%s", request);
330         }
331
332         return true;
333 }
334
335 bool send_ans_key(node_t *to) {
336         if(to->status.sptps) {
337                 abort();
338         }
339
340 #ifdef DISABLE_LEGACY
341         return false;
342 #else
343         size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
344         size_t keyhexlen = HEX_SIZE(keylen);
345         char *key = alloca(keyhexlen);
346
347         randomize(key, keylen);
348
349         cipher_free(to->incipher);
350         to->incipher = NULL;
351
352         digest_free(to->indigest);
353         to->indigest = NULL;
354
355         if(myself->incipher) {
356                 to->incipher = cipher_alloc();
357
358                 if(!cipher_open_by_nid(to->incipher, cipher_get_nid(myself->incipher))) {
359                         abort();
360                 }
361
362                 if(!cipher_set_key(to->incipher, key, false)) {
363                         abort();
364                 }
365         }
366
367         if(myself->indigest) {
368                 to->indigest = digest_alloc();
369
370                 if(!digest_open_by_nid(to->indigest,
371                                        digest_get_nid(myself->indigest),
372                                        digest_length(myself->indigest))) {
373                         abort();
374                 }
375
376                 if(!digest_set_key(to->indigest, key, keylen)) {
377                         abort();
378                 }
379         }
380
381         to->incompression = myself->incompression;
382
383         bin2hex(key, key, keylen);
384
385         // Reset sequence number and late packet window
386         to->received_seqno = 0;
387         to->received = 0;
388
389         if(replaywin) {
390                 memset(to->late, 0, replaywin);
391         }
392
393         to->status.validkey_in = true;
394
395         bool sent = send_request(to->nexthop->connection, "%d %s %s %s %d %d %lu %d", ANS_KEY,
396                                  myself->name, to->name, key,
397                                  cipher_get_nid(to->incipher),
398                                  digest_get_nid(to->indigest),
399                                  (unsigned long)digest_length(to->indigest),
400                                  to->incompression);
401
402         memzero(key, keyhexlen);
403
404         return sent;
405 #endif
406 }
407
408 bool ans_key_h(connection_t *c, const char *request) {
409         char from_name[MAX_STRING_SIZE];
410         char to_name[MAX_STRING_SIZE];
411         char key[MAX_STRING_SIZE];
412         char address[MAX_STRING_SIZE] = "";
413         char port[MAX_STRING_SIZE] = "";
414         int cipher, digest;
415         unsigned long maclength;
416         int compression;
417         node_t *from, *to;
418
419         if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %lu %d "MAX_STRING" "MAX_STRING,
420                         from_name, to_name, key, &cipher, &digest, &maclength,
421                         &compression, address, port) < 7) {
422                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
423                        c->hostname);
424                 return false;
425         }
426
427         if(!check_id(from_name) || !check_id(to_name)) {
428                 logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
429                 return false;
430         }
431
432         from = lookup_node(from_name);
433
434         if(!from) {
435                 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
436                        "ANS_KEY", c->name, c->hostname, from_name);
437                 return true;
438         }
439
440         to = lookup_node(to_name);
441
442         if(!to) {
443                 logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
444                        "ANS_KEY", c->name, c->hostname, to_name);
445                 return true;
446         }
447
448         /* Forward it if necessary */
449
450         if(to != myself) {
451                 if(tunnelserver) {
452                         return true;
453                 }
454
455                 if(!to->status.reachable) {
456                         logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
457                                "ANS_KEY", c->name, c->hostname, to_name);
458                         return true;
459                 }
460
461                 if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
462                         char *address, *port;
463                         logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
464                         sockaddr2str(&from->address, &address, &port);
465                         send_request(to->nexthop->connection, "%s %s %s", request, address, port);
466                         free(address);
467                         free(port);
468                         return true;
469                 }
470
471                 return send_request(to->nexthop->connection, "%s", request);
472         }
473
474 #ifndef DISABLE_LEGACY
475         /* Don't use key material until every check has passed. */
476         cipher_free(from->outcipher);
477         from->outcipher = NULL;
478
479         digest_free(from->outdigest);
480         from->outdigest = NULL;
481 #endif
482
483         if(!from->status.sptps) {
484                 from->status.validkey = false;
485         }
486
487         switch(compression) {
488         case COMPRESS_LZ4:
489 #ifdef HAVE_LZ4
490                 break;
491 #else
492                 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
493                 logger(DEBUG_ALWAYS, LOG_ERR, "LZ4 compression is unavailable on this node.");
494                 return true;
495 #endif
496
497         case COMPRESS_LZO_HI:
498         case COMPRESS_LZO_LO:
499 #ifdef HAVE_LZO
500                 break;
501 #else
502                 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
503                 logger(DEBUG_ALWAYS, LOG_ERR, "LZO compression is unavailable on this node.");
504                 return true;
505 #endif
506
507         case COMPRESS_ZLIB_9:
508         case COMPRESS_ZLIB_8:
509         case COMPRESS_ZLIB_7:
510         case COMPRESS_ZLIB_6:
511         case COMPRESS_ZLIB_5:
512         case COMPRESS_ZLIB_4:
513         case COMPRESS_ZLIB_3:
514         case COMPRESS_ZLIB_2:
515         case COMPRESS_ZLIB_1:
516 #ifdef HAVE_ZLIB
517                 break;
518 #else
519                 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
520                 logger(DEBUG_ALWAYS, LOG_ERR, "ZLIB compression is unavailable on this node.");
521                 return true;
522 #endif
523
524         case COMPRESS_NONE:
525                 break;
526
527         default:
528                 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
529                 logger(DEBUG_ALWAYS, LOG_ERR, "Compression level %i is unrecognized by this node.", compression);
530                 return true;
531         }
532
533         from->outcompression = compression;
534
535         /* SPTPS or old-style key exchange? */
536
537         if(from->status.sptps) {
538                 const size_t buflen = strlen(key);
539                 uint8_t *buf = alloca(buflen);
540                 size_t len = b64decode_tinc(key, buf, buflen);
541
542                 if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
543                         /* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
544                            so let's restart SPTPS in case that helps. But don't do that too often
545                            to prevent storms.
546                            Note that simply relying on handshake timeout is not enough, because
547                            that doesn't apply to key regeneration. */
548                         if(from->last_req_key < now.tv_sec - 10) {
549                                 logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
550                                 send_req_key(from);
551                         }
552
553                         return true;
554                 }
555
556                 if(from->status.validkey) {
557                         if(*address && *port) {
558                                 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
559                                 sockaddr_t sa = str2sockaddr(address, port);
560                                 update_node_udp(from, &sa);
561                         }
562                 }
563
564                 send_mtu_info(myself, from, MTU);
565
566                 return true;
567         }
568
569 #ifdef DISABLE_LEGACY
570         logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
571         return false;
572 #else
573         /* Check and lookup cipher and digest algorithms */
574
575         if(cipher) {
576                 from->outcipher = cipher_alloc();
577
578                 if(!cipher_open_by_nid(from->outcipher, cipher)) {
579                         cipher_free(from->outcipher);
580                         from->outcipher = NULL;
581                         logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
582                         return false;
583                 }
584         } else {
585                 from->outcipher = NULL;
586         }
587
588         if(digest) {
589                 from->outdigest = digest_alloc();
590
591                 if(!digest_open_by_nid(from->outdigest, digest, maclength)) {
592                         digest_free(from->outdigest);
593                         from->outdigest = NULL;
594                         logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
595                         return false;
596                 }
597         } else {
598                 from->outdigest = NULL;
599         }
600
601         if(maclength != digest_length(from->outdigest)) {
602                 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
603                 return false;
604         }
605
606         /* Process key */
607
608         size_t keylen = hex2bin(key, key, sizeof(key));
609
610         if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
611                 logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
612                 return true;
613         }
614
615         /* Update our copy of the origin's packet key */
616
617         if(from->outcipher && !cipher_set_key(from->outcipher, key, true)) {
618                 return false;
619         }
620
621         if(from->outdigest && !digest_set_key(from->outdigest, key, keylen)) {
622                 return false;
623         }
624
625         from->status.validkey = true;
626         from->sent_seqno = 0;
627
628         if(*address && *port) {
629                 logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
630                 sockaddr_t sa = str2sockaddr(address, port);
631                 update_node_udp(from, &sa);
632         }
633
634         return true;
635 #endif
636 }