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