ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/conf.C
(Generate patch)

Comparing gvpe/src/conf.C (file contents):
Revision 1.46 by pcg, Sun Aug 10 01:34:36 2008 UTC vs.
Revision 1.67 by root, Thu Oct 25 04:32:27 2018 UTC

1/* 1/*
2 conf.c -- configuration code 2 conf.C -- configuration code
3 Copyright (C) 2003-2008 Marc Lehmann <gvpe@schmorp.de> 3 Copyright (C) 2003-2008,2011,2018 Marc Lehmann <gvpe@schmorp.de>
4 4
5 This file is part of GVPE. 5 This file is part of GVPE.
6 6
7 GVPE is free software; you can redistribute it and/or modify it 7 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 8 under the terms of the GNU General Public License as published by the
38#include <errno.h> 38#include <errno.h>
39#include <netdb.h> 39#include <netdb.h>
40#include <sys/stat.h> 40#include <sys/stat.h>
41#include <sys/types.h> 41#include <sys/types.h>
42#include <unistd.h> 42#include <unistd.h>
43#include <pwd.h>
43 44
44#include "netcompat.h" 45#include "netcompat.h"
45 46
46#include <openssl/err.h> 47#include <openssl/err.h>
47#include <openssl/pem.h> 48#include <openssl/pem.h>
57char *thisnode; 58char *thisnode;
58char *identname; 59char *identname;
59 60
60struct configuration conf; 61struct configuration conf;
61 62
63u8
62u8 best_protocol (u8 protset) 64best_protocol (u8 protset)
63{ 65{
64 if (protset & PROT_IPv4 ) return PROT_IPv4; 66 if (protset & PROT_IPv4 ) return PROT_IPv4;
65 if (protset & PROT_ICMPv4) return PROT_ICMPv4; 67 if (protset & PROT_ICMPv4) return PROT_ICMPv4;
66 if (protset & PROT_UDPv4 ) return PROT_UDPv4; 68 if (protset & PROT_UDPv4 ) return PROT_UDPv4;
67 if (protset & PROT_TCPv4 ) return PROT_TCPv4; 69 if (protset & PROT_TCPv4 ) return PROT_TCPv4;
68 if (protset & PROT_DNSv4 ) return PROT_DNSv4; 70 if (protset & PROT_DNSv4 ) return PROT_DNSv4;
69 71
70 return 0; 72 return 0;
71} 73}
72 74
75const char *
73const char *strprotocol (u8 protocol) 76strprotocol (u8 protocol)
74{ 77{
75 if (protocol & PROT_IPv4 ) return "rawip"; 78 if (protocol & PROT_IPv4 ) return "rawip";
76 if (protocol & PROT_ICMPv4) return "icmp"; 79 if (protocol & PROT_ICMPv4) return "icmp";
77 if (protocol & PROT_UDPv4 ) return "udp"; 80 if (protocol & PROT_UDPv4 ) return "udp";
78 if (protocol & PROT_TCPv4 ) return "tcp"; 81 if (protocol & PROT_TCPv4 ) return "tcp";
103 return false; 106 return false;
104 107
105 return true; 108 return true;
106} 109}
107 110
108void
109conf_node::print ()
110{
111 printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %s%s%d\n",
112 id,
113 id >> 8, id & 0xff,
114 compress ? 'Y' : 'N',
115 connectmode == C_ONDEMAND ? "ondemand"
116 : connectmode == C_NEVER ? "never"
117 : connectmode == C_ALWAYS ? "always"
118 : connectmode == C_DISABLED ? "disabled"
119 : "",
120 nodename,
121 hostname ? hostname : "",
122 hostname ? ":" : "",
123 hostname ? udp_port : 0
124 );
125}
126
127conf_node::~conf_node () 111conf_node::~conf_node ()
128{ 112{
129#if 0 113#if 0
130 // does not work, because string pointers etc. are shared 114 // does not work, because string pointers etc. are shared
131 // is not called, however 115 // is not called, however
140 free (dns_hostname); 124 free (dns_hostname);
141#endif 125#endif
142#endif 126#endif
143} 127}
144 128
129void
145void configuration::init () 130configuration::init ()
146{ 131{
147 memset (this, 0, sizeof (*this)); 132 memset (this, 0, sizeof (*this));
148 133
149 mtu = DEFAULT_MTU; 134 mtu = DEFAULT_MTU;
135 nfmark = 0;
150 rekey = DEFAULT_REKEY; 136 rekey = DEFAULT_REKEY;
151 keepalive = DEFAULT_KEEPALIVE; 137 keepalive = DEFAULT_KEEPALIVE;
152 llevel = L_INFO; 138 llevel = L_INFO;
153 ip_proto = IPPROTO_GRE; 139 ip_proto = IPPROTO_GRE;
154#if ENABLE_ICMP 140#if ENABLE_ICMP
166 default_node.if_up_data = strdup (""); 152 default_node.if_up_data = strdup ("");
167 153
168#if ENABLE_DNS 154#if ENABLE_DNS
169 default_node.dns_port = 0; // default is 0 == client 155 default_node.dns_port = 0; // default is 0 == client
170 156
157 dns_case_preserving = true;
171 dns_forw_host = strdup ("127.0.0.1"); 158 dns_forw_host = strdup ("127.0.0.1");
172 dns_forw_port = 53; 159 dns_forw_port = 53;
173 dns_timeout_factor = DEFAULT_DNS_TIMEOUT_FACTOR; 160 dns_timeout_factor = DEFAULT_DNS_TIMEOUT_FACTOR;
174 dns_send_interval = DEFAULT_DNS_SEND_INTERVAL; 161 dns_send_interval = DEFAULT_DNS_SEND_INTERVAL;
175 dns_overlap_factor = DEFAULT_DNS_OVERLAP_FACTOR; 162 dns_overlap_factor = DEFAULT_DNS_OVERLAP_FACTOR;
176 dns_max_outstanding = DEFAULT_DNS_MAX_OUTSTANDING; 163 dns_max_outstanding = DEFAULT_DNS_MAX_OUTSTANDING;
177#endif 164#endif
178 165
179 conf.pidfilename = strdup (LOCALSTATEDIR "/run/gvpe.pid"); 166 pidfilename = strdup (LOCALSTATEDIR "/run/gvpe.pid");
167 seed_dev = strdup ("/dev/urandom");
168 reseed = DEFAULT_RESEED;
180} 169}
181 170
171void
182void configuration::cleanup() 172configuration::cleanup ()
183{ 173{
184 if (rsa_key) 174 if (rsa_key)
185 RSA_free (rsa_key); 175 RSA_free (rsa_key);
186 176
187 rsa_key = 0; 177 rsa_key = 0;
188 178
179 free (seed_dev); seed_dev = 0;
189 free (pidfilename); pidfilename = 0; 180 free (pidfilename); pidfilename = 0;
190 free (ifname); ifname = 0; 181 free (ifname); ifname = 0;
191#if ENABLE_HTTP_PROXY 182#if ENABLE_HTTP_PROXY
192 free (proxy_host); proxy_host = 0; 183 free (proxy_host); proxy_host = 0;
193 free (proxy_auth); proxy_auth = 0; 184 free (proxy_auth); proxy_auth = 0;
194#endif 185#endif
195#if ENABLE_DNS 186#if ENABLE_DNS
196 free (dns_forw_host); dns_forw_host = 0; 187 free (dns_forw_host); dns_forw_host = 0;
197#endif 188#endif
189 free (change_root); change_root = 0;
190 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;
198} 194}
199 195
200void 196void
201configuration::clear () 197configuration::clear ()
202{ 198{
206 nodes.clear (); 202 nodes.clear ();
207 203
208 cleanup (); 204 cleanup ();
209 init (); 205 init ();
210} 206}
207
208conf_node *
209configuration::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//static bool
219//is_true (const char *name)
220//{
221 //re
222//}
211 223
212#define parse_bool(target,name,trueval,falseval) do { \ 224#define parse_bool(target,name,trueval,falseval) do { \
213 if (!strcmp (val, "yes")) target = trueval; \ 225 if (!strcmp (val, "yes")) target = trueval; \
214 else if (!strcmp (val, "no")) target = falseval; \ 226 else if (!strcmp (val, "no")) target = falseval; \
215 else if (!strcmp (val, "true")) target = trueval; \ 227 else if (!strcmp (val, "true")) target = trueval; \
216 else if (!strcmp (val, "false")) target = falseval; \ 228 else if (!strcmp (val, "false")) target = falseval; \
217 else if (!strcmp (val, "on")) target = trueval; \ 229 else if (!strcmp (val, "on")) target = trueval; \
218 else if (!strcmp (val, "off")) target = falseval; \ 230 else if (!strcmp (val, "off")) target = falseval; \
219 else \ 231 else \
220 return _("illegal boolean value, only 'yes|true|on' or 'no|false|off' allowed. (ignored)"); \ 232 return _("illegal boolean value, only 'yes|true|on' or 'no|false|off' allowed, ignored"); \
221} while (0) 233} while (0)
222 234
223const char * 235const char *
224configuration_parser::parse_line (char *line) 236configuration_parser::parse_line (char *line)
225{ 237{
226 { 238 {
227 char *end = line + strlen (line); 239 char *end = line + strlen (line);
228 240
229 while (*end < ' ' && end >= line) 241 while (end >= line && *end < ' ')
230 end--; 242 end--;
231 243
232 *++end = 0; 244 *++end = 0;
233 } 245 }
234 246
240 return 0; /* no tokens on this line */ 252 return 0; /* no tokens on this line */
241 253
242 if (var[0] == '#') 254 if (var[0] == '#')
243 return 0; /* comment: ignore */ 255 return 0; /* comment: ignore */
244 256
257 if (!strcmp (var, "global"))
258 {
259 node = &conf.default_node;
260 return 0;
261 }
262
245 char *val = strtok (NULL, "\t\n\r ="); 263 char *val = strtok (NULL, "\t\n\r =");
246 264
247 if (!val || val[0] == '#') 265 if (!val || val[0] == '#')
248 return _("no value given for variable. (ignored)"); 266 return _("no value given for variable, ignored");
249 267
250 if (!strcmp (var, "on")) 268 else if (!strcmp (var, "on"))
251 { 269 {
252 if (!::thisnode 270 if (::thisnode
253 || (val[0] == '!' && strcmp (val + 1, ::thisnode)) 271 && ((val[0] == '!' && strcmp (val + 1, ::thisnode))
254 || !strcmp (val, ::thisnode)) 272 || !strcmp (val, ::thisnode)))
255 return parse_line (strtok (NULL, "\n\r")); 273 return parse_line (strtok (NULL, "\n\r"));
256 else 274 }
257 return 0; 275
276 else if (!strcmp (var, "include"))
277 {
278 char *fname = conf.config_filename (val);
279 parse_file (fname);
280 free (fname);
258 } 281 }
259 282
260 // truly global 283 // truly global
261 if (!strcmp (var, "loglevel")) 284 else if (!strcmp (var, "loglevel"))
262 { 285 {
263 loglevel l = string_to_loglevel (val); 286 loglevel l = string_to_loglevel (val);
264 287
265 if (l == L_NONE) 288 if (l == L_NONE)
266 return _("unknown loglevel. (skipping)"); 289 return _("unknown loglevel, ignored");
267 } 290 }
291 else if (!strcmp (var, "serial"))
292 strncpy (conf.serial, val, sizeof (conf.serial));
268 else if (!strcmp (var, "ip-proto")) 293 else if (!strcmp (var, "ip-proto"))
269 conf.ip_proto = atoi (val); 294 conf.ip_proto = atoi (val);
270 else if (!strcmp (var, "icmp-type")) 295 else if (!strcmp (var, "icmp-type"))
271 { 296 {
272#if ENABLE_ICMP 297#if ENABLE_ICMP
273 conf.icmp_type = atoi (val); 298 conf.icmp_type = atoi (val);
274#endif 299#endif
275 } 300 }
301 else if (!strcmp (var, "chuser"))
302 {
303 struct passwd *pw = getpwnam (val);
304 if (!pw)
305 return _("user specified for chuser not found");
276 306
277 // per config 307 conf.change_uid = pw->pw_uid;
308 conf.change_gid = pw->pw_gid;
309 }
310 else if (!strcmp (var, "chuid"))
311 conf.change_uid = atoi (val);
312 else if (!strcmp (var, "chgid"))
313 conf.change_gid = atoi (val);
314 else if (!strcmp (var, "chroot"))
315 free (conf.change_root), conf.change_root = strdup (val);
316
317 // per node
278 else if (!strcmp (var, "node")) 318 else if (!strcmp (var, "node"))
279 { 319 {
280 parse_argv (); 320 node = conf.find_node (val);
281 321
322 if (!node)
323 {
282 conf.default_node.id++; 324 conf.default_node.id++;
283 node = new conf_node (conf.default_node); 325 node = new conf_node (conf.default_node);
284 conf.nodes.push_back (node); 326 conf.nodes.push_back (node);
285 node->nodename = strdup (val); 327 node->nodename = strdup (val);
286
287 {
288 char *fname;
289 FILE *f;
290
291 asprintf (&fname, "%s/pubkey/%s", confbase, node->nodename);
292
293 f = fopen (fname, "r");
294 if (f)
295 {
296 node->rsa_key = RSA_new ();
297
298 if (!PEM_read_RSAPublicKey(f, &node->rsa_key, NULL, NULL))
299 {
300 ERR_load_RSA_strings (); ERR_load_PEM_strings ();
301 slog (L_ERR, _("unable to open public rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
302 exit (EXIT_FAILURE);
303 }
304
305 require (RSA_blinding_on (node->rsa_key, 0));
306
307 fclose (f);
308 } 328 }
309 else
310 {
311 slog (need_keys ? L_ERR : L_NOTICE, _("unable to read public rsa key file '%s': %s"), fname, strerror (errno));
312
313 if (need_keys)
314 exit (EXIT_FAILURE);
315 }
316
317 free (fname);
318 }
319
320 if (::thisnode && !strcmp (node->nodename, ::thisnode))
321 conf.thisnode = node;
322 } 329 }
323 else if (!strcmp (var, "private-key")) 330 else if (!strcmp (var, "private-key"))
324 free (conf.prikeyfile), conf.prikeyfile = strdup (val); 331 free (conf.prikeyfile), conf.prikeyfile = strdup (val);
325 else if (!strcmp (var, "ifpersist")) 332 else if (!strcmp (var, "ifpersist"))
326 parse_bool (conf.ifpersist, "ifpersist", true, false); 333 parse_bool (conf.ifpersist, "ifpersist", true, false);
330 conf.rekey = atoi (val); 337 conf.rekey = atoi (val);
331 else if (!strcmp (var, "keepalive")) 338 else if (!strcmp (var, "keepalive"))
332 conf.keepalive = atoi (val); 339 conf.keepalive = atoi (val);
333 else if (!strcmp (var, "mtu")) 340 else if (!strcmp (var, "mtu"))
334 conf.mtu = atoi (val); 341 conf.mtu = atoi (val);
342 else if (!strcmp (var, "nfmark"))
343 conf.nfmark = atoi (val);
344 else if (!strcmp (var, "seed-device"))
345 free (conf.seed_dev), conf.seed_dev = strdup (val);
346 else if (!strcmp (var, "seed-interval"))
347 conf.reseed = atoi (val);
335 else if (!strcmp (var, "if-up")) 348 else if (!strcmp (var, "if-up"))
336 free (conf.script_if_up), conf.script_if_up = strdup (val); 349 free (conf.script_if_up), conf.script_if_up = strdup (val);
337 else if (!strcmp (var, "node-up")) 350 else if (!strcmp (var, "node-up"))
338 free (conf.script_node_up), conf.script_node_up = strdup (val); 351 free (conf.script_node_up), conf.script_node_up = strdup (val);
352 else if (!strcmp (var, "node-change"))
353 free (conf.script_node_change), conf.script_node_change = strdup (val);
339 else if (!strcmp (var, "node-down")) 354 else if (!strcmp (var, "node-down"))
340 free (conf.script_node_down), conf.script_node_down = strdup (val); 355 free (conf.script_node_down), conf.script_node_down = strdup (val);
341 else if (!strcmp (var, "pid-file")) 356 else if (!strcmp (var, "pid-file"))
342 free (conf.pidfilename), conf.pidfilename = strdup (val); 357 free (conf.pidfilename), conf.pidfilename = strdup (val);
343 else if (!strcmp (var, "dns-forw-host")) 358 else if (!strcmp (var, "dns-forw-host"))
372 } 387 }
373 else if (!strcmp (var, "dns-max-outstanding")) 388 else if (!strcmp (var, "dns-max-outstanding"))
374 { 389 {
375#if ENABLE_DNS 390#if ENABLE_DNS
376 conf.dns_max_outstanding = atoi (val); 391 conf.dns_max_outstanding = atoi (val);
392#endif
393 }
394 else if (!strcmp (var, "dns-case-preserving"))
395 {
396#if ENABLE_DNS
397 parse_bool (conf.dns_case_preserving, "dns-case-preserving", true, false);
377#endif 398#endif
378 } 399 }
379 else if (!strcmp (var, "http-proxy-host")) 400 else if (!strcmp (var, "http-proxy-host"))
380 { 401 {
381#if ENABLE_HTTP_PROXY 402#if ENABLE_HTTP_PROXY
437 else if (!strcmp (val, "always")) 458 else if (!strcmp (val, "always"))
438 node->connectmode = conf_node::C_ALWAYS; 459 node->connectmode = conf_node::C_ALWAYS;
439 else if (!strcmp (val, "disabled")) 460 else if (!strcmp (val, "disabled"))
440 node->connectmode = conf_node::C_DISABLED; 461 node->connectmode = conf_node::C_DISABLED;
441 else 462 else
442 return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled'. (ignored)"); 463 return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled', ignored");
443 } 464 }
444 else if (!strcmp (var, "inherit-tos")) 465 else if (!strcmp (var, "inherit-tos"))
445 parse_bool (node->inherit_tos, "inherit-tos", true, false); 466 parse_bool (node->inherit_tos, "inherit-tos", true, false);
446 else if (!strcmp (var, "compress")) 467 else if (!strcmp (var, "compress"))
447 parse_bool (node->compress, "compress", true, false); 468 parse_bool (node->compress, "compress", true, false);
469 else if (!strcmp (var, "low-power"))
470 parse_bool (node->low_power, "low-power", true, false);
448 // all these bool options really really cost a lot of executable size! 471 // all these bool options really really cost a lot of executable size!
449 else if (!strcmp (var, "enable-tcp")) 472 else if (!strcmp (var, "enable-tcp"))
450 { 473 {
451#if ENABLE_TCP 474#if ENABLE_TCP
452 u8 v; parse_bool (v, "enable-tcp" , PROT_TCPv4, 0); node->protocols = (node->protocols & ~PROT_TCPv4) | v; 475 u8 v; parse_bool (v, "enable-tcp" , PROT_TCPv4, 0); node->protocols = (node->protocols & ~PROT_TCPv4) | v;
481 else if (!strcmp (var, "max-queue")) 504 else if (!strcmp (var, "max-queue"))
482 node->max_queue = atoi (val); 505 node->max_queue = atoi (val);
483 506
484 // unknown or misplaced 507 // unknown or misplaced
485 else 508 else
486 return _("unknown configuration directive. (ignored)"); 509 return _("unknown configuration directive - ignored");
487 510
488 return 0; 511 return 0;
489} 512}
490 513
514void
491void conf_node::finalise () 515conf_node::finalise ()
492{ 516{
493 if (max_queue < 1) 517 if (max_queue < 1)
494 { 518 {
495 slog (L_WARN, _("%s: max-queue value invalid, setting it to 1."), nodename); 519 slog (L_WARN, _("%s: max-queue value invalid, setting it to 1."), nodename);
496 max_queue = 1; 520 max_queue = 1;
497 } 521 }
498 522
499 if (routerprio && (connectmode != C_ALWAYS && connectmode != C_DISABLED)) 523 if (routerprio > 1 && (connectmode != C_ALWAYS && connectmode != C_DISABLED))
500 { 524 {
501 //slog (L_WARN, _("%s: has non-zero router-priority but either 'never' or 'ondemand' as connectmode, setting it to 'always'."), nodename); 525 //slog (L_WARN, _("%s: has non-zero router-priority but either 'never' or 'ondemand' as connectmode, setting it to 'always'."), nodename);
502 connectmode = C_ALWAYS; 526 connectmode = C_ALWAYS;
503 } 527 }
504} 528}
505 529
506void configuration_parser::parse_argv () 530void
531configuration_parser::parse_file (const char *fname)
507{ 532{
508 for (int i = 0; i < argc; ++i) 533 if (FILE *f = fopen (fname, "r"))
509 { 534 {
510 char *v = argv [i]; 535 char line [2048];
536 int lineno = 0;
511 537
512 if (!*v) 538 while (fgets (line, sizeof (line), f))
513 continue;
514
515 char *enode = v;
516
517 while (*enode != '.' && *enode > ' ' && *enode != '=' && *enode)
518 enode++;
519
520 if (*enode != '.')
521 enode = 0;
522
523 char *wnode = node == &conf.default_node
524 ? 0
525 : node->nodename;
526
527 if ((!wnode && !enode)
528 || (wnode && enode && !strncmp (wnode, v, enode - v)))
529 { 539 {
540 lineno++;
541
530 const char *warn = parse_line (enode ? enode + 1 : v); 542 const char *warn = parse_line (line);
531 543
532 if (warn) 544 if (warn)
533 slog (L_WARN, _("%s, while parsing command line option '%s'."), warn, v); 545 slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
534
535 *v = 0;
536 } 546 }
547
548 fclose (f);
549 }
550 else
551 {
552 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
553 exit (EXIT_FAILURE);
537 } 554 }
538} 555}
539 556
540configuration_parser::configuration_parser (configuration &conf, 557configuration_parser::configuration_parser (configuration &conf,
541 bool need_keys, 558 bool need_keys,
542 int argc, 559 int argc,
543 char **argv) 560 char **argv)
544: conf (conf),need_keys (need_keys), argc (argc), argv (argv) 561: conf (conf), need_keys (need_keys), argc (argc), argv (argv)
545{ 562{
546 char *fname; 563 char *fname;
547 FILE *f;
548 564
549 conf.clear (); 565 conf.clear ();
566 node = &conf.default_node;
550 567
551 asprintf (&fname, "%s/gvpe.conf", confbase); 568 asprintf (&fname, "%s/gvpe.conf", confbase);
552 f = fopen (fname, "r"); 569 parse_file (fname);
553
554 if (f)
555 {
556 char line[16384];
557 int lineno = 0;
558 node = &conf.default_node;
559
560 while (fgets (line, sizeof (line), f))
561 {
562 lineno++;
563
564 const char *warn = parse_line (line);
565
566 if (warn)
567 slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
568 }
569
570 fclose (f);
571
572 parse_argv ();
573 }
574 else
575 {
576 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
577 exit (EXIT_FAILURE);
578 }
579
580 free (fname); 570 free (fname);
581 571
582 fname = conf.config_filename (conf.prikeyfile, "hostkey"); 572 fname = conf.config_filename (conf.prikeyfile, "hostkey");
583 573
584 f = fopen (fname, "r"); 574 if (FILE *f = fopen (fname, "r"))
585 if (f)
586 { 575 {
587 conf.rsa_key = RSA_new (); 576 conf.rsa_key = RSA_new ();
588 577
589 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL)) 578 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL))
590 { 579 {
597 586
598 fclose (f); 587 fclose (f);
599 } 588 }
600 else 589 else
601 { 590 {
602 slog (need_keys ? L_ERR : L_NOTICE, _("unable to open private rsa key file '%s': %s"), fname, strerror (errno));
603
604 if (need_keys) 591 if (need_keys)
592 {
593 slog (need_keys ? L_ERR : L_NOTICE, _("unable to open private rsa key file '%s': %s"), fname, strerror (errno));
605 exit (EXIT_FAILURE); 594 exit (EXIT_FAILURE);
606 }
607
608 if (need_keys && ::thisnode
609 && conf.rsa_key && conf.thisnode && conf.thisnode->rsa_key)
610 if (BN_cmp (conf.rsa_key->n, conf.thisnode->rsa_key->n) != 0
611 || BN_cmp (conf.rsa_key->e, conf.thisnode->rsa_key->e) != 0)
612 {
613 slog (L_NOTICE, _("private hostkey and public node key mismatch: is '%s' the correct node?"), ::thisnode);
614 exit (EXIT_FAILURE);
615 } 595 }
596 }
616 597
617 free (fname); 598 free (fname);
618 599
600 fname = conf.config_filename (conf.pidfilename);
601 free (conf.pidfilename); conf.pidfilename = fname;
602
619 for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i) 603 for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i)
604 {
605 conf_node *node = *i;
606 char *fname;
607 FILE *f;
608
609 asprintf (&fname, "%s/pubkey/%s", confbase, node->nodename);
610
611 f = fopen (fname, "r");
612 if (f)
613 {
614 node->rsa_key = RSA_new ();
615
616 if (!PEM_read_RSAPublicKey (f, &node->rsa_key, NULL, NULL))
617 {
618 ERR_load_RSA_strings (); ERR_load_PEM_strings ();
619 slog (L_ERR, _("unable to open public rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
620 exit (EXIT_FAILURE);
621 }
622
623 require (RSA_blinding_on (node->rsa_key, 0));
624
625 fclose (f);
626 }
627 else
628 {
629 slog (need_keys ? L_ERR : L_NOTICE, _("unable to read public rsa key file '%s': %s"), fname, strerror (errno));
630
631 if (need_keys)
632 exit (EXIT_FAILURE);
633 }
634
635 free (fname);
636
620 (*i)->finalise (); 637 (*i)->finalise ();
621} 638 }
622 639
640 if (::thisnode)
641 {
642 conf.thisnode = conf.find_node (::thisnode);
643
644 if (need_keys)
645 {
646 if (!conf.thisnode)
647 {
648 slog (L_NOTICE, _("local node ('%s') not found in config file, aborting."), ::thisnode);
649 exit (EXIT_FAILURE);
650 }
651
652 if (conf.rsa_key && conf.thisnode->rsa_key)
653 {
654 const BIGNUM *conf_n, *conf_e, *thisnode_n, *thisnode_e;
655
656#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !LIBRESSL_VERSION_NUMBER
657 RSA_get0_key (conf.rsa_key, &conf_n, &conf_e, 0);
658 RSA_get0_key (conf.thisnode->rsa_key, &thisnode_n, &thisnode_e, 0);
659#else
660 conf_n = conf.thisnode->rsa_key->n;
661 conf_e = conf.thisnode->rsa_key->e;
662 thisnode_n = conf.rsa_key->n;
663 thisnode_e = conf.rsa_key->e;
664#endif
665 if (BN_cmp (conf_n, thisnode_n) != 0 || BN_cmp (conf_e, thisnode_e) != 0)
666 {
667 slog (L_NOTICE, _("private hostkey and public node key mismatch: is '%s' the correct node?"), ::thisnode);
668 exit (EXIT_FAILURE);
669 }
670 }
671 }
672 }
673
674 parse_argv ();
675}
676
677void
678configuration_parser::parse_argv ()
679{
680 for (int i = 0; i < argc; ++i)
681 {
682 char *v = argv [i];
683
684 if (!*v)
685 continue;
686
687 char *enode = v;
688
689 while (*enode != '.' && *enode > ' ' && *enode != '=' && *enode)
690 enode++;
691
692 if (*enode != '.')
693 enode = 0;
694
695 if (enode)
696 {
697 char *val = strdup (v);
698 val [enode - v] = 0;
699 node = conf.find_node (val);
700 free (val);
701
702 if (!node)
703 {
704 slog (L_WARN, _("command line option '%s' refers to unknown node, ignoring."), v);
705 continue;
706 }
707 }
708 else
709 node = &conf.default_node;
710
711 const char *warn = parse_line (enode ? enode + 1 : v);
712
713 if (warn)
714 slog (L_WARN, _("%s, while parsing command line option '%s'."), warn, v);
715 }
716}
717
718char *
623char *configuration::config_filename (const char *name, const char *dflt) 719configuration::config_filename (const char *name, const char *dflt)
624{ 720{
625 char *fname; 721 char *fname;
626 722
627 asprintf (&fname, name ? name : dflt, ::thisnode); 723 asprintf (&fname, name ? name : dflt, ::thisnode ? ::thisnode : "<unset>");
628 724
629 if (!ABSOLUTE_PATH (fname)) 725 if (!ABSOLUTE_PATH (fname))
630 { 726 {
631 char *rname = fname; 727 char *rname = fname;
632 asprintf (&fname, "%s/%s", confbase, rname); 728 asprintf (&fname, "%s/%s", confbase, rname);
633 free (rname); 729 free (rname);
634 } 730 }
635 731
636 return fname; 732 return fname;
733}
734
735void
736conf_node::print ()
737{
738 printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %02x %s%s%d\n",
739 id,
740 id >> 8, id & 0xff,
741 compress ? 'Y' : 'N',
742 connectmode == C_ONDEMAND ? "ondemand"
743 : connectmode == C_NEVER ? "never"
744 : connectmode == C_ALWAYS ? "always"
745 : connectmode == C_DISABLED ? "disabled"
746 : "",
747 nodename,
748 protocols,
749 hostname ? hostname : "",
750 hostname ? ":" : "",
751 hostname ? udp_port : 0
752 );
637} 753}
638 754
639void 755void
640configuration::print () 756configuration::print ()
641{ 757{
648 printf (_("interface: %s\n"), ifname); 764 printf (_("interface: %s\n"), ifname);
649 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>"); 765 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>");
650 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1); 766 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1);
651 printf ("\n"); 767 printf ("\n");
652 768
653 printf ("%4s %-17s %s %-8.8s %-10.10s %s\n", 769 printf ("%4s %-17s %s %-8.8s %-10.10s %04s %s\n",
654 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Host:Port")); 770 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Prot"), _("Host:Port"));
655 771
656 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i) 772 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i)
657 (*i)->print (); 773 (*i)->print ();
658 774
659 printf ("\n"); 775 printf ("\n");
669configuration::~configuration () 785configuration::~configuration ()
670{ 786{
671 cleanup (); 787 cleanup ();
672} 788}
673 789
674

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines