starter: Remove unused ARG_LST argument type
[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 <library.h>
21 #include <utils/debug.h>
22
23 #include "keywords.h"
24 #include "confread.h"
25 #include "args.h"
26
27 /* argument types */
28
29 typedef enum {
30 ARG_NONE,
31 ARG_ENUM,
32 ARG_UINT,
33 ARG_TIME,
34 ARG_ULNG,
35 ARG_ULLI,
36 ARG_UBIN,
37 ARG_PCNT,
38 ARG_STR,
39 ARG_MISC
40 } arg_t;
41
42 /* various keyword lists */
43
44 static const char *LST_bool[] = {
45 "no",
46 "yes",
47 NULL
48 };
49
50 static const char *LST_sendcert[] = {
51 "always",
52 "ifasked",
53 "never",
54 "yes",
55 "no",
56 NULL
57 };
58
59 static const char *LST_unique[] = {
60 "no",
61 "yes",
62 "replace",
63 "keep",
64 "never",
65 NULL
66 };
67
68 static const char *LST_strict[] = {
69 "no",
70 "yes",
71 "ifuri",
72 NULL
73 };
74 static const char *LST_dpd_action[] = {
75 "none",
76 "clear",
77 "hold",
78 "restart",
79 NULL
80 };
81
82 static const char *LST_startup[] = {
83 "ignore",
84 "add",
85 "route",
86 "start",
87 NULL
88 };
89
90 static const char *LST_keyexchange[] = {
91 "ike",
92 "ikev1",
93 "ikev2",
94 NULL
95 };
96
97 static const char *LST_authby[] = {
98 "psk",
99 "secret",
100 "pubkey",
101 "rsa",
102 "rsasig",
103 "ecdsa",
104 "ecdsasig",
105 "xauthpsk",
106 "xauthrsasig",
107 "never",
108 NULL
109 };
110
111 static const char *LST_fragmentation[] = {
112 "no",
113 "yes",
114 "force",
115 NULL
116 };
117
118 typedef struct {
119 arg_t type;
120 size_t offset;
121 const char **list;
122 } token_info_t;
123
124 static const token_info_t token_info[] =
125 {
126 /* config setup keywords */
127 { ARG_STR, offsetof(starter_config_t, setup.charondebug), NULL },
128 { ARG_ENUM, offsetof(starter_config_t, setup.uniqueids), LST_unique },
129 { ARG_ENUM, offsetof(starter_config_t, setup.cachecrls), LST_bool },
130 { ARG_ENUM, offsetof(starter_config_t, setup.strictcrlpolicy), LST_strict },
131 { ARG_MISC, 0, NULL /* KW_PKCS11_DEPRECATED */ },
132 { ARG_MISC, 0, NULL /* KW_SETUP_DEPRECATED */ },
133
134 /* conn section keywords */
135 { ARG_STR, offsetof(starter_conn_t, name), NULL },
136 { ARG_ENUM, offsetof(starter_conn_t, startup), LST_startup },
137 { ARG_ENUM, offsetof(starter_conn_t, keyexchange), LST_keyexchange },
138 { ARG_MISC, 0, NULL /* KW_TYPE */ },
139 { ARG_MISC, 0, NULL /* KW_COMPRESS */ },
140 { ARG_ENUM, offsetof(starter_conn_t, install_policy), LST_bool },
141 { ARG_ENUM, offsetof(starter_conn_t, aggressive), LST_bool },
142 { ARG_STR, offsetof(starter_conn_t, authby), LST_authby },
143 { ARG_STR, offsetof(starter_conn_t, eap_identity), NULL },
144 { ARG_STR, offsetof(starter_conn_t, aaa_identity), NULL },
145 { ARG_MISC, 0, NULL /* KW_MOBIKE */ },
146 { ARG_MISC, 0, NULL /* KW_FORCEENCAPS */ },
147 { ARG_ENUM, offsetof(starter_conn_t, fragmentation), LST_fragmentation },
148 { ARG_UBIN, offsetof(starter_conn_t, ikedscp), NULL },
149 { ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL },
150 { ARG_TIME, offsetof(starter_conn_t, sa_ipsec_life_seconds), NULL },
151 { ARG_TIME, offsetof(starter_conn_t, sa_rekey_margin), NULL },
152 { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_life_bytes), NULL },
153 { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_margin_bytes), NULL },
154 { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_life_packets), NULL },
155 { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_margin_packets), NULL },
156 { ARG_MISC, 0, NULL /* KW_KEYINGTRIES */ },
157 { ARG_PCNT, offsetof(starter_conn_t, sa_rekey_fuzz), NULL },
158 { ARG_MISC, 0, NULL /* KW_REKEY */ },
159 { ARG_MISC, 0, NULL /* KW_REAUTH */ },
160 { ARG_STR, offsetof(starter_conn_t, ike), NULL },
161 { ARG_STR, offsetof(starter_conn_t, esp), NULL },
162 { ARG_STR, offsetof(starter_conn_t, ah), NULL },
163 { ARG_TIME, offsetof(starter_conn_t, dpd_delay), NULL },
164 { ARG_TIME, offsetof(starter_conn_t, dpd_timeout), NULL },
165 { ARG_ENUM, offsetof(starter_conn_t, dpd_action), LST_dpd_action },
166 { ARG_ENUM, offsetof(starter_conn_t, close_action), LST_dpd_action },
167 { ARG_TIME, offsetof(starter_conn_t, inactivity), NULL },
168 { ARG_MISC, 0, NULL /* KW_MODECONFIG */ },
169 { ARG_MISC, 0, NULL /* KW_XAUTH */ },
170 { ARG_STR, offsetof(starter_conn_t, xauth_identity), NULL },
171 { ARG_ENUM, offsetof(starter_conn_t, me_mediation), LST_bool },
172 { ARG_STR, offsetof(starter_conn_t, me_mediated_by), NULL },
173 { ARG_STR, offsetof(starter_conn_t, me_peerid), NULL },
174 { ARG_UINT, offsetof(starter_conn_t, reqid), NULL },
175 { ARG_UINT, offsetof(starter_conn_t, replay_window), NULL },
176 { ARG_MISC, 0, NULL /* KW_MARK */ },
177 { ARG_MISC, 0, NULL /* KW_MARK_IN */ },
178 { ARG_MISC, 0, NULL /* KW_MARK_OUT */ },
179 { ARG_MISC, 0, NULL /* KW_TFC */ },
180 { ARG_MISC, 0, NULL /* KW_PFS_DEPRECATED */ },
181 { ARG_MISC, 0, NULL /* KW_CONN_DEPRECATED */ },
182
183 /* ca section keywords */
184 { ARG_STR, offsetof(starter_ca_t, name), NULL },
185 { ARG_ENUM, offsetof(starter_ca_t, startup), LST_startup },
186 { ARG_STR, offsetof(starter_ca_t, cacert), NULL },
187 { ARG_STR, offsetof(starter_ca_t, crluri), NULL },
188 { ARG_STR, offsetof(starter_ca_t, crluri2), NULL },
189 { ARG_STR, offsetof(starter_ca_t, ocspuri), NULL },
190 { ARG_STR, offsetof(starter_ca_t, ocspuri2), NULL },
191 { ARG_STR, offsetof(starter_ca_t, certuribase), NULL },
192 { ARG_MISC, 0, NULL /* KW_CA_DEPRECATED */ },
193
194 /* end keywords */
195 { ARG_STR, offsetof(starter_end_t, host), NULL },
196 { ARG_UINT, offsetof(starter_end_t, ikeport), NULL },
197 { ARG_STR, offsetof(starter_end_t, subnet), NULL },
198 { ARG_MISC, 0, NULL /* KW_PROTOPORT */ },
199 { ARG_STR, offsetof(starter_end_t, sourceip), NULL },
200 { ARG_STR, offsetof(starter_end_t, dns), NULL },
201 { ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool },
202 { ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
203 { ARG_ENUM, offsetof(starter_end_t, allow_any), LST_bool },
204 { ARG_STR, offsetof(starter_end_t, updown), NULL },
205 { ARG_STR, offsetof(starter_end_t, auth), NULL },
206 { ARG_STR, offsetof(starter_end_t, auth2), NULL },
207 { ARG_STR, offsetof(starter_end_t, id), NULL },
208 { ARG_STR, offsetof(starter_end_t, id2), NULL },
209 { ARG_STR, offsetof(starter_end_t, rsakey), NULL },
210 { ARG_STR, offsetof(starter_end_t, cert), NULL },
211 { ARG_STR, offsetof(starter_end_t, cert2), NULL },
212 { ARG_STR, offsetof(starter_end_t, cert_policy), NULL },
213 { ARG_ENUM, offsetof(starter_end_t, sendcert), LST_sendcert },
214 { ARG_STR, offsetof(starter_end_t, ca), NULL },
215 { ARG_STR, offsetof(starter_end_t, ca2), NULL },
216 { ARG_STR, offsetof(starter_end_t, groups), NULL },
217 { ARG_STR, offsetof(starter_end_t, groups2), NULL },
218 { ARG_MISC, 0, NULL /* KW_END_DEPRECATED */ },
219 };
220
221 /*
222 * assigns an argument value to a struct field
223 */
224 bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
225 bool *assigned)
226 {
227 char *p = base + token_info[token].offset;
228 const char **list = token_info[token].list;
229
230 int index = -1; /* used for enumeration arguments */
231
232 seen_t *seen = (seen_t*)base; /* seen flags are at the top of the struct */
233
234 *assigned = FALSE;
235
236 DBG3(DBG_APP, " %s=%s", kw->entry->name, kw->value);
237
238 if (*seen & SEEN_KW(token, first))
239 {
240 DBG1(DBG_APP, "# duplicate '%s' option", kw->entry->name);
241 return FALSE;
242 }
243
244 if (token == KW_ESP || token == KW_AH)
245 {
246 if (*seen & (SEEN_KW(KW_ESP, first) | SEEN_KW(KW_AH, first)))
247 {
248 DBG1(DBG_APP, "# can't have both 'ah' and 'esp' options");
249 return FALSE;
250 }
251 }
252
253 /* set flag that this argument has been seen */
254 *seen |= SEEN_KW(token, first);
255
256 /* is there a keyword list? */
257 if (list != NULL)
258 {
259 bool match = FALSE;
260
261 while (*list != NULL && !match)
262 {
263 index++;
264 match = streq(kw->value, *list++);
265 }
266 if (!match)
267 {
268 DBG1(DBG_APP, "# bad value: %s=%s", kw->entry->name, kw->value);
269 return FALSE;
270 }
271 }
272
273 switch (token_info[token].type)
274 {
275 case ARG_NONE:
276 DBG1(DBG_APP, "# option '%s' not supported yet", kw->entry->name);
277 return FALSE;
278 case ARG_ENUM:
279 {
280 if (index < 0)
281 {
282 DBG1(DBG_APP, "# bad enumeration value: %s=%s (%d)",
283 kw->entry->name, kw->value, index);
284 return FALSE;
285 }
286
287 if (token_info[token].list == LST_bool)
288 {
289 bool *b = (bool *)p;
290 *b = (index > 0);
291 }
292 else
293 {
294 int *i = (int *)p;
295 *i = index;
296 }
297 }
298 break;
299
300 case ARG_UINT:
301 {
302 char *endptr;
303 u_int *u = (u_int *)p;
304
305 *u = strtoul(kw->value, &endptr, 10);
306
307 if (*endptr != '\0')
308 {
309 DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
310 kw->value);
311 return FALSE;
312 }
313 }
314 break;
315 case ARG_ULNG:
316 case ARG_PCNT:
317 {
318 char *endptr;
319 unsigned long *l = (unsigned long *)p;
320
321 *l = strtoul(kw->value, &endptr, 10);
322
323 if (token_info[token].type == ARG_ULNG)
324 {
325 if (*endptr != '\0')
326 {
327 DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
328 kw->value);
329 return FALSE;
330 }
331 }
332 else
333 {
334 if ((*endptr != '%') || (endptr[1] != '\0') || endptr == kw->value)
335 {
336 DBG1(DBG_APP, "# bad percent value: %s=%s", kw->entry->name,
337 kw->value);
338 return FALSE;
339 }
340 }
341
342 }
343 break;
344 case ARG_ULLI:
345 {
346 char *endptr;
347 unsigned long long *ll = (unsigned long long *)p;
348
349 *ll = strtoull(kw->value, &endptr, 10);
350
351 if (*endptr != '\0')
352 {
353 DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
354 kw->value);
355 return FALSE;
356 }
357 }
358 break;
359 case ARG_UBIN:
360 {
361 char *endptr;
362 u_int *u = (u_int *)p;
363
364 *u = strtoul(kw->value, &endptr, 2);
365
366 if (*endptr != '\0')
367 {
368 DBG1(DBG_APP, "# bad binary value: %s=%s", kw->entry->name,
369 kw->value);
370 return FALSE;
371 }
372 }
373 break;
374 case ARG_TIME:
375 {
376 char *endptr;
377 time_t *t = (time_t *)p;
378
379 *t = strtoul(kw->value, &endptr, 10);
380
381 /* time in seconds? */
382 if (*endptr == '\0' || (*endptr == 's' && endptr[1] == '\0'))
383 {
384 break;
385 }
386 if (endptr[1] == '\0')
387 {
388 if (*endptr == 'm') /* time in minutes? */
389 {
390 *t *= 60;
391 break;
392 }
393 if (*endptr == 'h') /* time in hours? */
394 {
395 *t *= 3600;
396 break;
397 }
398 if (*endptr == 'd') /* time in days? */
399 {
400 *t *= 3600*24;
401 break;
402 }
403 }
404 DBG1(DBG_APP, "# bad duration value: %s=%s", kw->entry->name,
405 kw->value);
406 return FALSE;
407 }
408 case ARG_STR:
409 {
410 char **cp = (char **)p;
411
412 /* free any existing string */
413 free(*cp);
414
415 /* assign the new string */
416 *cp = strdupnull(kw->value);
417 break;
418 }
419 default:
420 return TRUE;
421 }
422
423 *assigned = TRUE;
424 return TRUE;
425 }
426
427 /*
428 * frees all dynamically allocated arguments in a struct
429 */
430 void free_args(kw_token_t first, kw_token_t last, char *base)
431 {
432 kw_token_t token;
433
434 for (token = first; token <= last; token++)
435 {
436 char *p = base + token_info[token].offset;
437
438 switch (token_info[token].type)
439 {
440 case ARG_STR:
441 {
442 char **cp = (char **)p;
443
444 free(*cp);
445 *cp = NULL;
446 }
447 break;
448 default:
449 break;
450 }
451 }
452 }
453
454 /*
455 * clone all dynamically allocated arguments in a struct
456 */
457 void clone_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
458 {
459 kw_token_t token;
460
461 for (token = first; token <= last; token++)
462 {
463 if (token_info[token].type == ARG_STR)
464 {
465 char **cp1 = (char **)(base1 + token_info[token].offset);
466 char **cp2 = (char **)(base2 + token_info[token].offset);
467
468 *cp1 = strdupnull(*cp2);
469 }
470 }
471 }
472
473 /*
474 * compare all arguments in a struct
475 */
476 bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
477 {
478 kw_token_t token;
479
480 for (token = first; token <= last; token++)
481 {
482 char *p1 = base1 + token_info[token].offset;
483 char *p2 = base2 + token_info[token].offset;
484
485 switch (token_info[token].type)
486 {
487 case ARG_ENUM:
488 if (token_info[token].list == LST_bool)
489 {
490 bool *b1 = (bool *)p1;
491 bool *b2 = (bool *)p2;
492
493 if (*b1 != *b2)
494 {
495 return FALSE;
496 }
497 }
498 else
499 {
500 int *i1 = (int *)p1;
501 int *i2 = (int *)p2;
502
503 if (*i1 != *i2)
504 {
505 return FALSE;
506 }
507 }
508 break;
509 case ARG_UINT:
510 {
511 u_int *u1 = (u_int *)p1;
512 u_int *u2 = (u_int *)p2;
513
514 if (*u1 != *u2)
515 {
516 return FALSE;
517 }
518 }
519 break;
520 case ARG_ULNG:
521 case ARG_PCNT:
522 {
523 unsigned long *l1 = (unsigned long *)p1;
524 unsigned long *l2 = (unsigned long *)p2;
525
526 if (*l1 != *l2)
527 {
528 return FALSE;
529 }
530 }
531 break;
532 case ARG_ULLI:
533 {
534 unsigned long long *ll1 = (unsigned long long *)p1;
535 unsigned long long *ll2 = (unsigned long long *)p2;
536
537 if (*ll1 != *ll2)
538 {
539 return FALSE;
540 }
541 }
542 break;
543 case ARG_TIME:
544 {
545 time_t *t1 = (time_t *)p1;
546 time_t *t2 = (time_t *)p2;
547
548 if (*t1 != *t2)
549 {
550 return FALSE;
551 }
552 }
553 break;
554 case ARG_STR:
555 {
556 char **cp1 = (char **)p1;
557 char **cp2 = (char **)p2;
558
559 if (*cp1 == NULL && *cp2 == NULL)
560 {
561 break;
562 }
563 if (*cp1 == NULL || *cp2 == NULL || strcmp(*cp1, *cp2) != 0)
564 {
565 return FALSE;
566 }
567 }
568 break;
569 default:
570 break;
571 }
572 }
573 return TRUE;
574 }