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