pkcs7: Allow for missing optional content field
[strongswan.git] / src / starter / args.c
1 /*
2 * Copyright (C) 2014 Tobias Brunner
3 * Copyright (C) 2006 Andreas Steffen
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 "confread.h"
24 #include "args.h"
25
26 /* argument types */
27
28 typedef enum {
29 ARG_NONE,
30 ARG_ENUM,
31 ARG_UINT,
32 ARG_TIME,
33 ARG_ULNG,
34 ARG_ULLI,
35 ARG_UBIN,
36 ARG_PCNT,
37 ARG_STR,
38 ARG_MISC
39 } arg_t;
40
41 /* various keyword lists */
42
43 static const char *LST_bool[] = {
44 "no",
45 "yes",
46 NULL
47 };
48
49 static const char *LST_sendcert[] = {
50 "always",
51 "ifasked",
52 "never",
53 "yes",
54 "no",
55 NULL
56 };
57
58 static const char *LST_unique[] = {
59 "no",
60 "yes",
61 "replace",
62 "keep",
63 "never",
64 NULL
65 };
66
67 static const char *LST_strict[] = {
68 "no",
69 "yes",
70 "ifuri",
71 NULL
72 };
73 static const char *LST_dpd_action[] = {
74 "none",
75 "clear",
76 "hold",
77 "restart",
78 NULL
79 };
80
81 static const char *LST_startup[] = {
82 "ignore",
83 "add",
84 "route",
85 "start",
86 NULL
87 };
88
89 static const char *LST_keyexchange[] = {
90 "ike",
91 "ikev1",
92 "ikev2",
93 NULL
94 };
95
96 static const char *LST_authby[] = {
97 "psk",
98 "secret",
99 "pubkey",
100 "rsa",
101 "rsasig",
102 "ecdsa",
103 "ecdsasig",
104 "xauthpsk",
105 "xauthrsasig",
106 "never",
107 NULL
108 };
109
110 static const char *LST_fragmentation[] = {
111 "no",
112 "accept",
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_ENUM, offsetof(starter_conn_t, sha256_96), LST_bool },
168 { ARG_TIME, offsetof(starter_conn_t, inactivity), NULL },
169 { ARG_MISC, 0, NULL /* KW_MODECONFIG */ },
170 { ARG_MISC, 0, NULL /* KW_XAUTH */ },
171 { ARG_STR, offsetof(starter_conn_t, xauth_identity), NULL },
172 { ARG_ENUM, offsetof(starter_conn_t, me_mediation), LST_bool },
173 { ARG_STR, offsetof(starter_conn_t, me_mediated_by), NULL },
174 { ARG_STR, offsetof(starter_conn_t, me_peerid), NULL },
175 { ARG_UINT, offsetof(starter_conn_t, reqid), NULL },
176 { ARG_UINT, offsetof(starter_conn_t, replay_window), NULL },
177 { ARG_MISC, 0, NULL /* KW_MARK */ },
178 { ARG_MISC, 0, NULL /* KW_MARK_IN */ },
179 { ARG_MISC, 0, NULL /* KW_MARK_OUT */ },
180 { ARG_MISC, 0, NULL /* KW_TFC */ },
181 { ARG_MISC, 0, NULL /* KW_PFS_DEPRECATED */ },
182 { ARG_MISC, 0, NULL /* KW_CONN_DEPRECATED */ },
183
184 /* ca section keywords */
185 { ARG_STR, offsetof(starter_ca_t, name), NULL },
186 { ARG_ENUM, offsetof(starter_ca_t, startup), LST_startup },
187 { ARG_STR, offsetof(starter_ca_t, cacert), NULL },
188 { ARG_STR, offsetof(starter_ca_t, crluri), NULL },
189 { ARG_STR, offsetof(starter_ca_t, crluri2), NULL },
190 { ARG_STR, offsetof(starter_ca_t, ocspuri), NULL },
191 { ARG_STR, offsetof(starter_ca_t, ocspuri2), NULL },
192 { ARG_STR, offsetof(starter_ca_t, certuribase), NULL },
193 { ARG_MISC, 0, NULL /* KW_CA_DEPRECATED */ },
194
195 /* end keywords */
196 { ARG_STR, offsetof(starter_end_t, host), NULL },
197 { ARG_UINT, offsetof(starter_end_t, ikeport), NULL },
198 { ARG_STR, offsetof(starter_end_t, subnet), NULL },
199 { ARG_MISC, 0, NULL /* KW_PROTOPORT */ },
200 { ARG_STR, offsetof(starter_end_t, sourceip), NULL },
201 { ARG_STR, offsetof(starter_end_t, dns), NULL },
202 { ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool },
203 { ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
204 { ARG_ENUM, offsetof(starter_end_t, allow_any), LST_bool },
205 { ARG_STR, offsetof(starter_end_t, updown), NULL },
206 { ARG_STR, offsetof(starter_end_t, auth), NULL },
207 { ARG_STR, offsetof(starter_end_t, auth2), NULL },
208 { ARG_STR, offsetof(starter_end_t, id), NULL },
209 { ARG_STR, offsetof(starter_end_t, id2), NULL },
210 { ARG_STR, offsetof(starter_end_t, rsakey), NULL },
211 { ARG_STR, offsetof(starter_end_t, cert), NULL },
212 { ARG_STR, offsetof(starter_end_t, cert2), NULL },
213 { ARG_STR, offsetof(starter_end_t, cert_policy), NULL },
214 { ARG_ENUM, offsetof(starter_end_t, sendcert), LST_sendcert },
215 { ARG_STR, offsetof(starter_end_t, ca), NULL },
216 { ARG_STR, offsetof(starter_end_t, ca2), NULL },
217 { ARG_STR, offsetof(starter_end_t, groups), NULL },
218 { ARG_STR, offsetof(starter_end_t, groups2), NULL },
219 { ARG_MISC, 0, NULL /* KW_END_DEPRECATED */ },
220 };
221
222 /*
223 * assigns an argument value to a struct field
224 */
225 bool assign_arg(kw_token_t token, kw_token_t first, char *key, char *value,
226 void *base, bool *assigned)
227 {
228 char *p = (char*)base + token_info[token].offset;
229 const char **list = token_info[token].list;
230 int index = -1; /* used for enumeration arguments */
231
232 *assigned = FALSE;
233
234 DBG3(DBG_APP, " %s=%s", key, value);
235
236 /* is there a keyword list? */
237 if (list != NULL)
238 {
239 bool match = FALSE;
240
241 while (*list != NULL && !match)
242 {
243 index++;
244 match = streq(value, *list++);
245 }
246 if (!match)
247 {
248 DBG1(DBG_APP, "# bad value: %s=%s", key, value);
249 return FALSE;
250 }
251 }
252
253 switch (token_info[token].type)
254 {
255 case ARG_NONE:
256 DBG1(DBG_APP, "# option '%s' not supported yet", key);
257 return FALSE;
258 case ARG_ENUM:
259 {
260 if (index < 0)
261 {
262 DBG1(DBG_APP, "# bad enumeration value: %s=%s (%d)",
263 key, value, index);
264 return FALSE;
265 }
266
267 if (token_info[token].list == LST_bool)
268 {
269 bool *b = (bool *)p;
270 *b = (index > 0);
271 }
272 else
273 { /* FIXME: this is not entirely correct as the args are enums */
274 int *i = (int *)p;
275 *i = index;
276 }
277 break;
278 }
279 case ARG_UINT:
280 {
281 char *endptr;
282 u_int *u = (u_int *)p;
283
284 *u = strtoul(value, &endptr, 10);
285
286 if (*endptr != '\0')
287 {
288 DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
289 return FALSE;
290 }
291 break;
292 }
293 case ARG_ULNG:
294 case ARG_PCNT:
295 {
296 char *endptr;
297 unsigned long *l = (unsigned long *)p;
298
299 *l = strtoul(value, &endptr, 10);
300
301 if (token_info[token].type == ARG_ULNG)
302 {
303 if (*endptr != '\0')
304 {
305 DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
306 return FALSE;
307 }
308 }
309 else
310 {
311 if ((*endptr != '%') || (endptr[1] != '\0') || endptr == value)
312 {
313 DBG1(DBG_APP, "# bad percent value: %s=%s", key, value);
314 return FALSE;
315 }
316 }
317 break;
318 }
319 case ARG_ULLI:
320 {
321 char *endptr;
322 unsigned long long *ll = (unsigned long long *)p;
323
324 *ll = strtoull(value, &endptr, 10);
325
326 if (*endptr != '\0')
327 {
328 DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
329 return FALSE;
330 }
331 break;
332 }
333 case ARG_UBIN:
334 {
335 char *endptr;
336 u_int *u = (u_int *)p;
337
338 *u = strtoul(value, &endptr, 2);
339
340 if (*endptr != '\0')
341 {
342 DBG1(DBG_APP, "# bad binary value: %s=%s", key, value);
343 return FALSE;
344 }
345 break;
346 }
347 case ARG_TIME:
348 {
349 char *endptr;
350 time_t *t = (time_t *)p;
351
352 *t = strtoul(value, &endptr, 10);
353
354 /* time in seconds? */
355 if (*endptr == '\0' || (*endptr == 's' && endptr[1] == '\0'))
356 {
357 break;
358 }
359 if (endptr[1] == '\0')
360 {
361 if (*endptr == 'm') /* time in minutes? */
362 {
363 *t *= 60;
364 break;
365 }
366 if (*endptr == 'h') /* time in hours? */
367 {
368 *t *= 3600;
369 break;
370 }
371 if (*endptr == 'd') /* time in days? */
372 {
373 *t *= 3600*24;
374 break;
375 }
376 }
377 DBG1(DBG_APP, "# bad duration value: %s=%s", key, value);
378 return FALSE;
379 }
380 case ARG_STR:
381 {
382 char **cp = (char **)p;
383
384 /* free any existing string */
385 free(*cp);
386 /* assign the new string */
387 *cp = strdupnull(value);
388 break;
389 }
390 default:
391 return TRUE;
392 }
393
394 *assigned = TRUE;
395 return TRUE;
396 }
397
398 /*
399 * frees all dynamically allocated arguments in a struct
400 */
401 void free_args(kw_token_t first, kw_token_t last, void *base)
402 {
403 kw_token_t token;
404
405 for (token = first; token <= last; token++)
406 {
407 char *p = (char*)base + token_info[token].offset;
408
409 switch (token_info[token].type)
410 {
411 case ARG_STR:
412 {
413 char **cp = (char **)p;
414
415 free(*cp);
416 *cp = NULL;
417 break;
418 }
419 default:
420 break;
421 }
422 }
423 }
424
425 /*
426 * compare all arguments in a struct
427 */
428 bool cmp_args(kw_token_t first, kw_token_t last, void *base1, void *base2)
429 {
430 kw_token_t token;
431
432 for (token = first; token <= last; token++)
433 {
434 char *p1 = (char*)base1 + token_info[token].offset;
435 char *p2 = (char*)base2 + token_info[token].offset;
436
437 switch (token_info[token].type)
438 {
439 case ARG_ENUM:
440 {
441 if (token_info[token].list == LST_bool)
442 {
443 bool *b1 = (bool *)p1;
444 bool *b2 = (bool *)p2;
445
446 if (*b1 != *b2)
447 {
448 return FALSE;
449 }
450 }
451 else
452 {
453 int *i1 = (int *)p1;
454 int *i2 = (int *)p2;
455
456 if (*i1 != *i2)
457 {
458 return FALSE;
459 }
460 }
461 break;
462 }
463 case ARG_UINT:
464 {
465 u_int *u1 = (u_int *)p1;
466 u_int *u2 = (u_int *)p2;
467
468 if (*u1 != *u2)
469 {
470 return FALSE;
471 }
472 break;
473 }
474 case ARG_ULNG:
475 case ARG_PCNT:
476 {
477 unsigned long *l1 = (unsigned long *)p1;
478 unsigned long *l2 = (unsigned long *)p2;
479
480 if (*l1 != *l2)
481 {
482 return FALSE;
483 }
484 break;
485 }
486 case ARG_ULLI:
487 {
488 unsigned long long *ll1 = (unsigned long long *)p1;
489 unsigned long long *ll2 = (unsigned long long *)p2;
490
491 if (*ll1 != *ll2)
492 {
493 return FALSE;
494 }
495 break;
496 }
497 case ARG_TIME:
498 {
499 time_t *t1 = (time_t *)p1;
500 time_t *t2 = (time_t *)p2;
501
502 if (*t1 != *t2)
503 {
504 return FALSE;
505 }
506 break;
507 }
508 case ARG_STR:
509 {
510 char **cp1 = (char **)p1;
511 char **cp2 = (char **)p2;
512
513 if (*cp1 == NULL && *cp2 == NULL)
514 {
515 break;
516 }
517 if (*cp1 == NULL || *cp2 == NULL || strcmp(*cp1, *cp2) != 0)
518 {
519 return FALSE;
520 }
521 break;
522 }
523 default:
524 break;
525 }
526 }
527 return TRUE;
528 }