Merge branch 'android-client-cert'
[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 #include <netdb.h>
23
24 #include <library.h>
25 #include <debug.h>
26
27 #include "keywords.h"
28 #include "confread.h"
29 #include "args.h"
30 #include "files.h"
31
32 #define IKE_LIFETIME_DEFAULT 10800 /* 3 hours */
33 #define IPSEC_LIFETIME_DEFAULT 3600 /* 1 hour */
34 #define SA_REPLACEMENT_MARGIN_DEFAULT 540 /* 9 minutes */
35 #define SA_REPLACEMENT_FUZZ_DEFAULT 100 /* 100% of margin */
36 #define SA_REPLACEMENT_RETRIES_DEFAULT 3
37
38 static const char ike_defaults[] = "aes128-sha1-modp2048,3des-sha1-modp1536";
39 static const char esp_defaults[] = "aes128-sha1-modp2048,3des-sha1-modp1536";
40
41 static const char firewall_defaults[] = "ipsec _updown iptables";
42
43 static bool daemon_exists(char *daemon, char *path)
44 {
45 struct stat st;
46 if (stat(path, &st) != 0)
47 {
48 DBG1(DBG_APP, "Disabling %sstart option, '%s' not found", daemon, path);
49 return FALSE;
50 }
51 return TRUE;
52 }
53
54 /**
55 * Process deprecated keywords
56 */
57 static bool is_deprecated(kw_token_t token, kw_list_t *kw, char *name)
58 {
59 switch (token)
60 {
61 case KW_SETUP_DEPRECATED:
62 case KW_PKCS11_DEPRECATED:
63 DBG1(DBG_APP, "# deprecated keyword '%s' in config setup",
64 kw->entry->name);
65 break;
66 case KW_CONN_DEPRECATED:
67 case KW_END_DEPRECATED:
68 case KW_PFS_DEPRECATED:
69 DBG1(DBG_APP, "# deprecated keyword '%s' in conn '%s'",
70 kw->entry->name, name);
71 break;
72 case KW_CA_DEPRECATED:
73 DBG1(DBG_APP, "# deprecated keyword '%s' in ca '%s'",
74 kw->entry->name, name);
75 break;
76 default:
77 return FALSE;
78 }
79 /* additional messages for some */
80 switch (token)
81 {
82 case KW_PKCS11_DEPRECATED:
83 DBG1(DBG_APP, " use the 'pkcs11' plugin instead", kw->entry->name);
84 break;
85 case KW_PFS_DEPRECATED:
86 DBG1(DBG_APP, " PFS is enabled by specifying a DH group in the "
87 "'esp' cipher suite", kw->entry->name);
88 break;
89 default:
90 break;
91 }
92 return TRUE;
93 }
94
95 static void default_values(starter_config_t *cfg)
96 {
97 if (cfg == NULL)
98 return;
99
100 memset(cfg, 0, sizeof(struct starter_config));
101
102 /* is there enough space for all seen flags? */
103 assert(KW_SETUP_LAST - KW_SETUP_FIRST <
104 sizeof(cfg->setup.seen) * BITS_PER_BYTE);
105 assert(KW_CONN_LAST - KW_CONN_FIRST <
106 sizeof(cfg->conn_default.seen) * BITS_PER_BYTE);
107 assert(KW_END_LAST - KW_END_FIRST <
108 sizeof(cfg->conn_default.right.seen) * BITS_PER_BYTE);
109 assert(KW_CA_LAST - KW_CA_FIRST <
110 sizeof(cfg->ca_default.seen) * BITS_PER_BYTE);
111
112 cfg->setup.seen = SEEN_NONE;
113 cfg->setup.uniqueids = TRUE;
114
115 #ifdef START_CHARON
116 cfg->setup.charonstart = TRUE;
117 #endif
118
119 cfg->conn_default.seen = SEEN_NONE;
120 cfg->conn_default.startup = STARTUP_NO;
121 cfg->conn_default.state = STATE_IGNORE;
122 cfg->conn_default.mode = MODE_TUNNEL;
123 cfg->conn_default.options = SA_OPTION_MOBIKE;
124
125 cfg->conn_default.ike = strdupnull(ike_defaults);
126 cfg->conn_default.esp = strdupnull(esp_defaults);
127 cfg->conn_default.sa_ike_life_seconds = IKE_LIFETIME_DEFAULT;
128 cfg->conn_default.sa_ipsec_life_seconds = IPSEC_LIFETIME_DEFAULT;
129 cfg->conn_default.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT;
130 cfg->conn_default.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT;
131 cfg->conn_default.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
132 cfg->conn_default.install_policy = TRUE;
133 cfg->conn_default.dpd_delay = 30; /* seconds */
134 cfg->conn_default.dpd_timeout = 150; /* seconds */
135
136 cfg->conn_default.left.seen = SEEN_NONE;
137 cfg->conn_default.right.seen = SEEN_NONE;
138
139 cfg->conn_default.left.sendcert = CERT_SEND_IF_ASKED;
140 cfg->conn_default.right.sendcert = CERT_SEND_IF_ASKED;
141
142 cfg->conn_default.left.ikeport = 500;
143 cfg->conn_default.right.ikeport = 500;
144
145 cfg->ca_default.seen = SEEN_NONE;
146 }
147
148 #define KW_SA_OPTION_FLAG(sy, sn, fl) \
149 if (streq(kw->value, sy)) { conn->options |= fl; } \
150 else if (streq(kw->value, sn)) { conn->options &= ~fl; } \
151 else { DBG1(DBG_APP, "# bad option value: %s=%s", kw->entry->name, kw->value); cfg->err++; }
152
153 static void load_setup(starter_config_t *cfg, config_parsed_t *cfgp)
154 {
155 kw_list_t *kw;
156
157 DBG2(DBG_APP, "Loading config setup");
158
159 for (kw = cfgp->config_setup; kw; kw = kw->next)
160 {
161 bool assigned = FALSE;
162
163 kw_token_t token = kw->entry->token;
164
165 if ((int)token < KW_SETUP_FIRST || token > KW_SETUP_LAST)
166 {
167 DBG1(DBG_APP, "# unsupported keyword '%s' in config setup",
168 kw->entry->name);
169 cfg->err++;
170 continue;
171 }
172
173 if (is_deprecated(token, kw, ""))
174 {
175 cfg->non_fatal_err++;
176 continue;
177 }
178
179 if (!assign_arg(token, KW_SETUP_FIRST, kw, (char *)cfg, &assigned))
180 {
181 DBG1(DBG_APP, " bad argument value in config setup");
182 cfg->err++;
183 continue;
184 }
185 }
186
187 /* verify the executables are actually available */
188 #ifdef START_CHARON
189 cfg->setup.charonstart = cfg->setup.charonstart &&
190 daemon_exists("charon", CHARON_CMD);
191 #else
192 cfg->setup.charonstart = FALSE;
193 #endif
194 }
195
196 static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
197 kw_list_t *kw, char *conn_name, starter_config_t *cfg)
198 {
199 bool assigned = FALSE;
200
201 char *name = kw->entry->name;
202 char *value = kw->value;
203
204 if (is_deprecated(token, kw, conn_name))
205 {
206 cfg->non_fatal_err++;
207 return;
208 }
209
210 if (!assign_arg(token, KW_END_FIRST, kw, (char *)end, &assigned))
211 goto err;
212
213 /* post processing of some keywords that were assigned automatically */
214 switch (token)
215 {
216 case KW_HOST:
217 if (value && strlen(value) > 0 && value[0] == '%')
218 {
219 if (streq(value, "%defaultroute"))
220 {
221 value = "%any";
222 }
223 if (!streq(value, "%any") && !streq(value, "%any4") &&
224 !streq(value, "%any6"))
225 { /* allow_any prefix */
226 end->allow_any = TRUE;
227 value++;
228 }
229 }
230 free(end->host);
231 end->host = strdupnull(value);
232 break;
233 case KW_SOURCEIP:
234 conn->mode = MODE_TUNNEL;
235 conn->proxy_mode = FALSE;
236 break;
237 case KW_SENDCERT:
238 if (end->sendcert == CERT_YES_SEND)
239 {
240 end->sendcert = CERT_ALWAYS_SEND;
241 }
242 else if (end->sendcert == CERT_NO_SEND)
243 {
244 end->sendcert = CERT_NEVER_SEND;
245 }
246 break;
247 default:
248 break;
249 }
250
251 if (assigned)
252 return;
253
254 /* individual processing of keywords that were not assigned automatically */
255 switch (token)
256 {
257 case KW_PROTOPORT:
258 {
259 struct protoent *proto;
260 struct servent *svc;
261 char *sep, *port = "", *endptr;
262 long int p;
263
264 sep = strchr(value, '/');
265 if (sep)
266 { /* protocol/port */
267 *sep = '\0';
268 port = sep + 1;
269 }
270
271 proto = getprotobyname(value);
272 if (proto)
273 {
274 end->protocol = proto->p_proto;
275 }
276 else
277 {
278 p = strtol(value, &endptr, 0);
279 if ((*value && *endptr) || p < 0 || p > 0xff)
280 {
281 DBG1(DBG_APP, "# bad protocol: %s=%s", name, value);
282 goto err;
283 }
284 end->protocol = (u_int8_t)p;
285 }
286
287 if (streq(port, "%any"))
288 {
289 end->port = 0;
290 }
291 else
292 {
293 svc = getservbyname(port, NULL);
294 if (svc)
295 {
296 end->port = ntohs(svc->s_port);
297 }
298 else
299 {
300 p = strtol(port, &endptr, 0);
301 if ((*port && *endptr) || p < 0 || p > 0xffff)
302 {
303 DBG1(DBG_APP, "# bad port: %s=%s", name, value);
304 goto err;
305 }
306 end->port = (u_int16_t)p;
307 }
308 }
309 if (sep)
310 { /* restore the original text in case also= is used */
311 *sep = '/';
312 }
313 break;
314 }
315 default:
316 break;
317 }
318 return;
319
320 err:
321 DBG1(DBG_APP, " bad argument value in conn '%s'", conn_name);
322 cfg->err++;
323 }
324
325 /*
326 * handles left|rightfirewall and left|rightupdown parameters
327 */
328 static void handle_firewall(const char *label, starter_end_t *end,
329 starter_config_t *cfg)
330 {
331 if (end->firewall && (end->seen & SEEN_KW(KW_FIREWALL, KW_END_FIRST)))
332 {
333 if (end->updown != NULL)
334 {
335 DBG1(DBG_APP, "# cannot have both %sfirewall and %supdown", label,
336 label);
337 cfg->err++;
338 }
339 else
340 {
341 end->updown = strdupnull(firewall_defaults);
342 end->firewall = FALSE;
343 }
344 }
345 }
346
347 static bool handle_mark(char *value, mark_t *mark)
348 {
349 char *sep, *endptr;
350
351 sep = strchr(value, '/');
352 if (sep)
353 {
354 *sep = '\0';
355 mark->mask = strtoul(sep+1, &endptr, 0);
356 if (*endptr != '\0')
357 {
358 DBG1(DBG_APP, "# invalid mark mask: %s", sep+1);
359 return FALSE;
360 }
361 }
362 else
363 {
364 mark->mask = 0xffffffff;
365 }
366 if (value == '\0')
367 {
368 mark->value = 0;
369 }
370 else
371 {
372 mark->value = strtoul(value, &endptr, 0);
373 if (*endptr != '\0')
374 {
375 DBG1(DBG_APP, "# invalid mark value: %s", value);
376 return FALSE;
377 }
378 }
379 if (sep)
380 { /* restore the original text in case also= is used */
381 *sep = '/';
382 }
383 /* apply the mask to ensure the value is in range */
384 mark->value &= mark->mask;
385 return TRUE;
386 }
387
388 /*
389 * parse a conn section
390 */
391 static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
392 {
393 char *conn_name = (conn->name == NULL)? "%default":conn->name;
394
395 for ( ; kw; kw = kw->next)
396 {
397 bool assigned = FALSE;
398
399 kw_token_t token = kw->entry->token;
400
401 if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST)
402 {
403 kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST
404 , kw, conn_name, cfg);
405 continue;
406 }
407 else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST)
408 {
409 kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST
410 , kw, conn_name, cfg);
411 continue;
412 }
413
414 if (token == KW_AUTO)
415 {
416 token = KW_CONN_SETUP;
417 }
418 else if (token == KW_ALSO)
419 {
420 if (cfg->parse_also)
421 {
422 also_t *also = malloc_thing(also_t);
423
424 also->name = strdupnull(kw->value);
425 also->next = conn->also;
426 conn->also = also;
427
428 DBG2(DBG_APP, " also=%s", kw->value);
429 }
430 continue;
431 }
432
433 if (token < KW_CONN_FIRST || token > KW_CONN_LAST)
434 {
435 DBG1(DBG_APP, "# unsupported keyword '%s' in conn '%s'",
436 kw->entry->name, conn_name);
437 cfg->err++;
438 continue;
439 }
440
441 if (is_deprecated(token, kw, conn_name))
442 {
443 cfg->non_fatal_err++;
444 continue;
445 }
446
447 if (!assign_arg(token, KW_CONN_FIRST, kw, (char *)conn, &assigned))
448 {
449 DBG1(DBG_APP, " bad argument value in conn '%s'", conn_name);
450 cfg->err++;
451 continue;
452 }
453
454 if (assigned)
455 continue;
456
457 switch (token)
458 {
459 case KW_TYPE:
460 conn->mode = MODE_TRANSPORT;
461 conn->proxy_mode = FALSE;
462 if (streq(kw->value, "tunnel"))
463 {
464 conn->mode = MODE_TUNNEL;
465 }
466 else if (streq(kw->value, "beet"))
467 {
468 conn->mode = MODE_BEET;
469 }
470 else if (streq(kw->value, "transport_proxy"))
471 {
472 conn->mode = MODE_TRANSPORT;
473 conn->proxy_mode = TRUE;
474 }
475 else if (streq(kw->value, "passthrough") || streq(kw->value, "pass"))
476 {
477 conn->mode = MODE_PASS;
478 }
479 else if (streq(kw->value, "drop") || streq(kw->value, "reject"))
480 {
481 conn->mode = MODE_DROP;
482 }
483 else if (!streq(kw->value, "transport"))
484 {
485 DBG1(DBG_APP, "# bad policy value: %s=%s", kw->entry->name,
486 kw->value);
487 cfg->err++;
488 }
489 break;
490 case KW_COMPRESS:
491 KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_COMPRESS)
492 break;
493 case KW_AUTH:
494 KW_SA_OPTION_FLAG("ah", "esp", SA_OPTION_AUTHENTICATE)
495 break;
496 case KW_MARK:
497 if (!handle_mark(kw->value, &conn->mark_in))
498 {
499 cfg->err++;
500 break;
501 }
502 conn->mark_out = conn->mark_in;
503 break;
504 case KW_MARK_IN:
505 if (!handle_mark(kw->value, &conn->mark_in))
506 {
507 cfg->err++;
508 }
509 break;
510 case KW_MARK_OUT:
511 if (!handle_mark(kw->value, &conn->mark_out))
512 {
513 cfg->err++;
514 }
515 break;
516 case KW_TFC:
517 if (streq(kw->value, "%mtu"))
518 {
519 conn->tfc = -1;
520 }
521 else
522 {
523 char *endptr;
524
525 conn->tfc = strtoul(kw->value, &endptr, 10);
526 if (*endptr != '\0')
527 {
528 DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
529 kw->value);
530 cfg->err++;
531 }
532 }
533 break;
534 case KW_KEYINGTRIES:
535 if (streq(kw->value, "%forever"))
536 {
537 conn->sa_keying_tries = 0;
538 }
539 else
540 {
541 char *endptr;
542
543 conn->sa_keying_tries = strtoul(kw->value, &endptr, 10);
544 if (*endptr != '\0')
545 {
546 DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
547 kw->value);
548 cfg->err++;
549 }
550 }
551 break;
552 case KW_REKEY:
553 KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REKEY)
554 break;
555 case KW_REAUTH:
556 KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REAUTH)
557 break;
558 case KW_MOBIKE:
559 KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_MOBIKE)
560 break;
561 case KW_FORCEENCAPS:
562 KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_FORCE_ENCAP)
563 break;
564 case KW_MODECONFIG:
565 KW_SA_OPTION_FLAG("push", "pull", SA_OPTION_MODECFG_PUSH)
566 break;
567 case KW_XAUTH:
568 KW_SA_OPTION_FLAG("server", "client", SA_OPTION_XAUTH_SERVER)
569 break;
570 default:
571 break;
572 }
573 }
574
575 handle_firewall("left", &conn->left, cfg);
576 handle_firewall("right", &conn->right, cfg);
577 }
578
579 /*
580 * initialize a conn object with the default conn
581 */
582 static void conn_default(char *name, starter_conn_t *conn, starter_conn_t *def)
583 {
584 memcpy(conn, def, sizeof(starter_conn_t));
585 conn->name = strdupnull(name);
586
587 clone_args(KW_CONN_FIRST, KW_CONN_LAST, (char *)conn, (char *)def);
588 clone_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left, (char *)&def->left);
589 clone_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->right, (char *)&def->right);
590 }
591
592 /*
593 * parse a ca section
594 */
595 static void load_ca(starter_ca_t *ca, kw_list_t *kw, starter_config_t *cfg)
596 {
597 char *ca_name = (ca->name == NULL)? "%default":ca->name;
598
599 for ( ; kw; kw = kw->next)
600 {
601 bool assigned = FALSE;
602
603 kw_token_t token = kw->entry->token;
604
605 if (token == KW_AUTO)
606 {
607 token = KW_CA_SETUP;
608 }
609 else if (token == KW_ALSO)
610 {
611 if (cfg->parse_also)
612 {
613 also_t *also = malloc_thing(also_t);
614
615 also->name = strdupnull(kw->value);
616 also->next = ca->also;
617 ca->also = also;
618
619 DBG2(DBG_APP, " also=%s", kw->value);
620 }
621 continue;
622 }
623
624 if (token < KW_CA_FIRST || token > KW_CA_LAST)
625 {
626 DBG1(DBG_APP, "# unsupported keyword '%s' in ca '%s'",
627 kw->entry->name, ca_name);
628 cfg->err++;
629 continue;
630 }
631
632 if (is_deprecated(token, kw, ca_name))
633 {
634 cfg->non_fatal_err++;
635 continue;
636 }
637
638 if (!assign_arg(token, KW_CA_FIRST, kw, (char *)ca, &assigned))
639 {
640 DBG1(DBG_APP, " bad argument value in ca '%s'", ca_name);
641 cfg->err++;
642 }
643 }
644
645 /* treat 'route' and 'start' as 'add' */
646 if (ca->startup != STARTUP_NO)
647 ca->startup = STARTUP_ADD;
648 }
649
650 /*
651 * initialize a ca object with the default ca
652 */
653 static void ca_default(char *name, starter_ca_t *ca, starter_ca_t *def)
654 {
655 memcpy(ca, def, sizeof(starter_ca_t));
656 ca->name = strdupnull(name);
657
658 clone_args(KW_CA_FIRST, KW_CA_LAST, (char *)ca, (char *)def);
659 }
660
661 static kw_list_t* find_also_conn(const char* name, starter_conn_t *conn,
662 starter_config_t *cfg);
663
664 static void load_also_conns(starter_conn_t *conn, also_t *also,
665 starter_config_t *cfg)
666 {
667 while (also != NULL)
668 {
669 kw_list_t *kw = find_also_conn(also->name, conn, cfg);
670
671 if (kw == NULL)
672 {
673 DBG1(DBG_APP, " conn '%s' cannot include '%s'", conn->name,
674 also->name);
675 }
676 else
677 {
678 DBG2(DBG_APP, "conn '%s' includes '%s'", conn->name, also->name);
679 /* only load if no error occurred in the first round */
680 if (cfg->err == 0)
681 load_conn(conn, kw, cfg);
682 }
683 also = also->next;
684 }
685 }
686
687 /*
688 * find a conn included by also
689 */
690 static kw_list_t* find_also_conn(const char* name, starter_conn_t *conn,
691 starter_config_t *cfg)
692 {
693 starter_conn_t *c = cfg->conn_first;
694
695 while (c != NULL)
696 {
697 if (streq(name, c->name))
698 {
699 if (conn->visit == c->visit)
700 {
701 DBG1(DBG_APP, "# detected also loop");
702 cfg->err++;
703 return NULL;
704 }
705 c->visit = conn->visit;
706 load_also_conns(conn, c->also, cfg);
707 return c->kw;
708 }
709 c = c->next;
710 }
711
712 DBG1(DBG_APP, "# also '%s' not found", name);
713 cfg->err++;
714 return NULL;
715 }
716
717 static kw_list_t* find_also_ca(const char* name, starter_ca_t *ca,
718 starter_config_t *cfg);
719
720 static void load_also_cas(starter_ca_t *ca, also_t *also, starter_config_t *cfg)
721 {
722 while (also != NULL)
723 {
724 kw_list_t *kw = find_also_ca(also->name, ca, cfg);
725
726 if (kw == NULL)
727 {
728 DBG1(DBG_APP, " ca '%s' cannot include '%s'", ca->name,
729 also->name);
730 }
731 else
732 {
733 DBG2(DBG_APP, "ca '%s' includes '%s'", ca->name, also->name);
734 /* only load if no error occurred in the first round */
735 if (cfg->err == 0)
736 load_ca(ca, kw, cfg);
737 }
738 also = also->next;
739 }
740 }
741
742 /*
743 * find a ca included by also
744 */
745 static kw_list_t* find_also_ca(const char* name, starter_ca_t *ca,
746 starter_config_t *cfg)
747 {
748 starter_ca_t *c = cfg->ca_first;
749
750 while (c != NULL)
751 {
752 if (streq(name, c->name))
753 {
754 if (ca->visit == c->visit)
755 {
756 DBG1(DBG_APP, "# detected also loop");
757 cfg->err++;
758 return NULL;
759 }
760 c->visit = ca->visit;
761 load_also_cas(ca, c->also, cfg);
762 return c->kw;
763 }
764 c = c->next;
765 }
766
767 DBG1(DBG_APP, "# also '%s' not found", name);
768 cfg->err++;
769 return NULL;
770 }
771
772 /*
773 * free the memory used by also_t objects
774 */
775 static void free_also(also_t *head)
776 {
777 while (head != NULL)
778 {
779 also_t *also = head;
780
781 head = also->next;
782 free(also->name);
783 free(also);
784 }
785 }
786
787 /*
788 * free the memory used by a starter_conn_t object
789 */
790 static void confread_free_conn(starter_conn_t *conn)
791 {
792 free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left);
793 free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->right);
794 free_args(KW_CONN_NAME, KW_CONN_LAST, (char *)conn);
795 free_also(conn->also);
796 }
797
798 /*
799 * free the memory used by a starter_ca_t object
800 */
801 static void
802 confread_free_ca(starter_ca_t *ca)
803 {
804 free_args(KW_CA_NAME, KW_CA_LAST, (char *)ca);
805 free_also(ca->also);
806 }
807
808 /*
809 * free the memory used by a starter_config_t object
810 */
811 void confread_free(starter_config_t *cfg)
812 {
813 starter_conn_t *conn = cfg->conn_first;
814 starter_ca_t *ca = cfg->ca_first;
815
816 free_args(KW_SETUP_FIRST, KW_SETUP_LAST, (char *)cfg);
817
818 confread_free_conn(&cfg->conn_default);
819
820 while (conn != NULL)
821 {
822 starter_conn_t *conn_aux = conn;
823
824 conn = conn->next;
825 confread_free_conn(conn_aux);
826 free(conn_aux);
827 }
828
829 confread_free_ca(&cfg->ca_default);
830
831 while (ca != NULL)
832 {
833 starter_ca_t *ca_aux = ca;
834
835 ca = ca->next;
836 confread_free_ca(ca_aux);
837 free(ca_aux);
838 }
839
840 free(cfg);
841 }
842
843 /*
844 * load and parse an IPsec configuration file
845 */
846 starter_config_t* confread_load(const char *file)
847 {
848 starter_config_t *cfg = NULL;
849 config_parsed_t *cfgp;
850 section_list_t *sconn, *sca;
851 starter_conn_t *conn;
852 starter_ca_t *ca;
853
854 u_int total_err;
855 u_int visit = 0;
856
857 /* load IPSec configuration file */
858 cfgp = parser_load_conf(file);
859 if (!cfgp)
860 {
861 return NULL;
862 }
863 cfg = malloc_thing(starter_config_t);
864
865 /* set default values */
866 default_values(cfg);
867
868 /* load config setup section */
869 load_setup(cfg, cfgp);
870
871 /* in the first round parse also statements */
872 cfg->parse_also = TRUE;
873
874 /* find %default ca section */
875 for (sca = cfgp->ca_first; sca; sca = sca->next)
876 {
877 if (streq(sca->name, "%default"))
878 {
879 DBG2(DBG_APP, "Loading ca %%default");
880 load_ca(&cfg->ca_default, sca->kw, cfg);
881 }
882 }
883
884 /* parameters defined in ca %default sections can be overloads */
885 cfg->ca_default.seen = SEEN_NONE;
886
887 /* load other ca sections */
888 for (sca = cfgp->ca_first; sca; sca = sca->next)
889 {
890 u_int previous_err;
891
892 /* skip %default ca section */
893 if (streq(sca->name, "%default"))
894 continue;
895
896 DBG2(DBG_APP, "Loading ca '%s'", sca->name);
897 ca = malloc_thing(starter_ca_t);
898
899 ca_default(sca->name, ca, &cfg->ca_default);
900 ca->kw = sca->kw;
901 ca->next = NULL;
902
903 previous_err = cfg->err;
904 load_ca(ca, ca->kw, cfg);
905 if (cfg->err > previous_err)
906 {
907 /* errors occurred - free the ca */
908 confread_free_ca(ca);
909 cfg->non_fatal_err += cfg->err - previous_err;
910 cfg->err = previous_err;
911 }
912 else
913 {
914 /* success - insert the ca into the chained list */
915 if (cfg->ca_last)
916 cfg->ca_last->next = ca;
917 cfg->ca_last = ca;
918 if (!cfg->ca_first)
919 cfg->ca_first = ca;
920 }
921 }
922
923 for (ca = cfg->ca_first; ca; ca = ca->next)
924 {
925 also_t *also = ca->also;
926
927 while (also != NULL)
928 {
929 kw_list_t *kw = find_also_ca(also->name, cfg->ca_first, cfg);
930
931 load_ca(ca, kw, cfg);
932 also = also->next;
933 }
934
935 if (ca->startup != STARTUP_NO)
936 ca->state = STATE_TO_ADD;
937 }
938
939 /* find %default conn sections */
940 for (sconn = cfgp->conn_first; sconn; sconn = sconn->next)
941 {
942 if (streq(sconn->name, "%default"))
943 {
944 DBG2(DBG_APP, "Loading conn %%default");
945 load_conn(&cfg->conn_default, sconn->kw, cfg);
946 }
947 }
948
949 /* parameters defined in conn %default sections can be overloaded */
950 cfg->conn_default.seen = SEEN_NONE;
951 cfg->conn_default.right.seen = SEEN_NONE;
952 cfg->conn_default.left.seen = SEEN_NONE;
953
954 /* load other conn sections */
955 for (sconn = cfgp->conn_first; sconn; sconn = sconn->next)
956 {
957 u_int previous_err;
958
959 /* skip %default conn section */
960 if (streq(sconn->name, "%default"))
961 continue;
962
963 DBG2(DBG_APP, "Loading conn '%s'", sconn->name);
964 conn = malloc_thing(starter_conn_t);
965
966 conn_default(sconn->name, conn, &cfg->conn_default);
967 conn->kw = sconn->kw;
968 conn->next = NULL;
969
970 previous_err = cfg->err;
971 load_conn(conn, conn->kw, cfg);
972 if (cfg->err > previous_err)
973 {
974 /* error occurred - free the conn */
975 confread_free_conn(conn);
976 cfg->non_fatal_err += cfg->err - previous_err;
977 cfg->err = previous_err;
978 }
979 else
980 {
981 /* success - insert the conn into the chained list */
982 if (cfg->conn_last)
983 cfg->conn_last->next = conn;
984 cfg->conn_last = conn;
985 if (!cfg->conn_first)
986 cfg->conn_first = conn;
987 }
988 }
989
990 /* in the second round do not parse also statements */
991 cfg->parse_also = FALSE;
992
993 for (ca = cfg->ca_first; ca; ca = ca->next)
994 {
995 ca->visit = ++visit;
996 load_also_cas(ca, ca->also, cfg);
997
998 if (ca->startup != STARTUP_NO)
999 ca->state = STATE_TO_ADD;
1000 }
1001
1002 for (conn = cfg->conn_first; conn; conn = conn->next)
1003 {
1004 conn->visit = ++visit;
1005 load_also_conns(conn, conn->also, cfg);
1006
1007 if (conn->startup != STARTUP_NO)
1008 conn->state = STATE_TO_ADD;
1009 }
1010
1011 parser_free_conf(cfgp);
1012
1013 total_err = cfg->err + cfg->non_fatal_err;
1014 if (total_err > 0)
1015 {
1016 DBG1(DBG_APP, "### %d parsing error%s (%d fatal) ###",
1017 total_err, (total_err > 1)?"s":"", cfg->err);
1018 }
1019
1020 return cfg;
1021 }