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