606f1e32719cfd70f742e8f634aef8dd6670b537
[strongswan.git] / src / starter / confread.c
1 /* strongSwan IPsec config file parser
2 * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * RCSID $Id$
15 */
16
17 #include <stddef.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <assert.h>
21
22 #include <freeswan.h>
23
24 #include "../pluto/constants.h"
25 #include "../pluto/defs.h"
26 #include "../pluto/log.h"
27
28 #include "keywords.h"
29 #include "parser.h"
30 #include "confread.h"
31 #include "args.h"
32 #include "interfaces.h"
33
34 /* strings containing a colon are interpreted as an IPv6 address */
35 #define ip_version(string) (strchr(string, '.') ? AF_INET : AF_INET6)
36
37 static const char ike_defaults[] = "aes128-sha-modp2048";
38 static const char esp_defaults[] = "aes128-sha1, 3des-md5";
39
40 static const char firewall_defaults[] = "ipsec _updown iptables";
41
42 static void default_values(starter_config_t *cfg)
43 {
44 if (cfg == NULL)
45 return;
46
47 memset(cfg, 0, sizeof(struct starter_config));
48
49 /* is there enough space for all seen flags? */
50 assert(KW_SETUP_LAST - KW_SETUP_FIRST <
51 sizeof(cfg->setup.seen) * BITS_PER_BYTE);
52 assert(KW_CONN_LAST - KW_CONN_FIRST <
53 sizeof(cfg->conn_default.seen) * BITS_PER_BYTE);
54 assert(KW_END_LAST - KW_END_FIRST <
55 sizeof(cfg->conn_default.right.seen) * BITS_PER_BYTE);
56 assert(KW_CA_LAST - KW_CA_FIRST <
57 sizeof(cfg->ca_default.seen) * BITS_PER_BYTE);
58
59 cfg->setup.seen = LEMPTY;
60 cfg->setup.fragicmp = TRUE;
61 cfg->setup.hidetos = TRUE;
62 cfg->setup.uniqueids = TRUE;
63 cfg->setup.interfaces = new_list("%defaultroute");
64 cfg->setup.charonstart = TRUE;
65 cfg->setup.plutostart = TRUE;
66
67 cfg->conn_default.seen = LEMPTY;
68 cfg->conn_default.startup = STARTUP_NO;
69 cfg->conn_default.state = STATE_IGNORE;
70 cfg->conn_default.policy = POLICY_ENCRYPT | POLICY_TUNNEL | POLICY_RSASIG |
71 POLICY_PFS | POLICY_MOBIKE;
72
73 cfg->conn_default.ike = clone_str(ike_defaults, "ike_defaults");
74 cfg->conn_default.esp = clone_str(esp_defaults, "esp_defaults");
75 cfg->conn_default.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
76 cfg->conn_default.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT;
77 cfg->conn_default.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT;
78 cfg->conn_default.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT;
79 cfg->conn_default.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
80 cfg->conn_default.addr_family = AF_INET;
81 cfg->conn_default.tunnel_addr_family = AF_INET;
82 cfg->conn_default.dpd_delay = 30; /* seconds */
83 cfg->conn_default.dpd_timeout = 150; /* seconds */
84
85 cfg->conn_default.left.seen = LEMPTY;
86 cfg->conn_default.right.seen = LEMPTY;
87
88 cfg->conn_default.left.sendcert = CERT_SEND_IF_ASKED;
89 cfg->conn_default.right.sendcert = CERT_SEND_IF_ASKED;
90
91 anyaddr(AF_INET, &cfg->conn_default.left.addr);
92 anyaddr(AF_INET, &cfg->conn_default.left.nexthop);
93 anyaddr(AF_INET, &cfg->conn_default.right.addr);
94 anyaddr(AF_INET, &cfg->conn_default.right.nexthop);
95
96 cfg->ca_default.seen = LEMPTY;
97 }
98
99 #define KW_POLICY_FLAG(sy, sn, fl) \
100 if (streq(kw->value, sy)) { conn->policy |= fl; } \
101 else if (streq(kw->value, sn)) { conn->policy &= ~fl; } \
102 else { plog("# bad policy value: %s=%s", kw->entry->name, kw->value); cfg->err++; }
103
104 static void
105 load_setup(starter_config_t *cfg, config_parsed_t *cfgp)
106 {
107 kw_list_t *kw;
108
109 DBG(DBG_CONTROL,
110 DBG_log("Loading config setup")
111 )
112
113 for (kw = cfgp->config_setup; kw; kw = kw->next)
114 {
115 bool assigned = FALSE;
116
117 kw_token_t token = kw->entry->token;
118
119 if (token < KW_SETUP_FIRST || token > KW_SETUP_LAST)
120 {
121 plog("# unsupported keyword '%s' in config setup", kw->entry->name);
122 cfg->err++;
123 continue;
124 }
125
126 if (!assign_arg(token, KW_SETUP_FIRST, kw, (char *)cfg, &assigned))
127 {
128 plog(" bad argument value in config setup");
129 cfg->err++;
130 continue;
131 }
132 }
133 }
134
135 static void
136 kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token
137 , kw_list_t *kw, char *conn_name, starter_config_t *cfg)
138 {
139 err_t ugh = NULL;
140 bool assigned = FALSE;
141 int has_port_wildcard; /* set if port is %any */
142
143 char *name = kw->entry->name;
144 char *value = kw->value;
145
146 if (!assign_arg(token, KW_END_FIRST, kw, (char *)end, &assigned))
147 goto err;
148
149 if (token == KW_SENDCERT)
150 {
151 if (end->sendcert == CERT_YES_SEND)
152 end->sendcert = CERT_ALWAYS_SEND;
153 else if (end->sendcert == CERT_NO_SEND)
154 end->sendcert = CERT_NEVER_SEND;
155 }
156
157 if (assigned)
158 return;
159
160 switch (token)
161 {
162 case KW_HOST:
163 if (streq(value, "%defaultroute"))
164 {
165 if (cfg->defaultroute.defined)
166 {
167 end->addr = cfg->defaultroute.addr;
168 end->nexthop = cfg->defaultroute.nexthop;
169 }
170 else
171 {
172 plog("# default route not known: %s=%s", name, value);
173 goto err;
174 }
175 }
176 else if (streq(value, "%any") || streq(value, "%any4"))
177 {
178 anyaddr(conn->addr_family, &end->addr);
179 }
180 else if (streq(value, "%any6"))
181 {
182 conn->addr_family = AF_INET6;
183 anyaddr(conn->addr_family, &end->addr);
184 }
185 else if (streq(value, "%group"))
186 {
187 ip_address any;
188
189 conn->policy |= POLICY_GROUP | POLICY_TUNNEL;
190 anyaddr(conn->addr_family, &end->addr);
191 anyaddr(conn->tunnel_addr_family, &any);
192 end->has_client = TRUE;
193 }
194 else
195 {
196 /* check for allow_any prefix */
197 if (value[0] == '%')
198 {
199 end->allow_any = TRUE;
200 value++;
201 }
202 conn->addr_family = ip_version(value);
203 ugh = ttoaddr(value, 0, conn->addr_family, &end->addr);
204 if (ugh != NULL)
205 {
206 plog("# bad addr: %s=%s [%s]", name, value, ugh);
207 if (streq(ugh, "does not look numeric and name lookup failed"))
208 {
209 end->dns_failed = TRUE;
210 anyaddr(conn->addr_family, &end->addr);
211 }
212 else
213 {
214 goto err;
215 }
216 }
217 }
218 break;
219 case KW_NEXTHOP:
220 if (streq(value, "%defaultroute"))
221 {
222 if (cfg->defaultroute.defined)
223 end->nexthop = cfg->defaultroute.nexthop;
224 else
225 {
226 plog("# default route not known: %s=%s", name, value);
227 goto err;
228 }
229 }
230 else if (streq(value, "%direct"))
231 {
232 ugh = anyaddr(conn->addr_family, &end->nexthop);
233 }
234 else
235 {
236 conn->addr_family = ip_version(value);
237 ugh = ttoaddr(value, 0, conn->addr_family, &end->nexthop);
238 }
239 if (ugh != NULL)
240 {
241 plog("# bad addr: %s=%s [%s]", name, value, ugh);
242 goto err;
243 }
244 break;
245 case KW_SUBNET:
246 if ((strlen(value) >= 6 && strncmp(value,"vhost:",6) == 0)
247 || (strlen(value) >= 5 && strncmp(value,"vnet:",5) == 0))
248 {
249 end->virt = clone_str(value, "virt");
250 }
251 else
252 {
253 ip_subnet net;
254 char *pos;
255 int len = 0;
256
257 end->has_client = TRUE;
258 conn->tunnel_addr_family = ip_version(value);
259
260 pos = strchr(value, ',');
261 if (pos)
262 {
263 len = pos - value;
264 }
265 ugh = ttosubnet(value, len, ip_version(value), &net);
266 if (ugh != NULL)
267 {
268 plog("# bad subnet: %s=%s [%s]", name, value, ugh);
269 goto err;
270 }
271 end->subnet = clone_str(value, "subnet");
272 }
273 break;
274 case KW_SUBNETWITHIN:
275 {
276 ip_subnet net;
277
278 end->has_client = TRUE;
279 end->has_client_wildcard = TRUE;
280 conn->tunnel_addr_family = ip_version(value);
281
282 ugh = ttosubnet(value, 0, ip_version(value), &net);
283 if (ugh != NULL)
284 {
285 plog("# bad subnet: %s=%s [%s]", name, value, ugh);
286 goto err;
287 }
288 end->subnet = clone_str(value, "subnetwithin");
289 break;
290 }
291 case KW_PROTOPORT:
292 ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &has_port_wildcard);
293 end->has_port_wildcard = has_port_wildcard;
294 break;
295 case KW_SOURCEIP:
296 if (end->has_natip)
297 {
298 plog("# natip and sourceip cannot be defined at the same time");
299 goto err;
300 }
301 if (streq(value, "%modeconfig") || streq(value, "%modecfg") ||
302 streq(value, "%config") || streq(value, "%cfg"))
303 {
304 end->modecfg = TRUE;
305 }
306 else
307 {
308 ip_address addr;
309 ip_subnet net;
310
311 conn->tunnel_addr_family = ip_version(value);
312 if (strchr(value, '/'))
313 { /* CIDR notation, address pool */
314 ugh = ttosubnet(value, 0, conn->tunnel_addr_family, &net);
315 }
316 else if (value[0] != '%')
317 { /* old style fixed srcip, a %poolname otherwise */
318 ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr);
319 }
320 if (ugh != NULL)
321 {
322 plog("# bad addr: %s=%s [%s]", name, value, ugh);
323 goto err;
324 }
325 end->srcip = clone_str(value, "srcip");
326 }
327 conn->policy |= POLICY_TUNNEL;
328 break;
329 case KW_NATIP:
330 if (end->srcip)
331 {
332 plog("# natip and sourceip cannot be defined at the same time");
333 goto err;
334 }
335 if (streq(value, "%defaultroute"))
336 {
337 char buf[64];
338
339 if (cfg->defaultroute.defined)
340 {
341 addrtot(&cfg->defaultroute.addr, 0, buf, sizeof(buf));
342 end->srcip = clone_str(buf, "natip");
343 }
344 else
345 {
346 plog("# default route not known: %s=%s", name, value);
347 goto err;
348 }
349 }
350 else
351 {
352 ip_address addr;
353
354 conn->tunnel_addr_family = ip_version(value);
355 ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr);
356 if (ugh != NULL)
357 {
358 plog("# bad addr: %s=%s [%s]", name, value, ugh);
359 goto err;
360 }
361 end->srcip = clone_str(value, "srcip");
362 }
363 end->has_natip = TRUE;
364 conn->policy |= POLICY_TUNNEL;
365 break;
366 default:
367 break;
368 }
369 return;
370
371 err:
372 plog(" bad argument value in conn '%s'", conn_name);
373 cfg->err++;
374 }
375
376 /*
377 * handles left|right=<FQDN> DNS resolution failure
378 */
379 static void
380 handle_dns_failure( const char *label, starter_end_t *end, starter_config_t *cfg)
381 {
382 if (end->dns_failed)
383 {
384 if (end->allow_any)
385 {
386 plog("# fallback to %s=%%any due to '%%' prefix or %sallowany=yes",
387 label, label);
388 }
389 else
390 {
391 /* declare an error */
392 cfg->err++;
393 }
394 }
395 }
396
397 /*
398 * handles left|rightfirewall and left|rightupdown parameters
399 */
400 static void
401 handle_firewall( const char *label, starter_end_t *end, starter_config_t *cfg)
402 {
403 if (end->firewall && (end->seen & LELEM(KW_FIREWALL - KW_END_FIRST)))
404 {
405 if (end->updown != NULL)
406 {
407 plog("# cannot have both %sfirewall and %supdown", label, label);
408 cfg->err++;
409 }
410 else
411 {
412 end->updown = clone_str(firewall_defaults, "firewall_defaults");
413 end->firewall = FALSE;
414 }
415 }
416 }
417
418 /*
419 * parse a conn section
420 */
421 static void
422 load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
423 {
424 char *conn_name = (conn->name == NULL)? "%default":conn->name;
425
426 for ( ; kw; kw = kw->next)
427 {
428 bool assigned = FALSE;
429
430 kw_token_t token = kw->entry->token;
431
432 if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST)
433 {
434 kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST
435 , kw, conn_name, cfg);
436 continue;
437 }
438 else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST)
439 {
440 kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST
441 , kw, conn_name, cfg);
442 continue;
443 }
444
445 if (token == KW_AUTO)
446 {
447 token = KW_CONN_SETUP;
448 }
449 else if (token == KW_ALSO)
450 {
451 if (cfg->parse_also)
452 {
453 also_t *also = alloc_thing(also_t, "also_t");
454
455 also->name = clone_str(kw->value, "also");
456 also->next = conn->also;
457 conn->also = also;
458
459 DBG(DBG_CONTROL,
460 DBG_log(" also=%s", kw->value)
461 )
462 }
463 continue;
464 }
465
466 if (token < KW_CONN_FIRST || token > KW_CONN_LAST)
467 {
468 plog("# unsupported keyword '%s' in conn '%s'"
469 , kw->entry->name, conn_name);
470 cfg->err++;
471 continue;
472 }
473
474 if (!assign_arg(token, KW_CONN_FIRST, kw, (char *)conn, &assigned))
475 {
476 plog(" bad argument value in conn '%s'", conn_name);
477 cfg->err++;
478 continue;
479 }
480
481 if (assigned)
482 continue;
483
484 switch (token)
485 {
486 case KW_TYPE:
487 conn->policy &= ~(POLICY_TUNNEL | POLICY_SHUNT_MASK);
488 if (streq(kw->value, "tunnel"))
489 conn->policy |= POLICY_TUNNEL;
490 else if (streq(kw->value, "beet"))
491 conn->policy |= POLICY_BEET;
492 else if (streq(kw->value, "passthrough") || streq(kw->value, "pass"))
493 conn->policy |= POLICY_SHUNT_PASS;
494 else if (streq(kw->value, "drop"))
495 conn->policy |= POLICY_SHUNT_DROP;
496 else if (streq(kw->value, "reject"))
497 conn->policy |= POLICY_SHUNT_REJECT;
498 else if (strcmp(kw->value, "transport") != 0)
499 {
500 plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
501 cfg->err++;
502 }
503 break;
504 case KW_PFS:
505 KW_POLICY_FLAG("yes", "no", POLICY_PFS)
506 break;
507 case KW_COMPRESS:
508 KW_POLICY_FLAG("yes", "no", POLICY_COMPRESS)
509 break;
510 case KW_AUTH:
511 KW_POLICY_FLAG("ah", "esp", POLICY_AUTHENTICATE)
512 break;
513 case KW_AUTHBY:
514 conn->policy &= ~(POLICY_ID_AUTH_MASK | POLICY_ENCRYPT);
515
516 if (!(streq(kw->value, "never") || streq(kw->value, "eap")))
517 {
518 char *value = kw->value;
519 char *second = strchr(kw->value, '|');
520
521 if (second != NULL)
522 *second = '\0';
523
524 /* also handles the cases secret|rsasig and rsasig|secret */
525 for (;;)
526 {
527 if (streq(value, "rsasig"))
528 conn->policy |= POLICY_RSASIG | POLICY_ENCRYPT;
529 else if (streq(value, "secret") || streq(value, "psk"))
530 conn->policy |= POLICY_PSK | POLICY_ENCRYPT;
531 else if (streq(value, "xauthrsasig"))
532 conn->policy |= POLICY_XAUTH_RSASIG | POLICY_ENCRYPT;
533 else if (streq(value, "xauthpsk"))
534 conn->policy |= POLICY_XAUTH_PSK | POLICY_ENCRYPT;
535 else
536 {
537 plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
538 cfg->err++;
539 break;
540 }
541 if (second == NULL)
542 break;
543 value = second;
544 second = NULL; /* traverse the loop no more than twice */
545 }
546 }
547 break;
548 case KW_EAP:
549 {
550 char *sep;
551
552 /* check for vendor-type format */
553 sep = strchr(kw->value, '-');
554 if (sep)
555 {
556 *(sep++) = '\0';
557 conn->eap_type = atoi(kw->value);
558 conn->eap_vendor = atoi(sep);
559 if (conn->eap_type == 0 || conn->eap_vendor == 0)
560 {
561 plog("# invalid EAP type: %s=%s", kw->entry->name, kw->value);
562 cfg->err++;
563 }
564 break;
565 }
566 if (streq(kw->value, "aka"))
567 {
568 conn->eap_type = 23;
569 }
570 else if (streq(kw->value, "sim"))
571 {
572 conn->eap_type = 18;
573 }
574 else if (streq(kw->value, "md5"))
575 {
576 conn->eap_type = 4;
577 }
578 else
579 {
580 conn->eap_type = atoi(kw->value);
581 if (conn->eap_type == 0)
582 {
583 plog("# unknown EAP type: %s=%s", kw->entry->name, kw->value);
584 cfg->err++;
585 }
586 }
587 break;
588 }
589 case KW_KEYINGTRIES:
590 if (streq(kw->value, "%forever"))
591 {
592 conn->sa_keying_tries = 0;
593 }
594 else
595 {
596 char *endptr;
597
598 conn->sa_keying_tries = strtoul(kw->value, &endptr, 10);
599 if (*endptr != '\0')
600 {
601 plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
602 cfg->err++;
603 }
604 }
605 break;
606 case KW_REKEY:
607 KW_POLICY_FLAG("no", "yes", POLICY_DONT_REKEY)
608 break;
609 case KW_REAUTH:
610 KW_POLICY_FLAG("no", "yes", POLICY_DONT_REAUTH)
611 break;
612 case KW_MOBIKE:
613 KW_POLICY_FLAG("yes", "no", POLICY_MOBIKE)
614 break;
615 case KW_FORCEENCAPS:
616 KW_POLICY_FLAG("yes", "no", POLICY_FORCE_ENCAP)
617 break;
618 case KW_MODECONFIG:
619 KW_POLICY_FLAG("push", "pull", POLICY_MODECFG_PUSH)
620 break;
621 case KW_XAUTH:
622 KW_POLICY_FLAG("server", "client", POLICY_XAUTH_SERVER)
623 break;
624 default:
625 break;
626 }
627 }
628
629 handle_dns_failure("left", &conn->left, cfg);
630 handle_dns_failure("right", &conn->right, cfg);
631 handle_firewall("left", &conn->left, cfg);
632 handle_firewall("right", &conn->right, cfg);
633 }
634
635 /*
636 * initialize a conn object with the default conn
637 */
638 static void
639 conn_default(char *name, starter_conn_t *conn, starter_conn_t *def)
640 {
641 memcpy(conn, def, sizeof(starter_conn_t));
642 conn->name = clone_str(name, "conn name");
643
644 clone_args(KW_CONN_FIRST, KW_CONN_LAST, (char *)conn, (char *)def);
645 clone_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left, (char *)&def->left);
646 clone_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->right, (char *)&def->right);
647 }
648
649 /*
650 * parse a ca section
651 */
652 static void
653 load_ca(starter_ca_t *ca, kw_list_t *kw, starter_config_t *cfg)
654 {
655 char *ca_name = (ca->name == NULL)? "%default":ca->name;
656
657 for ( ; kw; kw = kw->next)
658 {
659 bool assigned = FALSE;
660
661 kw_token_t token = kw->entry->token;
662
663 if (token == KW_AUTO)
664 {
665 token = KW_CA_SETUP;
666 }
667 else if (token == KW_ALSO)
668 {
669 if (cfg->parse_also)
670 {
671 also_t *also = alloc_thing(also_t, "also_t");
672
673 also->name = clone_str(kw->value, "also");
674 also->next = ca->also;
675 ca->also = also;
676
677 DBG(DBG_CONTROL,
678 DBG_log(" also=%s", kw->value)
679 )
680 }
681 continue;
682 }
683
684 if (token < KW_CA_FIRST || token > KW_CA_LAST)
685 {
686 plog("# unsupported keyword '%s' in ca '%s'", kw->entry->name, ca_name);
687 cfg->err++;
688 continue;
689 }
690
691 if (!assign_arg(token, KW_CA_FIRST, kw, (char *)ca, &assigned))
692 {
693 plog(" bad argument value in ca '%s'", ca_name);
694 cfg->err++;
695 }
696 }
697
698 /* treat 'route' and 'start' as 'add' */
699 if (ca->startup != STARTUP_NO)
700 ca->startup = STARTUP_ADD;
701 }
702
703 /*
704 * initialize a ca object with the default ca
705 */
706 static void
707 ca_default(char *name, starter_ca_t *ca, starter_ca_t *def)
708 {
709 memcpy(ca, def, sizeof(starter_ca_t));
710 ca->name = clone_str(name, "ca name");
711
712 clone_args(KW_CA_FIRST, KW_CA_LAST, (char *)ca, (char *)def);
713 }
714
715 static kw_list_t*
716 find_also_conn(const char* name, starter_conn_t *conn, starter_config_t *cfg);
717
718 static void
719 load_also_conns(starter_conn_t *conn, also_t *also, starter_config_t *cfg)
720 {
721 while (also != NULL)
722 {
723 kw_list_t *kw = find_also_conn(also->name, conn, cfg);
724
725 if (kw == NULL)
726 {
727 plog(" conn '%s' cannot include '%s'", conn->name, also->name);
728 }
729 else
730 {
731 DBG(DBG_CONTROL,
732 DBG_log("conn '%s' includes '%s'", conn->name, also->name)
733 )
734 /* only load if no error occurred in the first round */
735 if (cfg->err == 0)
736 load_conn(conn, kw, cfg);
737 }
738 also = also->next;
739 }
740 }
741
742 /*
743 * find a conn included by also
744 */
745 static kw_list_t*
746 find_also_conn(const char* name, starter_conn_t *conn, starter_config_t *cfg)
747 {
748 starter_conn_t *c = cfg->conn_first;
749
750 while (c != NULL)
751 {
752 if (streq(name, c->name))
753 {
754 if (conn->visit == c->visit)
755 {
756 plog("# detected also loop");
757 cfg->err++;
758 return NULL;
759 }
760 c->visit = conn->visit;
761 load_also_conns(conn, c->also, cfg);
762 return c->kw;
763 }
764 c = c->next;
765 }
766
767 plog("# also '%s' not found", name);
768 cfg->err++;
769 return NULL;
770 }
771
772 static kw_list_t*
773 find_also_ca(const char* name, starter_ca_t *ca, starter_config_t *cfg);
774
775 static void
776 load_also_cas(starter_ca_t *ca, also_t *also, starter_config_t *cfg)
777 {
778 while (also != NULL)
779 {
780 kw_list_t *kw = find_also_ca(also->name, ca, cfg);
781
782 if (kw == NULL)
783 {
784 plog(" ca '%s' cannot include '%s'", ca->name, also->name);
785 }
786 else
787 {
788 DBG(DBG_CONTROL,
789 DBG_log("ca '%s' includes '%s'", ca->name, also->name)
790 )
791 /* only load if no error occurred in the first round */
792 if (cfg->err == 0)
793 load_ca(ca, kw, cfg);
794 }
795 also = also->next;
796 }
797 }
798
799 /*
800 * find a ca included by also
801 */
802 static kw_list_t*
803 find_also_ca(const char* name, starter_ca_t *ca, starter_config_t *cfg)
804 {
805 starter_ca_t *c = cfg->ca_first;
806
807 while (c != NULL)
808 {
809 if (streq(name, c->name))
810 {
811 if (ca->visit == c->visit)
812 {
813 plog("# detected also loop");
814 cfg->err++;
815 return NULL;
816 }
817 c->visit = ca->visit;
818 load_also_cas(ca, c->also, cfg);
819 return c->kw;
820 }
821 c = c->next;
822 }
823
824 plog("# also '%s' not found", name);
825 cfg->err++;
826 return NULL;
827 }
828
829 /*
830 * free the memory used by also_t objects
831 */
832 static void
833 free_also(also_t *head)
834 {
835 while (head != NULL)
836 {
837 also_t *also = head;
838
839 head = also->next;
840 pfree(also->name);
841 pfree(also);
842 }
843 }
844
845 /*
846 * free the memory used by a starter_conn_t object
847 */
848 static void
849 confread_free_conn(starter_conn_t *conn)
850 {
851 pfree(conn->left.subnet);
852 pfree(conn->right.subnet);
853 pfree(conn->left.virt);
854 pfree(conn->right.virt);
855 pfree(conn->left.srcip);
856 pfree(conn->right.srcip);
857 free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left);
858 free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->right);
859 free_args(KW_CONN_NAME, KW_CONN_LAST, (char *)conn);
860 free_also(conn->also);
861 }
862
863 /*
864 * free the memory used by a starter_ca_t object
865 */
866 static void
867 confread_free_ca(starter_ca_t *ca)
868 {
869 free_args(KW_CA_NAME, KW_CA_LAST, (char *)ca);
870 free_also(ca->also);
871 }
872
873 /*
874 * free the memory used by a starter_config_t object
875 */
876 void
877 confread_free(starter_config_t *cfg)
878 {
879 starter_conn_t *conn = cfg->conn_first;
880 starter_ca_t *ca = cfg->ca_first;
881
882 free_args(KW_SETUP_FIRST, KW_SETUP_LAST, (char *)cfg);
883
884 confread_free_conn(&cfg->conn_default);
885
886 while (conn != NULL)
887 {
888 starter_conn_t *conn_aux = conn;
889
890 conn = conn->next;
891 confread_free_conn(conn_aux);
892 pfree(conn_aux);
893 }
894
895 confread_free_ca(&cfg->ca_default);
896
897 while (ca != NULL)
898 {
899 starter_ca_t *ca_aux = ca;
900
901 ca = ca->next;
902 confread_free_ca(ca_aux);
903 pfree(ca_aux);
904 }
905
906 pfree(cfg);
907 }
908
909 /*
910 * load and parse an IPsec configuration file
911 */
912 starter_config_t *
913 confread_load(const char *file)
914 {
915 starter_config_t *cfg = NULL;
916 config_parsed_t *cfgp;
917 section_list_t *sconn, *sca;
918 starter_conn_t *conn;
919 starter_ca_t *ca;
920
921 u_int total_err;
922 u_int visit = 0;
923
924 /* load IPSec configuration file */
925 cfgp = parser_load_conf(file);
926 if (!cfgp)
927 return NULL;
928
929 cfg = (starter_config_t *)alloc_thing(starter_config_t, "starter_config_t");
930
931 /* set default values */
932 default_values(cfg);
933
934 /* determine default route */
935 get_defaultroute(&cfg->defaultroute);
936
937 /* load config setup section */
938 load_setup(cfg, cfgp);
939
940 /* in the first round parse also statements */
941 cfg->parse_also = TRUE;
942
943 /* find %default ca section */
944 for (sca = cfgp->ca_first; sca; sca = sca->next)
945 {
946 if (streq(sca->name, "%default"))
947 {
948 DBG(DBG_CONTROL,
949 DBG_log("Loading ca %%default")
950 )
951 load_ca(&cfg->ca_default, sca->kw, cfg);
952 }
953 }
954
955 /* parameters defined in ca %default sections can be overloads */
956 cfg->ca_default.seen = LEMPTY;
957
958 /* load other ca sections */
959 for (sca = cfgp->ca_first; sca; sca = sca->next)
960 {
961 u_int previous_err;
962
963 /* skip %default ca section */
964 if (streq(sca->name, "%default"))
965 continue;
966
967 DBG(DBG_CONTROL,
968 DBG_log("Loading ca '%s'", sca->name)
969 )
970 ca = (starter_ca_t *)alloc_thing(starter_ca_t, "starter_ca_t");
971
972 ca_default(sca->name, ca, &cfg->ca_default);
973 ca->kw = sca->kw;
974 ca->next = NULL;
975
976 previous_err = cfg->err;
977 load_ca(ca, ca->kw, cfg);
978 if (cfg->err > previous_err)
979 {
980 /* errors occurred - free the ca */
981 confread_free_ca(ca);
982 cfg->non_fatal_err += cfg->err - previous_err;
983 cfg->err = previous_err;
984 }
985 else
986 {
987 /* success - insert the ca into the chained list */
988 if (cfg->ca_last)
989 cfg->ca_last->next = ca;
990 cfg->ca_last = ca;
991 if (!cfg->ca_first)
992 cfg->ca_first = ca;
993 }
994 }
995
996 for (ca = cfg->ca_first; ca; ca = ca->next)
997 {
998 also_t *also = ca->also;
999
1000 while (also != NULL)
1001 {
1002 kw_list_t *kw = find_also_ca(also->name, cfg->ca_first, cfg);
1003
1004 load_ca(ca, kw, cfg);
1005 also = also->next;
1006 }
1007
1008 if (ca->startup != STARTUP_NO)
1009 ca->state = STATE_TO_ADD;
1010 }
1011
1012 /* find %default conn sections */
1013 for (sconn = cfgp->conn_first; sconn; sconn = sconn->next)
1014 {
1015 if (streq(sconn->name, "%default"))
1016 {
1017 DBG(DBG_CONTROL,
1018 DBG_log("Loading conn %%default")
1019 )
1020 load_conn(&cfg->conn_default, sconn->kw, cfg);
1021 }
1022 }
1023
1024 /* parameter defined in conn %default sections can be overloaded */
1025 cfg->conn_default.seen = LEMPTY;
1026 cfg->conn_default.right.seen = LEMPTY;
1027 cfg->conn_default.left.seen = LEMPTY;
1028
1029 /* load other conn sections */
1030 for (sconn = cfgp->conn_first; sconn; sconn = sconn->next)
1031 {
1032 u_int previous_err;
1033
1034 /* skip %default conn section */
1035 if (streq(sconn->name, "%default"))
1036 continue;
1037
1038 DBG(DBG_CONTROL,
1039 DBG_log("Loading conn '%s'", sconn->name)
1040 )
1041 conn = (starter_conn_t *)alloc_thing(starter_conn_t, "starter_conn_t");
1042
1043 conn_default(sconn->name, conn, &cfg->conn_default);
1044 conn->kw = sconn->kw;
1045 conn->next = NULL;
1046
1047 previous_err = cfg->err;
1048 load_conn(conn, conn->kw, cfg);
1049 if (cfg->err > previous_err)
1050 {
1051 /* error occurred - free the conn */
1052 confread_free_conn(conn);
1053 cfg->non_fatal_err += cfg->err - previous_err;
1054 cfg->err = previous_err;
1055 }
1056 else
1057 {
1058 /* success - insert the conn into the chained list */
1059 if (cfg->conn_last)
1060 cfg->conn_last->next = conn;
1061 cfg->conn_last = conn;
1062 if (!cfg->conn_first)
1063 cfg->conn_first = conn;
1064 }
1065 }
1066
1067 /* in the second round do not parse also statements */
1068 cfg->parse_also = FALSE;
1069
1070 for (ca = cfg->ca_first; ca; ca = ca->next)
1071 {
1072 ca->visit = ++visit;
1073 load_also_cas(ca, ca->also, cfg);
1074
1075 if (ca->startup != STARTUP_NO)
1076 ca->state = STATE_TO_ADD;
1077 }
1078
1079 for (conn = cfg->conn_first; conn; conn = conn->next)
1080 {
1081 conn->visit = ++visit;
1082 load_also_conns(conn, conn->also, cfg);
1083
1084 if (conn->startup != STARTUP_NO)
1085 conn->state = STATE_TO_ADD;
1086 }
1087
1088 parser_free_conf(cfgp);
1089
1090 total_err = cfg->err + cfg->non_fatal_err;
1091 if (total_err > 0)
1092 {
1093 plog("### %d parsing error%s (%d fatal) ###"
1094 , total_err, (total_err > 1)?"s":"", cfg->err);
1095 }
1096
1097 return cfg;
1098 }