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