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