]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/starter/args.c
support of xfrm marks for IKEv2
[thirdparty/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
240 /* ca section keywords */
241 { ARG_STR, offsetof(starter_ca_t, name), NULL },
242 { ARG_ENUM, offsetof(starter_ca_t, startup), LST_startup },
243 { ARG_STR, offsetof(starter_ca_t, cacert), NULL },
244 { ARG_STR, offsetof(starter_ca_t, ldaphost), NULL },
245 { ARG_STR, offsetof(starter_ca_t, ldapbase), NULL },
246 { ARG_STR, offsetof(starter_ca_t, crluri), NULL },
247 { ARG_STR, offsetof(starter_ca_t, crluri2), NULL },
248 { ARG_STR, offsetof(starter_ca_t, ocspuri), NULL },
249 { ARG_STR, offsetof(starter_ca_t, ocspuri2), NULL },
250 { ARG_STR, offsetof(starter_ca_t, certuribase), NULL },
251
252 /* end keywords */
253 { ARG_MISC, 0, NULL /* KW_HOST */ },
254 { ARG_UINT, offsetof(starter_end_t, ikeport), NULL },
255 { ARG_MISC, 0, NULL /* KW_NEXTHOP */ },
256 { ARG_STR, offsetof(starter_end_t, subnet), NULL },
257 { ARG_MISC, 0, NULL /* KW_SUBNETWITHIN */ },
258 { ARG_MISC, 0, NULL /* KW_PROTOPORT */ },
259 { ARG_STR, offsetof(starter_end_t, sourceip), NULL },
260 { ARG_MISC, 0, NULL /* KW_NATIP */ },
261 { ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool },
262 { ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
263 { ARG_ENUM, offsetof(starter_end_t, allow_any), LST_bool },
264 { ARG_STR, offsetof(starter_end_t, updown), NULL },
265 { ARG_STR, offsetof(starter_end_t, auth), NULL },
266 { ARG_STR, offsetof(starter_end_t, auth2), NULL },
267 { ARG_STR, offsetof(starter_end_t, id), NULL },
268 { ARG_STR, offsetof(starter_end_t, id2), NULL },
269 { ARG_STR, offsetof(starter_end_t, rsakey), NULL },
270 { ARG_STR, offsetof(starter_end_t, cert), NULL },
271 { ARG_STR, offsetof(starter_end_t, cert2), NULL },
272 { ARG_ENUM, offsetof(starter_end_t, sendcert), LST_sendcert },
273 { ARG_STR, offsetof(starter_end_t, ca), NULL },
274 { ARG_STR, offsetof(starter_end_t, ca2), NULL },
275 { ARG_STR, offsetof(starter_end_t, groups), NULL },
276 { ARG_STR, offsetof(starter_end_t, iface), NULL }
277 };
278
279 static void free_list(char **list)
280 {
281 char **s;
282
283 for (s = list; *s; s++)
284 {
285 free(*s);
286 }
287 free(list);
288 }
289
290 char** new_list(char *value)
291 {
292 char *val, *b, *e, *end, **ret;
293 int count;
294
295 val = value ? clone_str(value) : NULL;
296 if (!val)
297 {
298 return NULL;
299 }
300 end = val + strlen(val);
301 for (b = val, count = 0; b < end;)
302 {
303 for (e = b; ((*e != ' ') && (*e != '\0')); e++);
304 *e = '\0';
305 if (e != b)
306 {
307 count++;
308 }
309 b = e + 1;
310 }
311 if (count == 0)
312 {
313 free(val);
314 return NULL;
315 }
316 ret = (char **)malloc((count+1) * sizeof(char *));
317
318 for (b = val, count = 0; b < end; )
319 {
320 for (e = b; (*e != '\0'); e++);
321 if (e != b)
322 {
323 ret[count++] = clone_str(b);
324 }
325 b = e + 1;
326 }
327 ret[count] = NULL;
328 free(val);
329 return ret;
330 }
331
332
333 /*
334 * assigns an argument value to a struct field
335 */
336 bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
337 bool *assigned)
338 {
339 char *p = base + token_info[token].offset;
340 const char **list = token_info[token].list;
341
342 int index = -1; /* used for enumeration arguments */
343
344 lset_t *seen = (lset_t *)base; /* seen flags are at the top of the struct */
345 lset_t f = LELEM(token - first); /* compute flag position of argument */
346
347 *assigned = FALSE;
348
349 DBG(DBG_CONTROLMORE,
350 DBG_log(" %s=%s", kw->entry->name, kw->value)
351 )
352
353 if (*seen & f)
354 {
355 plog("# duplicate '%s' option", kw->entry->name);
356 return FALSE;
357 }
358
359 /* set flag that this argument has been seen */
360 *seen |= f;
361
362 /* is there a keyword list? */
363 if (list != NULL && token_info[token].type != ARG_LST)
364 {
365 bool match = FALSE;
366
367 while (*list != NULL && !match)
368 {
369 index++;
370 match = streq(kw->value, *list++);
371 }
372 if (!match)
373 {
374 plog("# bad value: %s=%s", kw->entry->name, kw->value);
375 return FALSE;
376 }
377 }
378
379 switch (token_info[token].type)
380 {
381 case ARG_NONE:
382 plog("# option '%s' not supported yet", kw->entry->name);
383 return FALSE;
384 case ARG_ENUM:
385 {
386 if (index < 0)
387 {
388 plog("# bad enumeration value: %s=%s (%d)"
389 , kw->entry->name, kw->value, index);
390 return FALSE;
391 }
392
393 if (token_info[token].list == LST_bool)
394 {
395 bool *b = (bool *)p;
396 *b = (index > 0);
397 }
398 else
399 {
400 int *i = (int *)p;
401 *i = index;
402 }
403 }
404 break;
405
406 case ARG_UINT:
407 {
408 char *endptr;
409 u_int *u = (u_int *)p;
410
411 *u = strtoul(kw->value, &endptr, 10);
412
413 if (*endptr != '\0')
414 {
415 plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
416 return FALSE;
417 }
418 }
419 break;
420 case ARG_ULNG:
421 case ARG_PCNT:
422 {
423 char *endptr;
424 unsigned long *l = (unsigned long *)p;
425
426 *l = strtoul(kw->value, &endptr, 10);
427
428 if (token_info[token].type == ARG_ULNG)
429 {
430 if (*endptr != '\0')
431 {
432 plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
433 return FALSE;
434 }
435 }
436 else
437 {
438 if ((*endptr != '%') || (endptr[1] != '\0') || endptr == kw->value)
439 {
440 plog("# bad percent value: %s=%s", kw->entry->name, kw->value);
441 return FALSE;
442 }
443 }
444
445 }
446 break;
447 case ARG_ULLI:
448 {
449 char *endptr;
450 unsigned long long *ll = (unsigned long long *)p;
451
452 *ll = strtoull(kw->value, &endptr, 10);
453
454 if (*endptr != '\0')
455 {
456 plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
457 return FALSE;
458 }
459 }
460 break;
461 case ARG_TIME:
462 {
463 char *endptr;
464 time_t *t = (time_t *)p;
465
466 *t = strtoul(kw->value, &endptr, 10);
467
468 /* time in seconds? */
469 if (*endptr == '\0' || (*endptr == 's' && endptr[1] == '\0'))
470 {
471 break;
472 }
473 if (endptr[1] == '\0')
474 {
475 if (*endptr == 'm') /* time in minutes? */
476 {
477 *t *= 60;
478 break;
479 }
480 if (*endptr == 'h') /* time in hours? */
481 {
482 *t *= 3600;
483 break;
484 }
485 if (*endptr == 'd') /* time in days? */
486 {
487 *t *= 3600*24;
488 break;
489 }
490 }
491 plog("# bad duration value: %s=%s", kw->entry->name, kw->value);
492 return FALSE;
493 }
494 case ARG_STR:
495 {
496 char **cp = (char **)p;
497
498 /* free any existing string */
499 free(*cp);
500
501 /* assign the new string */
502 *cp = clone_str(kw->value);
503 }
504 break;
505 case ARG_LST:
506 {
507 char ***listp = (char ***)p;
508
509 /* free any existing list */
510 if (*listp != NULL)
511 {
512 free_list(*listp);
513 }
514 /* create a new list and assign values */
515 *listp = new_list(kw->value);
516
517 /* is there a keyword list? */
518 if (list != NULL)
519 {
520 char ** lst;
521
522 for (lst = *listp; lst && *lst; lst++)
523 {
524 bool match = FALSE;
525
526 list = token_info[token].list;
527
528 while (*list != NULL && !match)
529 {
530 match = streq(*lst, *list++);
531 }
532 if (!match)
533 {
534 plog("# bad value: %s=%s", kw->entry->name, *lst);
535 return FALSE;
536 }
537 }
538 }
539 }
540 default:
541 return TRUE;
542 }
543
544 *assigned = TRUE;
545 return TRUE;
546 }
547
548 /*
549 * frees all dynamically allocated arguments in a struct
550 */
551 void free_args(kw_token_t first, kw_token_t last, char *base)
552 {
553 kw_token_t token;
554
555 for (token = first; token <= last; token++)
556 {
557 char *p = base + token_info[token].offset;
558
559 switch (token_info[token].type)
560 {
561 case ARG_STR:
562 {
563 char **cp = (char **)p;
564
565 free(*cp);
566 *cp = NULL;
567 }
568 break;
569 case ARG_LST:
570 {
571 char ***listp = (char ***)p;
572
573 if (*listp != NULL)
574 {
575 free_list(*listp);
576 *listp = NULL;
577 }
578 }
579 break;
580 default:
581 break;
582 }
583 }
584 }
585
586 /*
587 * clone all dynamically allocated arguments in a struct
588 */
589 void clone_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
590 {
591 kw_token_t token;
592
593 for (token = first; token <= last; token++)
594 {
595 if (token_info[token].type == ARG_STR)
596 {
597 char **cp1 = (char **)(base1 + token_info[token].offset);
598 char **cp2 = (char **)(base2 + token_info[token].offset);
599
600 *cp1 = clone_str(*cp2);
601 }
602 }
603 }
604
605 static bool cmp_list(char **list1, char **list2)
606 {
607 if ((list1 == NULL) && (list2 == NULL))
608 {
609 return TRUE;
610 }
611 if ((list1 == NULL) || (list2 == NULL))
612 {
613 return FALSE;
614 }
615
616 for ( ; *list1 && *list2; list1++, list2++)
617 {
618 if (strcmp(*list1,*list2) != 0)
619 {
620 return FALSE;
621 }
622 }
623
624 if ((*list1 != NULL) || (*list2 != NULL))
625 {
626 return FALSE;
627 }
628
629 return TRUE;
630 }
631
632 /*
633 * compare all arguments in a struct
634 */
635 bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
636 {
637 kw_token_t token;
638
639 for (token = first; token <= last; token++)
640 {
641 char *p1 = base1 + token_info[token].offset;
642 char *p2 = base2 + token_info[token].offset;
643
644 switch (token_info[token].type)
645 {
646 case ARG_ENUM:
647 if (token_info[token].list == LST_bool)
648 {
649 bool *b1 = (bool *)p1;
650 bool *b2 = (bool *)p2;
651
652 if (*b1 != *b2)
653 {
654 return FALSE;
655 }
656 }
657 else
658 {
659 int *i1 = (int *)p1;
660 int *i2 = (int *)p2;
661
662 if (*i1 != *i2)
663 {
664 return FALSE;
665 }
666 }
667 break;
668 case ARG_UINT:
669 {
670 u_int *u1 = (u_int *)p1;
671 u_int *u2 = (u_int *)p2;
672
673 if (*u1 != *u2)
674 {
675 return FALSE;
676 }
677 }
678 break;
679 case ARG_ULNG:
680 case ARG_PCNT:
681 {
682 unsigned long *l1 = (unsigned long *)p1;
683 unsigned long *l2 = (unsigned long *)p2;
684
685 if (*l1 != *l2)
686 {
687 return FALSE;
688 }
689 }
690 break;
691 case ARG_ULLI:
692 {
693 unsigned long long *ll1 = (unsigned long long *)p1;
694 unsigned long long *ll2 = (unsigned long long *)p2;
695
696 if (*ll1 != *ll2)
697 {
698 return FALSE;
699 }
700 }
701 break;
702 case ARG_TIME:
703 {
704 time_t *t1 = (time_t *)p1;
705 time_t *t2 = (time_t *)p2;
706
707 if (*t1 != *t2)
708 {
709 return FALSE;
710 }
711 }
712 break;
713 case ARG_STR:
714 {
715 char **cp1 = (char **)p1;
716 char **cp2 = (char **)p2;
717
718 if (*cp1 == NULL && *cp2 == NULL)
719 {
720 break;
721 }
722 if (*cp1 == NULL || *cp2 == NULL || strcmp(*cp1, *cp2) != 0)
723 {
724 return FALSE;
725 }
726 }
727 break;
728 case ARG_LST:
729 {
730 char ***listp1 = (char ***)p1;
731 char ***listp2 = (char ***)p2;
732
733 if (!cmp_list(*listp1, *listp2))
734 {
735 return FALSE;
736 }
737 }
738 break;
739 default:
740 break;
741 }
742 }
743 return TRUE;
744 }