Moving files, first attempt at gcrypt compatibility, more interface
[tinc] / src / pokey / pokey.c
1 /*
2     tincd.c -- the main file for tincd
3     Copyright (C) 1998-2002 Ivo Timmermans <ivo@o2w.nl>
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: pokey.c,v 1.3 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 <getopt.h>
28 #include <signal.h>
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <syslog.h>
32 #include <unistd.h>
33 #include <signal.h>
34 #include <string.h>
35 #include <termios.h>
36
37 #ifdef HAVE_SYS_IOCTL_H
38 # include <sys/ioctl.h>
39 #endif
40
41 #include <openssl/rand.h>
42 #include <openssl/rsa.h>
43 #include <openssl/pem.h>
44 #include <openssl/evp.h>
45
46 #include <gtk/gtk.h>
47 #include <glade/glade.h>
48
49 #include <utils.h>
50 #include <xalloc.h>
51
52 #include "conf.h"
53 #include "interface.h"
54 #include "net.h"
55 #include "netutl.h"
56 #include "process.h"
57 #include "protocol.h"
58 #include "subnet.h"
59 #include "logging.h"
60
61 #include "system.h"
62
63 /* The name this program was run with. */
64 char *program_name;
65
66 /* If nonzero, display usage information and exit. */
67 int show_help;
68
69 /* If nonzero, print the version on standard output and exit.  */
70 int show_version;
71
72 /* If nonzero, it will attempt to kill a running tincd and exit. */
73 int kill_tincd = 0;
74
75 /* If nonzero, generate public/private keypair for this host/net. */
76 int generate_keys = 0;
77
78 /* If nonzero, use null ciphers and skip all key exchanges. */
79 int bypass_security = 0;
80
81 char *identname;                 /* program name for syslog */
82 char *pidfilename;               /* pid file location */
83 char **g_argv;                   /* a copy of the cmdline arguments */
84 char **environment;              /* A pointer to the environment on startup */
85
86 /* GTK Interface */
87 GladeXML *xml = NULL;
88
89
90 static struct option const long_options[] =
91 {
92   { "config", required_argument, NULL, 'c' },
93   { "kill", optional_argument, NULL, 'k' },
94   { "net", required_argument, NULL, 'n' },
95   { "help", no_argument, &show_help, 1 },
96   { "version", no_argument, &show_version, 1 },
97   { "no-detach", no_argument, &do_detach, 0 },
98   { "generate-keys", optional_argument, NULL, 'K'},
99   { "debug", optional_argument, NULL, 'd'},
100   { "bypass-security", no_argument, &bypass_security, 1 },
101   { NULL, 0, NULL, 0 }
102 };
103
104 static void
105 usage(int status)
106 {
107   if(status != 0)
108     fprintf(stderr, _("Try `%s --help\' for more information.\n"), program_name);
109   else
110     {
111       printf(_("Usage: %s [option]...\n\n"), program_name);
112       printf(_("  -c, --config=DIR           Read configuration options from DIR.\n"
113                "  -D, --no-detach            Don't fork and detach.\n"
114                "  -d, --debug[=LEVEL]        Increase debug level or set it to LEVEL.\n"
115                "  -k, --kill[=SIGNAL]        Attempt to kill a running tincd and exit.\n"
116                "  -n, --net=NETNAME          Connect to net NETNAME.\n"));
117       printf(_("  -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n"
118                "      --help                 Display this help and exit.\n"
119                "      --version              Output version information and exit.\n\n"));
120       printf(_("Report bugs to tinc@nl.linux.org.\n"));
121     }
122   exit(status);
123 }
124
125 void
126 parse_options(int argc, char **argv, char **envp)
127 {
128   int r;
129   int option_index = 0;
130   
131   while((r = getopt_long(argc, argv, "c:Dd::k::n:K::", long_options, &option_index)) != EOF)
132     {
133       switch(r)
134         {
135         case 0: /* long option */
136           break;
137         case 'c': /* config file */
138           confbase = xmalloc(strlen(optarg)+1);
139           strcpy(confbase, optarg);
140           break;
141         case 'D': /* no detach */
142           do_detach = 0;
143           break;
144         case 'd': /* inc debug level */
145           if(optarg)
146             debug_lvl = atoi(optarg);
147           else
148             debug_lvl++;
149           break;
150         case 'k': /* kill old tincds */
151           kill_tincd = optarg?atoi(optarg):SIGTERM;
152           break;
153         case 'n': /* net name given */
154           netname = xmalloc(strlen(optarg)+1);
155           strcpy(netname, optarg);
156           break;
157         case 'K': /* generate public/private keypair */
158           if(optarg)
159             {
160               generate_keys = atoi(optarg);
161               if(generate_keys < 512)
162                 {
163                   fprintf(stderr, _("Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n"),
164                           optarg);
165                   usage(1);
166                 }
167               generate_keys &= ~7;      /* Round it to bytes */
168             }
169           else
170             generate_keys = 1024;
171           break;
172         case '?':
173           usage(1);
174         default:
175           break;
176         }
177     }
178 }
179
180 /* This function prettyprints the key generation process */
181
182 void indicator(int a, int b, void *p)
183 {
184   switch(a)
185   {
186     case 0:
187       fprintf(stderr, ".");
188       break;
189     case 1:
190       fprintf(stderr, "+");
191       break;
192     case 2:
193       fprintf(stderr, "-");
194       break;
195     case 3:
196       switch(b)
197         {
198           case 0:
199             fprintf(stderr, " p\n");      
200             break;
201           case 1:
202             fprintf(stderr, " q\n");
203             break;
204           default:
205             fprintf(stderr, "?");
206          }
207        break;
208     default:
209       fprintf(stderr, "?");
210   }
211 }
212
213 /*
214   Generate a public/private RSA keypair, and ask for a file to store
215   them in.
216 */
217 int keygen(int bits)
218 {
219   RSA *rsa_key;
220   FILE *f;
221   char *name = NULL;
222   char *filename;
223
224   fprintf(stderr, _("Generating %d bits keys:\n"), bits);
225   rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL);
226
227   if(!rsa_key)
228     {
229       fprintf(stderr, _("Error during key generation!\n"));
230       return -1;
231     }
232   else
233     fprintf(stderr, _("Done.\n"));
234
235   get_config_string(lookup_config(config_tree, "Name"), &name);
236
237   if(name)
238     asprintf(&filename, "%s/hosts/%s", confbase, name);
239   else
240     asprintf(&filename, "%s/rsa_key.pub", confbase);
241
242   if((f = ask_and_safe_open(filename, _("public RSA key"), "a")) == NULL)
243     return -1;
244
245   if(ftell(f))
246     fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n"));
247
248   PEM_write_RSAPublicKey(f, rsa_key);
249   fclose(f);
250   free(filename);
251   
252   asprintf(&filename, "%s/rsa_key.priv", confbase);
253   if((f = ask_and_safe_open(filename, _("private RSA key"), "a")) == NULL)
254     return -1;
255
256   if(ftell(f))
257     fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n"));
258
259   PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL);
260   fclose(f);
261   free(filename);
262
263   return 0;
264 }
265
266 /*
267   Set all files and paths according to netname
268 */
269 void make_names(void)
270 {
271   if(netname)
272     {
273       if(!pidfilename)
274         asprintf(&pidfilename, LOCALSTATEDIR "/run/tinc.%s.pid", netname);
275       if(!confbase)
276         asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname);
277       else
278         log(0, LOG_INFO,
279             _("Both netname and configuration directory given, using the latter..."));
280       if(!identname)
281         asprintf(&identname, "tinc.%s", netname);
282     }
283   else
284     {
285       if(!pidfilename)
286         pidfilename = LOCALSTATEDIR "/run/tinc.pid";
287       if(!confbase)
288         asprintf(&confbase, "%s/tinc", CONFDIR);
289       if(!identname)
290         identname = "tinc";
291     }
292 }
293
294 int
295 main(int argc, char **argv, char **envp)
296 {
297   char *fake_argv[] = { argv[0], NULL };
298   program_name = argv[0];
299
300   setlocale (LC_ALL, "");
301   bindtextdomain (PACKAGE, LOCALEDIR);
302   textdomain (PACKAGE);
303
304   environment = envp;
305   parse_options(argc, argv, envp);
306
307   if(show_version)
308     {
309       printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE, VERSION, __DATE__, __TIME__, PROT_CURRENT);
310       printf(_("Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n"
311                "See the AUTHORS file for a complete list.\n\n"
312                "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
313                "and you are welcome to redistribute it under certain conditions;\n"
314                "see the file COPYING for details.\n"));
315
316       return 0;
317     }
318
319   if(show_help)
320     usage(0);
321
322   log_add_hook(log_default);
323
324   gnome_init("Pokey", "0.0", 1, fake_argv);
325
326   g_argv = argv;
327
328   make_names();
329   init_configuration(&config_tree);
330
331   /* Slllluuuuuuurrrrp! */
332 cp
333   RAND_load_file("/dev/urandom", 1024);
334
335 #ifdef HAVE_SSLEAY_ADD_ALL_ALGORITHMS
336   SSLeay_add_all_algorithms();
337 #else
338   OpenSSL_add_all_algorithms();
339 #endif
340
341 cp
342   if(read_server_config())
343     exit(1);
344 cp
345   setup_signals();
346
347   if(init_interface())
348     {
349       log(0, TLOG_ERROR,
350           _("Could not setup all necessary interface elements.\n"));
351       exit(1);
352     }
353   
354   if(!setup_network_connections())
355     {
356       main_loop();
357       cleanup_and_exit(1);
358     }
359
360   log_add_hook(log_default);
361   
362   log(0, TLOG_ERROR,
363       _("Could not set up network connections"));
364   cp_trace();
365
366   return 1;
367 }