ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/conf.C
Revision: 1.61
Committed: Tue Jul 16 16:44:36 2013 UTC (10 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.60: +8 -4 lines
Log Message:
3.x

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