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