Return to args.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / starter |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2014 Tobias Brunner ! 3: * Copyright (C) 2006 Andreas Steffen ! 4: * HSR 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: "accept", ! 114: "yes", ! 115: "force", ! 116: NULL ! 117: }; ! 118: ! 119: typedef struct { ! 120: arg_t type; ! 121: size_t offset; ! 122: const char **list; ! 123: } token_info_t; ! 124: ! 125: static const token_info_t token_info[] = ! 126: { ! 127: /* config setup keywords */ ! 128: { ARG_STR, offsetof(starter_config_t, setup.charondebug), NULL }, ! 129: { ARG_ENUM, offsetof(starter_config_t, setup.uniqueids), LST_unique }, ! 130: { ARG_ENUM, offsetof(starter_config_t, setup.cachecrls), LST_bool }, ! 131: { ARG_ENUM, offsetof(starter_config_t, setup.strictcrlpolicy), LST_strict }, ! 132: { ARG_MISC, 0, NULL /* KW_PKCS11_DEPRECATED */ }, ! 133: { ARG_MISC, 0, NULL /* KW_SETUP_DEPRECATED */ }, ! 134: ! 135: /* conn section keywords */ ! 136: { ARG_STR, offsetof(starter_conn_t, name), NULL }, ! 137: { ARG_ENUM, offsetof(starter_conn_t, startup), LST_startup }, ! 138: { ARG_ENUM, offsetof(starter_conn_t, keyexchange), LST_keyexchange }, ! 139: { ARG_MISC, 0, NULL /* KW_TYPE */ }, ! 140: { ARG_MISC, 0, NULL /* KW_COMPRESS */ }, ! 141: { ARG_ENUM, offsetof(starter_conn_t, install_policy), LST_bool }, ! 142: { ARG_ENUM, offsetof(starter_conn_t, aggressive), LST_bool }, ! 143: { ARG_STR, offsetof(starter_conn_t, authby), LST_authby }, ! 144: { ARG_STR, offsetof(starter_conn_t, eap_identity), NULL }, ! 145: { ARG_STR, offsetof(starter_conn_t, aaa_identity), NULL }, ! 146: { ARG_MISC, 0, NULL /* KW_MOBIKE */ }, ! 147: { ARG_MISC, 0, NULL /* KW_FORCEENCAPS */ }, ! 148: { ARG_ENUM, offsetof(starter_conn_t, fragmentation), LST_fragmentation }, ! 149: { ARG_UBIN, offsetof(starter_conn_t, ikedscp), NULL }, ! 150: { ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL }, ! 151: { ARG_TIME, offsetof(starter_conn_t, sa_ipsec_life_seconds), NULL }, ! 152: { ARG_TIME, offsetof(starter_conn_t, sa_rekey_margin), NULL }, ! 153: { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_life_bytes), NULL }, ! 154: { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_margin_bytes), NULL }, ! 155: { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_life_packets), NULL }, ! 156: { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_margin_packets), NULL }, ! 157: { ARG_MISC, 0, NULL /* KW_KEYINGTRIES */ }, ! 158: { ARG_PCNT, offsetof(starter_conn_t, sa_rekey_fuzz), NULL }, ! 159: { ARG_MISC, 0, NULL /* KW_REKEY */ }, ! 160: { ARG_MISC, 0, NULL /* KW_REAUTH */ }, ! 161: { ARG_STR, offsetof(starter_conn_t, ike), NULL }, ! 162: { ARG_STR, offsetof(starter_conn_t, esp), NULL }, ! 163: { ARG_STR, offsetof(starter_conn_t, ah), NULL }, ! 164: { ARG_TIME, offsetof(starter_conn_t, dpd_delay), NULL }, ! 165: { ARG_TIME, offsetof(starter_conn_t, dpd_timeout), NULL }, ! 166: { ARG_ENUM, offsetof(starter_conn_t, dpd_action), LST_dpd_action }, ! 167: { ARG_ENUM, offsetof(starter_conn_t, close_action), LST_dpd_action }, ! 168: { ARG_ENUM, offsetof(starter_conn_t, sha256_96), LST_bool }, ! 169: { ARG_TIME, offsetof(starter_conn_t, inactivity), NULL }, ! 170: { ARG_MISC, 0, NULL /* KW_MODECONFIG */ }, ! 171: { ARG_MISC, 0, NULL /* KW_XAUTH */ }, ! 172: { ARG_STR, offsetof(starter_conn_t, xauth_identity), NULL }, ! 173: { ARG_ENUM, offsetof(starter_conn_t, me_mediation), LST_bool }, ! 174: { ARG_STR, offsetof(starter_conn_t, me_mediated_by), NULL }, ! 175: { ARG_STR, offsetof(starter_conn_t, me_peerid), NULL }, ! 176: { ARG_UINT, offsetof(starter_conn_t, reqid), NULL }, ! 177: { ARG_UINT, offsetof(starter_conn_t, replay_window), NULL }, ! 178: { ARG_MISC, 0, NULL /* KW_MARK */ }, ! 179: { ARG_MISC, 0, NULL /* KW_MARK_IN */ }, ! 180: { ARG_MISC, 0, NULL /* KW_MARK_OUT */ }, ! 181: { ARG_MISC, 0, NULL /* KW_TFC */ }, ! 182: { ARG_MISC, 0, NULL /* KW_PFS_DEPRECATED */ }, ! 183: { ARG_MISC, 0, NULL /* KW_CONN_DEPRECATED */ }, ! 184: ! 185: /* ca section keywords */ ! 186: { ARG_STR, offsetof(starter_ca_t, name), NULL }, ! 187: { ARG_ENUM, offsetof(starter_ca_t, startup), LST_startup }, ! 188: { ARG_STR, offsetof(starter_ca_t, cacert), NULL }, ! 189: { ARG_STR, offsetof(starter_ca_t, crluri), NULL }, ! 190: { ARG_STR, offsetof(starter_ca_t, crluri2), NULL }, ! 191: { ARG_STR, offsetof(starter_ca_t, ocspuri), NULL }, ! 192: { ARG_STR, offsetof(starter_ca_t, ocspuri2), NULL }, ! 193: { ARG_STR, offsetof(starter_ca_t, certuribase), NULL }, ! 194: { ARG_MISC, 0, NULL /* KW_CA_DEPRECATED */ }, ! 195: ! 196: /* end keywords */ ! 197: { ARG_STR, offsetof(starter_end_t, host), NULL }, ! 198: { ARG_UINT, offsetof(starter_end_t, ikeport), NULL }, ! 199: { ARG_STR, offsetof(starter_end_t, subnet), NULL }, ! 200: { ARG_MISC, 0, NULL /* KW_PROTOPORT */ }, ! 201: { ARG_STR, offsetof(starter_end_t, sourceip), NULL }, ! 202: { ARG_STR, offsetof(starter_end_t, dns), NULL }, ! 203: { ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool }, ! 204: { ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool }, ! 205: { ARG_ENUM, offsetof(starter_end_t, allow_any), LST_bool }, ! 206: { ARG_STR, offsetof(starter_end_t, updown), NULL }, ! 207: { ARG_STR, offsetof(starter_end_t, auth), NULL }, ! 208: { ARG_STR, offsetof(starter_end_t, auth2), NULL }, ! 209: { ARG_STR, offsetof(starter_end_t, id), NULL }, ! 210: { ARG_STR, offsetof(starter_end_t, id2), NULL }, ! 211: { ARG_STR, offsetof(starter_end_t, rsakey), NULL }, ! 212: { ARG_STR, offsetof(starter_end_t, cert), NULL }, ! 213: { ARG_STR, offsetof(starter_end_t, cert2), NULL }, ! 214: { ARG_STR, offsetof(starter_end_t, cert_policy), NULL }, ! 215: { ARG_ENUM, offsetof(starter_end_t, sendcert), LST_sendcert }, ! 216: { ARG_STR, offsetof(starter_end_t, ca), NULL }, ! 217: { ARG_STR, offsetof(starter_end_t, ca2), NULL }, ! 218: { ARG_STR, offsetof(starter_end_t, groups), NULL }, ! 219: { ARG_STR, offsetof(starter_end_t, groups2), NULL }, ! 220: { ARG_MISC, 0, NULL /* KW_END_DEPRECATED */ }, ! 221: }; ! 222: ! 223: /* ! 224: * assigns an argument value to a struct field ! 225: */ ! 226: bool assign_arg(kw_token_t token, kw_token_t first, char *key, char *value, ! 227: void *base, bool *assigned) ! 228: { ! 229: char *p = (char*)base + token_info[token].offset; ! 230: const char **list = token_info[token].list; ! 231: int index = -1; /* used for enumeration arguments */ ! 232: ! 233: *assigned = FALSE; ! 234: ! 235: DBG3(DBG_APP, " %s=%s", key, value); ! 236: ! 237: /* is there a keyword list? */ ! 238: if (list != NULL) ! 239: { ! 240: bool match = FALSE; ! 241: ! 242: while (*list != NULL && !match) ! 243: { ! 244: index++; ! 245: match = streq(value, *list++); ! 246: } ! 247: if (!match) ! 248: { ! 249: DBG1(DBG_APP, "# bad value: %s=%s", key, value); ! 250: return FALSE; ! 251: } ! 252: } ! 253: ! 254: switch (token_info[token].type) ! 255: { ! 256: case ARG_NONE: ! 257: DBG1(DBG_APP, "# option '%s' not supported yet", key); ! 258: return FALSE; ! 259: case ARG_ENUM: ! 260: { ! 261: if (index < 0) ! 262: { ! 263: DBG1(DBG_APP, "# bad enumeration value: %s=%s (%d)", ! 264: key, value, index); ! 265: return FALSE; ! 266: } ! 267: ! 268: if (token_info[token].list == LST_bool) ! 269: { ! 270: bool *b = (bool *)p; ! 271: *b = (index > 0); ! 272: } ! 273: else ! 274: { /* FIXME: this is not entirely correct as the args are enums */ ! 275: int *i = (int *)p; ! 276: *i = index; ! 277: } ! 278: break; ! 279: } ! 280: case ARG_UINT: ! 281: { ! 282: char *endptr; ! 283: u_int *u = (u_int *)p; ! 284: ! 285: *u = strtoul(value, &endptr, 10); ! 286: ! 287: if (*endptr != '\0') ! 288: { ! 289: DBG1(DBG_APP, "# bad integer value: %s=%s", key, value); ! 290: return FALSE; ! 291: } ! 292: break; ! 293: } ! 294: case ARG_ULNG: ! 295: case ARG_PCNT: ! 296: { ! 297: char *endptr; ! 298: unsigned long *l = (unsigned long *)p; ! 299: ! 300: *l = strtoul(value, &endptr, 10); ! 301: ! 302: if (token_info[token].type == ARG_ULNG) ! 303: { ! 304: if (*endptr != '\0') ! 305: { ! 306: DBG1(DBG_APP, "# bad integer value: %s=%s", key, value); ! 307: return FALSE; ! 308: } ! 309: } ! 310: else ! 311: { ! 312: if ((*endptr != '%') || (endptr[1] != '\0') || endptr == value) ! 313: { ! 314: DBG1(DBG_APP, "# bad percent value: %s=%s", key, value); ! 315: return FALSE; ! 316: } ! 317: } ! 318: break; ! 319: } ! 320: case ARG_ULLI: ! 321: { ! 322: char *endptr; ! 323: unsigned long long *ll = (unsigned long long *)p; ! 324: ! 325: *ll = strtoull(value, &endptr, 10); ! 326: ! 327: if (*endptr != '\0') ! 328: { ! 329: DBG1(DBG_APP, "# bad integer value: %s=%s", key, value); ! 330: return FALSE; ! 331: } ! 332: break; ! 333: } ! 334: case ARG_UBIN: ! 335: { ! 336: char *endptr; ! 337: u_int *u = (u_int *)p; ! 338: ! 339: *u = strtoul(value, &endptr, 2); ! 340: ! 341: if (*endptr != '\0') ! 342: { ! 343: DBG1(DBG_APP, "# bad binary value: %s=%s", key, value); ! 344: return FALSE; ! 345: } ! 346: break; ! 347: } ! 348: case ARG_TIME: ! 349: { ! 350: char *endptr; ! 351: time_t *t = (time_t *)p; ! 352: ! 353: *t = strtoul(value, &endptr, 10); ! 354: ! 355: /* time in seconds? */ ! 356: if (*endptr == '\0' || (*endptr == 's' && endptr[1] == '\0')) ! 357: { ! 358: break; ! 359: } ! 360: if (endptr[1] == '\0') ! 361: { ! 362: if (*endptr == 'm') /* time in minutes? */ ! 363: { ! 364: *t *= 60; ! 365: break; ! 366: } ! 367: if (*endptr == 'h') /* time in hours? */ ! 368: { ! 369: *t *= 3600; ! 370: break; ! 371: } ! 372: if (*endptr == 'd') /* time in days? */ ! 373: { ! 374: *t *= 3600*24; ! 375: break; ! 376: } ! 377: } ! 378: DBG1(DBG_APP, "# bad duration value: %s=%s", key, value); ! 379: return FALSE; ! 380: } ! 381: case ARG_STR: ! 382: { ! 383: char **cp = (char **)p; ! 384: ! 385: /* free any existing string */ ! 386: free(*cp); ! 387: /* assign the new string */ ! 388: *cp = strdupnull(value); ! 389: break; ! 390: } ! 391: default: ! 392: return TRUE; ! 393: } ! 394: ! 395: *assigned = TRUE; ! 396: return TRUE; ! 397: } ! 398: ! 399: /* ! 400: * frees all dynamically allocated arguments in a struct ! 401: */ ! 402: void free_args(kw_token_t first, kw_token_t last, void *base) ! 403: { ! 404: kw_token_t token; ! 405: ! 406: for (token = first; token <= last; token++) ! 407: { ! 408: char *p = (char*)base + token_info[token].offset; ! 409: ! 410: switch (token_info[token].type) ! 411: { ! 412: case ARG_STR: ! 413: { ! 414: char **cp = (char **)p; ! 415: ! 416: free(*cp); ! 417: *cp = NULL; ! 418: break; ! 419: } ! 420: default: ! 421: break; ! 422: } ! 423: } ! 424: } ! 425: ! 426: /* ! 427: * compare all arguments in a struct ! 428: */ ! 429: bool cmp_args(kw_token_t first, kw_token_t last, void *base1, void *base2) ! 430: { ! 431: kw_token_t token; ! 432: ! 433: for (token = first; token <= last; token++) ! 434: { ! 435: char *p1 = (char*)base1 + token_info[token].offset; ! 436: char *p2 = (char*)base2 + token_info[token].offset; ! 437: ! 438: switch (token_info[token].type) ! 439: { ! 440: case ARG_ENUM: ! 441: { ! 442: if (token_info[token].list == LST_bool) ! 443: { ! 444: bool *b1 = (bool *)p1; ! 445: bool *b2 = (bool *)p2; ! 446: ! 447: if (*b1 != *b2) ! 448: { ! 449: return FALSE; ! 450: } ! 451: } ! 452: else ! 453: { ! 454: int *i1 = (int *)p1; ! 455: int *i2 = (int *)p2; ! 456: ! 457: if (*i1 != *i2) ! 458: { ! 459: return FALSE; ! 460: } ! 461: } ! 462: break; ! 463: } ! 464: case ARG_UINT: ! 465: { ! 466: u_int *u1 = (u_int *)p1; ! 467: u_int *u2 = (u_int *)p2; ! 468: ! 469: if (*u1 != *u2) ! 470: { ! 471: return FALSE; ! 472: } ! 473: break; ! 474: } ! 475: case ARG_ULNG: ! 476: case ARG_PCNT: ! 477: { ! 478: unsigned long *l1 = (unsigned long *)p1; ! 479: unsigned long *l2 = (unsigned long *)p2; ! 480: ! 481: if (*l1 != *l2) ! 482: { ! 483: return FALSE; ! 484: } ! 485: break; ! 486: } ! 487: case ARG_ULLI: ! 488: { ! 489: unsigned long long *ll1 = (unsigned long long *)p1; ! 490: unsigned long long *ll2 = (unsigned long long *)p2; ! 491: ! 492: if (*ll1 != *ll2) ! 493: { ! 494: return FALSE; ! 495: } ! 496: break; ! 497: } ! 498: case ARG_TIME: ! 499: { ! 500: time_t *t1 = (time_t *)p1; ! 501: time_t *t2 = (time_t *)p2; ! 502: ! 503: if (*t1 != *t2) ! 504: { ! 505: return FALSE; ! 506: } ! 507: break; ! 508: } ! 509: case ARG_STR: ! 510: { ! 511: char **cp1 = (char **)p1; ! 512: char **cp2 = (char **)p2; ! 513: ! 514: if (*cp1 == NULL && *cp2 == NULL) ! 515: { ! 516: break; ! 517: } ! 518: if (*cp1 == NULL || *cp2 == NULL || strcmp(*cp1, *cp2) != 0) ! 519: { ! 520: return FALSE; ! 521: } ! 522: break; ! 523: } ! 524: default: ! 525: break; ! 526: } ! 527: } ! 528: return TRUE; ! 529: }