configure: Fix typo when enabling CPAN modules as dependency
[strongswan.git] / src / starter / args.c
1 /*
2 * Copyright (C) 2014 Tobias Brunner
3 * Copyright (C) 2006 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stddef.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include <library.h>
22 #include <utils/debug.h>
23
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, char *key, char *value,
225 void *base, bool *assigned)
226 {
227 char *p = (char*)base + token_info[token].offset;
228 const char **list = token_info[token].list;
229 int index = -1; /* used for enumeration arguments */
230
231 *assigned = FALSE;
232
233 DBG3(DBG_APP, " %s=%s", key, value);
234
235 /* is there a keyword list? */
236 if (list != NULL)
237 {
238 bool match = FALSE;
239
240 while (*list != NULL && !match)
241 {
242 index++;
243 match = streq(value, *list++);
244 }
245 if (!match)
246 {
247 DBG1(DBG_APP, "# bad value: %s=%s", key, value);
248 return FALSE;
249 }
250 }
251
252 switch (token_info[token].type)
253 {
254 case ARG_NONE:
255 DBG1(DBG_APP, "# option '%s' not supported yet", key);
256 return FALSE;
257 case ARG_ENUM:
258 {
259 if (index < 0)
260 {
261 DBG1(DBG_APP, "# bad enumeration value: %s=%s (%d)",
262 key, value, index);
263 return FALSE;
264 }
265
266 if (token_info[token].list == LST_bool)
267 {
268 bool *b = (bool *)p;
269 *b = (index > 0);
270 }
271 else
272 { /* FIXME: this is not entirely correct as the args are enums */
273 int *i = (int *)p;
274 *i = index;
275 }
276 break;
277 }
278 case ARG_UINT:
279 {
280 char *endptr;
281 u_int *u = (u_int *)p;
282
283 *u = strtoul(value, &endptr, 10);
284
285 if (*endptr != '\0')
286 {
287 DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
288 return FALSE;
289 }
290 break;
291 }
292 case ARG_ULNG:
293 case ARG_PCNT:
294 {
295 char *endptr;
296 unsigned long *l = (unsigned long *)p;
297
298 *l = strtoul(value, &endptr, 10);
299
300 if (token_info[token].type == ARG_ULNG)
301 {
302 if (*endptr != '\0')
303 {
304 DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
305 return FALSE;
306 }
307 }
308 else
309 {
310 if ((*endptr != '%') || (endptr[1] != '\0') || endptr == value)
311 {
312 DBG1(DBG_APP, "# bad percent value: %s=%s", key, value);
313 return FALSE;
314 }
315 }
316 break;
317 }
318 case ARG_ULLI:
319 {
320 char *endptr;
321 unsigned long long *ll = (unsigned long long *)p;
322
323 *ll = strtoull(value, &endptr, 10);
324
325 if (*endptr != '\0')
326 {
327 DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
328 return FALSE;
329 }
330 break;
331 }
332 case ARG_UBIN:
333 {
334 char *endptr;
335 u_int *u = (u_int *)p;
336
337 *u = strtoul(value, &endptr, 2);
338
339 if (*endptr != '\0')
340 {
341 DBG1(DBG_APP, "# bad binary value: %s=%s", key, value);
342 return FALSE;
343 }
344 break;
345 }
346 case ARG_TIME:
347 {
348 char *endptr;
349 time_t *t = (time_t *)p;
350
351 *t = strtoul(value, &endptr, 10);
352
353 /* time in seconds? */
354 if (*endptr == '\0' || (*endptr == 's' && endptr[1] == '\0'))
355 {
356 break;
357 }
358 if (endptr[1] == '\0')
359 {
360 if (*endptr == 'm') /* time in minutes? */
361 {
362 *t *= 60;
363 break;
364 }
365 if (*endptr == 'h') /* time in hours? */
366 {
367 *t *= 3600;
368 break;
369 }
370 if (*endptr == 'd') /* time in days? */
371 {
372 *t *= 3600*24;
373 break;
374 }
375 }
376 DBG1(DBG_APP, "# bad duration value: %s=%s", key, value);
377 return FALSE;
378 }
379 case ARG_STR:
380 {
381 char **cp = (char **)p;
382
383 /* free any existing string */
384 free(*cp);
385 /* assign the new string */
386 *cp = strdupnull(value);
387 break;
388 }
389 default:
390 return TRUE;
391 }
392
393 *assigned = TRUE;
394 return TRUE;
395 }
396
397 /*
398 * frees all dynamically allocated arguments in a struct
399 */
400 void free_args(kw_token_t first, kw_token_t last, void *base)
401 {
402 kw_token_t token;
403
404 for (token = first; token <= last; token++)
405 {
406 char *p = (char*)base + token_info[token].offset;
407
408 switch (token_info[token].type)
409 {
410 case ARG_STR:
411 {
412 char **cp = (char **)p;
413
414 free(*cp);
415 *cp = NULL;
416 break;
417 }
418 default:
419 break;
420 }
421 }
422 }
423
424 /*
425 * compare all arguments in a struct
426 */
427 bool cmp_args(kw_token_t first, kw_token_t last, void *base1, void *base2)
428 {
429 kw_token_t token;
430
431 for (token = first; token <= last; token++)
432 {
433 char *p1 = (char*)base1 + token_info[token].offset;
434 char *p2 = (char*)base2 + token_info[token].offset;
435
436 switch (token_info[token].type)
437 {
438 case ARG_ENUM:
439 {
440 if (token_info[token].list == LST_bool)
441 {
442 bool *b1 = (bool *)p1;
443 bool *b2 = (bool *)p2;
444
445 if (*b1 != *b2)
446 {
447 return FALSE;
448 }
449 }
450 else
451 {
452 int *i1 = (int *)p1;
453 int *i2 = (int *)p2;
454
455 if (*i1 != *i2)
456 {
457 return FALSE;
458 }
459 }
460 break;
461 }
462 case ARG_UINT:
463 {
464 u_int *u1 = (u_int *)p1;
465 u_int *u2 = (u_int *)p2;
466
467 if (*u1 != *u2)
468 {
469 return FALSE;
470 }
471 break;
472 }
473 case ARG_ULNG:
474 case ARG_PCNT:
475 {
476 unsigned long *l1 = (unsigned long *)p1;
477 unsigned long *l2 = (unsigned long *)p2;
478
479 if (*l1 != *l2)
480 {
481 return FALSE;
482 }
483 break;
484 }
485 case ARG_ULLI:
486 {
487 unsigned long long *ll1 = (unsigned long long *)p1;
488 unsigned long long *ll2 = (unsigned long long *)p2;
489
490 if (*ll1 != *ll2)
491 {
492 return FALSE;
493 }
494 break;
495 }
496 case ARG_TIME:
497 {
498 time_t *t1 = (time_t *)p1;
499 time_t *t2 = (time_t *)p2;
500
501 if (*t1 != *t2)
502 {
503 return FALSE;
504 }
505 break;
506 }
507 case ARG_STR:
508 {
509 char **cp1 = (char **)p1;
510 char **cp2 = (char **)p2;
511
512 if (*cp1 == NULL && *cp2 == NULL)
513 {
514 break;
515 }
516 if (*cp1 == NULL || *cp2 == NULL || strcmp(*cp1, *cp2) != 0)
517 {
518 return FALSE;
519 }
520 break;
521 }
522 default:
523 break;
524 }
525 }
526 return TRUE;
527 }