ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/gvpectrl.C
Revision: 1.25
Committed: Thu Oct 6 03:03:09 2022 UTC (19 months, 2 weeks ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.24: +1 -2 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.23 2003-2016 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 root 1.25 /* some libcs are buggy and require an extra seek to the end */
252 root 1.21
253     FILE *pubf = fopen (pub, "ab");
254     if (!pubf || fseek (pubf, 0, SEEK_END))
255     {
256     perror (pub);
257     exit (EXIT_FAILURE);
258     }
259    
260     if (ftell (pubf))
261     {
262     fclose (pubf);
263     return 1;
264     }
265    
266     FILE *privf = fopen (priv, "ab");
267     if (!privf || fseek (privf, 0, SEEK_END))
268     {
269     perror (priv);
270     exit (EXIT_FAILURE);
271     }
272    
273     if (ftell (privf))
274     {
275     fclose (pubf);
276     fclose (privf);
277     return 1;
278     }
279    
280     RSA *rsa = RSA_new ();
281     BIGNUM *e = BN_new ();
282     BN_set_bit (e, 0); BN_set_bit (e, 16); // 0x10001, 65537
283    
284     #if 0
285     #if OPENSSL_VERSION_NUMBER < 0x10100000
286     BN_GENCB cb_100;
287     BN_GENCB *cb = &cb_100;
288     #else
289     BN_GENCB *cb = BN_GENCB_new ();
290     require (cb);
291     #endif
292    
293     BN_GENCB_set (cb, indicator, 0);
294     require (RSA_generate_key_ex (rsa, RSABITS, e, cb));
295     #else
296     require (RSA_generate_key_ex (rsa, RSABITS, e, 0));
297     #endif
298    
299     require (PEM_write_RSAPublicKey (pubf, rsa));
300     require (PEM_write_RSAPrivateKey (privf, rsa, NULL, NULL, 0, NULL, NULL));
301    
302     fclose (pubf);
303     fclose (privf);
304    
305     BN_free (e);
306     RSA_free (rsa);
307    
308     return 0;
309     }
310    
311     static int
312     keygen_all ()
313 pcg 1.1 {
314     char *fname;
315    
316     asprintf (&fname, "%s/pubkey", confbase);
317     mkdir (fname, 0700);
318     free (fname);
319    
320     for (configuration::node_vector::iterator i = conf.nodes.begin (); i != conf.nodes.end (); ++i)
321     {
322     conf_node *node = *i;
323    
324 root 1.15 ::thisnode = node->nodename;
325    
326 root 1.21 char *pub = conf.config_filename ("pubkey/%s", 0);
327     char *priv = conf.config_filename (conf.prikeyfile, "hostkey");
328 pcg 1.1
329 root 1.21 int status = keygen (pub, priv);
330 pcg 1.1
331 root 1.21 if (status == 0)
332 pcg 1.1 {
333 pcg 1.8 if (!quiet)
334 root 1.21 fprintf (stderr, _("generated %d bits key for %s.\n"), RSABITS, node->nodename);
335 pcg 1.1 }
336 root 1.21 else if (status == 1)
337     fprintf (stderr, _("'%s' keypair already exists, skipping node %s.\n"), pub, node->nodename);
338 pcg 1.1
339 root 1.21 free (priv);
340     free (pub);
341     }
342 root 1.15
343 root 1.21 return 0;
344     }
345 pcg 1.1
346 root 1.21 static int
347     keygen_one (const char *pubname)
348     {
349     char *privname;
350 root 1.18
351 root 1.22 asprintf (&privname, "%s.privkey", pubname);
352 root 1.20
353 root 1.21 int status = keygen (pubname, privname);
354 root 1.13
355 root 1.21 if (status == 0)
356     {
357     if (!quiet)
358     fprintf (stderr, _("generated %d bits key as %s.\n"), RSABITS, pubname);
359     }
360     else if (status == 1)
361     {
362     fprintf (stderr, _("'%s' keypair already exists, not generating key.\n"), pubname);
363     exit (EXIT_FAILURE);
364 pcg 1.1 }
365    
366 root 1.24 free (privname);
367    
368     return 0;
369 pcg 1.1 }
370    
371     int
372     main (int argc, char **argv, char **envp)
373     {
374     set_identity (argv[0]);
375     log_to (LOGTO_STDERR);
376    
377     setlocale (LC_ALL, "");
378     bindtextdomain (PACKAGE, LOCALEDIR);
379     textdomain (PACKAGE);
380    
381     parse_options (argc, argv, envp);
382    
383     if (show_version)
384     {
385 pcg 1.6 printf (_("%s version %s (built %s %s, protocol version %d.%d)\n"), get_identity (),
386 pcg 1.1 VERSION, __DATE__, __TIME__, PROTOCOL_MAJOR, PROTOCOL_MINOR);
387     printf (_("Built with kernel interface %s/%s.\n"), IFTYPE, IFSUBTYPE);
388     printf (_
389 root 1.13 ("Copyright (C) 2003-2013 Marc Lehmann <gvpe@schmorp.de> and others.\n"
390 pcg 1.1 "See the AUTHORS file for a complete list.\n\n"
391     "vpe comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
392     "and you are welcome to redistribute it under certain conditions;\n"
393     "see the file COPYING for details.\n"));
394    
395     return 0;
396     }
397    
398     if (show_help)
399     usage (0);
400    
401 pcg 1.3 {
402     configuration_parser (conf, false, 0, 0);
403     }
404 pcg 1.1
405 root 1.15 if (debug_info)
406     {
407     printf ("cipher_nid=%d\n", EVP_CIPHER_nid (CIPHER ()));
408     printf ("mac_nid=%d\n", EVP_MD_type (MAC_DIGEST ()));
409     printf ("auth_nid=%d\n", EVP_MD_type (AUTH_DIGEST ()));
410     printf ("sizeof_auth_data=%d\n", sizeof (auth_data));
411     printf ("sizeof_rsa_data=%d\n", sizeof (rsa_data));
412 root 1.17 printf ("sizeof_rsa_data_extra_auth=%d\n", sizeof (((rsa_data *)0)->extra_auth));
413 root 1.16 printf ("raw_overhead=%d\n", VPE_OVERHEAD);
414     printf ("vpn_overhead=%d\n", VPE_OVERHEAD + 6 + 6);
415     printf ("udp_overhead=%d\n", UDP_OVERHEAD + VPE_OVERHEAD + 6 + 6);
416 root 1.15 exit (EXIT_SUCCESS);
417     }
418    
419 root 1.21 if (generate_key)
420     {
421     RAND_load_file (conf.seed_dev, SEED_SIZE);
422     exit (keygen_one (generate_key));
423     }
424    
425 pcg 1.1 if (generate_keys)
426     {
427 root 1.14 RAND_load_file (conf.seed_dev, SEED_SIZE);
428 root 1.21 exit (keygen_all ());
429 pcg 1.1 }
430    
431 pcg 1.2 if (kill_gvpe)
432     exit (kill_other (kill_gvpe));
433 pcg 1.1
434     if (show_config)
435     {
436     conf.print ();
437     exit (EXIT_SUCCESS);
438     }
439    
440     usage (1);
441     }
442 root 1.15