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