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