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