ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/conf.C
Revision: 1.67
Committed: Thu Oct 25 04:32:27 2018 UTC (5 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.66: +19 -7 lines
Log Message:
3.1

File Contents

# User Rev Content
1 pcg 1.1 /*
2 root 1.55 conf.C -- configuration code
3 root 1.67 Copyright (C) 2003-2008,2011,2018 Marc Lehmann <gvpe@schmorp.de>
4 pcg 1.1
5 pcg 1.31 This file is part of GVPE.
6    
7 pcg 1.44 GVPE is free software; you can redistribute it and/or modify it
8     under the terms of the GNU General Public License as published by the
9     Free Software Foundation; either version 3 of the License, or (at your
10     option) any later version.
11    
12     This program is distributed in the hope that it will be useful, but
13     WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15     Public License for more details.
16    
17     You should have received a copy of the GNU General Public License along
18     with this program; if not, see <http://www.gnu.org/licenses/>.
19    
20     Additional permission under GNU GPL version 3 section 7
21    
22     If you modify this Program, or any covered work, by linking or
23     combining it with the OpenSSL project's OpenSSL library (or a modified
24     version of that library), containing parts covered by the terms of the
25     OpenSSL or SSLeay licenses, the licensors of this Program grant you
26     additional permission to convey the resulting work. Corresponding
27     Source for a non-source form of such a combination shall include the
28     source code for the parts of OpenSSL used as well as that of the
29     covered work.
30 pcg 1.1 */
31    
32     #include "config.h"
33    
34     #include <cstdio>
35     #include <cstdlib>
36     #include <cstring>
37    
38     #include <errno.h>
39     #include <netdb.h>
40     #include <sys/stat.h>
41     #include <sys/types.h>
42     #include <unistd.h>
43 root 1.59 #include <pwd.h>
44 pcg 1.1
45 pcg 1.17 #include "netcompat.h"
46 pcg 1.5
47 pcg 1.1 #include <openssl/err.h>
48     #include <openssl/pem.h>
49     #include <openssl/rsa.h>
50     #include <openssl/rand.h>
51 pcg 1.22 #include <openssl/bn.h>
52 pcg 1.1
53     #include "conf.h"
54     #include "slog.h"
55     #include "util.h"
56    
57     char *confbase;
58     char *thisnode;
59     char *identname;
60    
61     struct configuration conf;
62    
63 root 1.52 u8
64     best_protocol (u8 protset)
65 pcg 1.7 {
66 pcg 1.13 if (protset & PROT_IPv4 ) return PROT_IPv4;
67     if (protset & PROT_ICMPv4) return PROT_ICMPv4;
68     if (protset & PROT_UDPv4 ) return PROT_UDPv4;
69     if (protset & PROT_TCPv4 ) return PROT_TCPv4;
70 pcg 1.24 if (protset & PROT_DNSv4 ) return PROT_DNSv4;
71 pcg 1.7
72 pcg 1.9 return 0;
73 pcg 1.7 }
74    
75 root 1.52 const char *
76     strprotocol (u8 protocol)
77 pcg 1.7 {
78 pcg 1.13 if (protocol & PROT_IPv4 ) return "rawip";
79     if (protocol & PROT_ICMPv4) return "icmp";
80     if (protocol & PROT_UDPv4 ) return "udp";
81     if (protocol & PROT_TCPv4 ) return "tcp";
82 pcg 1.24 if (protocol & PROT_DNSv4 ) return "dns";
83 pcg 1.7
84     return "<unknown>";
85     }
86    
87 pcg 1.42 static bool
88     match_list (const vector<const char *> &list, const char *str)
89     {
90     for (vector<const char *>::const_iterator i = list.end (); i-- > list.begin (); )
91     if ((*i)[0] == '*' && !(*i)[1])
92     return true;
93     else if (!strcmp (*i, str))
94     return true;
95    
96     return false;
97     }
98    
99     bool
100 pcg 1.46 conf_node::may_direct (struct conf_node *other)
101 pcg 1.42 {
102     if (match_list (allow_direct, other->nodename))
103     return true;
104    
105     if (match_list (deny_direct, other->nodename))
106     return false;
107    
108     return true;
109     }
110    
111 pcg 1.12 conf_node::~conf_node ()
112 pcg 1.1 {
113 pcg 1.39 #if 0
114     // does not work, because string pointers etc. are shared
115     // is not called, however
116 pcg 1.12 if (rsa_key)
117     RSA_free (rsa_key);
118    
119     free (nodename);
120     free (hostname);
121 pcg 1.39 free (if_up_data);
122 pcg 1.30 #if ENABLE_DNS
123 pcg 1.28 free (domain);
124 pcg 1.30 free (dns_hostname);
125     #endif
126 pcg 1.39 #endif
127 pcg 1.1 }
128    
129 root 1.52 void
130     configuration::init ()
131 pcg 1.1 {
132     memset (this, 0, sizeof (*this));
133    
134 pcg 1.19 mtu = DEFAULT_MTU;
135 pcg 1.50 nfmark = 0;
136 pcg 1.1 rekey = DEFAULT_REKEY;
137     keepalive = DEFAULT_KEEPALIVE;
138 pcg 1.2 llevel = L_INFO;
139 pcg 1.5 ip_proto = IPPROTO_GRE;
140 pcg 1.16 #if ENABLE_ICMP
141 pcg 1.13 icmp_type = ICMP_ECHOREPLY;
142 pcg 1.16 #endif
143 pcg 1.1
144 pcg 1.5 default_node.udp_port = DEFAULT_UDPPORT;
145 pcg 1.24 default_node.tcp_port = DEFAULT_UDPPORT; // ehrm
146 pcg 1.1 default_node.connectmode = conf_node::C_ALWAYS;
147     default_node.compress = true;
148 pcg 1.29 default_node.protocols = 0;
149 pcg 1.27 default_node.max_retry = DEFAULT_MAX_RETRY;
150 pcg 1.43 default_node.max_ttl = DEFAULT_MAX_TTL;
151     default_node.max_queue = DEFAULT_MAX_QUEUE;
152 pcg 1.39 default_node.if_up_data = strdup ("");
153 pcg 1.25
154 pcg 1.30 #if ENABLE_DNS
155 pcg 1.32 default_node.dns_port = 0; // default is 0 == client
156 pcg 1.38
157 root 1.55 dns_case_preserving = true;
158 pcg 1.38 dns_forw_host = strdup ("127.0.0.1");
159     dns_forw_port = 53;
160     dns_timeout_factor = DEFAULT_DNS_TIMEOUT_FACTOR;
161     dns_send_interval = DEFAULT_DNS_SEND_INTERVAL;
162     dns_overlap_factor = DEFAULT_DNS_OVERLAP_FACTOR;
163     dns_max_outstanding = DEFAULT_DNS_MAX_OUTSTANDING;
164 pcg 1.30 #endif
165    
166 root 1.60 pidfilename = strdup (LOCALSTATEDIR "/run/gvpe.pid");
167     seed_dev = strdup ("/dev/urandom");
168     reseed = DEFAULT_RESEED;
169 pcg 1.1 }
170    
171 root 1.52 void
172     configuration::cleanup ()
173 pcg 1.1 {
174     if (rsa_key)
175     RSA_free (rsa_key);
176    
177 pcg 1.12 rsa_key = 0;
178 pcg 1.1
179 root 1.60 free (seed_dev); seed_dev = 0;
180 pcg 1.51 free (pidfilename); pidfilename = 0;
181     free (ifname); ifname = 0;
182 root 1.53 #if ENABLE_HTTP_PROXY
183 pcg 1.51 free (proxy_host); proxy_host = 0;
184     free (proxy_auth); proxy_auth = 0;
185 root 1.53 #endif
186     #if ENABLE_DNS
187 pcg 1.51 free (dns_forw_host); dns_forw_host = 0;
188     #endif
189 root 1.59 free (change_root); change_root = 0;
190 pcg 1.51 free (script_if_up); script_if_up = 0;
191     free (script_node_up); script_node_up = 0;
192     free (script_node_change); script_node_change = 0;
193     free (script_node_down); script_node_down = 0;
194 pcg 1.1 }
195    
196     void
197 pcg 1.40 configuration::clear ()
198 pcg 1.1 {
199     for (configuration::node_vector::iterator i = nodes.begin(); i != nodes.end(); ++i)
200     delete *i;
201    
202     nodes.clear ();
203    
204     cleanup ();
205     init ();
206     }
207    
208 root 1.62 conf_node *
209     configuration::find_node (const char *name)
210     {
211     for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i)
212     if (!strcmp ((*i)->nodename, name))
213     return *i;
214    
215     return 0;
216     }
217    
218 root 1.55 //static bool
219     //is_true (const char *name)
220     //{
221     //re
222     //}
223    
224 pcg 1.37 #define parse_bool(target,name,trueval,falseval) do { \
225     if (!strcmp (val, "yes")) target = trueval; \
226 pcg 1.5 else if (!strcmp (val, "no")) target = falseval; \
227     else if (!strcmp (val, "true")) target = trueval; \
228     else if (!strcmp (val, "false")) target = falseval; \
229     else if (!strcmp (val, "on")) target = trueval; \
230     else if (!strcmp (val, "off")) target = falseval; \
231     else \
232 root 1.56 return _("illegal boolean value, only 'yes|true|on' or 'no|false|off' allowed, ignored"); \
233 pcg 1.37 } while (0)
234 pcg 1.5
235 pcg 1.40 const char *
236     configuration_parser::parse_line (char *line)
237 pcg 1.1 {
238 pcg 1.40 {
239     char *end = line + strlen (line);
240    
241 root 1.66 while (end >= line && *end < ' ')
242 pcg 1.40 end--;
243 pcg 1.1
244 pcg 1.40 *++end = 0;
245     }
246 pcg 1.1
247 pcg 1.40 char *tok = line;
248     const char *var = strtok (tok, "\t =");
249     tok = 0;
250 pcg 1.1
251 pcg 1.40 if (!var || !var[0])
252     return 0; /* no tokens on this line */
253 pcg 1.1
254 pcg 1.40 if (var[0] == '#')
255     return 0; /* comment: ignore */
256 pcg 1.1
257 root 1.63 if (!strcmp (var, "global"))
258     {
259     node = &conf.default_node;
260     return 0;
261     }
262    
263 pcg 1.40 char *val = strtok (NULL, "\t\n\r =");
264 pcg 1.1
265 pcg 1.40 if (!val || val[0] == '#')
266 root 1.56 return _("no value given for variable, ignored");
267 pcg 1.1
268 root 1.55 else if (!strcmp (var, "on"))
269 pcg 1.40 {
270 root 1.56 if (::thisnode
271     && ((val[0] == '!' && strcmp (val + 1, ::thisnode))
272     || !strcmp (val, ::thisnode)))
273 pcg 1.40 return parse_line (strtok (NULL, "\n\r"));
274 root 1.55 }
275    
276     else if (!strcmp (var, "include"))
277     {
278     char *fname = conf.config_filename (val);
279     parse_file (fname);
280     free (fname);
281 pcg 1.40 }
282 pcg 1.1
283 pcg 1.40 // truly global
284 root 1.55 else if (!strcmp (var, "loglevel"))
285 pcg 1.40 {
286     loglevel l = string_to_loglevel (val);
287 pcg 1.1
288 pcg 1.40 if (l == L_NONE)
289 root 1.56 return _("unknown loglevel, ignored");
290 pcg 1.40 }
291 root 1.64 else if (!strcmp (var, "serial"))
292     strncpy (conf.serial, val, sizeof (conf.serial));
293 pcg 1.40 else if (!strcmp (var, "ip-proto"))
294     conf.ip_proto = atoi (val);
295     else if (!strcmp (var, "icmp-type"))
296     {
297 pcg 1.16 #if ENABLE_ICMP
298 pcg 1.40 conf.icmp_type = atoi (val);
299 pcg 1.16 #endif
300 pcg 1.40 }
301 root 1.59 else if (!strcmp (var, "chuser"))
302     {
303     struct passwd *pw = getpwnam (val);
304     if (!pw)
305     return _("user specified for chuser not found");
306    
307     conf.change_uid = pw->pw_uid;
308     conf.change_gid = pw->pw_gid;
309     }
310     else if (!strcmp (var, "chuid"))
311     conf.change_uid = atoi (val);
312     else if (!strcmp (var, "chgid"))
313     conf.change_gid = atoi (val);
314     else if (!strcmp (var, "chroot"))
315     free (conf.change_root), conf.change_root = strdup (val);
316 pcg 1.1
317 root 1.59 // per node
318 pcg 1.40 else if (!strcmp (var, "node"))
319     {
320 root 1.62 node = conf.find_node (val);
321 pcg 1.1
322 root 1.62 if (!node)
323     {
324     conf.default_node.id++;
325     node = new conf_node (conf.default_node);
326     conf.nodes.push_back (node);
327     node->nodename = strdup (val);
328     }
329 pcg 1.40 }
330     else if (!strcmp (var, "private-key"))
331     free (conf.prikeyfile), conf.prikeyfile = strdup (val);
332     else if (!strcmp (var, "ifpersist"))
333     parse_bool (conf.ifpersist, "ifpersist", true, false);
334     else if (!strcmp (var, "ifname"))
335     free (conf.ifname), conf.ifname = strdup (val);
336     else if (!strcmp (var, "rekey"))
337     conf.rekey = atoi (val);
338     else if (!strcmp (var, "keepalive"))
339     conf.keepalive = atoi (val);
340     else if (!strcmp (var, "mtu"))
341     conf.mtu = atoi (val);
342 pcg 1.50 else if (!strcmp (var, "nfmark"))
343     conf.nfmark = atoi (val);
344 root 1.60 else if (!strcmp (var, "seed-device"))
345     free (conf.seed_dev), conf.seed_dev = strdup (val);
346     else if (!strcmp (var, "seed-interval"))
347     conf.reseed = atoi (val);
348 pcg 1.40 else if (!strcmp (var, "if-up"))
349     free (conf.script_if_up), conf.script_if_up = strdup (val);
350     else if (!strcmp (var, "node-up"))
351     free (conf.script_node_up), conf.script_node_up = strdup (val);
352 pcg 1.51 else if (!strcmp (var, "node-change"))
353     free (conf.script_node_change), conf.script_node_change = strdup (val);
354 pcg 1.40 else if (!strcmp (var, "node-down"))
355     free (conf.script_node_down), conf.script_node_down = strdup (val);
356     else if (!strcmp (var, "pid-file"))
357     free (conf.pidfilename), conf.pidfilename = strdup (val);
358     else if (!strcmp (var, "dns-forw-host"))
359     {
360 pcg 1.30 #if ENABLE_DNS
361 pcg 1.40 free (conf.dns_forw_host), conf.dns_forw_host = strdup (val);
362 pcg 1.34 #endif
363 pcg 1.40 }
364     else if (!strcmp (var, "dns-forw-port"))
365     {
366 pcg 1.34 #if ENABLE_DNS
367 pcg 1.40 conf.dns_forw_port = atoi (val);
368 pcg 1.28 #endif
369 pcg 1.40 }
370     else if (!strcmp (var, "dns-timeout-factor"))
371     {
372 pcg 1.38 #if ENABLE_DNS
373 pcg 1.40 conf.dns_timeout_factor = atof (val);
374 pcg 1.38 #endif
375 pcg 1.40 }
376     else if (!strcmp (var, "dns-send-interval"))
377     {
378 pcg 1.38 #if ENABLE_DNS
379 pcg 1.40 conf.dns_send_interval = atoi (val);
380 pcg 1.38 #endif
381 pcg 1.40 }
382     else if (!strcmp (var, "dns-overlap-factor"))
383     {
384 pcg 1.38 #if ENABLE_DNS
385 pcg 1.40 conf.dns_overlap_factor = atof (val);
386 pcg 1.38 #endif
387 pcg 1.40 }
388     else if (!strcmp (var, "dns-max-outstanding"))
389     {
390 pcg 1.38 #if ENABLE_DNS
391 pcg 1.40 conf.dns_max_outstanding = atoi (val);
392 pcg 1.38 #endif
393 pcg 1.40 }
394 root 1.55 else if (!strcmp (var, "dns-case-preserving"))
395     {
396     #if ENABLE_DNS
397     parse_bool (conf.dns_case_preserving, "dns-case-preserving", true, false);
398     #endif
399     }
400 pcg 1.40 else if (!strcmp (var, "http-proxy-host"))
401     {
402 pcg 1.12 #if ENABLE_HTTP_PROXY
403 pcg 1.40 free (conf.proxy_host), conf.proxy_host = strdup (val);
404 pcg 1.20 #endif
405 pcg 1.40 }
406     else if (!strcmp (var, "http-proxy-port"))
407     {
408 pcg 1.20 #if ENABLE_HTTP_PROXY
409 pcg 1.40 conf.proxy_port = atoi (val);
410 pcg 1.20 #endif
411 pcg 1.40 }
412     else if (!strcmp (var, "http-proxy-auth"))
413     {
414 pcg 1.20 #if ENABLE_HTTP_PROXY
415 pcg 1.40 conf.proxy_auth = (char *)base64_encode ((const u8 *)val, strlen (val));
416 pcg 1.12 #endif
417 pcg 1.40 }
418 pcg 1.1
419 pcg 1.40 /* node-specific, non-defaultable */
420     else if (node != &conf.default_node && !strcmp (var, "hostname"))
421     free (node->hostname), node->hostname = strdup (val);
422    
423     /* node-specific, defaultable */
424     else if (!strcmp (var, "udp-port"))
425     node->udp_port = atoi (val);
426     else if (!strcmp (var, "tcp-port"))
427     node->tcp_port = atoi (val);
428     else if (!strcmp (var, "dns-hostname"))
429     {
430 pcg 1.30 #if ENABLE_DNS
431 pcg 1.40 free (node->dns_hostname), node->dns_hostname = strdup (val);
432 pcg 1.34 #endif
433 pcg 1.40 }
434     else if (!strcmp (var, "dns-port"))
435     {
436 pcg 1.34 #if ENABLE_DNS
437 pcg 1.40 node->dns_port = atoi (val);
438 pcg 1.34 #endif
439 pcg 1.40 }
440     else if (!strcmp (var, "dns-domain"))
441     {
442 pcg 1.34 #if ENABLE_DNS
443 pcg 1.40 free (node->domain), node->domain = strdup (val);
444 pcg 1.28 #endif
445 pcg 1.40 }
446     else if (!strcmp (var, "if-up-data"))
447     free (node->if_up_data), node->if_up_data = strdup (val);
448     else if (!strcmp (var, "router-priority"))
449     node->routerprio = atoi (val);
450     else if (!strcmp (var, "max-retry"))
451     node->max_retry = atoi (val);
452     else if (!strcmp (var, "connect"))
453     {
454     if (!strcmp (val, "ondemand"))
455     node->connectmode = conf_node::C_ONDEMAND;
456     else if (!strcmp (val, "never"))
457     node->connectmode = conf_node::C_NEVER;
458     else if (!strcmp (val, "always"))
459     node->connectmode = conf_node::C_ALWAYS;
460     else if (!strcmp (val, "disabled"))
461     node->connectmode = conf_node::C_DISABLED;
462     else
463 root 1.56 return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled', ignored");
464 pcg 1.40 }
465     else if (!strcmp (var, "inherit-tos"))
466     parse_bool (node->inherit_tos, "inherit-tos", true, false);
467     else if (!strcmp (var, "compress"))
468     parse_bool (node->compress, "compress", true, false);
469 root 1.65 else if (!strcmp (var, "low-power"))
470     parse_bool (node->low_power, "low-power", true, false);
471 pcg 1.40 // all these bool options really really cost a lot of executable size!
472     else if (!strcmp (var, "enable-tcp"))
473     {
474 pcg 1.11 #if ENABLE_TCP
475 pcg 1.40 u8 v; parse_bool (v, "enable-tcp" , PROT_TCPv4, 0); node->protocols = (node->protocols & ~PROT_TCPv4) | v;
476 pcg 1.13 #endif
477 pcg 1.40 }
478     else if (!strcmp (var, "enable-icmp"))
479     {
480 pcg 1.13 #if ENABLE_ICMP
481 pcg 1.40 u8 v; parse_bool (v, "enable-icmp" , PROT_ICMPv4, 0); node->protocols = (node->protocols & ~PROT_ICMPv4) | v;
482 pcg 1.11 #endif
483 pcg 1.40 }
484     else if (!strcmp (var, "enable-dns"))
485     {
486 pcg 1.24 #if ENABLE_DNS
487 pcg 1.40 u8 v; parse_bool (v, "enable-dns" , PROT_DNSv4, 0); node->protocols = (node->protocols & ~PROT_DNSv4) | v;
488 pcg 1.24 #endif
489 pcg 1.40 }
490     else if (!strcmp (var, "enable-udp"))
491     {
492     u8 v; parse_bool (v, "enable-udp" , PROT_UDPv4, 0); node->protocols = (node->protocols & ~PROT_UDPv4) | v;
493     }
494     else if (!strcmp (var, "enable-rawip"))
495     {
496     u8 v; parse_bool (v, "enable-rawip", PROT_IPv4, 0); node->protocols = (node->protocols & ~PROT_IPv4 ) | v;
497     }
498 pcg 1.42 else if (!strcmp (var, "allow-direct"))
499     node->allow_direct.push_back (strdup (val));
500     else if (!strcmp (var, "deny-direct"))
501     node->deny_direct.push_back (strdup (val));
502 pcg 1.43 else if (!strcmp (var, "max-ttl"))
503     node->max_ttl = atof (val);
504     else if (!strcmp (var, "max-queue"))
505 pcg 1.46 node->max_queue = atoi (val);
506 pcg 1.40
507     // unknown or misplaced
508     else
509 root 1.55 return _("unknown configuration directive - ignored");
510 pcg 1.40
511     return 0;
512     }
513    
514 root 1.52 void
515     conf_node::finalise ()
516 pcg 1.46 {
517     if (max_queue < 1)
518     {
519     slog (L_WARN, _("%s: max-queue value invalid, setting it to 1."), nodename);
520     max_queue = 1;
521     }
522    
523 pcg 1.49 if (routerprio > 1 && (connectmode != C_ALWAYS && connectmode != C_DISABLED))
524 pcg 1.46 {
525 pcg 1.48 //slog (L_WARN, _("%s: has non-zero router-priority but either 'never' or 'ondemand' as connectmode, setting it to 'always'."), nodename);
526 pcg 1.46 connectmode = C_ALWAYS;
527     }
528     }
529    
530 root 1.52 void
531 root 1.55 configuration_parser::parse_file (const char *fname)
532 pcg 1.40 {
533 root 1.55 if (FILE *f = fopen (fname, "r"))
534 pcg 1.40 {
535 root 1.55 char line [2048];
536 pcg 1.40 int lineno = 0;
537    
538     while (fgets (line, sizeof (line), f))
539     {
540     lineno++;
541    
542     const char *warn = parse_line (line);
543    
544     if (warn)
545     slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
546 pcg 1.1 }
547    
548     fclose (f);
549     }
550     else
551     {
552     slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
553 pcg 1.22 exit (EXIT_FAILURE);
554 pcg 1.1 }
555 root 1.55 }
556    
557     configuration_parser::configuration_parser (configuration &conf,
558     bool need_keys,
559     int argc,
560     char **argv)
561 root 1.62 : conf (conf), need_keys (need_keys), argc (argc), argv (argv)
562 root 1.55 {
563     char *fname;
564 pcg 1.1
565 root 1.55 conf.clear ();
566 root 1.56 node = &conf.default_node;
567 root 1.55
568     asprintf (&fname, "%s/gvpe.conf", confbase);
569     parse_file (fname);
570 pcg 1.1 free (fname);
571    
572 pcg 1.40 fname = conf.config_filename (conf.prikeyfile, "hostkey");
573 pcg 1.1
574 root 1.55 if (FILE *f = fopen (fname, "r"))
575 pcg 1.1 {
576 pcg 1.40 conf.rsa_key = RSA_new ();
577 pcg 1.1
578 pcg 1.40 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL))
579 pcg 1.1 {
580     ERR_load_RSA_strings (); ERR_load_PEM_strings ();
581     slog (L_ERR, _("unable to read private rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
582 pcg 1.22 exit (EXIT_FAILURE);
583 pcg 1.1 }
584    
585 pcg 1.40 require (RSA_blinding_on (conf.rsa_key, 0));
586 pcg 1.1
587     fclose (f);
588     }
589     else
590     {
591     if (need_keys)
592 root 1.61 {
593     slog (need_keys ? L_ERR : L_NOTICE, _("unable to open private rsa key file '%s': %s"), fname, strerror (errno));
594     exit (EXIT_FAILURE);
595     }
596 pcg 1.1 }
597 pcg 1.22
598 root 1.55 free (fname);
599    
600 root 1.61 fname = conf.config_filename (conf.pidfilename);
601     free (conf.pidfilename); conf.pidfilename = fname;
602    
603 pcg 1.46 for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i)
604 root 1.62 {
605     conf_node *node = *i;
606     char *fname;
607     FILE *f;
608    
609     asprintf (&fname, "%s/pubkey/%s", confbase, node->nodename);
610    
611     f = fopen (fname, "r");
612     if (f)
613     {
614     node->rsa_key = RSA_new ();
615    
616     if (!PEM_read_RSAPublicKey (f, &node->rsa_key, NULL, NULL))
617     {
618     ERR_load_RSA_strings (); ERR_load_PEM_strings ();
619     slog (L_ERR, _("unable to open public rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
620     exit (EXIT_FAILURE);
621     }
622    
623     require (RSA_blinding_on (node->rsa_key, 0));
624    
625     fclose (f);
626     }
627     else
628     {
629     slog (need_keys ? L_ERR : L_NOTICE, _("unable to read public rsa key file '%s': %s"), fname, strerror (errno));
630    
631     if (need_keys)
632     exit (EXIT_FAILURE);
633     }
634    
635     free (fname);
636    
637     (*i)->finalise ();
638     }
639    
640     if (::thisnode)
641     {
642     conf.thisnode = conf.find_node (::thisnode);
643    
644     if (need_keys)
645     {
646     if (!conf.thisnode)
647     {
648     slog (L_NOTICE, _("local node ('%s') not found in config file, aborting."), ::thisnode);
649     exit (EXIT_FAILURE);
650     }
651    
652     if (conf.rsa_key && conf.thisnode->rsa_key)
653 root 1.67 {
654     const BIGNUM *conf_n, *conf_e, *thisnode_n, *thisnode_e;
655    
656     #if OPENSSL_VERSION_NUMBER >= 0x10100000 && !LIBRESSL_VERSION_NUMBER
657     RSA_get0_key (conf.rsa_key, &conf_n, &conf_e, 0);
658     RSA_get0_key (conf.thisnode->rsa_key, &thisnode_n, &thisnode_e, 0);
659     #else
660     conf_n = conf.thisnode->rsa_key->n;
661     conf_e = conf.thisnode->rsa_key->e;
662     thisnode_n = conf.rsa_key->n;
663     thisnode_e = conf.rsa_key->e;
664     #endif
665     if (BN_cmp (conf_n, thisnode_n) != 0 || BN_cmp (conf_e, thisnode_e) != 0)
666     {
667     slog (L_NOTICE, _("private hostkey and public node key mismatch: is '%s' the correct node?"), ::thisnode);
668     exit (EXIT_FAILURE);
669     }
670     }
671 root 1.62 }
672     }
673    
674     parse_argv ();
675     }
676    
677     void
678     configuration_parser::parse_argv ()
679     {
680     for (int i = 0; i < argc; ++i)
681     {
682     char *v = argv [i];
683    
684     if (!*v)
685     continue;
686    
687     char *enode = v;
688    
689     while (*enode != '.' && *enode > ' ' && *enode != '=' && *enode)
690     enode++;
691    
692     if (*enode != '.')
693     enode = 0;
694    
695     if (enode)
696     {
697     char *val = strdup (v);
698     val [enode - v] = 0;
699     node = conf.find_node (val);
700     free (val);
701    
702     if (!node)
703     {
704     slog (L_WARN, _("command line option '%s' refers to unknown node, ignoring."), v);
705     continue;
706     }
707     }
708     else
709     node = &conf.default_node;
710    
711     const char *warn = parse_line (enode ? enode + 1 : v);
712    
713     if (warn)
714     slog (L_WARN, _("%s, while parsing command line option '%s'."), warn, v);
715     }
716 pcg 1.1 }
717    
718 root 1.52 char *
719     configuration::config_filename (const char *name, const char *dflt)
720 pcg 1.1 {
721     char *fname;
722    
723 root 1.61 asprintf (&fname, name ? name : dflt, ::thisnode ? ::thisnode : "<unset>");
724 pcg 1.1
725     if (!ABSOLUTE_PATH (fname))
726     {
727     char *rname = fname;
728     asprintf (&fname, "%s/%s", confbase, rname);
729     free (rname);
730     }
731    
732     return fname;
733     }
734    
735     void
736 root 1.54 conf_node::print ()
737     {
738     printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %02x %s%s%d\n",
739     id,
740     id >> 8, id & 0xff,
741     compress ? 'Y' : 'N',
742     connectmode == C_ONDEMAND ? "ondemand"
743     : connectmode == C_NEVER ? "never"
744     : connectmode == C_ALWAYS ? "always"
745     : connectmode == C_DISABLED ? "disabled"
746     : "",
747     nodename,
748     protocols,
749     hostname ? hostname : "",
750     hostname ? ":" : "",
751     hostname ? udp_port : 0
752     );
753     }
754    
755     void
756 pcg 1.1 configuration::print ()
757     {
758     printf (_("\nConfiguration\n\n"));
759     printf (_("# of nodes: %d\n"), nodes.size ());
760     printf (_("this node: %s\n"), thisnode ? thisnode->nodename : "<unset>");
761     printf (_("MTU: %d\n"), mtu);
762     printf (_("rekeying interval: %d\n"), rekey);
763     printf (_("keepalive interval: %d\n"), keepalive);
764     printf (_("interface: %s\n"), ifname);
765     printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>");
766 pcg 1.15 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1);
767 pcg 1.1 printf ("\n");
768    
769 root 1.54 printf ("%4s %-17s %s %-8.8s %-10.10s %04s %s\n",
770     _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Prot"), _("Host:Port"));
771 pcg 1.1
772     for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i)
773     (*i)->print ();
774    
775     printf ("\n");
776     }
777    
778 pcg 1.12 configuration::configuration ()
779     {
780 pcg 1.27 asprintf (&confbase, "%s/gvpe", CONFDIR);
781 pcg 1.26
782 pcg 1.12 init ();
783     }
784    
785     configuration::~configuration ()
786 pcg 1.1 {
787 pcg 1.12 cleanup ();
788 pcg 1.1 }
789 pcg 1.12