added charondebug config parameter to set debug level at startup
[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_STR, offsetof(starter_conn_t, ike), NULL },
194 { ARG_STR, offsetof(starter_conn_t, esp), NULL },
195 { ARG_STR, offsetof(starter_conn_t, pfsgroup), LST_pfsgroup },
196 { ARG_TIME, offsetof(starter_conn_t, dpd_delay), NULL },
197 { ARG_TIME, offsetof(starter_conn_t, dpd_timeout), NULL },
198 { ARG_ENUM, offsetof(starter_conn_t, dpd_action), LST_dpd_action },
199
200 /* ca section keywords */
201 { ARG_STR, offsetof(starter_ca_t, name), NULL },
202 { ARG_ENUM, offsetof(starter_ca_t, startup), LST_startup },
203 { ARG_STR, offsetof(starter_ca_t, cacert), NULL },
204 { ARG_STR, offsetof(starter_ca_t, ldaphost), NULL },
205 { ARG_STR, offsetof(starter_ca_t, ldapbase), NULL },
206 { ARG_STR, offsetof(starter_ca_t, crluri), NULL },
207 { ARG_STR, offsetof(starter_ca_t, crluri2), NULL },
208 { ARG_STR, offsetof(starter_ca_t, ocspuri), NULL },
209
210 /* end keywords */
211 { ARG_MISC, 0, NULL /* KW_HOST */ },
212 { ARG_MISC, 0, NULL /* KW_NEXTHOP */ },
213 { ARG_MISC, 0, NULL /* KW_SUBNET */ },
214 { ARG_MISC, 0, NULL /* KW_SUBNETWITHIN */ },
215 { ARG_MISC, 0, NULL /* KW_PROTOPORT */ },
216 { ARG_MISC, 0, NULL /* KW_SOURCEIP */ },
217 { ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool },
218 { ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
219 { ARG_STR, offsetof(starter_end_t, updown), NULL },
220 { ARG_STR, offsetof(starter_end_t, id), NULL },
221 { ARG_STR, offsetof(starter_end_t, rsakey), NULL },
222 { ARG_STR, offsetof(starter_end_t, cert), NULL },
223 { ARG_ENUM, offsetof(starter_end_t, sendcert), LST_sendcert },
224 { ARG_STR, offsetof(starter_end_t, ca), NULL },
225 { ARG_STR, offsetof(starter_end_t, groups), NULL },
226 { ARG_STR, offsetof(starter_end_t, iface), NULL }
227 };
228
229 static void
230 free_list(char **list)
231 {
232 char **s;
233
234 for (s = list; *s; s++)
235 pfree(*s);
236 pfree(list);
237 }
238
239 char **
240 new_list(char *value)
241 {
242 char *val, *b, *e, *end, **ret;
243 int count;
244
245 val = value ? clone_str(value, "list value") : NULL;
246 if (!val)
247 return NULL;
248 end = val + strlen(val);
249 for (b = val, count = 0; b < end;)
250 {
251 for (e = b; ((*e != ' ') && (*e != '\0')); e++);
252 *e = '\0';
253 if (e != b)
254 count++;
255 b = e + 1;
256 }
257 if (count == 0)
258 {
259 pfree(val);
260 return NULL;
261 }
262 ret = (char **)alloc_bytes((count+1) * sizeof(char *), "list");
263
264 for (b = val, count = 0; b < end; )
265 {
266 for (e = b; (*e != '\0'); e++);
267 if (e != b)
268 ret[count++] = clone_str(b, "list value");
269 b = e + 1;
270 }
271 ret[count] = NULL;
272 pfree(val);
273 return ret;
274 }
275
276
277 /*
278 * assigns an argument value to a struct field
279 */
280 bool
281 assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base
282 , bool *assigned)
283 {
284 char *p = base + token_info[token].offset;
285 const char **list = token_info[token].list;
286
287 int index = -1; /* used for enumeration arguments */
288
289 lset_t *seen = (lset_t *)base; /* seen flags are at the top of the struct */
290 lset_t f = LELEM(token - first); /* compute flag position of argument */
291
292 *assigned = FALSE;
293
294 DBG(DBG_CONTROLMORE,
295 DBG_log(" %s=%s", kw->entry->name, kw->value)
296 )
297
298 if (*seen & f)
299 {
300 plog("# duplicate '%s' option", kw->entry->name);
301 return FALSE;
302 }
303
304 /* set flag that this argument has been seen */
305 *seen |= f;
306
307 /* is there a keyword list? */
308 if (list != NULL && token_info[token].type != ARG_LST)
309 {
310 bool match = FALSE;
311
312 while (*list != NULL && !match)
313 {
314 index++;
315 match = streq(kw->value, *list++);
316 }
317 if (!match)
318 {
319 plog("# bad value: %s=%s", kw->entry->name, kw->value);
320 return FALSE;
321 }
322 }
323
324 switch (token_info[token].type)
325 {
326 case ARG_NONE:
327 plog("# option '%s' not supported yet", kw->entry->name);
328 return FALSE;
329 case ARG_ENUM:
330 {
331 int *i = (int *)p;
332
333 if (index < 0)
334 {
335 plog("# bad enumeration value: %s=%s (%d)"
336 , kw->entry->name, kw->value, index);
337 return FALSE;
338 }
339 *i = index;
340 }
341 break;
342
343 case ARG_UINT:
344 {
345 char *endptr;
346 u_int *u = (u_int *)p;
347
348 *u = strtoul(kw->value, &endptr, 10);
349
350 if (*endptr != '\0')
351 {
352 plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
353 return FALSE;
354 }
355 }
356 break;
357 case ARG_ULNG:
358 case ARG_PCNT:
359 {
360 char *endptr;
361 unsigned long *l = (unsigned long *)p;
362
363 *l = strtoul(kw->value, &endptr, 10);
364
365 if (token_info[token].type == ARG_ULNG)
366 {
367 if (*endptr != '\0')
368 {
369 plog("# bad integer value: %s=%s", kw->entry->name, kw->value);
370 return FALSE;
371 }
372 }
373 else
374 {
375 if ((*endptr != '%') || (endptr[1] != '\0') || endptr == kw->value)
376 {
377 plog("# bad percent value: %s=%s", kw->entry->name, kw->value);
378 return FALSE;
379 }
380 }
381
382 }
383 break;
384 case ARG_TIME:
385 {
386 char *endptr;
387 time_t *t = (time_t *)p;
388
389 *t = strtoul(kw->value, &endptr, 10);
390
391 /* time in seconds? */
392 if (*endptr == '\0' || (*endptr == 's' && endptr[1] == '\0'))
393 break;
394
395 if (endptr[1] == '\0')
396 {
397 if (*endptr == 'm') /* time in minutes? */
398 {
399 *t *= 60;
400 break;
401 }
402 if (*endptr == 'h') /* time in hours? */
403 {
404 *t *= 3600;
405 break;
406 }
407 if (*endptr == 'd') /* time in days? */
408 {
409 *t *= 3600*24;
410 break;
411 }
412 }
413 plog("# bad duration value: %s=%s", kw->entry->name, kw->value);
414 return FALSE;
415 }
416 case ARG_STR:
417 {
418 char **cp = (char **)p;
419
420 /* free any existing string */
421 pfreeany(*cp);
422
423 /* assign the new string */
424 *cp = clone_str(kw->value, "str_value");
425 }
426 break;
427 case ARG_LST:
428 {
429 char ***listp = (char ***)p;
430
431 /* free any existing list */
432 if (*listp != NULL)
433 free_list(*listp);
434
435 /* create a new list and assign values */
436 *listp = new_list(kw->value);
437
438 /* is there a keyword list? */
439 if (list != NULL)
440 {
441 char ** lst;
442
443 for (lst = *listp; lst && *lst; lst++)
444 {
445 bool match = FALSE;
446
447 list = token_info[token].list;
448
449 while (*list != NULL && !match)
450 {
451 match = streq(*lst, *list++);
452 }
453 if (!match)
454 {
455 plog("# bad value: %s=%s", kw->entry->name, *lst);
456 return FALSE;
457 }
458 }
459 }
460 }
461 default:
462 return TRUE;
463 }
464
465 *assigned = TRUE;
466 return TRUE;
467 }
468
469 /*
470 * frees all dynamically allocated arguments in a struct
471 */
472 void
473 free_args(kw_token_t first, kw_token_t last, char *base)
474 {
475 kw_token_t token;
476
477 for (token = first; token <= last; token++)
478 {
479 char *p = base + token_info[token].offset;
480
481 switch (token_info[token].type)
482 {
483 case ARG_STR:
484 {
485 char **cp = (char **)p;
486
487 pfreeany(*cp);
488 *cp = NULL;
489 }
490 break;
491 case ARG_LST:
492 {
493 char ***listp = (char ***)p;
494
495 if (*listp != NULL)
496 {
497 free_list(*listp);
498 *listp = NULL;
499 }
500 }
501 break;
502 default:
503 break;
504 }
505 }
506 }
507
508 /*
509 * clone all dynamically allocated arguments in a struct
510 */
511 void
512 clone_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
513 {
514 kw_token_t token;
515
516 for (token = first; token <= last; token++)
517 {
518 if (token_info[token].type == ARG_STR)
519 {
520 char **cp1 = (char **)(base1 + token_info[token].offset);
521 char **cp2 = (char **)(base2 + token_info[token].offset);
522
523 *cp1 = clone_str(*cp2, "cloned str");
524 }
525 }
526 }
527
528 static bool
529 cmp_list(char **list1, char **list2)
530 {
531 if ((list1 == NULL) && (list2 == NULL))
532 return TRUE;
533 if ((list1 == NULL) || (list2 == NULL))
534 return FALSE;
535
536 for ( ; *list1 && *list2; list1++, list2++)
537 {
538 if (strcmp(*list1,*list2) != 0)
539 return FALSE;
540 }
541
542 if ((*list1 != NULL) || (*list2 != NULL))
543 return FALSE;
544
545 return TRUE;
546 }
547
548 /*
549 * compare all arguments in a struct
550 */
551 bool
552 cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
553 {
554 kw_token_t token;
555
556 for (token = first; token <= last; token++)
557 {
558 char *p1 = base1 + token_info[token].offset;
559 char *p2 = base2 + token_info[token].offset;
560
561 switch (token_info[token].type)
562 {
563 case ARG_ENUM:
564 {
565 int *i1 = (int *)p1;
566 int *i2 = (int *)p2;
567
568 if (*i1 != *i2)
569 return FALSE;
570 }
571 break;
572 case ARG_UINT:
573 {
574 u_int *u1 = (u_int *)p1;
575 u_int *u2 = (u_int *)p2;
576
577 if (*u1 != *u2)
578 return FALSE;
579 }
580 break;
581 case ARG_ULNG:
582 case ARG_PCNT:
583 {
584 unsigned long *l1 = (unsigned long *)p1;
585 unsigned long *l2 = (unsigned long *)p2;
586
587 if (*l1 != *l2)
588 return FALSE;
589 }
590 break;
591 case ARG_TIME:
592 {
593 time_t *t1 = (time_t *)p1;
594 time_t *t2 = (time_t *)p2;
595
596 if (*t1 != *t2)
597 return FALSE;
598 }
599 break;
600 case ARG_STR:
601 {
602 char **cp1 = (char **)p1;
603 char **cp2 = (char **)p2;
604
605 if (*cp1 == NULL && *cp2 == NULL)
606 break;
607 if (*cp1 == NULL || *cp2 == NULL || strcmp(*cp1, *cp2) != 0)
608 return FALSE;
609 }
610 break;
611 case ARG_LST:
612 {
613 char ***listp1 = (char ***)p1;
614 char ***listp2 = (char ***)p2;
615
616 if (!cmp_list(*listp1, *listp2))
617 return FALSE;
618 }
619 break;
620 default:
621 break;
622 }
623 }
624 return TRUE;
625 }