ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/conf.C
Revision: 1.63
Committed: Thu Jul 18 13:35:16 2013 UTC (10 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.62: +6 -2 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*
2 root 1.55 conf.C -- configuration code
3     Copyright (C) 2003-2008,2011 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     while (*end < ' ' && end >= line)
242     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     else if (!strcmp (var, "ip-proto"))
292     conf.ip_proto = atoi (val);
293     else if (!strcmp (var, "icmp-type"))
294     {
295 pcg 1.16 #if ENABLE_ICMP
296 pcg 1.40 conf.icmp_type = atoi (val);
297 pcg 1.16 #endif
298 pcg 1.40 }
299 root 1.59 else if (!strcmp (var, "chuser"))
300     {
301     struct passwd *pw = getpwnam (val);
302     if (!pw)
303     return _("user specified for chuser not found");
304    
305     conf.change_uid = pw->pw_uid;
306     conf.change_gid = pw->pw_gid;
307     }
308     else if (!strcmp (var, "chuid"))
309     conf.change_uid = atoi (val);
310     else if (!strcmp (var, "chgid"))
311     conf.change_gid = atoi (val);
312     else if (!strcmp (var, "chroot"))
313     free (conf.change_root), conf.change_root = strdup (val);
314 pcg 1.1
315 root 1.59 // per node
316 pcg 1.40 else if (!strcmp (var, "node"))
317     {
318 root 1.62 node = conf.find_node (val);
319 pcg 1.1
320 root 1.62 if (!node)
321     {
322     conf.default_node.id++;
323     node = new conf_node (conf.default_node);
324     conf.nodes.push_back (node);
325     node->nodename = strdup (val);
326     }
327 pcg 1.40 }
328     else if (!strcmp (var, "private-key"))
329     free (conf.prikeyfile), conf.prikeyfile = strdup (val);
330     else if (!strcmp (var, "ifpersist"))
331     parse_bool (conf.ifpersist, "ifpersist", true, false);
332     else if (!strcmp (var, "ifname"))
333     free (conf.ifname), conf.ifname = strdup (val);
334     else if (!strcmp (var, "rekey"))
335     conf.rekey = atoi (val);
336     else if (!strcmp (var, "keepalive"))
337     conf.keepalive = atoi (val);
338     else if (!strcmp (var, "mtu"))
339     conf.mtu = atoi (val);
340 pcg 1.50 else if (!strcmp (var, "nfmark"))
341     conf.nfmark = atoi (val);
342 root 1.60 else if (!strcmp (var, "seed-device"))
343     free (conf.seed_dev), conf.seed_dev = strdup (val);
344     else if (!strcmp (var, "seed-interval"))
345     conf.reseed = atoi (val);
346 pcg 1.40 else if (!strcmp (var, "if-up"))
347     free (conf.script_if_up), conf.script_if_up = strdup (val);
348     else if (!strcmp (var, "node-up"))
349     free (conf.script_node_up), conf.script_node_up = strdup (val);
350 pcg 1.51 else if (!strcmp (var, "node-change"))
351     free (conf.script_node_change), conf.script_node_change = strdup (val);
352 pcg 1.40 else if (!strcmp (var, "node-down"))
353     free (conf.script_node_down), conf.script_node_down = strdup (val);
354     else if (!strcmp (var, "pid-file"))
355     free (conf.pidfilename), conf.pidfilename = strdup (val);
356     else if (!strcmp (var, "dns-forw-host"))
357     {
358 pcg 1.30 #if ENABLE_DNS
359 pcg 1.40 free (conf.dns_forw_host), conf.dns_forw_host = strdup (val);
360 pcg 1.34 #endif
361 pcg 1.40 }
362     else if (!strcmp (var, "dns-forw-port"))
363     {
364 pcg 1.34 #if ENABLE_DNS
365 pcg 1.40 conf.dns_forw_port = atoi (val);
366 pcg 1.28 #endif
367 pcg 1.40 }
368     else if (!strcmp (var, "dns-timeout-factor"))
369     {
370 pcg 1.38 #if ENABLE_DNS
371 pcg 1.40 conf.dns_timeout_factor = atof (val);
372 pcg 1.38 #endif
373 pcg 1.40 }
374     else if (!strcmp (var, "dns-send-interval"))
375     {
376 pcg 1.38 #if ENABLE_DNS
377 pcg 1.40 conf.dns_send_interval = atoi (val);
378 pcg 1.38 #endif
379 pcg 1.40 }
380     else if (!strcmp (var, "dns-overlap-factor"))
381     {
382 pcg 1.38 #if ENABLE_DNS
383 pcg 1.40 conf.dns_overlap_factor = atof (val);
384 pcg 1.38 #endif
385 pcg 1.40 }
386     else if (!strcmp (var, "dns-max-outstanding"))
387     {
388 pcg 1.38 #if ENABLE_DNS
389 pcg 1.40 conf.dns_max_outstanding = atoi (val);
390 pcg 1.38 #endif
391 pcg 1.40 }
392 root 1.55 else if (!strcmp (var, "dns-case-preserving"))
393     {
394     #if ENABLE_DNS
395     parse_bool (conf.dns_case_preserving, "dns-case-preserving", true, false);
396     #endif
397     }
398 pcg 1.40 else if (!strcmp (var, "http-proxy-host"))
399     {
400 pcg 1.12 #if ENABLE_HTTP_PROXY
401 pcg 1.40 free (conf.proxy_host), conf.proxy_host = strdup (val);
402 pcg 1.20 #endif
403 pcg 1.40 }
404     else if (!strcmp (var, "http-proxy-port"))
405     {
406 pcg 1.20 #if ENABLE_HTTP_PROXY
407 pcg 1.40 conf.proxy_port = atoi (val);
408 pcg 1.20 #endif
409 pcg 1.40 }
410     else if (!strcmp (var, "http-proxy-auth"))
411     {
412 pcg 1.20 #if ENABLE_HTTP_PROXY
413 pcg 1.40 conf.proxy_auth = (char *)base64_encode ((const u8 *)val, strlen (val));
414 pcg 1.12 #endif
415 pcg 1.40 }
416 pcg 1.1
417 pcg 1.40 /* node-specific, non-defaultable */
418     else if (node != &conf.default_node && !strcmp (var, "hostname"))
419     free (node->hostname), node->hostname = strdup (val);
420    
421     /* node-specific, defaultable */
422     else if (!strcmp (var, "udp-port"))
423     node->udp_port = atoi (val);
424     else if (!strcmp (var, "tcp-port"))
425     node->tcp_port = atoi (val);
426     else if (!strcmp (var, "dns-hostname"))
427     {
428 pcg 1.30 #if ENABLE_DNS
429 pcg 1.40 free (node->dns_hostname), node->dns_hostname = strdup (val);
430 pcg 1.34 #endif
431 pcg 1.40 }
432     else if (!strcmp (var, "dns-port"))
433     {
434 pcg 1.34 #if ENABLE_DNS
435 pcg 1.40 node->dns_port = atoi (val);
436 pcg 1.34 #endif
437 pcg 1.40 }
438     else if (!strcmp (var, "dns-domain"))
439     {
440 pcg 1.34 #if ENABLE_DNS
441 pcg 1.40 free (node->domain), node->domain = strdup (val);
442 pcg 1.28 #endif
443 pcg 1.40 }
444     else if (!strcmp (var, "if-up-data"))
445     free (node->if_up_data), node->if_up_data = strdup (val);
446     else if (!strcmp (var, "router-priority"))
447     node->routerprio = atoi (val);
448     else if (!strcmp (var, "max-retry"))
449     node->max_retry = atoi (val);
450     else if (!strcmp (var, "connect"))
451     {
452     if (!strcmp (val, "ondemand"))
453     node->connectmode = conf_node::C_ONDEMAND;
454     else if (!strcmp (val, "never"))
455     node->connectmode = conf_node::C_NEVER;
456     else if (!strcmp (val, "always"))
457     node->connectmode = conf_node::C_ALWAYS;
458     else if (!strcmp (val, "disabled"))
459     node->connectmode = conf_node::C_DISABLED;
460     else
461 root 1.56 return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled', ignored");
462 pcg 1.40 }
463     else if (!strcmp (var, "inherit-tos"))
464     parse_bool (node->inherit_tos, "inherit-tos", true, false);
465     else if (!strcmp (var, "compress"))
466     parse_bool (node->compress, "compress", true, false);
467     // all these bool options really really cost a lot of executable size!
468     else if (!strcmp (var, "enable-tcp"))
469     {
470 pcg 1.11 #if ENABLE_TCP
471 pcg 1.40 u8 v; parse_bool (v, "enable-tcp" , PROT_TCPv4, 0); node->protocols = (node->protocols & ~PROT_TCPv4) | v;
472 pcg 1.13 #endif
473 pcg 1.40 }
474     else if (!strcmp (var, "enable-icmp"))
475     {
476 pcg 1.13 #if ENABLE_ICMP
477 pcg 1.40 u8 v; parse_bool (v, "enable-icmp" , PROT_ICMPv4, 0); node->protocols = (node->protocols & ~PROT_ICMPv4) | v;
478 pcg 1.11 #endif
479 pcg 1.40 }
480     else if (!strcmp (var, "enable-dns"))
481     {
482 pcg 1.24 #if ENABLE_DNS
483 pcg 1.40 u8 v; parse_bool (v, "enable-dns" , PROT_DNSv4, 0); node->protocols = (node->protocols & ~PROT_DNSv4) | v;
484 pcg 1.24 #endif
485 pcg 1.40 }
486     else if (!strcmp (var, "enable-udp"))
487     {
488     u8 v; parse_bool (v, "enable-udp" , PROT_UDPv4, 0); node->protocols = (node->protocols & ~PROT_UDPv4) | v;
489     }
490     else if (!strcmp (var, "enable-rawip"))
491     {
492     u8 v; parse_bool (v, "enable-rawip", PROT_IPv4, 0); node->protocols = (node->protocols & ~PROT_IPv4 ) | v;
493     }
494 pcg 1.42 else if (!strcmp (var, "allow-direct"))
495     node->allow_direct.push_back (strdup (val));
496     else if (!strcmp (var, "deny-direct"))
497     node->deny_direct.push_back (strdup (val));
498 pcg 1.43 else if (!strcmp (var, "max-ttl"))
499     node->max_ttl = atof (val);
500     else if (!strcmp (var, "max-queue"))
501 pcg 1.46 node->max_queue = atoi (val);
502 pcg 1.40
503     // unknown or misplaced
504     else
505 root 1.55 return _("unknown configuration directive - ignored");
506 pcg 1.40
507     return 0;
508     }
509    
510 root 1.52 void
511     conf_node::finalise ()
512 pcg 1.46 {
513     if (max_queue < 1)
514     {
515     slog (L_WARN, _("%s: max-queue value invalid, setting it to 1."), nodename);
516     max_queue = 1;
517     }
518    
519 pcg 1.49 if (routerprio > 1 && (connectmode != C_ALWAYS && connectmode != C_DISABLED))
520 pcg 1.46 {
521 pcg 1.48 //slog (L_WARN, _("%s: has non-zero router-priority but either 'never' or 'ondemand' as connectmode, setting it to 'always'."), nodename);
522 pcg 1.46 connectmode = C_ALWAYS;
523     }
524     }
525    
526 root 1.52 void
527 root 1.55 configuration_parser::parse_file (const char *fname)
528 pcg 1.40 {
529 root 1.55 if (FILE *f = fopen (fname, "r"))
530 pcg 1.40 {
531 root 1.55 char line [2048];
532 pcg 1.40 int lineno = 0;
533    
534     while (fgets (line, sizeof (line), f))
535     {
536     lineno++;
537    
538     const char *warn = parse_line (line);
539    
540     if (warn)
541     slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
542 pcg 1.1 }
543    
544     fclose (f);
545     }
546     else
547     {
548     slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
549 pcg 1.22 exit (EXIT_FAILURE);
550 pcg 1.1 }
551 root 1.55 }
552    
553     configuration_parser::configuration_parser (configuration &conf,
554     bool need_keys,
555     int argc,
556     char **argv)
557 root 1.62 : conf (conf), need_keys (need_keys), argc (argc), argv (argv)
558 root 1.55 {
559     char *fname;
560 pcg 1.1
561 root 1.55 conf.clear ();
562 root 1.56 node = &conf.default_node;
563 root 1.55
564     asprintf (&fname, "%s/gvpe.conf", confbase);
565     parse_file (fname);
566 pcg 1.1 free (fname);
567    
568 pcg 1.40 fname = conf.config_filename (conf.prikeyfile, "hostkey");
569 pcg 1.1
570 root 1.55 if (FILE *f = fopen (fname, "r"))
571 pcg 1.1 {
572 pcg 1.40 conf.rsa_key = RSA_new ();
573 pcg 1.1
574 pcg 1.40 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL))
575 pcg 1.1 {
576     ERR_load_RSA_strings (); ERR_load_PEM_strings ();
577     slog (L_ERR, _("unable to read private rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
578 pcg 1.22 exit (EXIT_FAILURE);
579 pcg 1.1 }
580    
581 pcg 1.40 require (RSA_blinding_on (conf.rsa_key, 0));
582 pcg 1.1
583     fclose (f);
584     }
585     else
586     {
587     if (need_keys)
588 root 1.61 {
589     slog (need_keys ? L_ERR : L_NOTICE, _("unable to open private rsa key file '%s': %s"), fname, strerror (errno));
590     exit (EXIT_FAILURE);
591     }
592 pcg 1.1 }
593 pcg 1.22
594 root 1.55 free (fname);
595    
596 root 1.61 fname = conf.config_filename (conf.pidfilename);
597     free (conf.pidfilename); conf.pidfilename = fname;
598    
599 pcg 1.46 for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i)
600 root 1.62 {
601     conf_node *node = *i;
602     char *fname;
603     FILE *f;
604    
605     asprintf (&fname, "%s/pubkey/%s", confbase, node->nodename);
606    
607     f = fopen (fname, "r");
608     if (f)
609     {
610     node->rsa_key = RSA_new ();
611    
612     if (!PEM_read_RSAPublicKey (f, &node->rsa_key, NULL, NULL))
613     {
614     ERR_load_RSA_strings (); ERR_load_PEM_strings ();
615     slog (L_ERR, _("unable to open public rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
616     exit (EXIT_FAILURE);
617     }
618    
619     require (RSA_blinding_on (node->rsa_key, 0));
620    
621     fclose (f);
622     }
623     else
624     {
625     slog (need_keys ? L_ERR : L_NOTICE, _("unable to read public rsa key file '%s': %s"), fname, strerror (errno));
626    
627     if (need_keys)
628     exit (EXIT_FAILURE);
629     }
630    
631     free (fname);
632    
633     (*i)->finalise ();
634     }
635    
636     if (::thisnode)
637     {
638     conf.thisnode = conf.find_node (::thisnode);
639    
640     if (need_keys)
641     {
642     if (!conf.thisnode)
643     {
644     slog (L_NOTICE, _("local node ('%s') not found in config file, aborting."), ::thisnode);
645     exit (EXIT_FAILURE);
646     }
647    
648     if (conf.rsa_key && conf.thisnode->rsa_key)
649     if (BN_cmp (conf.rsa_key->n, conf.thisnode->rsa_key->n) != 0
650     || BN_cmp (conf.rsa_key->e, conf.thisnode->rsa_key->e) != 0)
651     {
652     slog (L_NOTICE, _("private hostkey and public node key mismatch: is '%s' the correct node?"), ::thisnode);
653     exit (EXIT_FAILURE);
654     }
655     }
656     }
657    
658     parse_argv ();
659     }
660    
661     void
662     configuration_parser::parse_argv ()
663     {
664     for (int i = 0; i < argc; ++i)
665     {
666     char *v = argv [i];
667    
668     if (!*v)
669     continue;
670    
671     char *enode = v;
672    
673     while (*enode != '.' && *enode > ' ' && *enode != '=' && *enode)
674     enode++;
675    
676     if (*enode != '.')
677     enode = 0;
678    
679     if (enode)
680     {
681     char *val = strdup (v);
682     val [enode - v] = 0;
683     node = conf.find_node (val);
684     free (val);
685    
686     if (!node)
687     {
688     slog (L_WARN, _("command line option '%s' refers to unknown node, ignoring."), v);
689     continue;
690     }
691     }
692     else
693     node = &conf.default_node;
694    
695     const char *warn = parse_line (enode ? enode + 1 : v);
696    
697     if (warn)
698     slog (L_WARN, _("%s, while parsing command line option '%s'."), warn, v);
699     }
700 pcg 1.1 }
701    
702 root 1.52 char *
703     configuration::config_filename (const char *name, const char *dflt)
704 pcg 1.1 {
705     char *fname;
706    
707 root 1.61 asprintf (&fname, name ? name : dflt, ::thisnode ? ::thisnode : "<unset>");
708 pcg 1.1
709     if (!ABSOLUTE_PATH (fname))
710     {
711     char *rname = fname;
712     asprintf (&fname, "%s/%s", confbase, rname);
713     free (rname);
714     }
715    
716     return fname;
717     }
718    
719     void
720 root 1.54 conf_node::print ()
721     {
722     printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %02x %s%s%d\n",
723     id,
724     id >> 8, id & 0xff,
725     compress ? 'Y' : 'N',
726     connectmode == C_ONDEMAND ? "ondemand"
727     : connectmode == C_NEVER ? "never"
728     : connectmode == C_ALWAYS ? "always"
729     : connectmode == C_DISABLED ? "disabled"
730     : "",
731     nodename,
732     protocols,
733     hostname ? hostname : "",
734     hostname ? ":" : "",
735     hostname ? udp_port : 0
736     );
737     }
738    
739     void
740 pcg 1.1 configuration::print ()
741     {
742     printf (_("\nConfiguration\n\n"));
743     printf (_("# of nodes: %d\n"), nodes.size ());
744     printf (_("this node: %s\n"), thisnode ? thisnode->nodename : "<unset>");
745     printf (_("MTU: %d\n"), mtu);
746     printf (_("rekeying interval: %d\n"), rekey);
747     printf (_("keepalive interval: %d\n"), keepalive);
748     printf (_("interface: %s\n"), ifname);
749     printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>");
750 pcg 1.15 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1);
751 pcg 1.1 printf ("\n");
752    
753 root 1.54 printf ("%4s %-17s %s %-8.8s %-10.10s %04s %s\n",
754     _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Prot"), _("Host:Port"));
755 pcg 1.1
756     for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i)
757     (*i)->print ();
758    
759     printf ("\n");
760     }
761    
762 pcg 1.12 configuration::configuration ()
763     {
764 pcg 1.27 asprintf (&confbase, "%s/gvpe", CONFDIR);
765 pcg 1.26
766 pcg 1.12 init ();
767     }
768    
769     configuration::~configuration ()
770 pcg 1.1 {
771 pcg 1.12 cleanup ();
772 pcg 1.1 }
773 pcg 1.12