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.43 by pcg, Thu Aug 7 16:34:21 2008 UTC vs.
Revision 1.62 by root, Wed Jul 17 16:40:57 2013 UTC

1/* 1/*
2 conf.c -- configuration code 2 conf.C -- configuration code
3 Copyright (C) 2003-2005 Marc Lehmann <gvpe@schmorp.de> 3 Copyright (C) 2003-2008,2011 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 7 GVPE is free software; you can redistribute it and/or modify it
8 it under the terms of the GNU General Public License as published by 8 under the terms of the GNU General Public License as published by the
9 the Free Software Foundation; either version 2 of the License, or 9 Free Software Foundation; either version 3 of the License, or (at your
10 (at your option) any later version. 10 option) any later version.
11 11
12 This program is distributed in the hope that it will be useful, 12 This program is distributed in the hope that it will be useful, but
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 GNU General Public License for more details. 15 Public License for more details.
16 16
17 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License along
18 along with gvpe; if not, write to the Free Software 18 with this program; if not, see <http://www.gnu.org/licenses/>.
19 Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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.
20*/ 30*/
21 31
22#include "config.h" 32#include "config.h"
23 33
24#include <cstdio> 34#include <cstdio>
28#include <errno.h> 38#include <errno.h>
29#include <netdb.h> 39#include <netdb.h>
30#include <sys/stat.h> 40#include <sys/stat.h>
31#include <sys/types.h> 41#include <sys/types.h>
32#include <unistd.h> 42#include <unistd.h>
43#include <pwd.h>
33 44
34#include "netcompat.h" 45#include "netcompat.h"
35 46
36#include <openssl/err.h> 47#include <openssl/err.h>
37#include <openssl/pem.h> 48#include <openssl/pem.h>
47char *thisnode; 58char *thisnode;
48char *identname; 59char *identname;
49 60
50struct configuration conf; 61struct configuration conf;
51 62
63u8
52u8 best_protocol (u8 protset) 64best_protocol (u8 protset)
53{ 65{
54 if (protset & PROT_IPv4 ) return PROT_IPv4; 66 if (protset & PROT_IPv4 ) return PROT_IPv4;
55 if (protset & PROT_ICMPv4) return PROT_ICMPv4; 67 if (protset & PROT_ICMPv4) return PROT_ICMPv4;
56 if (protset & PROT_UDPv4 ) return PROT_UDPv4; 68 if (protset & PROT_UDPv4 ) return PROT_UDPv4;
57 if (protset & PROT_TCPv4 ) return PROT_TCPv4; 69 if (protset & PROT_TCPv4 ) return PROT_TCPv4;
58 if (protset & PROT_DNSv4 ) return PROT_DNSv4; 70 if (protset & PROT_DNSv4 ) return PROT_DNSv4;
59 71
60 return 0; 72 return 0;
61} 73}
62 74
75const char *
63const char *strprotocol (u8 protocol) 76strprotocol (u8 protocol)
64{ 77{
65 if (protocol & PROT_IPv4 ) return "rawip"; 78 if (protocol & PROT_IPv4 ) return "rawip";
66 if (protocol & PROT_ICMPv4) return "icmp"; 79 if (protocol & PROT_ICMPv4) return "icmp";
67 if (protocol & PROT_UDPv4 ) return "udp"; 80 if (protocol & PROT_UDPv4 ) return "udp";
68 if (protocol & PROT_TCPv4 ) return "tcp"; 81 if (protocol & PROT_TCPv4 ) return "tcp";
82 95
83 return false; 96 return false;
84} 97}
85 98
86bool 99bool
87conf_node::can_direct (struct conf_node *other) 100conf_node::may_direct (struct conf_node *other)
88{ 101{
89 if (match_list (allow_direct, other->nodename)) 102 if (match_list (allow_direct, other->nodename))
90 return true; 103 return true;
91 104
92 if (match_list (deny_direct, other->nodename)) 105 if (match_list (deny_direct, other->nodename))
93 return false; 106 return false;
94 107
95 return true; 108 return true;
96}
97
98void
99conf_node::print ()
100{
101 printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %s%s%d\n",
102 id,
103 id >> 8, id & 0xff,
104 compress ? 'Y' : 'N',
105 connectmode == C_ONDEMAND ? "ondemand" :
106 connectmode == C_NEVER ? "never" :
107 connectmode == C_ALWAYS ? "always" : "",
108 nodename,
109 hostname ? hostname : "",
110 hostname ? ":" : "",
111 hostname ? udp_port : 0
112 );
113} 109}
114 110
115conf_node::~conf_node () 111conf_node::~conf_node ()
116{ 112{
117#if 0 113#if 0
128 free (dns_hostname); 124 free (dns_hostname);
129#endif 125#endif
130#endif 126#endif
131} 127}
132 128
129void
133void configuration::init () 130configuration::init ()
134{ 131{
135 memset (this, 0, sizeof (*this)); 132 memset (this, 0, sizeof (*this));
136 133
137 mtu = DEFAULT_MTU; 134 mtu = DEFAULT_MTU;
135 nfmark = 0;
138 rekey = DEFAULT_REKEY; 136 rekey = DEFAULT_REKEY;
139 keepalive = DEFAULT_KEEPALIVE; 137 keepalive = DEFAULT_KEEPALIVE;
140 llevel = L_INFO; 138 llevel = L_INFO;
141 ip_proto = IPPROTO_GRE; 139 ip_proto = IPPROTO_GRE;
142#if ENABLE_ICMP 140#if ENABLE_ICMP
154 default_node.if_up_data = strdup (""); 152 default_node.if_up_data = strdup ("");
155 153
156#if ENABLE_DNS 154#if ENABLE_DNS
157 default_node.dns_port = 0; // default is 0 == client 155 default_node.dns_port = 0; // default is 0 == client
158 156
157 dns_case_preserving = true;
159 dns_forw_host = strdup ("127.0.0.1"); 158 dns_forw_host = strdup ("127.0.0.1");
160 dns_forw_port = 53; 159 dns_forw_port = 53;
161 dns_timeout_factor = DEFAULT_DNS_TIMEOUT_FACTOR; 160 dns_timeout_factor = DEFAULT_DNS_TIMEOUT_FACTOR;
162 dns_send_interval = DEFAULT_DNS_SEND_INTERVAL; 161 dns_send_interval = DEFAULT_DNS_SEND_INTERVAL;
163 dns_overlap_factor = DEFAULT_DNS_OVERLAP_FACTOR; 162 dns_overlap_factor = DEFAULT_DNS_OVERLAP_FACTOR;
164 dns_max_outstanding = DEFAULT_DNS_MAX_OUTSTANDING; 163 dns_max_outstanding = DEFAULT_DNS_MAX_OUTSTANDING;
165#endif 164#endif
166 165
167 conf.pidfilename = strdup (LOCALSTATEDIR "/run/gvpe.pid"); 166 pidfilename = strdup (LOCALSTATEDIR "/run/gvpe.pid");
167 seed_dev = strdup ("/dev/urandom");
168 reseed = DEFAULT_RESEED;
168} 169}
169 170
171void
170void configuration::cleanup() 172configuration::cleanup ()
171{ 173{
172 if (rsa_key) 174 if (rsa_key)
173 RSA_free (rsa_key); 175 RSA_free (rsa_key);
174 176
175 rsa_key = 0; 177 rsa_key = 0;
176 178
179 free (seed_dev); seed_dev = 0;
177 free (pidfilename); pidfilename = 0; 180 free (pidfilename); pidfilename = 0;
178 free (ifname); ifname = 0; 181 free (ifname); ifname = 0;
179#if ENABLE_HTTP_PROXY 182#if ENABLE_HTTP_PROXY
180 free (proxy_host); proxy_host = 0; 183 free (proxy_host); proxy_host = 0;
181 free (proxy_auth); proxy_auth = 0; 184 free (proxy_auth); proxy_auth = 0;
182#endif 185#endif
183#if ENABLE_DNS 186#if ENABLE_DNS
184 free (dns_forw_host); dns_forw_host = 0; 187 free (dns_forw_host); dns_forw_host = 0;
185#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;
186} 194}
187 195
188void 196void
189configuration::clear () 197configuration::clear ()
190{ 198{
194 nodes.clear (); 202 nodes.clear ();
195 203
196 cleanup (); 204 cleanup ();
197 init (); 205 init ();
198} 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//}
199 223
200#define parse_bool(target,name,trueval,falseval) do { \ 224#define parse_bool(target,name,trueval,falseval) do { \
201 if (!strcmp (val, "yes")) target = trueval; \ 225 if (!strcmp (val, "yes")) target = trueval; \
202 else if (!strcmp (val, "no")) target = falseval; \ 226 else if (!strcmp (val, "no")) target = falseval; \
203 else if (!strcmp (val, "true")) target = trueval; \ 227 else if (!strcmp (val, "true")) target = trueval; \
204 else if (!strcmp (val, "false")) target = falseval; \ 228 else if (!strcmp (val, "false")) target = falseval; \
205 else if (!strcmp (val, "on")) target = trueval; \ 229 else if (!strcmp (val, "on")) target = trueval; \
206 else if (!strcmp (val, "off")) target = falseval; \ 230 else if (!strcmp (val, "off")) target = falseval; \
207 else \ 231 else \
208 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"); \
209} while (0) 233} while (0)
210 234
211const char * 235const char *
212configuration_parser::parse_line (char *line) 236configuration_parser::parse_line (char *line)
213{ 237{
231 return 0; /* comment: ignore */ 255 return 0; /* comment: ignore */
232 256
233 char *val = strtok (NULL, "\t\n\r ="); 257 char *val = strtok (NULL, "\t\n\r =");
234 258
235 if (!val || val[0] == '#') 259 if (!val || val[0] == '#')
236 return _("no value given for variable. (ignored)"); 260 return _("no value given for variable, ignored");
237 261
238 if (!strcmp (var, "on")) 262 else if (!strcmp (var, "on"))
239 { 263 {
240 if (!::thisnode 264 if (::thisnode
241 || (val[0] == '!' && strcmp (val + 1, ::thisnode)) 265 && ((val[0] == '!' && strcmp (val + 1, ::thisnode))
242 || !strcmp (val, ::thisnode)) 266 || !strcmp (val, ::thisnode)))
243 return parse_line (strtok (NULL, "\n\r")); 267 return parse_line (strtok (NULL, "\n\r"));
244 else 268 }
245 return 0; 269
270 else if (!strcmp (var, "include"))
271 {
272 char *fname = conf.config_filename (val);
273 parse_file (fname);
274 free (fname);
246 } 275 }
247 276
248 // truly global 277 // truly global
249 if (!strcmp (var, "loglevel")) 278 else if (!strcmp (var, "loglevel"))
250 { 279 {
251 loglevel l = string_to_loglevel (val); 280 loglevel l = string_to_loglevel (val);
252 281
253 if (l == L_NONE) 282 if (l == L_NONE)
254 return _("unknown loglevel. (skipping)"); 283 return _("unknown loglevel, ignored");
255 } 284 }
256 else if (!strcmp (var, "ip-proto")) 285 else if (!strcmp (var, "ip-proto"))
257 conf.ip_proto = atoi (val); 286 conf.ip_proto = atoi (val);
258 else if (!strcmp (var, "icmp-type")) 287 else if (!strcmp (var, "icmp-type"))
259 { 288 {
260#if ENABLE_ICMP 289#if ENABLE_ICMP
261 conf.icmp_type = atoi (val); 290 conf.icmp_type = atoi (val);
262#endif 291#endif
263 } 292 }
293 else if (!strcmp (var, "chuser"))
294 {
295 struct passwd *pw = getpwnam (val);
296 if (!pw)
297 return _("user specified for chuser not found");
264 298
265 // per config 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
309 // per node
310 else if (!strcmp (var, "global"))
311 node = &conf.default_node;
266 else if (!strcmp (var, "node")) 312 else if (!strcmp (var, "node"))
267 { 313 {
268 parse_argv (); 314 node = conf.find_node (val);
269 315
316 if (!node)
317 {
270 conf.default_node.id++; 318 conf.default_node.id++;
271 node = new conf_node (conf.default_node); 319 node = new conf_node (conf.default_node);
272 conf.nodes.push_back (node); 320 conf.nodes.push_back (node);
273 node->nodename = strdup (val); 321 node->nodename = strdup (val);
274
275 {
276 char *fname;
277 FILE *f;
278
279 asprintf (&fname, "%s/pubkey/%s", confbase, node->nodename);
280
281 f = fopen (fname, "r");
282 if (f)
283 {
284 node->rsa_key = RSA_new ();
285
286 if (!PEM_read_RSAPublicKey(f, &node->rsa_key, NULL, NULL))
287 {
288 ERR_load_RSA_strings (); ERR_load_PEM_strings ();
289 slog (L_ERR, _("unable to open public rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
290 exit (EXIT_FAILURE);
291 }
292
293 require (RSA_blinding_on (node->rsa_key, 0));
294
295 fclose (f);
296 } 322 }
297 else
298 {
299 slog (need_keys ? L_ERR : L_NOTICE, _("unable to read public rsa key file '%s': %s"), fname, strerror (errno));
300
301 if (need_keys)
302 exit (EXIT_FAILURE);
303 }
304
305 free (fname);
306 }
307
308 if (::thisnode && !strcmp (node->nodename, ::thisnode))
309 conf.thisnode = node;
310 } 323 }
311 else if (!strcmp (var, "private-key")) 324 else if (!strcmp (var, "private-key"))
312 free (conf.prikeyfile), conf.prikeyfile = strdup (val); 325 free (conf.prikeyfile), conf.prikeyfile = strdup (val);
313 else if (!strcmp (var, "ifpersist")) 326 else if (!strcmp (var, "ifpersist"))
314 parse_bool (conf.ifpersist, "ifpersist", true, false); 327 parse_bool (conf.ifpersist, "ifpersist", true, false);
318 conf.rekey = atoi (val); 331 conf.rekey = atoi (val);
319 else if (!strcmp (var, "keepalive")) 332 else if (!strcmp (var, "keepalive"))
320 conf.keepalive = atoi (val); 333 conf.keepalive = atoi (val);
321 else if (!strcmp (var, "mtu")) 334 else if (!strcmp (var, "mtu"))
322 conf.mtu = atoi (val); 335 conf.mtu = atoi (val);
336 else if (!strcmp (var, "nfmark"))
337 conf.nfmark = atoi (val);
338 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);
323 else if (!strcmp (var, "if-up")) 342 else if (!strcmp (var, "if-up"))
324 free (conf.script_if_up), conf.script_if_up = strdup (val); 343 free (conf.script_if_up), conf.script_if_up = strdup (val);
325 else if (!strcmp (var, "node-up")) 344 else if (!strcmp (var, "node-up"))
326 free (conf.script_node_up), conf.script_node_up = strdup (val); 345 free (conf.script_node_up), conf.script_node_up = strdup (val);
346 else if (!strcmp (var, "node-change"))
347 free (conf.script_node_change), conf.script_node_change = strdup (val);
327 else if (!strcmp (var, "node-down")) 348 else if (!strcmp (var, "node-down"))
328 free (conf.script_node_down), conf.script_node_down = strdup (val); 349 free (conf.script_node_down), conf.script_node_down = strdup (val);
329 else if (!strcmp (var, "pid-file")) 350 else if (!strcmp (var, "pid-file"))
330 free (conf.pidfilename), conf.pidfilename = strdup (val); 351 free (conf.pidfilename), conf.pidfilename = strdup (val);
331 else if (!strcmp (var, "dns-forw-host")) 352 else if (!strcmp (var, "dns-forw-host"))
360 } 381 }
361 else if (!strcmp (var, "dns-max-outstanding")) 382 else if (!strcmp (var, "dns-max-outstanding"))
362 { 383 {
363#if ENABLE_DNS 384#if ENABLE_DNS
364 conf.dns_max_outstanding = atoi (val); 385 conf.dns_max_outstanding = atoi (val);
386#endif
387 }
388 else if (!strcmp (var, "dns-case-preserving"))
389 {
390#if ENABLE_DNS
391 parse_bool (conf.dns_case_preserving, "dns-case-preserving", true, false);
365#endif 392#endif
366 } 393 }
367 else if (!strcmp (var, "http-proxy-host")) 394 else if (!strcmp (var, "http-proxy-host"))
368 { 395 {
369#if ENABLE_HTTP_PROXY 396#if ENABLE_HTTP_PROXY
425 else if (!strcmp (val, "always")) 452 else if (!strcmp (val, "always"))
426 node->connectmode = conf_node::C_ALWAYS; 453 node->connectmode = conf_node::C_ALWAYS;
427 else if (!strcmp (val, "disabled")) 454 else if (!strcmp (val, "disabled"))
428 node->connectmode = conf_node::C_DISABLED; 455 node->connectmode = conf_node::C_DISABLED;
429 else 456 else
430 return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled'. (ignored)"); 457 return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled', ignored");
431 } 458 }
432 else if (!strcmp (var, "inherit-tos")) 459 else if (!strcmp (var, "inherit-tos"))
433 parse_bool (node->inherit_tos, "inherit-tos", true, false); 460 parse_bool (node->inherit_tos, "inherit-tos", true, false);
434 else if (!strcmp (var, "compress")) 461 else if (!strcmp (var, "compress"))
435 parse_bool (node->compress, "compress", true, false); 462 parse_bool (node->compress, "compress", true, false);
469 else if (!strcmp (var, "max-queue")) 496 else if (!strcmp (var, "max-queue"))
470 node->max_queue = atoi (val); 497 node->max_queue = atoi (val);
471 498
472 // unknown or misplaced 499 // unknown or misplaced
473 else 500 else
474 return _("unknown configuration directive. (ignored)"); 501 return _("unknown configuration directive - ignored");
475 502
476 return 0; 503 return 0;
477} 504}
478 505
479void configuration_parser::parse_argv () 506void
507conf_node::finalise ()
480{ 508{
481 for (int i = 0; i < argc; ++i) 509 if (max_queue < 1)
510 {
511 slog (L_WARN, _("%s: max-queue value invalid, setting it to 1."), nodename);
512 max_queue = 1;
482 { 513 }
483 char *v = argv [i];
484 514
485 if (!*v) 515 if (routerprio > 1 && (connectmode != C_ALWAYS && connectmode != C_DISABLED))
486 continue; 516 {
517 //slog (L_WARN, _("%s: has non-zero router-priority but either 'never' or 'ondemand' as connectmode, setting it to 'always'."), nodename);
518 connectmode = C_ALWAYS;
519 }
520}
487 521
488 char *enode = v; 522void
523configuration_parser::parse_file (const char *fname)
524{
525 if (FILE *f = fopen (fname, "r"))
526 {
527 char line [2048];
528 int lineno = 0;
489 529
490 while (*enode != '.' && *enode > ' ' && *enode != '=' && *enode) 530 while (fgets (line, sizeof (line), f))
491 enode++;
492
493 if (*enode != '.')
494 enode = 0;
495
496 char *wnode = node == &conf.default_node
497 ? 0
498 : node->nodename;
499
500 if ((!wnode && !enode)
501 || (wnode && enode && !strncmp (wnode, v, enode - v)))
502 { 531 {
532 lineno++;
533
503 const char *warn = parse_line (enode ? enode + 1 : v); 534 const char *warn = parse_line (line);
504 535
505 if (warn) 536 if (warn)
506 slog (L_WARN, _("%s, while parsing command line option '%s'."), warn, v); 537 slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
507
508 *v = 0;
509 } 538 }
539
540 fclose (f);
541 }
542 else
543 {
544 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
545 exit (EXIT_FAILURE);
510 } 546 }
511} 547}
512 548
513configuration_parser::configuration_parser (configuration &conf, 549configuration_parser::configuration_parser (configuration &conf,
514 bool need_keys, 550 bool need_keys,
515 int argc, 551 int argc,
516 char **argv) 552 char **argv)
517: conf (conf),need_keys (need_keys), argc (argc), argv (argv) 553: conf (conf), need_keys (need_keys), argc (argc), argv (argv)
518{ 554{
519 char *fname; 555 char *fname;
520 FILE *f;
521 556
522 conf.clear (); 557 conf.clear ();
558 node = &conf.default_node;
523 559
524 asprintf (&fname, "%s/gvpe.conf", confbase); 560 asprintf (&fname, "%s/gvpe.conf", confbase);
525 f = fopen (fname, "r"); 561 parse_file (fname);
526
527 if (f)
528 {
529 char line[16384];
530 int lineno = 0;
531 node = &conf.default_node;
532
533 while (fgets (line, sizeof (line), f))
534 {
535 lineno++;
536
537 const char *warn = parse_line (line);
538
539 if (warn)
540 slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
541 }
542
543 fclose (f);
544
545 parse_argv ();
546 }
547 else
548 {
549 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
550 exit (EXIT_FAILURE);
551 }
552
553 free (fname); 562 free (fname);
554 563
555 fname = conf.config_filename (conf.prikeyfile, "hostkey"); 564 fname = conf.config_filename (conf.prikeyfile, "hostkey");
556 565
557 f = fopen (fname, "r"); 566 if (FILE *f = fopen (fname, "r"))
558 if (f)
559 { 567 {
560 conf.rsa_key = RSA_new (); 568 conf.rsa_key = RSA_new ();
561 569
562 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL)) 570 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL))
563 { 571 {
570 578
571 fclose (f); 579 fclose (f);
572 } 580 }
573 else 581 else
574 { 582 {
575 slog (need_keys ? L_ERR : L_NOTICE, _("unable to open private rsa key file '%s': %s"), fname, strerror (errno));
576
577 if (need_keys) 583 if (need_keys)
584 {
585 slog (need_keys ? L_ERR : L_NOTICE, _("unable to open private rsa key file '%s': %s"), fname, strerror (errno));
578 exit (EXIT_FAILURE); 586 exit (EXIT_FAILURE);
579 }
580
581 if (need_keys && ::thisnode
582 && conf.rsa_key && conf.thisnode && conf.thisnode->rsa_key)
583 if (BN_cmp (conf.rsa_key->n, conf.thisnode->rsa_key->n) != 0
584 || BN_cmp (conf.rsa_key->e, conf.thisnode->rsa_key->e) != 0)
585 {
586 slog (L_NOTICE, _("private hostkey and public node key mismatch: is '%s' the correct node?"), ::thisnode);
587 exit (EXIT_FAILURE);
588 } 587 }
588 }
589 589
590 free (fname); 590 free (fname);
591}
592 591
592 fname = conf.config_filename (conf.pidfilename);
593 free (conf.pidfilename); conf.pidfilename = fname;
594
595 for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i)
596 {
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
657void
658configuration_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}
697
698char *
593char *configuration::config_filename (const char *name, const char *dflt) 699configuration::config_filename (const char *name, const char *dflt)
594{ 700{
595 char *fname; 701 char *fname;
596 702
597 asprintf (&fname, name ? name : dflt, ::thisnode); 703 asprintf (&fname, name ? name : dflt, ::thisnode ? ::thisnode : "<unset>");
598 704
599 if (!ABSOLUTE_PATH (fname)) 705 if (!ABSOLUTE_PATH (fname))
600 { 706 {
601 char *rname = fname; 707 char *rname = fname;
602 asprintf (&fname, "%s/%s", confbase, rname); 708 asprintf (&fname, "%s/%s", confbase, rname);
603 free (rname); 709 free (rname);
604 } 710 }
605 711
606 return fname; 712 return fname;
713}
714
715void
716conf_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 );
607} 733}
608 734
609void 735void
610configuration::print () 736configuration::print ()
611{ 737{
618 printf (_("interface: %s\n"), ifname); 744 printf (_("interface: %s\n"), ifname);
619 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>"); 745 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>");
620 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1); 746 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1);
621 printf ("\n"); 747 printf ("\n");
622 748
623 printf ("%4s %-17s %s %-8.8s %-10.10s %s\n", 749 printf ("%4s %-17s %s %-8.8s %-10.10s %04s %s\n",
624 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Host:Port")); 750 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Prot"), _("Host:Port"));
625 751
626 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i) 752 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i)
627 (*i)->print (); 753 (*i)->print ();
628 754
629 printf ("\n"); 755 printf ("\n");
639configuration::~configuration () 765configuration::~configuration ()
640{ 766{
641 cleanup (); 767 cleanup ();
642} 768}
643 769
644

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines