ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/gvpectrl.C
Revision: 1.22
Committed: Wed Nov 2 06:54:13 2016 UTC (7 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.21: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*
2 pcg 1.2 gvpectrl.C -- the main file for gvpectrl
3 pcg 1.1 Copyright (C) 1998-2002 Ivo Timmermans <ivo@o2w.nl>
4     2000-2002 Guus Sliepen <guus@sliepen.eu.org>
5 root 1.13 2003-2013 Marc Lehmann <gvpe@schmorp.de>
6 pcg 1.1
7     This file is part of GVPE.
8    
9 pcg 1.7 GVPE is free software; you can redistribute it and/or modify it
10     under the terms of the GNU General Public License as published by the
11     Free Software Foundation; either version 3 of the License, or (at your
12     option) any later version.
13    
14     This program is distributed in the hope that it will be useful, but
15     WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17     Public License for more details.
18    
19     You should have received a copy of the GNU General Public License along
20     with this program; if not, see <http://www.gnu.org/licenses/>.
21    
22     Additional permission under GNU GPL version 3 section 7
23    
24     If you modify this Program, or any covered work, by linking or
25     combining it with the OpenSSL project's OpenSSL library (or a modified
26     version of that library), containing parts covered by the terms of the
27     OpenSSL or SSLeay licenses, the licensors of this Program grant you
28     additional permission to convey the resulting work. Corresponding
29     Source for a non-source form of such a combination shall include the
30     source code for the parts of OpenSSL used as well as that of the
31     covered work.
32 pcg 1.1 */
33    
34     #include "config.h"
35    
36     #include <cstdio>
37     #include <cstring>
38     #include <cstdlib>
39    
40     #include <errno.h>
41     #include <fcntl.h>
42     #include <getopt.h>
43     #include <signal.h>
44     #include <sys/stat.h>
45     #include <sys/types.h>
46     #include <unistd.h>
47     #include <signal.h>
48    
49 root 1.13 #include <openssl/bn.h>
50 pcg 1.1 #include <openssl/rand.h>
51     #include <openssl/rsa.h>
52     #include <openssl/pem.h>
53     #include <openssl/evp.h>
54    
55     #include "pidfile.h"
56    
57     #include "conf.h"
58     #include "slog.h"
59     #include "util.h"
60     #include "vpn.h"
61    
62     /* If nonzero, display usage information and exit. */
63     static int show_help;
64    
65     /* If nonzero, print the version on standard output and exit. */
66     static int show_version;
67    
68 pcg 1.2 /* If nonzero, it will attempt to kill a running gvpe and exit. */
69     static int kill_gvpe;
70 pcg 1.1
71 pcg 1.2 /* If nonzero, it will attempt to kill a running gvpe and exit. */
72 pcg 1.1 static int show_config;
73    
74 pcg 1.8 /* If nonzero, do not output anything but warnings/errors/very unusual conditions */
75     static int quiet;
76    
77 root 1.21 /* If nonzero, generate single public/private keypair. */
78     static const char *generate_key;
79    
80 pcg 1.1 /* If nonzero, generate public/private keypair for this net. */
81     static int generate_keys;
82    
83 root 1.15 // output some debugging info, interna constants &c
84     static int debug_info;
85    
86 pcg 1.1 static struct option const long_options[] =
87 root 1.10 {
88     {"config", required_argument, NULL, 'c'},
89     {"kill", optional_argument, NULL, 'k'},
90     {"help", no_argument, &show_help, 1},
91     {"version", no_argument, &show_version, 1},
92 root 1.21 {"generate-key", required_argument, NULL, 'g'},
93     {"generate-keys", no_argument, NULL, 'G'},
94 root 1.10 {"quiet", no_argument, &quiet, 1},
95     {"show-config", no_argument, &show_config, 's'},
96 root 1.15 {"debug-info", no_argument, &debug_info, 1},
97 root 1.10 {NULL, 0, NULL, 0}
98     };
99 pcg 1.1
100     static void
101     usage (int status)
102     {
103     if (status != 0)
104     fprintf (stderr, _("Try `%s --help\' for more information.\n"), get_identity ());
105     else
106     {
107     printf (_("Usage: %s [option]...\n\n"), get_identity ());
108     printf (_
109     (" -c, --config=DIR Read configuration options from DIR.\n"
110 pcg 1.2 " -k, --kill[=SIGNAL] Attempt to kill a running gvpe and exit.\n"
111 root 1.21 " -g, --generate-key=file Generate public/private RSA keypair.\n"
112     " -G, --generate-keys Generate all public/private RSA keypairs.\n"
113 pcg 1.1 " -s, --show-config Display the configuration information.\n"
114 pcg 1.8 " -q, --quiet Be quite quiet.\n"
115 pcg 1.1 " --help Display this help and exit.\n"
116     " --version Output version information and exit.\n\n"));
117 pcg 1.5 printf (_("Report bugs to <gvpe@schmorp.de>.\n"));
118 pcg 1.1 }
119    
120     exit (status);
121     }
122    
123 root 1.10 static void
124 pcg 1.1 parse_options (int argc, char **argv, char **envp)
125     {
126     int r;
127     int option_index = 0;
128    
129 root 1.21 while ((r = getopt_long (argc, argv, "c:k::qg:Gs", long_options, &option_index)) != EOF)
130 pcg 1.1 {
131     switch (r)
132     {
133 root 1.10 case 0: /* long option */
134     break;
135 pcg 1.1
136 root 1.10 case 'c': /* config file */
137     confbase = strdup (optarg);
138     break;
139    
140     case 'k': /* kill old gvpes */
141     if (optarg)
142     {
143     if (!strcasecmp (optarg, "HUP"))
144     kill_gvpe = SIGHUP;
145     else if (!strcasecmp (optarg, "TERM"))
146     kill_gvpe = SIGTERM;
147     else if (!strcasecmp (optarg, "KILL"))
148     kill_gvpe = SIGKILL;
149     else if (!strcasecmp (optarg, "USR1"))
150     kill_gvpe = SIGUSR1;
151     else if (!strcasecmp (optarg, "USR2"))
152     kill_gvpe = SIGUSR2;
153     else if (!strcasecmp (optarg, "INT"))
154     kill_gvpe = SIGINT;
155     else if (!strcasecmp (optarg, "ALRM"))
156     kill_gvpe = SIGALRM;
157     else
158     {
159     kill_gvpe = atoi (optarg);
160    
161     if (!kill_gvpe)
162     {
163     fprintf (stderr,
164     _
165     ("Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n"),
166     optarg);
167     usage (1);
168     }
169     }
170     }
171     else
172     kill_gvpe = SIGTERM;
173    
174     break;
175    
176     case 'g': /* generate public/private keypair */
177 root 1.21 generate_key = optarg;
178     break;
179    
180     case 'G': /* generate public/private keypairs */
181     generate_keys = 1;
182 root 1.10 break;
183    
184     case 's':
185     show_config = 1;
186     break;
187    
188     case 'q':
189     quiet = 1;
190     break;
191 pcg 1.8
192 root 1.10 case '?':
193     usage (1);
194 pcg 1.1
195 root 1.10 default:
196     break;
197 pcg 1.1 }
198     }
199     }
200    
201 root 1.10 // this function prettyprints the key generation process
202 root 1.13 static int
203     indicator (int a, int b, BN_GENCB *cb)
204 pcg 1.1 {
205 pcg 1.8 if (quiet)
206 root 1.13 return 1;
207 pcg 1.8
208 pcg 1.1 switch (a)
209     {
210 root 1.10 case 0:
211     fprintf (stderr, ".");
212     break;
213    
214     case 1:
215     fprintf (stderr, "+");
216     break;
217    
218     case 2:
219     fprintf (stderr, "-");
220     break;
221    
222     case 3:
223     switch (b)
224     {
225     case 0:
226     fprintf (stderr, " p\n");
227     break;
228    
229     case 1:
230     fprintf (stderr, " q\n");
231     break;
232    
233     default:
234     fprintf (stderr, "?");
235     }
236     break;
237 pcg 1.1
238 root 1.10 default:
239     fprintf (stderr, "?");
240 pcg 1.1 }
241 root 1.13
242     return 1;
243 pcg 1.1 }
244    
245     /*
246     * generate public/private RSA keypairs for all hosts that don't have one.
247     */
248 root 1.10 static int
249 root 1.21 keygen (const char *pub, const char *priv)
250     {
251    
252     FILE *pubf = fopen (pub, "ab");
253     if (!pubf || fseek (pubf, 0, SEEK_END))
254     {
255     perror (pub);
256     exit (EXIT_FAILURE);
257     }
258    
259     if (ftell (pubf))
260     {
261     fclose (pubf);
262     return 1;
263     }
264    
265     FILE *privf = fopen (priv, "ab");
266    
267     /* some libcs are buggy and require an extra seek to the end */
268     if (!privf || fseek (privf, 0, SEEK_END))
269     {
270     perror (priv);
271     exit (EXIT_FAILURE);
272     }
273    
274     if (ftell (privf))
275     {
276     fclose (pubf);
277     fclose (privf);
278     return 1;
279     }
280    
281     RSA *rsa = RSA_new ();
282     BIGNUM *e = BN_new ();
283     BN_set_bit (e, 0); BN_set_bit (e, 16); // 0x10001, 65537
284    
285     #if 0
286     #if OPENSSL_VERSION_NUMBER < 0x10100000
287     BN_GENCB cb_100;
288     BN_GENCB *cb = &cb_100;
289     #else
290     BN_GENCB *cb = BN_GENCB_new ();
291     require (cb);
292     #endif
293    
294     BN_GENCB_set (cb, indicator, 0);
295     require (RSA_generate_key_ex (rsa, RSABITS, e, cb));
296     #else
297     require (RSA_generate_key_ex (rsa, RSABITS, e, 0));
298     #endif
299    
300     require (PEM_write_RSAPublicKey (pubf, rsa));
301     require (PEM_write_RSAPrivateKey (privf, rsa, NULL, NULL, 0, NULL, NULL));
302    
303     fclose (pubf);
304     fclose (privf);
305    
306     BN_free (e);
307     RSA_free (rsa);
308    
309     return 0;
310     }
311    
312     static int
313     keygen_all ()
314 pcg 1.1 {
315     char *fname;
316    
317     asprintf (&fname, "%s/pubkey", confbase);
318     mkdir (fname, 0700);
319     free (fname);
320    
321     for (configuration::node_vector::iterator i = conf.nodes.begin (); i != conf.nodes.end (); ++i)
322     {
323     conf_node *node = *i;
324    
325 root 1.15 ::thisnode = node->nodename;
326    
327 root 1.21 char *pub = conf.config_filename ("pubkey/%s", 0);
328     char *priv = conf.config_filename (conf.prikeyfile, "hostkey");
329 pcg 1.1
330 root 1.21 int status = keygen (pub, priv);
331 pcg 1.1
332 root 1.21 if (status == 0)
333 pcg 1.1 {
334 pcg 1.8 if (!quiet)
335 root 1.21 fprintf (stderr, _("generated %d bits key for %s.\n"), RSABITS, node->nodename);
336 pcg 1.1 }
337 root 1.21 else if (status == 1)
338     fprintf (stderr, _("'%s' keypair already exists, skipping node %s.\n"), pub, node->nodename);
339 pcg 1.1
340 root 1.21 free (priv);
341     free (pub);
342     }
343 root 1.15
344 root 1.21 return 0;
345     }
346 pcg 1.1
347 root 1.21 static int
348     keygen_one (const char *pubname)
349     {
350     char *privname;
351 root 1.18
352 root 1.22 asprintf (&privname, "%s.privkey", pubname);
353 root 1.20
354 root 1.21 int status = keygen (pubname, privname);
355 root 1.13
356 root 1.21 if (status == 0)
357     {
358     if (!quiet)
359     fprintf (stderr, _("generated %d bits key as %s.\n"), RSABITS, pubname);
360     }
361     else if (status == 1)
362     {
363     fprintf (stderr, _("'%s' keypair already exists, not generating key.\n"), pubname);
364     exit (EXIT_FAILURE);
365 pcg 1.1 }
366    
367 root 1.21 free(privname);
368 pcg 1.1 }
369    
370     int
371     main (int argc, char **argv, char **envp)
372     {
373     set_identity (argv[0]);
374     log_to (LOGTO_STDERR);
375    
376     setlocale (LC_ALL, "");
377     bindtextdomain (PACKAGE, LOCALEDIR);
378     textdomain (PACKAGE);
379    
380     parse_options (argc, argv, envp);
381    
382     if (show_version)
383     {
384 pcg 1.6 printf (_("%s version %s (built %s %s, protocol version %d.%d)\n"), get_identity (),
385 pcg 1.1 VERSION, __DATE__, __TIME__, PROTOCOL_MAJOR, PROTOCOL_MINOR);
386     printf (_("Built with kernel interface %s/%s.\n"), IFTYPE, IFSUBTYPE);
387     printf (_
388 root 1.13 ("Copyright (C) 2003-2013 Marc Lehmann <gvpe@schmorp.de> and others.\n"
389 pcg 1.1 "See the AUTHORS file for a complete list.\n\n"
390     "vpe comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
391     "and you are welcome to redistribute it under certain conditions;\n"
392     "see the file COPYING for details.\n"));
393    
394     return 0;
395     }
396    
397     if (show_help)
398     usage (0);
399    
400 pcg 1.3 {
401     configuration_parser (conf, false, 0, 0);
402     }
403 pcg 1.1
404 root 1.15 if (debug_info)
405     {
406     printf ("cipher_nid=%d\n", EVP_CIPHER_nid (CIPHER ()));
407     printf ("mac_nid=%d\n", EVP_MD_type (MAC_DIGEST ()));
408     printf ("auth_nid=%d\n", EVP_MD_type (AUTH_DIGEST ()));
409     printf ("sizeof_auth_data=%d\n", sizeof (auth_data));
410     printf ("sizeof_rsa_data=%d\n", sizeof (rsa_data));
411 root 1.17 printf ("sizeof_rsa_data_extra_auth=%d\n", sizeof (((rsa_data *)0)->extra_auth));
412 root 1.16 printf ("raw_overhead=%d\n", VPE_OVERHEAD);
413     printf ("vpn_overhead=%d\n", VPE_OVERHEAD + 6 + 6);
414     printf ("udp_overhead=%d\n", UDP_OVERHEAD + VPE_OVERHEAD + 6 + 6);
415 root 1.15 exit (EXIT_SUCCESS);
416     }
417    
418 root 1.21 if (generate_key)
419     {
420     RAND_load_file (conf.seed_dev, SEED_SIZE);
421     exit (keygen_one (generate_key));
422     }
423    
424 pcg 1.1 if (generate_keys)
425     {
426 root 1.14 RAND_load_file (conf.seed_dev, SEED_SIZE);
427 root 1.21 exit (keygen_all ());
428 pcg 1.1 }
429    
430 pcg 1.2 if (kill_gvpe)
431     exit (kill_other (kill_gvpe));
432 pcg 1.1
433     if (show_config)
434     {
435     conf.print ();
436     exit (EXIT_SUCCESS);
437     }
438    
439     usage (1);
440     }
441 root 1.15