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