Rebuild library.lo after changing ./configure options
[strongswan.git] / src / starter / args.c
1 /* automatic handling of confread struct arguments
2 * Copyright (C) 2006 Andreas Steffen
3 * Hochschule fuer Technik Rapperswil, Switzerland
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <stddef.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include <freeswan.h>
21
22 #include "../pluto/constants.h"
23 #include "../pluto/defs.h"
24 #include "../pluto/log.h"
25
26 #include "keywords.h"
27 #include "parser.h"
28 #include "confread.h"
29 #include "args.h"
30
31 /* argument types */
32
33 typedef enum {
34 ARG_NONE,
35 ARG_ENUM,
36 ARG_UINT,
37 ARG_TIME,
38 ARG_ULNG,
39 ARG_ULLI,
40 ARG_PCNT,
41 ARG_STR,
42 ARG_LST,
43 ARG_MISC
44 } arg_t;
45
46 /* various keyword lists */
47
48 static const char *LST_bool[] = {
49 "no",
50 "yes",
51 NULL
52 };
53
54 static const char *LST_sendcert[] = {
55 "always",
56 "ifasked",
57 "never",
58 "yes",
59 "no",
60 NULL
61 };
62
63 static const char *LST_unique[] = {
64 "no",
65 "yes",
66 "replace",
67 "keep",
68 NULL
69 };
70
71 static const char *LST_strict[] = {
72 "no",
73 "yes",
74 "ifuri",
75 NULL
76 };
77 static const char *LST_dpd_action[] = {
78 "none",
79 "clear",
80 "hold",
81 "restart",
82 NULL
83 };
84
85 static const char *LST_startup[] = {
86 "ignore",
87 "add",
88 "route",
89 "start",
90 NULL
91 };
92
93 static const char *LST_packetdefault[] = {
94 "drop",
95 "reject",
96 "pass",
97 NULL
98 };
99
100 static const char *LST_keyexchange[] = {
101 "ike",
102 "ikev1",
103 "ikev2",
104 NULL
105 };
106
107 static const char *LST_pfsgroup[] = {
108 "modp1024",
109 "modp1536",
110 "modp2048",
111 "modp3072",
112 "modp4096",
113 "modp6144",
114 "modp8192",
115 "ecp192",
116 "ecp224",
117 "ecp256",
118 "ecp384",
119 "ecp521",
120 NULL
121 };
122
123 static const char *LST_plutodebug[] = {
124 "none",
125 "all",
126 "raw",
127 "crypt",
128 "parsing",
129 "emitting",
130 "control",
131 "lifecycle",
132 "klips",
133 "dns",
134 "natt",
135 "oppo",
136 "controlmore",
137 "private",
138 NULL
139 };
140
141 static const char *LST_klipsdebug[] = {
142 "tunnel",
143 "tunnel-xmit",
144 "pfkey",
145 "xform",
146 "eroute",
147 "spi",
148 "radij",
149 "esp",
150 "ah",
151 "ipcomp",
152 "verbose",
153 "all",
154 "none",
155 NULL
156 };
157
158 typedef struct {
159 arg_t type;
160 size_t offset;
161 const char **list;
162 } token_info_t;
163
164 static const token_info_t token_info[] =
165 {
166 /* config setup keywords */
167 { ARG_LST, offsetof(starter_config_t, setup.interfaces), NULL },
168 { ARG_STR, offsetof(starter_config_t, setup.dumpdir), NULL },
169 { ARG_ENUM, offsetof(starter_config_t, setup.charonstart), LST_bool },
170 { ARG_ENUM, offsetof(starter_config_t, setup.plutostart), LST_bool },
171
172 /* pluto/charon keywords */
173 { ARG_LST, offsetof(starter_config_t, setup.plutodebug), LST_plutodebug },
174 { ARG_STR, offsetof(starter_config_t, setup.charondebug), NULL },
175 { ARG_STR, offsetof(starter_config_t, setup.prepluto), NULL },
176 { ARG_STR, offsetof(starter_config_t, setup.postpluto), NULL },
177 { ARG_STR, offsetof(starter_config_t, setup.plutostderrlog), NULL },
178 { ARG_ENUM, offsetof(starter_config_t, setup.uniqueids), LST_unique },
179 { ARG_UINT, offsetof(starter_config_t, setup.overridemtu), NULL },
180 { ARG_TIME, offsetof(starter_config_t, setup.crlcheckinterval), NULL },
181 { ARG_ENUM, offsetof(starter_config_t, setup.cachecrls), LST_bool },
182 { ARG_ENUM, offsetof(starter_config_t, setup.strictcrlpolicy), LST_strict },
183 { ARG_ENUM, offsetof(starter_config_t, setup.nocrsend), LST_bool },
184 { ARG_ENUM, offsetof(starter_config_t, setup.nat_traversal), LST_bool },
185 { ARG_TIME, offsetof(starter_config_t, setup.keep_alive), NULL },
186 { ARG_ENUM, offsetof(starter_config_t, setup.force_keepalive), LST_bool },
187 { ARG_STR, offsetof(starter_config_t, setup.virtual_private), NULL },
188 { ARG_STR, offsetof(starter_config_t, setup.pkcs11module), NULL },
189 { ARG_STR, offsetof(starter_config_t, setup.pkcs11initargs), NULL },
190 { ARG_ENUM, offsetof(starter_config_t, setup.pkcs11keepstate), LST_bool },
191 { ARG_ENUM, offsetof(starter_config_t, setup.pkcs11proxy), LST_bool },
192
193 /* KLIPS keywords */
194 { ARG_LST, offsetof(starter_config_t, setup.klipsdebug), LST_klipsdebug },
195 { ARG_ENUM, offsetof(starter_config_t, setup.fragicmp), LST_bool },
196 { ARG_STR, offsetof(starter_config_t, setup.packetdefault), LST_packetdefault },
197 { ARG_ENUM, offsetof(starter_config_t, setup.hidetos), LST_bool },
198
199 /* conn section keywords */
200 { ARG_STR, offsetof(starter_conn_t, name), NULL },
201 { ARG_ENUM, offsetof(starter_conn_t, startup), LST_startup },
202 { ARG_ENUM, offsetof(starter_conn_t, keyexchange), LST_keyexchange },
203 { ARG_MISC, 0, NULL /* KW_TYPE */ },
204 { ARG_MISC, 0, NULL /* KW_PFS */ },
205 { ARG_MISC, 0, NULL /* KW_COMPRESS */ },
206 { ARG_ENUM, offsetof(starter_conn_t, install_policy), LST_bool },
207 { ARG_MISC, 0, NULL /* KW_AUTH */ },
208 { ARG_MISC, 0, NULL /* KW_AUTHBY */ },
209 { ARG_MISC, 0, NULL /* KW_EAP */ },
210 { ARG_STR, offsetof(starter_conn_t, eap_identity), NULL },
211 { ARG_MISC, 0, NULL /* KW_MOBIKE */ },
212 { ARG_MISC, 0, NULL /* KW_FORCEENCAPS */ },
213 { ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL },
214 { ARG_TIME, offsetof(starter_conn_t, sa_ipsec_life_seconds), NULL },
215 { ARG_TIME, offsetof(starter_conn_t, sa_rekey_margin), NULL },
216 { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_life_bytes), NULL },
217 { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_margin_bytes), NULL },
218 { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_life_packets), NULL },
219 { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_margin_packets), NULL },
220 { ARG_MISC, 0, NULL /* KW_KEYINGTRIES */ },
221 { ARG_PCNT, offsetof(starter_conn_t, sa_rekey_fuzz), NULL },
222 { ARG_MISC, 0, NULL /* KW_REKEY */ },
223 { ARG_MISC, 0, NULL /* KW_REAUTH */ },
224 { ARG_STR, offsetof(starter_conn_t, ike), NULL },
225 { ARG_STR, offsetof(starter_conn_t, esp), NULL },
226 { ARG_STR, offsetof(starter_conn_t, pfsgroup), LST_pfsgroup },
227 { ARG_TIME, offsetof(starter_conn_t, dpd_delay), NULL },
228 { ARG_TIME, offsetof(starter_conn_t, dpd_timeout), NULL },
229 { ARG_ENUM, offsetof(starter_conn_t, dpd_action), LST_dpd_action },
230 { ARG_TIME, offsetof(starter_conn_t, inactivity), NULL },
231 { ARG_MISC, 0, NULL /* KW_MODECONFIG */ },
232 { ARG_MISC, 0, NULL /* KW_XAUTH */ },
233 { ARG_STR, offsetof(starter_conn_t, xauth_identity), NULL },
234 { ARG_ENUM, offsetof(starter_conn_t, me_mediation), LST_bool },
235 { ARG_STR, offsetof(starter_conn_t, me_mediated_by), NULL },
236 { ARG_STR, offsetof(starter_conn_t, me_peerid), NULL },
237 { ARG_UINT, offsetof(starter_conn_t, reqid), NULL },
238 { ARG_MISC, 0, NULL /* KW_MARK */ },
239 { ARG_MISC, 0, NULL /* KW_MARK_IN */ },
240 { ARG_MISC, 0, NULL /* KW_MARK_OUT */ },
241
242 /* ca section keywords */
243 { ARG_STR, offsetof(starter_ca_t, name), NULL },
244 { ARG_ENUM, offsetof(starter_ca_t, startup), LST_startup },
245 { ARG_STR, offsetof(starter_ca_t, cacert), NULL },
246 { ARG_STR, offsetof(starter_ca_t, ldaphost), NULL },
247 { ARG_STR, offsetof(starter_ca_t, ldapbase), NULL },
248 { ARG_STR, offsetof(starter_ca_t, crluri), NULL },
249 { ARG_STR, offsetof(starter_ca_t, crluri2), NULL },
250 { ARG_STR, offsetof(starter_ca_t, ocspuri), NULL },
251 { ARG_STR, offsetof(starter_ca_t, ocspuri2), NULL },
252 { ARG_STR, offsetof(starter_ca_t, certuribase), NULL },
253
254 /* end keywords */
255 { ARG_MISC, 0, NULL /* KW_HOST */ },
256 { ARG_UINT, offsetof(starter_end_t, ikeport), NULL },
257 { ARG_MISC, 0, NULL /* KW_NEXTHOP */ },
258 { ARG_STR, offsetof(starter_end_t, subnet), NULL },
259 { ARG_MISC, 0, NULL /* KW_SUBNETWITHIN */ },
260 { ARG_MISC, 0, NULL /* KW_PROTOPORT */ },
261 { ARG_STR, offsetof(starter_end_t, sourceip), NULL },
262 { ARG_MISC, 0, NULL /* KW_NATIP */ },
263 { ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool },
264 { ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
265 { ARG_ENUM, offsetof(starter_end_t, allow_any), LST_bool },
266 { ARG_STR, offsetof(starter_end_t, updown), NULL },
267 { ARG_STR, offsetof(starter_end_t, auth), NULL },
268 { ARG_STR, offsetof(starter_end_t, auth2), NULL },
269 { ARG_STR, offsetof(starter_end_t, id), NULL },
270 { ARG_STR, offsetof(starter_end_t, id2), NULL },
271 { ARG_STR, offsetof(starter_end_t, rsakey), NULL },
272 { ARG_STR, offsetof(starter_end_t, cert), NULL },
273 { ARG_STR, offsetof(starter_end_t, cert2), NULL },
274 { ARG_ENUM, offsetof(starter_end_t, sendcert), LST_sendcert },
275 { ARG_STR, offsetof(starter_end_t, ca), NULL },
276 { ARG_STR, offsetof(starter_end_t, ca2), NULL },
277 { ARG_STR, offsetof(starter_end_t, groups), NULL },
278 { ARG_STR, offsetof(starter_end_t, iface), NULL }
279 };
280
281 static void free_list(char **list)
282 {
283 char **s;
284
285 for (s = list; *s; s++)
286 {
287 free(*s);
288 }
289 free(list);
290 }
291
292 char** new_list(char *value)
293 {
294 char *val, *b, *e, *end, **ret;
295 int count;
296
297 val = value ? clone_str(value) : NULL;
298 if (!val)
299 {
300 return NULL;
301 }
302 end = val + strlen(val);
303 for (b = val, count = 0; b < end;)
304 {
305 for (e = b; ((*e != ' ') && (*e != '\0')); e++);
306 *e = '\0';
307 if (e != b)
308 {
309 count++;
310 }
311 b = e + 1;
312 }
313 if (count == 0)
314 {
315 free(val);
316 return NULL;
317 }
318 ret = (char **)malloc((count+1) * sizeof(char *));
319
320 for (b = val, count = 0; b < end; )
321 {
322 for (e = b; (*e != '\0'); e++);
323 if (e != b)
324 {
325 ret[count++] = clone_str(b);
326 }
327 b = e + 1;
328 }
329 ret[count] = NULL;
330 free(val);
331 return ret;
332 }
333
334
335 /*
336 * assigns an argument value to a struct field
337 */
338 bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
339 bool *assigned)
340 {
341 char *p = base + token_info[token].offset;
342 const char **list = token_info[token].list;
343
344 int index = -1; /* used for enumeration arguments */
345
346 lset_t *seen = (lset_t *)base; /* seen flags are at the top of the struct */
347 lset_t f = LELEM(token - first); /* compute flag position of argument */
348
349 *assigned = FALSE;
350
351 DBG(DBG_CONTROLMORE,
352 DBG_log(" %s=%s", kw->entry->name, kw->value)
353 )
354
355 if (*seen & f)
356 {
357 plog("# duplicate '%s' option", kw->entry->name);
358 return FALSE;
359 }
360
361 /* set flag that this argument has been seen */
362 *seen |= f;
363
364 /* is there a keyword list? */
365 if (list != NULL && token_info[token].type != ARG_LST)
366 {
367 bool match = FALSE;
368
369 while (*list != NULL && !match)
370 {
371 index++;
372 match = streq(kw->value, *list++);
373 }
374 if (!match)
375 {
376 plog("# bad value: %s=%s", kw->entry->name, kw->value);
377 return FALSE;
378 }
379 }
380
381 switch (token_info[token].type)
382 {
383 case ARG_NONE:
384 plog("# option '%s' not supported yet", kw->entry->name);
385 return FALSE;
386 case ARG_ENUM:
387 {
388 if (index < 0)
389 {
390 plog("# bad enumeration value: %s=%s (%d)"
391 , kw->entry->name, kw->value, index);
392 return FALSE;
393 }
394
395 if (token_info[token].list == LST_bool)
396 {
397 bool *b = (bool *)p;
398 *b = (index > 0);
399 }
400 else
401 {
402 int *i = (int *)p;
403 *i = index;
404 }
405 }
406 break;
407
408 case ARG_UINT:
409 {
410 char *endptr;
411 u_int *u = (u_int *)p;
412
413 *u = strtoul(kw->value, &endptr, 10);
414
415 if (*endptr != '\0')
416 {
417 plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
418 return FALSE;
419 }
420 }
421 break;
422 case ARG_ULNG:
423 case ARG_PCNT:
424 {
425 char *endptr;
426 unsigned long *l = (unsigned long *)p;
427
428 *l = strtoul(kw->value, &endptr, 10);
429
430 if (token_info[token].type == ARG_ULNG)
431 {
432 if (*endptr != '\0')
433 {
434 plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
435 return FALSE;
436 }
437 }
438 else
439 {
440 if ((*endptr != '%') || (endptr[1] != '\0') || endptr == kw->value)
441 {
442 plog("# bad percent value: %s=%s", kw->entry->name, kw->value);
443 return FALSE;
444 }
445 }
446
447 }
448 break;
449 case ARG_ULLI:
450 {
451 char *endptr;
452 unsigned long long *ll = (unsigned long long *)p;
453
454 *ll = strtoull(kw->value, &endptr, 10);
455
456 if (*endptr != '\0')
457 {
458 plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
459 return FALSE;
460 }
461 }
462 break;
463 case ARG_TIME:
464 {
465 char *endptr;
466 time_t *t = (time_t *)p;
467
468 *t = strtoul(kw->value, &endptr, 10);
469
470 /* time in seconds? */
471 if (*endptr == '\0' || (*endptr == 's' && endptr[1] == '\0'))
472 {
473 break;
474 }
475 if (endptr[1] == '\0')
476 {
477 if (*endptr == 'm') /* time in minutes? */
478 {
479 *t *= 60;
480 break;
481 }
482 if (*endptr == 'h') /* time in hours? */
483 {
484 *t *= 3600;
485 break;
486 }
487 if (*endptr == 'd') /* time in days? */
488 {
489 *t *= 3600*24;
490 break;
491 }
492 }
493 plog("# bad duration value: %s=%s", kw->entry->name, kw->value);
494 return FALSE;
495 }
496 case ARG_STR:
497 {
498 char **cp = (char **)p;
499
500 /* free any existing string */
501 free(*cp);
502
503 /* assign the new string */
504 *cp = clone_str(kw->value);
505 }
506 break;
507 case ARG_LST:
508 {
509 char ***listp = (char ***)p;
510
511 /* free any existing list */
512 if (*listp != NULL)
513 {
514 free_list(*listp);
515 }
516 /* create a new list and assign values */
517 *listp = new_list(kw->value);
518
519 /* is there a keyword list? */
520 if (list != NULL)
521 {
522 char ** lst;
523
524 for (lst = *listp; lst && *lst; lst++)
525 {
526 bool match = FALSE;
527
528 list = token_info[token].list;
529
530 while (*list != NULL && !match)
531 {
532 match = streq(*lst, *list++);
533 }
534 if (!match)
535 {
536 plog("# bad value: %s=%s", kw->entry->name, *lst);
537 return FALSE;
538 }
539 }
540 }
541 }
542 default:
543 return TRUE;
544 }
545
546 *assigned = TRUE;
547 return TRUE;
548 }
549
550 /*
551 * frees all dynamically allocated arguments in a struct
552 */
553 void free_args(kw_token_t first, kw_token_t last, char *base)
554 {
555 kw_token_t token;
556
557 for (token = first; token <= last; token++)
558 {
559 char *p = base + token_info[token].offset;
560
561 switch (token_info[token].type)
562 {
563 case ARG_STR:
564 {
565 char **cp = (char **)p;
566
567 free(*cp);
568 *cp = NULL;
569 }
570 break;
571 case ARG_LST:
572 {
573 char ***listp = (char ***)p;
574
575 if (*listp != NULL)
576 {
577 free_list(*listp);
578 *listp = NULL;
579 }
580 }
581 break;
582 default:
583 break;
584 }
585 }
586 }
587
588 /*
589 * clone all dynamically allocated arguments in a struct
590 */
591 void clone_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
592 {
593 kw_token_t token;
594
595 for (token = first; token <= last; token++)
596 {
597 if (token_info[token].type == ARG_STR)
598 {
599 char **cp1 = (char **)(base1 + token_info[token].offset);
600 char **cp2 = (char **)(base2 + token_info[token].offset);
601
602 *cp1 = clone_str(*cp2);
603 }
604 }
605 }
606
607 static bool cmp_list(char **list1, char **list2)
608 {
609 if ((list1 == NULL) && (list2 == NULL))
610 {
611 return TRUE;
612 }
613 if ((list1 == NULL) || (list2 == NULL))
614 {
615 return FALSE;
616 }
617
618 for ( ; *list1 && *list2; list1++, list2++)
619 {
620 if (strcmp(*list1,*list2) != 0)
621 {
622 return FALSE;
623 }
624 }
625
626 if ((*list1 != NULL) || (*list2 != NULL))
627 {
628 return FALSE;
629 }
630
631 return TRUE;
632 }
633
634 /*
635 * compare all arguments in a struct
636 */
637 bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
638 {
639 kw_token_t token;
640
641 for (token = first; token <= last; token++)
642 {
643 char *p1 = base1 + token_info[token].offset;
644 char *p2 = base2 + token_info[token].offset;
645
646 switch (token_info[token].type)
647 {
648 case ARG_ENUM:
649 if (token_info[token].list == LST_bool)
650 {
651 bool *b1 = (bool *)p1;
652 bool *b2 = (bool *)p2;
653
654 if (*b1 != *b2)
655 {
656 return FALSE;
657 }
658 }
659 else
660 {
661 int *i1 = (int *)p1;
662 int *i2 = (int *)p2;
663
664 if (*i1 != *i2)
665 {
666 return FALSE;
667 }
668 }
669 break;
670 case ARG_UINT:
671 {
672 u_int *u1 = (u_int *)p1;
673 u_int *u2 = (u_int *)p2;
674
675 if (*u1 != *u2)
676 {
677 return FALSE;
678 }
679 }
680 break;
681 case ARG_ULNG:
682 case ARG_PCNT:
683 {
684 unsigned long *l1 = (unsigned long *)p1;
685 unsigned long *l2 = (unsigned long *)p2;
686
687 if (*l1 != *l2)
688 {
689 return FALSE;
690 }
691 }
692 break;
693 case ARG_ULLI:
694 {
695 unsigned long long *ll1 = (unsigned long long *)p1;
696 unsigned long long *ll2 = (unsigned long long *)p2;
697
698 if (*ll1 != *ll2)
699 {
700 return FALSE;
701 }
702 }
703 break;
704 case ARG_TIME:
705 {
706 time_t *t1 = (time_t *)p1;
707 time_t *t2 = (time_t *)p2;
708
709 if (*t1 != *t2)
710 {
711 return FALSE;
712 }
713 }
714 break;
715 case ARG_STR:
716 {
717 char **cp1 = (char **)p1;
718 char **cp2 = (char **)p2;
719
720 if (*cp1 == NULL && *cp2 == NULL)
721 {
722 break;
723 }
724 if (*cp1 == NULL || *cp2 == NULL || strcmp(*cp1, *cp2) != 0)
725 {
726 return FALSE;
727 }
728 }
729 break;
730 case ARG_LST:
731 {
732 char ***listp1 = (char ***)p1;
733 char ***listp2 = (char ***)p2;
734
735 if (!cmp_list(*listp1, *listp2))
736 {
737 return FALSE;
738 }
739 }
740 break;
741 default:
742 break;
743 }
744 }
745 return TRUE;
746 }