Moving files, first attempt at gcrypt compatibility, more interface
[tinc] / src / net_setup.c
1 /*
2     net_setup.c -- Setup.
3     Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
4                   2000-2002 Guus Sliepen <guus@sliepen.warande.net>
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
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: net_setup.c,v 1.4 2002/04/28 12:46:26 zarq Exp $
21 */
22
23 #include "config.h"
24
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <netdb.h>
28 #include <netinet/in.h>
29 #ifdef HAVE_LINUX
30  #include <netinet/ip.h>
31  #include <netinet/tcp.h>
32 #endif
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <signal.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40 #include <sys/ioctl.h>
41 /* SunOS really wants sys/socket.h BEFORE net/if.h,
42    and FreeBSD wants these lines below the rest. */
43 #include <arpa/inet.h>
44 #include <sys/socket.h>
45 #include <net/if.h>
46
47 #ifdef USE_OPENSSL
48 #include <openssl/pem.h>
49 #include <openssl/rsa.h>
50 #include <openssl/rand.h>
51 #endif
52
53 #ifdef USE_GCRYPT
54 #include <gcrypt.h>
55 #endif
56
57 #include <utils.h>
58 #include <xalloc.h>
59 #include <avl_tree.h>
60 #include <list.h>
61
62 #include "conf.h"
63 #include "connection.h"
64 #include "meta.h"
65 #include "net.h"
66 #include "netutl.h"
67 #include "process.h"
68 #include "protocol.h"
69 #include "subnet.h"
70 #include "graph.h"
71 #include "process.h"
72 #include "route.h"
73 #include "device.h"
74 #include "event.h"
75 #include "logging.h"
76
77 #include "system.h"
78
79 char *myport;
80
81 int read_rsa_public_key(connection_t *c)
82 {
83   char *key;
84 #ifdef USE_OPENSSL
85   FILE *fp;
86   char *fname;
87 cp
88   if(!c->rsa_key)
89     c->rsa_key = RSA_new();
90 #endif
91 cp
92   
93   /* First, check for simple PublicKey statement */
94
95   if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key))
96     {
97 #ifdef USE_OPENSSL
98       BN_hex2bn(&c->rsa_key->n, key);
99       BN_hex2bn(&c->rsa_key->e, "FFFF");
100 #endif
101 #ifdef USE_GCRYPT
102       int rc = gcry_sexp_build(&c->rsa_key, NULL, "(public-key(rsa(n%s)(e%s)))",
103                                key, "FFFF");
104       if(!rc)
105         {
106           syslog(LOG_ERR, _("gcry_sexp_build error: %d (%s)"),
107                  rc, gcry_strerror(-1));
108           return -1;
109         }
110 #endif
111       free(key);
112       return 0;
113     }
114
115 #ifdef USE_OPENSSL
116   /* Else, check for PublicKeyFile statement and read it */
117
118   if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname))
119     {
120       if(is_safe_path(fname))
121         {
122           if((fp = fopen(fname, "r")) == NULL)
123             {
124               syslog(LOG_ERR, _("Error reading RSA public key file `%s': %s"),
125                      fname, strerror(errno));
126               free(fname);
127               return -1;
128             }
129           free(fname);
130           c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
131           fclose(fp);
132           if(!c->rsa_key)
133             {
134               syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"),
135                      fname, strerror(errno));
136               return -1;
137             }
138           return 0;
139         }
140       else
141         {
142           free(fname);
143           return -1;
144         }
145     }
146
147   /* Else, check if a harnessed public key is in the config file */
148
149   asprintf(&fname, "%s/hosts/%s", confbase, c->name);
150   if((fp = fopen(fname, "r")))
151     {
152       c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
153       fclose(fp);
154     }
155
156   free(fname);
157
158   if(c->rsa_key)
159     return 0;
160   else
161     {
162       syslog(LOG_ERR, _("No public key for %s specified!"), c->name);
163       return -1;
164     }
165 #endif
166 #ifdef USE_GCRYPT
167   syslog(LOG_ERR, _("Only PublicKey statements are supported when using gcrypt for now."));
168   return -1;
169 #endif
170 }
171
172 int read_rsa_private_key(void)
173 {
174 #ifdef USE_OPENSSL
175   FILE *fp;
176   char *fname;
177 #endif
178   char *key;
179 cp
180   if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key))
181     {
182 #ifdef USE_OPENSSL
183       myself->connection->rsa_key = RSA_new();
184       BN_hex2bn(&myself->connection->rsa_key->d, key);
185       BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
186 #endif
187 #ifdef USE_GCRYPT
188       int rc = gcry_sexp_build(&myself->connection->rsa_key, NULL,
189                                "(public-key(rsa(n%s)(e%s)))",
190                                key, "FFFF");
191       if(!rc)
192         {
193           syslog(LOG_ERR, _("gcry_sexp_build error: %d (%s)"),
194                  rc, gcry_strerror(-1));
195           return -1;
196         }
197 #endif
198       free(key);
199       return 0;
200     }
201
202 #ifdef USE_OPENSSL
203   if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
204     asprintf(&fname, "%s/rsa_key.priv", confbase);
205
206   if(is_safe_path(fname))
207     {
208       if((fp = fopen(fname, "r")) == NULL)
209         {
210           syslog(LOG_ERR, _("Error reading RSA private key file `%s': %s"),
211                  fname, strerror(errno));
212           free(fname);
213           return -1;
214         }
215       free(fname);
216       myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
217       fclose(fp);
218       if(!myself->connection->rsa_key)
219         {
220           syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"),
221                  fname, strerror(errno));
222           return -1;
223         }
224       return 0;
225     }
226
227   free(fname);
228   return -1;
229 #endif
230 #ifdef USE_GCRYPT
231   syslog(LOG_ERR, _("Only PrivateKey statements are supported when using gcrypt for now."));
232   return -1;
233 #endif
234 }
235
236 /*
237   Configure node_t myself and set up the local sockets (listen only)
238 */
239 int setup_myself(void)
240 {
241   config_t *cfg;
242   subnet_t *subnet;
243   char *name, *hostname, *mode, *afname, *cipher, *digest;
244   struct addrinfo hint, *ai, *aip;
245   int choice, err;
246 cp
247   myself = new_node();
248   myself->connection = new_connection();
249   init_configuration(&myself->connection->config_tree);
250
251   asprintf(&myself->hostname, _("MYSELF"));
252   asprintf(&myself->connection->hostname, _("MYSELF"));
253
254   myself->connection->options = 0;
255   myself->connection->protocol_version = PROT_CURRENT;
256
257   if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */
258     {
259       syslog(LOG_ERR, _("Name for tinc daemon required!"));
260       return -1;
261     }
262
263   if(check_id(name))
264     {
265       syslog(LOG_ERR, _("Invalid name for myself!"));
266       free(name);
267       return -1;
268     }
269
270   myself->name = name;
271   myself->connection->name = xstrdup(name);
272
273 cp
274   if(read_rsa_private_key())
275     return -1;
276
277   if(read_connection_config(myself->connection))
278     {
279       syslog(LOG_ERR, _("Cannot open host configuration file for myself!"));
280       return -1;
281     }
282
283   if(read_rsa_public_key(myself->connection))
284     return -1;
285 cp
286
287   if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport))
288     asprintf(&myport, "655");
289
290 /* Read in all the subnets specified in the host configuration file */
291
292   cfg = lookup_config(myself->connection->config_tree, "Subnet");
293
294   while(cfg)
295     {
296       if(!get_config_subnet(cfg, &subnet))
297         return -1;
298
299       subnet_add(myself, subnet);
300
301       cfg = lookup_config_next(myself->connection->config_tree, cfg);
302     }
303
304 cp
305   /* Check some options */
306
307   if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice))
308     if(choice)
309       myself->options |= OPTION_INDIRECT;
310
311   if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice))
312     if(choice)
313       myself->options |= OPTION_TCPONLY;
314
315   if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice))
316     if(choice)
317       myself->options |= OPTION_INDIRECT;
318
319   if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice))
320     if(choice)
321       myself->options |= OPTION_TCPONLY;
322
323   if(myself->options & OPTION_TCPONLY)
324     myself->options |= OPTION_INDIRECT;
325
326   if(get_config_string(lookup_config(config_tree, "Mode"), &mode))
327     {
328       if(!strcasecmp(mode, "router"))
329         routing_mode = RMODE_ROUTER;
330       else if (!strcasecmp(mode, "switch"))
331         routing_mode = RMODE_SWITCH;
332       else if (!strcasecmp(mode, "hub"))
333         routing_mode = RMODE_HUB;
334       else
335         {
336           syslog(LOG_ERR, _("Invalid routing mode!"));
337           return -1;
338         }
339       free(mode);
340     }
341   else
342     routing_mode = RMODE_ROUTER;
343
344   get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
345 #if !defined(SOL_IP) || !defined(IP_TOS)
346   if(priorityinheritance)
347     syslog(LOG_WARNING, _("PriorityInheritance not supported on this platform"));
348 #endif
349
350   if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
351     macexpire= 600;
352
353   if(get_config_int(lookup_config(myself->connection->config_tree, "MaxTimeout"), &maxtimeout))
354     {
355       if(maxtimeout <= 0)
356         {
357           syslog(LOG_ERR, _("Bogus maximum timeout!"));
358           return -1;
359         }
360     }
361   else
362     maxtimeout = 900;
363
364   if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname))
365     {
366       if(!strcasecmp(afname, "IPv4"))
367         addressfamily = AF_INET;
368       else if (!strcasecmp(afname, "IPv6"))
369         addressfamily = AF_INET6;
370       else if (!strcasecmp(afname, "any"))
371         addressfamily = AF_UNSPEC;
372       else
373         {
374           syslog(LOG_ERR, _("Invalid address family!"));
375           return -1;
376         }
377       free(afname);
378     }
379   else
380     addressfamily = AF_INET;
381
382   get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);
383 cp
384   /* Generate packet encryption key */
385
386   if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
387     {
388       if(!strcasecmp(cipher, "none"))
389         {
390 #ifdef USE_OPENSSL
391           myself->cipher = NULL;
392 #endif
393 #ifdef USE_GCRYPT
394           myself->cipher = gcry_cipher_open(GCRY_CIPHER_NONE, GCRY_CIPHER_MODE_NONE, 0);
395 #endif
396         }
397       else
398         {
399 #ifdef USE_OPENSSL
400           if(!(myself->cipher = EVP_get_cipherbyname(cipher)))
401 #endif
402 #ifdef USE_GCRYPT
403           /* FIXME */
404           myself->cipher = gcry_cipher_open(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 0);
405           if(0)
406 #endif
407             {
408               syslog(LOG_ERR, _("Unrecognized cipher type!"));
409               return -1;
410             }
411         }
412     }
413   else
414     {
415 #ifdef USE_OPENSSL
416       myself->cipher = EVP_bf_cbc();
417 #endif
418 #ifdef USE_GCRYPT
419       myself->cipher = gcry_cipher_open(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 0);
420 #endif
421     }
422
423 #ifdef USE_OPENSSL
424   if(myself->cipher)
425     myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
426 #endif
427 #ifdef USE_GCRYPT
428   if(myself->cipher)
429     myself->keylength = 16;  /* FIXME */
430 #endif
431   else
432     myself->keylength = 1;
433
434 #ifdef USE_OPENSSL
435   myself->connection->outcipher = EVP_bf_ofb();
436 #endif
437 #ifdef USE_GCRYPT
438   /* FIXME: CHANGE this to something like aes - but openssl
439      compatibility mode for now */
440   myself->connection->outcipher = gcry_cipher_open(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_OFB, 0);
441 #endif
442
443 #ifdef USE_OPENSSL
444   myself->key = (char *)xmalloc(myself->keylength);
445   RAND_pseudo_bytes(myself->key, myself->keylength);
446 #endif
447 #ifdef USE_GCYRPT
448   myself->key = gcry_random_bytes(myself->keylength, GCRY_WEAK_RANDOM);
449 #endif
450
451   if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
452     keylifetime = 3600;
453
454   keyexpires = now + keylifetime;
455
456   /* Check if we want to use message authentication codes... */
457
458   if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
459     {
460       if(!strcasecmp(digest, "none"))
461         {
462 #ifdef USE_OPENSSL
463           myself->digest = NULL;
464 #endif
465 #ifdef USE_GCRYPT
466           myself->digest = gcry_md_open(GCRY_MD_NONE, GCRY_MD_FLAG_HMAC);
467 #endif
468         }
469       else
470         {
471 #ifdef USE_OPENSSL
472           if(!(myself->digest = EVP_get_digestbyname(digest)))
473 #endif
474 #ifdef USE_GCRYPT
475           /* FIXME */
476           if(!(myself->digest = gcry_md_open(GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC)))
477 #endif
478             {
479               syslog(LOG_ERR, _("Unrecognized digest type!"));
480               return -1;
481             }
482         }
483     }
484   else
485 #ifdef USE_OPENSSL
486     myself->digest = EVP_sha1();
487 #endif
488 #ifdef USE_GCRYPT
489     myself->digest = gcry_md_open(GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
490 #endif
491
492 #ifdef USE_OPENSSL
493   myself->connection->outdigest = EVP_sha1();
494 #endif
495 #ifdef USE_GCRYPT
496   myself->connection->outdigest = gcry_md_open(GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
497 #endif
498
499   if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength))
500     {
501       if(myself->digest)
502         {
503 #ifdef USE_OPENSSL
504           if(myself->maclength > myself->digest->md_size)
505             {
506               syslog(LOG_ERR, _("MAC length exceeds size of digest!"));
507               return -1;
508             }
509           else if (myself->maclength < 0)
510             {
511               syslog(LOG_ERR, _("Bogus MAC length!"));
512               return -1;
513             }
514 #endif
515 #ifdef USE_GCRYPT
516           /* FIXME */
517           myself->maclength = 12;
518 #endif
519         }
520     }
521   else
522     myself->maclength = 4;
523
524   myself->connection->outmaclength = 0;
525
526   /* Compression */
527
528   if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression))
529     {
530       if(myself->compression < 0 || myself->compression > 9)
531         {
532           syslog(LOG_ERR, _("Bogus compression level!"));
533           return -1;
534         }
535     }
536   else
537     myself->compression = 0;
538
539   myself->connection->outcompression = 0;
540 cp
541   /* Done */
542
543   myself->nexthop = myself;
544   myself->via = myself;
545   myself->status.active = 1;
546   myself->status.reachable = 1;
547   node_add(myself);
548
549   graph();
550
551 cp
552   /* Open sockets */
553   
554   memset(&hint, 0, sizeof(hint));
555   
556   hint.ai_family = addressfamily;
557   hint.ai_socktype = SOCK_STREAM;
558   hint.ai_protocol = IPPROTO_TCP;
559   hint.ai_flags = AI_PASSIVE;
560
561   if((err = getaddrinfo(NULL, myport, &hint, &ai)) || !ai)
562     {
563       syslog(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(err));
564       return -1;
565     }
566
567   for(aip = ai; aip; aip = aip->ai_next)
568     {
569       if((listen_socket[listen_sockets].tcp = setup_listen_socket((sockaddr_t *)aip->ai_addr)) < 0)
570         continue;
571
572       if((listen_socket[listen_sockets].udp = setup_vpn_in_socket((sockaddr_t *)aip->ai_addr)) < 0)
573         continue;
574
575       if(debug_lvl >= DEBUG_CONNECTIONS)
576         {
577           hostname = sockaddr2hostname((sockaddr_t *)aip->ai_addr);
578           syslog(LOG_NOTICE, _("Listening on %s"), hostname);
579           free(hostname);
580         }
581
582       listen_socket[listen_sockets].sa.sa = *aip->ai_addr;
583       listen_sockets++;
584     }
585
586   freeaddrinfo(ai);
587
588   if(listen_sockets)
589     syslog(LOG_NOTICE, _("Ready"));
590   else
591     {
592       syslog(LOG_ERR, _("Unable to create any listening socket!"));
593       return -1;
594     }
595 cp
596   return 0;
597 }
598
599 /*
600   setup all initial network connections
601 */
602 int setup_network_connections(void)
603 {
604 cp
605   now = time(NULL);
606
607   init_connections();
608   init_subnets();
609   init_nodes();
610   init_edges();
611   init_events();
612   init_requests();
613
614   if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
615     {
616       if(pingtimeout < 1)
617         {
618           pingtimeout = 86400;
619         }
620     }
621   else
622     pingtimeout = 60;
623
624   if(setup_device() < 0)
625     return -1;
626
627   /* Run tinc-up script to further initialize the tap interface */
628   execute_script("tinc-up");
629
630   if(setup_myself() < 0)
631     return -1;
632
633   try_outgoing_connections();
634 cp
635   return 0;
636 }
637
638 /*
639   close all open network connections
640 */
641 void close_network_connections(void)
642 {
643   avl_node_t *node, *next;
644   connection_t *c;
645   int i;
646 cp
647   for(node = connection_tree->head; node; node = next)
648     {
649       next = node->next;
650       c = (connection_t *)node->data;
651       if(c->outgoing)
652         free(c->outgoing->name), free(c->outgoing), c->outgoing = NULL;
653       terminate_connection(c, 0);
654     }
655
656   if(myself && myself->connection)
657     terminate_connection(myself->connection, 0);
658
659   for(i = 0; i < listen_sockets; i++)
660     {
661       close(listen_socket[i].tcp);
662       close(listen_socket[i].udp);
663     }
664
665   exit_requests();
666   exit_events();
667   exit_edges();
668   exit_subnets();
669   exit_nodes();
670   exit_connections();
671
672   execute_script("tinc-down");
673
674   close_device();
675 cp
676   return;
677 }