Return to vici_config.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / vici |
1.1 misho 1: /* 2: * Copyright (C) 2014 Martin Willi 3: * Copyright (C) 2014 revosec AG 4: * 5: * Copyright (C) 2015-2019 Tobias Brunner 6: * Copyright (C) 2015-2018 Andreas Steffen 7: * HSR Hochschule fuer Technik Rapperswil 8: * 9: * This program is free software; you can redistribute it and/or modify it 10: * under the terms of the GNU General Public License as published by the 11: * Free Software Foundation; either version 2 of the License, or (at your 12: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 13: * 14: * This program is distributed in the hope that it will be useful, but 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17: * for more details. 18: */ 19: 20: /* 21: * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi> 22: * 23: * Permission is hereby granted, free of charge, to any person obtaining a copy 24: * of this software and associated documentation files (the "Software"), to deal 25: * in the Software without restriction, including without limitation the rights 26: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 27: * copies of the Software, and to permit persons to whom the Software is 28: * furnished to do so, subject to the following conditions: 29: * 30: * The above copyright notice and this permission notice shall be included in 31: * all copies or substantial portions of the Software. 32: * 33: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 34: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 35: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 36: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 37: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 38: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 39: * THE SOFTWARE. 40: */ 41: 42: #define _GNU_SOURCE 43: 44: #include "vici_config.h" 45: #include "vici_builder.h" 46: 47: #include <daemon.h> 48: #include <threading/rwlock.h> 49: #include <threading/rwlock_condvar.h> 50: #include <collections/array.h> 1.1.1.2 ! misho 51: #include <collections/hashtable.h> 1.1 misho 52: #include <collections/linked_list.h> 53: 54: #include <pubkey_cert.h> 55: 56: #include <stdio.h> 57: 58: /** 59: * Magic value for an undefined lifetime 60: */ 61: #define LFT_UNDEFINED (~(uint64_t)0) 62: 63: /** 64: * Default IKE rekey time 65: */ 66: #define LFT_DEFAULT_IKE_REKEY_TIME (4 * 60 * 60) 67: 68: /** 69: * Default CHILD rekey time 70: */ 71: #define LFT_DEFAULT_CHILD_REKEY_TIME (1 * 60 * 60) 72: 73: /** 74: * Default CHILD rekey bytes 75: */ 76: #define LFT_DEFAULT_CHILD_REKEY_BYTES 0 77: 78: /** 79: * Default CHILD rekey packets 80: */ 81: #define LFT_DEFAULT_CHILD_REKEY_PACKETS 0 82: 83: /** 84: * Undefined replay window 85: */ 86: #define REPLAY_UNDEFINED (~(uint32_t)0) 87: 88: typedef struct private_vici_config_t private_vici_config_t; 89: 90: /** 91: * Private data of an vici_config_t object. 92: */ 93: struct private_vici_config_t { 94: 95: /** 96: * Public vici_config_t interface. 97: */ 98: vici_config_t public; 99: 100: /** 101: * Dispatcher 102: */ 103: vici_dispatcher_t *dispatcher; 104: 105: /** 1.1.1.2 ! misho 106: * Hashtable of loaded connections, as peer_cfg_t 1.1 misho 107: */ 1.1.1.2 ! misho 108: hashtable_t *conns; 1.1 misho 109: 110: /** 1.1.1.2 ! misho 111: * Lock for conns table 1.1 misho 112: */ 113: rwlock_t *lock; 114: 115: /** 116: * Condvar used to sync running actions 117: */ 118: rwlock_condvar_t *condvar; 119: 120: /** 121: * True while we run or undo a start action 122: */ 123: bool handling_actions; 124: 125: /** 126: * Credential backend managed by VICI used for our certificates 127: */ 128: vici_cred_t *cred; 129: 130: /** 131: * Auxiliary certification authority information 132: */ 133: vici_authority_t *authority; 134: 135: }; 136: 1.1.1.2 ! misho 137: CALLBACK(peer_filter, bool, ! 138: void *data, enumerator_t *orig, va_list args) ! 139: { ! 140: peer_cfg_t **out; ! 141: ! 142: VA_ARGS_VGET(args, out); ! 143: ! 144: if (orig->enumerate(orig, NULL, out)) ! 145: { ! 146: return TRUE; ! 147: } ! 148: return FALSE; ! 149: } ! 150: 1.1 misho 151: METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, 152: private_vici_config_t *this, identification_t *me, identification_t *other) 153: { 154: this->lock->read_lock(this->lock); 1.1.1.2 ! misho 155: return enumerator_create_filter(this->conns->create_enumerator(this->conns), ! 156: peer_filter, this->lock, ! 157: (void*)this->lock->unlock); 1.1 misho 158: } 159: 160: CALLBACK(ike_filter, bool, 161: void *data, enumerator_t *orig, va_list args) 162: { 163: peer_cfg_t *cfg; 164: ike_cfg_t **out; 165: 166: VA_ARGS_VGET(args, out); 167: 1.1.1.2 ! misho 168: if (orig->enumerate(orig, NULL, &cfg)) 1.1 misho 169: { 170: *out = cfg->get_ike_cfg(cfg); 171: return TRUE; 172: } 173: return FALSE; 174: } 175: 176: METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, 177: private_vici_config_t *this, host_t *me, host_t *other) 178: { 179: this->lock->read_lock(this->lock); 180: return enumerator_create_filter(this->conns->create_enumerator(this->conns), 181: ike_filter, this->lock, 182: (void*)this->lock->unlock); 183: } 184: 185: METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, 186: private_vici_config_t *this, char *name) 187: { 1.1.1.2 ! misho 188: peer_cfg_t *found; 1.1 misho 189: 190: this->lock->read_lock(this->lock); 1.1.1.2 ! misho 191: found = this->conns->get(this->conns, name); ! 192: if (found) 1.1 misho 193: { 1.1.1.2 ! misho 194: found->get_ref(found); 1.1 misho 195: } 196: this->lock->unlock(this->lock); 197: return found; 198: } 199: 200: /** 201: * Create a (error) reply message 202: */ 203: static vici_message_t* create_reply(char *fmt, ...) 204: { 205: vici_builder_t *builder; 206: va_list args; 207: 208: builder = vici_builder_create(); 209: builder->add_kv(builder, "success", fmt ? "no" : "yes"); 210: if (fmt) 211: { 212: va_start(args, fmt); 213: builder->vadd_kv(builder, "errmsg", fmt, args); 214: va_end(args); 215: } 216: return builder->finalize(builder); 217: } 218: 219: /** 220: * A rule to parse a key/value or list item 221: */ 222: typedef struct { 223: /** name of the key/value or list */ 224: char *name; 225: /** function to parse value */ 226: bool (*parse)(void *out, chunk_t value); 227: /** result, passed to parse() */ 228: void *out; 229: } parse_rule_t; 230: 231: /** 232: * Parse key/values using a rule-set 233: */ 234: static bool parse_rules(parse_rule_t *rules, int count, char *name, 235: chunk_t value, vici_message_t **reply) 236: { 237: int i; 238: 239: for (i = 0; i < count; i++) 240: { 241: if (streq(name, rules[i].name)) 242: { 243: if (rules[i].parse(rules[i].out, value)) 244: { 245: return TRUE; 246: } 247: *reply = create_reply("invalid value for: %s, config discarded", 248: name); 249: return FALSE; 250: } 251: } 252: *reply = create_reply("unknown option: %s, config discarded", name); 253: return FALSE; 254: } 255: 256: /** 257: * Parse callback data, passed to each callback 258: */ 259: typedef struct { 260: private_vici_config_t *this; 261: vici_message_t *reply; 262: } request_data_t; 263: 264: /** 265: * Certificate data 266: */ 267: typedef struct { 268: request_data_t *request; 269: char *handle; 270: uint32_t slot; 271: char *module; 272: char *file; 273: } cert_data_t; 274: 275: /** 276: * Clean up certificate data 277: */ 278: static void free_cert_data(cert_data_t *data) 279: { 280: free(data->handle); 281: free(data->module); 282: free(data->file); 283: free(data); 284: } 285: 286: /** 287: * Auth config data 288: */ 289: typedef struct { 290: request_data_t *request; 291: auth_cfg_t *cfg; 292: uint32_t round; 293: } auth_data_t; 294: 295: /** 296: * Clean up auth config data 297: */ 298: static void free_auth_data(auth_data_t *data) 299: { 300: DESTROY_IF(data->cfg); 301: free(data); 302: } 303: 304: /** 305: * Data associated to a peer config 306: */ 307: typedef struct { 308: request_data_t *request; 309: uint32_t version; 310: bool aggressive; 311: bool encap; 312: bool mobike; 313: bool send_certreq; 314: bool pull; 315: identification_t *ppk_id; 316: bool ppk_required; 317: cert_policy_t send_cert; 318: uint64_t dpd_delay; 319: uint64_t dpd_timeout; 320: fragmentation_t fragmentation; 321: childless_t childless; 322: unique_policy_t unique; 323: uint32_t keyingtries; 324: uint32_t local_port; 325: uint32_t remote_port; 326: char *local_addrs; 327: char *remote_addrs; 328: linked_list_t *local; 329: linked_list_t *remote; 330: linked_list_t *proposals; 331: linked_list_t *children; 332: linked_list_t *vips; 333: char *pools; 334: uint64_t reauth_time; 335: uint64_t rekey_time; 336: uint64_t over_time; 337: uint64_t rand_time; 338: uint8_t dscp; 339: uint32_t if_id_in; 340: uint32_t if_id_out; 341: #ifdef ME 342: bool mediation; 343: char *mediated_by; 344: identification_t *peer_id; 345: #endif /* ME */ 346: } peer_data_t; 347: 348: /** 349: * Log relevant auth config data 350: */ 351: static void log_auth(auth_cfg_t *auth) 352: { 353: enumerator_t *enumerator; 354: auth_rule_t rule; 355: union { 356: uintptr_t u; 357: identification_t *id; 358: certificate_t *cert; 359: char *str; 360: } v; 361: 362: enumerator = auth->create_enumerator(auth); 363: while (enumerator->enumerate(enumerator, &rule, &v)) 364: { 365: switch (rule) 366: { 367: case AUTH_RULE_AUTH_CLASS: 368: DBG2(DBG_CFG, " class = %N", auth_class_names, v.u); 369: break; 370: case AUTH_RULE_EAP_TYPE: 371: DBG2(DBG_CFG, " eap-type = %N", eap_type_names, v.u); 372: break; 373: case AUTH_RULE_EAP_VENDOR: 374: DBG2(DBG_CFG, " eap-vendor = %u", v.u); 375: break; 376: case AUTH_RULE_XAUTH_BACKEND: 377: DBG2(DBG_CFG, " xauth = %s", v.str); 378: break; 379: case AUTH_RULE_CRL_VALIDATION: 380: DBG2(DBG_CFG, " revocation = %N", cert_validation_names, v.u); 381: break; 382: case AUTH_RULE_IDENTITY: 383: DBG2(DBG_CFG, " id = %Y", v.id); 384: break; 385: case AUTH_RULE_CA_IDENTITY: 386: DBG2(DBG_CFG, " ca_id = %Y", v.id); 387: break; 388: case AUTH_RULE_AAA_IDENTITY: 389: DBG2(DBG_CFG, " aaa_id = %Y", v.id); 390: break; 391: case AUTH_RULE_EAP_IDENTITY: 392: DBG2(DBG_CFG, " eap_id = %Y", v.id); 393: break; 394: case AUTH_RULE_XAUTH_IDENTITY: 395: DBG2(DBG_CFG, " xauth_id = %Y", v.id); 396: break; 397: case AUTH_RULE_GROUP: 398: DBG2(DBG_CFG, " group = %Y", v.id); 399: break; 400: case AUTH_RULE_SUBJECT_CERT: 401: DBG2(DBG_CFG, " cert = %Y", v.cert->get_subject(v.cert)); 402: break; 403: case AUTH_RULE_CA_CERT: 404: DBG2(DBG_CFG, " cacert = %Y", v.cert->get_subject(v.cert)); 405: break; 406: default: 407: break; 408: } 409: } 410: enumerator->destroy(enumerator); 411: } 412: 413: /** 414: * Log parsed peer data 415: */ 416: static void log_peer_data(peer_data_t *data) 417: { 418: enumerator_t *enumerator; 419: auth_data_t *auth; 420: host_t *host; 421: 422: DBG2(DBG_CFG, " version = %u", data->version); 423: DBG2(DBG_CFG, " local_addrs = %s", data->local_addrs); 424: DBG2(DBG_CFG, " remote_addrs = %s", data->remote_addrs); 425: DBG2(DBG_CFG, " local_port = %u", data->local_port); 426: DBG2(DBG_CFG, " remote_port = %u", data->remote_port); 427: DBG2(DBG_CFG, " send_certreq = %u", data->send_certreq); 428: DBG2(DBG_CFG, " send_cert = %N", cert_policy_names, data->send_cert); 429: DBG2(DBG_CFG, " ppk_id = %Y", data->ppk_id); 430: DBG2(DBG_CFG, " ppk_required = %u", data->ppk_required); 431: DBG2(DBG_CFG, " mobike = %u", data->mobike); 432: DBG2(DBG_CFG, " aggressive = %u", data->aggressive); 433: DBG2(DBG_CFG, " dscp = 0x%.2x", data->dscp); 434: DBG2(DBG_CFG, " encap = %u", data->encap); 435: DBG2(DBG_CFG, " dpd_delay = %llu", data->dpd_delay); 436: DBG2(DBG_CFG, " dpd_timeout = %llu", data->dpd_timeout); 437: DBG2(DBG_CFG, " fragmentation = %u", data->fragmentation); 438: DBG2(DBG_CFG, " childless = %u", data->childless); 439: DBG2(DBG_CFG, " unique = %N", unique_policy_names, data->unique); 440: DBG2(DBG_CFG, " keyingtries = %u", data->keyingtries); 441: DBG2(DBG_CFG, " reauth_time = %llu", data->reauth_time); 442: DBG2(DBG_CFG, " rekey_time = %llu", data->rekey_time); 443: DBG2(DBG_CFG, " over_time = %llu", data->over_time); 444: DBG2(DBG_CFG, " rand_time = %llu", data->rand_time); 445: DBG2(DBG_CFG, " proposals = %#P", data->proposals); 446: DBG2(DBG_CFG, " if_id_in = %u", data->if_id_in); 447: DBG2(DBG_CFG, " if_id_out = %u", data->if_id_out); 448: #ifdef ME 449: DBG2(DBG_CFG, " mediation = %u", data->mediation); 450: if (data->mediated_by) 451: { 452: DBG2(DBG_CFG, " mediated_by = %s", data->mediated_by); 453: DBG2(DBG_CFG, " mediation_peer = %Y", data->peer_id); 454: } 455: #endif /* ME */ 456: 457: if (data->vips->get_count(data->vips)) 458: { 459: DBG2(DBG_CFG, " vips:"); 460: } 461: enumerator = data->vips->create_enumerator(data->vips); 462: while (enumerator->enumerate(enumerator, &host)) 463: { 464: DBG2(DBG_CFG, " %H", host); 465: } 466: enumerator->destroy(enumerator); 467: 468: enumerator = data->local->create_enumerator(data->local); 469: while (enumerator->enumerate(enumerator, &auth)) 470: { 471: DBG2(DBG_CFG, " local:"); 472: log_auth(auth->cfg); 473: } 474: enumerator->destroy(enumerator); 475: 476: enumerator = data->remote->create_enumerator(data->remote); 477: while (enumerator->enumerate(enumerator, &auth)) 478: { 479: DBG2(DBG_CFG, " remote:"); 480: log_auth(auth->cfg); 481: } 482: enumerator->destroy(enumerator); 483: } 484: 485: /** 486: * Clean up peer config data 487: */ 488: static void free_peer_data(peer_data_t *data) 489: { 490: data->local->destroy_function(data->local, (void*)free_auth_data); 491: data->remote->destroy_function(data->remote, (void*)free_auth_data); 492: data->children->destroy_offset(data->children, 493: offsetof(child_cfg_t, destroy)); 494: data->proposals->destroy_offset(data->proposals, 495: offsetof(proposal_t, destroy)); 496: data->vips->destroy_offset(data->vips, offsetof(host_t, destroy)); 497: free(data->pools); 498: free(data->local_addrs); 499: free(data->remote_addrs); 500: DESTROY_IF(data->ppk_id); 501: #ifdef ME 502: free(data->mediated_by); 503: DESTROY_IF(data->peer_id); 504: #endif /* ME */ 505: } 506: 507: /** 508: * CHILD config data 509: */ 510: typedef struct { 511: request_data_t *request; 512: linked_list_t *proposals; 513: linked_list_t *local_ts; 514: linked_list_t *remote_ts; 515: uint32_t replay_window; 516: child_cfg_create_t cfg; 517: } child_data_t; 518: 519: /** 520: * Log parsed CHILD config data 521: */ 522: static void log_child_data(child_data_t *data, char *name) 523: { 524: child_cfg_create_t *cfg = &data->cfg; 525: 526: #define has_opt(opt) ({ (cfg->options & (opt)) == (opt); }) 527: DBG2(DBG_CFG, " child %s:", name); 528: DBG2(DBG_CFG, " rekey_time = %llu", cfg->lifetime.time.rekey); 529: DBG2(DBG_CFG, " life_time = %llu", cfg->lifetime.time.life); 530: DBG2(DBG_CFG, " rand_time = %llu", cfg->lifetime.time.jitter); 531: DBG2(DBG_CFG, " rekey_bytes = %llu", cfg->lifetime.bytes.rekey); 532: DBG2(DBG_CFG, " life_bytes = %llu", cfg->lifetime.bytes.life); 533: DBG2(DBG_CFG, " rand_bytes = %llu", cfg->lifetime.bytes.jitter); 534: DBG2(DBG_CFG, " rekey_packets = %llu", cfg->lifetime.packets.rekey); 535: DBG2(DBG_CFG, " life_packets = %llu", cfg->lifetime.packets.life); 536: DBG2(DBG_CFG, " rand_packets = %llu", cfg->lifetime.packets.jitter); 537: DBG2(DBG_CFG, " updown = %s", cfg->updown); 538: DBG2(DBG_CFG, " hostaccess = %u", has_opt(OPT_HOSTACCESS)); 539: DBG2(DBG_CFG, " ipcomp = %u", has_opt(OPT_IPCOMP)); 540: DBG2(DBG_CFG, " mode = %N%s", ipsec_mode_names, cfg->mode, 541: has_opt(OPT_PROXY_MODE) ? "_PROXY" : ""); 542: DBG2(DBG_CFG, " policies = %u", !has_opt(OPT_NO_POLICIES)); 543: DBG2(DBG_CFG, " policies_fwd_out = %u", has_opt(OPT_FWD_OUT_POLICIES)); 544: if (data->replay_window != REPLAY_UNDEFINED) 545: { 546: DBG2(DBG_CFG, " replay_window = %u", data->replay_window); 547: } 548: DBG2(DBG_CFG, " dpd_action = %N", action_names, cfg->dpd_action); 549: DBG2(DBG_CFG, " start_action = %N", action_names, cfg->start_action); 550: DBG2(DBG_CFG, " close_action = %N", action_names, cfg->close_action); 551: DBG2(DBG_CFG, " reqid = %u", cfg->reqid); 552: DBG2(DBG_CFG, " tfc = %d", cfg->tfc); 553: DBG2(DBG_CFG, " priority = %d", cfg->priority); 554: DBG2(DBG_CFG, " interface = %s", cfg->interface); 555: DBG2(DBG_CFG, " if_id_in = %u", cfg->if_id_in); 556: DBG2(DBG_CFG, " if_id_out = %u", cfg->if_id_out); 557: DBG2(DBG_CFG, " mark_in = %u/%u", 558: cfg->mark_in.value, cfg->mark_in.mask); 559: DBG2(DBG_CFG, " mark_in_sa = %u", has_opt(OPT_MARK_IN_SA)); 560: DBG2(DBG_CFG, " mark_out = %u/%u", 561: cfg->mark_out.value, cfg->mark_out.mask); 562: DBG2(DBG_CFG, " set_mark_in = %u/%u", 563: cfg->set_mark_in.value, cfg->set_mark_in.mask); 564: DBG2(DBG_CFG, " set_mark_out = %u/%u", 565: cfg->set_mark_out.value, cfg->set_mark_out.mask); 566: DBG2(DBG_CFG, " inactivity = %llu", cfg->inactivity); 567: DBG2(DBG_CFG, " proposals = %#P", data->proposals); 568: DBG2(DBG_CFG, " local_ts = %#R", data->local_ts); 569: DBG2(DBG_CFG, " remote_ts = %#R", data->remote_ts); 570: DBG2(DBG_CFG, " hw_offload = %N", hw_offload_names, cfg->hw_offload); 571: DBG2(DBG_CFG, " sha256_96 = %u", has_opt(OPT_SHA256_96)); 572: DBG2(DBG_CFG, " copy_df = %u", !has_opt(OPT_NO_COPY_DF)); 573: DBG2(DBG_CFG, " copy_ecn = %u", !has_opt(OPT_NO_COPY_ECN)); 574: DBG2(DBG_CFG, " copy_dscp = %N", dscp_copy_names, cfg->copy_dscp); 575: } 576: 577: /** 578: * Clean up CHILD config data 579: */ 580: static void free_child_data(child_data_t *data) 581: { 582: data->proposals->destroy_offset(data->proposals, 583: offsetof(proposal_t, destroy)); 584: data->local_ts->destroy_offset(data->local_ts, 585: offsetof(traffic_selector_t, destroy)); 586: data->remote_ts->destroy_offset(data->remote_ts, 587: offsetof(traffic_selector_t, destroy)); 588: free(data->cfg.updown); 589: free(data->cfg.interface); 590: } 591: 592: /** 593: * Common proposal parsing 594: */ 595: static bool parse_proposal(linked_list_t *list, protocol_id_t proto, chunk_t v) 596: { 597: char buf[BUF_LEN]; 598: proposal_t *proposal; 599: 600: if (!vici_stringify(v, buf, sizeof(buf))) 601: { 602: return FALSE; 603: } 604: if (strcaseeq("default", buf)) 605: { 606: proposal = proposal_create_default(proto); 607: if (proposal) 608: { 609: list->insert_last(list, proposal); 610: } 611: proposal = proposal_create_default_aead(proto); 612: if (proposal) 613: { 614: list->insert_last(list, proposal); 615: } 616: return TRUE; 617: } 618: proposal = proposal_create_from_string(proto, buf); 619: if (proposal) 620: { 621: list->insert_last(list, proposal); 622: return TRUE; 623: } 624: return FALSE; 625: } 626: 627: /** 628: * Parse IKE proposal 629: */ 630: CALLBACK(parse_ike_proposal, bool, 631: linked_list_t *out, chunk_t v) 632: { 633: return parse_proposal(out, PROTO_IKE, v); 634: } 635: 636: /** 637: * Parse ESP proposal 638: */ 639: CALLBACK(parse_esp_proposal, bool, 640: linked_list_t *out, chunk_t v) 641: { 642: return parse_proposal(out, PROTO_ESP, v); 643: } 644: 645: /** 646: * Parse AH proposal 647: */ 648: CALLBACK(parse_ah_proposal, bool, 649: linked_list_t *out, chunk_t v) 650: { 651: return parse_proposal(out, PROTO_AH, v); 652: } 653: 654: /** 655: * Parse a traffic selector 656: */ 657: CALLBACK(parse_ts, bool, 658: linked_list_t *out, chunk_t v) 659: { 660: char buf[BUF_LEN], *protoport, *sep, *port = "", *end; 661: traffic_selector_t *ts = NULL; 662: struct protoent *protoent; 663: struct servent *svc; 664: long int p; 665: uint16_t from = 0, to = 0xffff; 666: uint8_t proto = 0; 667: 668: if (!vici_stringify(v, buf, sizeof(buf))) 669: { 670: return FALSE; 671: } 672: 673: protoport = strchr(buf, '['); 674: if (protoport) 675: { 676: *(protoport++) = '\0'; 677: 678: sep = strrchr(protoport, ']'); 679: if (!sep) 680: { 681: return FALSE; 682: } 683: *sep = '\0'; 684: 685: sep = strchr(protoport, '/'); 686: if (sep) 687: { /* protocol/port */ 688: *sep = '\0'; 689: port = sep + 1; 690: } 691: 692: if (streq(protoport, "any")) 693: { 694: proto = 0; 695: } 696: else 697: { 698: protoent = getprotobyname(protoport); 699: if (protoent) 700: { 701: proto = protoent->p_proto; 702: } 703: else 704: { 705: p = strtol(protoport, &end, 0); 706: if ((*protoport && *end) || p < 0 || p > 0xff) 707: { 708: return FALSE; 709: } 710: proto = (uint8_t)p; 711: } 712: } 713: if (streq(port, "opaque")) 714: { 715: from = 0xffff; 716: to = 0; 717: } 718: else if (*port && !streq(port, "any")) 719: { 720: svc = getservbyname(port, NULL); 721: if (svc) 722: { 723: from = to = ntohs(svc->s_port); 724: } 725: else 726: { 727: p = strtol(port, &end, 0); 728: if (p < 0 || p > 0xffff) 729: { 730: return FALSE; 731: } 732: from = p; 733: if (*end == '-') 734: { 735: port = end + 1; 736: p = strtol(port, &end, 0); 737: if (p < 0 || p > 0xffff) 738: { 739: return FALSE; 740: } 741: } 742: to = p; 743: if (*end) 744: { 745: return FALSE; 746: } 747: } 748: } 749: } 750: if (streq(buf, "dynamic")) 751: { 752: ts = traffic_selector_create_dynamic(proto, from, to); 753: } 754: else if (strchr(buf, '-')) 755: { 756: host_t *lower, *upper; 757: ts_type_t type; 758: 759: if (host_create_from_range(buf, &lower, &upper)) 760: { 761: type = (lower->get_family(lower) == AF_INET) ? 762: TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE; 763: ts = traffic_selector_create_from_bytes(proto, type, 764: lower->get_address(lower), from, 765: upper->get_address(upper), to); 766: lower->destroy(lower); 767: upper->destroy(upper); 768: } 769: } 770: else 771: { 772: ts = traffic_selector_create_from_cidr(buf, proto, from, to); 773: } 774: if (!ts) 775: { 776: return FALSE; 777: } 778: out->insert_last(out, ts); 779: return TRUE; 780: } 781: 782: /** 783: * Parse a string 784: */ 785: CALLBACK(parse_string, bool, 786: char **out, chunk_t v) 787: { 788: if (!chunk_printable(v, NULL, ' ')) 789: { 790: return FALSE; 791: } 792: free(*out); 793: *out = NULL; 794: if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1) 795: { 796: return FALSE; 797: } 798: return TRUE; 799: } 800: 801: /** 802: * Map a string to an integer 803: */ 804: typedef struct { 805: char *str; 806: int d; 807: } enum_map_t; 808: 809: /** 810: * Parse a string to an integer mapping 811: */ 812: static bool parse_map(enum_map_t *map, int count, int *out, chunk_t v) 813: { 814: char buf[BUF_LEN]; 815: int i; 816: 817: if (!vici_stringify(v, buf, sizeof(buf))) 818: { 819: return FALSE; 820: } 821: for (i = 0; i < count; i++) 822: { 823: if (strcaseeq(map[i].str, buf)) 824: { 825: *out = map[i].d; 826: return TRUE; 827: } 828: } 829: return FALSE; 830: } 831: 832: /** 833: * Parse a boolean 834: */ 835: CALLBACK(parse_bool, bool, 836: bool *out, chunk_t v) 837: { 838: enum_map_t map[] = { 839: { "yes", TRUE }, 840: { "true", TRUE }, 841: { "enabled", TRUE }, 842: { "1", TRUE }, 843: { "no", FALSE }, 844: { "false", FALSE }, 845: { "disabled", FALSE }, 846: { "0", FALSE }, 847: }; 848: int d; 849: 850: if (parse_map(map, countof(map), &d, v)) 851: { 852: *out = d; 853: return TRUE; 854: } 855: return FALSE; 856: } 857: 858: /** 859: * Parse a ipsec_mode_t 860: */ 861: CALLBACK(parse_mode, bool, 862: child_cfg_create_t *cfg, chunk_t v) 863: { 864: enum_map_t map[] = { 865: { "tunnel", MODE_TUNNEL }, 866: { "transport", MODE_TRANSPORT }, 867: { "transport_proxy", MODE_TRANSPORT }, 868: { "beet", MODE_BEET }, 869: { "drop", MODE_DROP }, 870: { "pass", MODE_PASS }, 871: }; 872: int d; 873: 874: if (parse_map(map, countof(map), &d, v)) 875: { 876: cfg->mode = d; 877: if ((d == MODE_TRANSPORT) && (v.len > 9)) 878: { 879: cfg->options |= OPT_PROXY_MODE; 880: } 881: return TRUE; 882: } 883: return FALSE; 884: } 885: 886: /** 887: * Enable a child_cfg_option_t, the flag controls whether the option is enabled 888: * if the parsed value is TRUE or FALSE. 889: */ 890: static bool parse_option(child_cfg_option_t *out, child_cfg_option_t opt, 891: chunk_t v, bool add_if_true) 892: { 893: bool val; 894: 895: if (parse_bool(&val, v)) 896: { 897: if (val == add_if_true) 898: { 899: *out |= opt; 900: } 901: return TRUE; 902: } 903: return FALSE; 904: } 905: 906: /** 907: * Parse OPT_HOSTACCESS option 908: */ 909: CALLBACK(parse_opt_haccess, bool, 910: child_cfg_option_t *out, chunk_t v) 911: { 912: return parse_option(out, OPT_HOSTACCESS, v, TRUE); 913: } 914: 915: /** 916: * Parse OPT_NO_POLICIES option 917: */ 918: CALLBACK(parse_opt_policies, bool, 919: child_cfg_option_t *out, chunk_t v) 920: { 921: return parse_option(out, OPT_NO_POLICIES, v, FALSE); 922: } 923: 924: /** 925: * Parse OPT_FWD_OUT_POLICIES option 926: */ 927: CALLBACK(parse_opt_fwd_out, bool, 928: child_cfg_option_t *out, chunk_t v) 929: { 930: return parse_option(out, OPT_FWD_OUT_POLICIES, v, TRUE); 931: } 932: 933: /** 934: * Parse OPT_IPCOMP option 935: */ 936: CALLBACK(parse_opt_ipcomp, bool, 937: child_cfg_option_t *out, chunk_t v) 938: { 939: return parse_option(out, OPT_IPCOMP, v, TRUE); 940: } 941: 942: /** 943: * Parse OPT_SHA256_96 option 944: */ 945: CALLBACK(parse_opt_sha256_96, bool, 946: child_cfg_option_t *out, chunk_t v) 947: { 948: return parse_option(out, OPT_SHA256_96, v, TRUE); 949: } 950: 951: /** 952: * Parse OPT_MARK_IN_SA option 953: */ 954: CALLBACK(parse_opt_mark_in, bool, 955: child_cfg_option_t *out, chunk_t v) 956: { 957: return parse_option(out, OPT_MARK_IN_SA, v, TRUE); 958: } 959: 960: /** 961: * Parse OPT_NO_COPY_DF option 962: */ 963: CALLBACK(parse_opt_copy_df, bool, 964: child_cfg_option_t *out, chunk_t v) 965: { 966: return parse_option(out, OPT_NO_COPY_DF, v, FALSE); 967: } 968: 969: /** 970: * Parse OPT_NO_COPY_ECN option 971: */ 972: CALLBACK(parse_opt_copy_ecn, bool, 973: child_cfg_option_t *out, chunk_t v) 974: { 975: return parse_option(out, OPT_NO_COPY_ECN, v, FALSE); 976: } 977: 978: /** 979: * Parse a dscp_copy_t 980: */ 981: CALLBACK(parse_copy_dscp, bool, 982: dscp_copy_t *out, chunk_t v) 983: { 984: enum_map_t map[] = { 985: { "no", DSCP_COPY_NO }, 986: { "in", DSCP_COPY_IN_ONLY }, 987: { "out", DSCP_COPY_OUT_ONLY }, 988: { "yes", DSCP_COPY_YES }, 989: }; 990: int d; 991: 992: if (parse_map(map, countof(map), &d, v)) 993: { 994: *out = d; 995: return TRUE; 996: } 997: return FALSE; 998: } 999: 1000: /** 1001: * Parse an action_t 1002: */ 1003: CALLBACK(parse_action, bool, 1004: action_t *out, chunk_t v) 1005: { 1006: enum_map_t map[] = { 1007: { "start", ACTION_RESTART }, 1008: { "restart", ACTION_RESTART }, 1009: { "route", ACTION_ROUTE }, 1010: { "trap", ACTION_ROUTE }, 1011: { "none", ACTION_NONE }, 1012: { "clear", ACTION_NONE }, 1013: }; 1014: int d; 1015: 1016: if (parse_map(map, countof(map), &d, v)) 1017: { 1018: *out = d; 1019: return TRUE; 1020: } 1021: return FALSE; 1022: } 1023: 1024: /** 1025: * Parse an hw_offload_t 1026: */ 1027: CALLBACK(parse_hw_offload, bool, 1028: action_t *out, chunk_t v) 1029: { 1030: enum_map_t map[] = { 1031: { "no", HW_OFFLOAD_NO }, 1032: { "yes", HW_OFFLOAD_YES }, 1033: { "auto", HW_OFFLOAD_AUTO }, 1034: }; 1035: int d; 1036: 1037: if (parse_map(map, countof(map), &d, v)) 1038: { 1039: *out = d; 1040: return TRUE; 1041: } 1042: return FALSE; 1043: } 1044: 1045: /** 1046: * Parse a uint32_t with the given base 1047: */ 1048: static bool parse_uint32_base(uint32_t *out, chunk_t v, int base) 1049: { 1050: char buf[16], *end; 1051: u_long l; 1052: 1053: if (!vici_stringify(v, buf, sizeof(buf))) 1054: { 1055: return FALSE; 1056: } 1057: l = strtoul(buf, &end, base); 1058: if (*end == 0) 1059: { 1060: *out = l; 1061: return TRUE; 1062: } 1063: return FALSE; 1064: } 1065: 1066: /** 1067: * Parse a uint32_t 1068: */ 1069: CALLBACK(parse_uint32, bool, 1070: uint32_t *out, chunk_t v) 1071: { 1072: return parse_uint32_base(out, v, 0); 1073: } 1074: 1075: /** 1076: * Parse a uint32_t in binary encoding 1077: */ 1078: CALLBACK(parse_uint32_bin, bool, 1079: uint32_t *out, chunk_t v) 1080: { 1081: return parse_uint32_base(out, v, 2); 1082: } 1083: 1084: /** 1085: * Parse a uint64_t 1086: */ 1087: CALLBACK(parse_uint64, bool, 1088: uint64_t *out, chunk_t v) 1089: { 1090: char buf[16], *end; 1091: unsigned long long l; 1092: 1093: if (!vici_stringify(v, buf, sizeof(buf))) 1094: { 1095: return FALSE; 1096: } 1097: l = strtoull(buf, &end, 0); 1098: if (*end == 0) 1099: { 1100: *out = l; 1101: return TRUE; 1102: } 1103: return FALSE; 1104: } 1105: 1106: /** 1107: * Parse a relative time 1108: */ 1109: CALLBACK(parse_time, bool, 1110: uint64_t *out, chunk_t v) 1111: { 1112: char buf[16], *end; 1113: u_long l; 1114: 1115: if (!vici_stringify(v, buf, sizeof(buf))) 1116: { 1117: return FALSE; 1118: } 1119: 1120: l = strtoul(buf, &end, 0); 1121: while (*end == ' ') 1122: { 1123: end++; 1124: } 1125: switch (*end) 1126: { 1127: case 'd': 1128: case 'D': 1129: l *= 24; 1130: /* fall */ 1131: case 'h': 1132: case 'H': 1133: l *= 60; 1134: /* fall */ 1135: case 'm': 1136: case 'M': 1137: l *= 60; 1138: /* fall */ 1139: case 's': 1140: case 'S': 1141: end++; 1142: break; 1143: case '\0': 1144: break; 1145: default: 1146: return FALSE; 1147: } 1148: if (*end) 1149: { 1150: return FALSE; 1151: } 1152: *out = l; 1153: return TRUE; 1154: } 1155: 1156: /** 1157: * Parse a relative time (32-bit) 1158: */ 1159: CALLBACK(parse_time32, bool, 1160: uint32_t *out, chunk_t v) 1161: { 1162: uint64_t time; 1163: 1164: if (parse_time(&time, v)) 1165: { 1166: *out = time; 1167: return TRUE; 1168: } 1169: return FALSE; 1170: } 1171: 1172: /** 1173: * Parse byte volume 1174: */ 1175: CALLBACK(parse_bytes, bool, 1176: uint64_t *out, chunk_t v) 1177: { 1178: char buf[16], *end; 1179: unsigned long long l; 1180: 1181: if (!vici_stringify(v, buf, sizeof(buf))) 1182: { 1183: return FALSE; 1184: } 1185: 1186: l = strtoull(buf, &end, 0); 1187: while (*end == ' ') 1188: { 1189: end++; 1190: } 1191: switch (*end) 1192: { 1193: case 'g': 1194: case 'G': 1195: l *= 1024; 1196: /* fall */ 1197: case 'm': 1198: case 'M': 1199: l *= 1024; 1200: /* fall */ 1201: case 'k': 1202: case 'K': 1203: l *= 1024; 1204: end++; 1205: break; 1206: case '\0': 1207: break; 1208: default: 1209: return FALSE; 1210: } 1211: if (*end) 1212: { 1213: return FALSE; 1214: } 1215: *out = l; 1216: return TRUE; 1217: } 1218: 1219: /** 1220: * Parse a mark_t 1221: */ 1222: CALLBACK(parse_mark, bool, 1223: mark_t *out, chunk_t v) 1224: { 1225: char buf[32]; 1226: 1227: if (!vici_stringify(v, buf, sizeof(buf))) 1228: { 1229: return FALSE; 1230: } 1231: return mark_from_string(buf, MARK_OP_UNIQUE, out); 1232: } 1233: 1234: /** 1235: * Parse a mark_t when using it as set_mark. 1236: */ 1237: CALLBACK(parse_set_mark, bool, 1238: mark_t *out, chunk_t v) 1239: { 1240: char buf[32]; 1241: 1242: if (!vici_stringify(v, buf, sizeof(buf))) 1243: { 1244: return FALSE; 1245: } 1246: return mark_from_string(buf, MARK_OP_SAME, out); 1247: } 1248: 1249: /** 1250: * Parse interface ID 1251: */ 1252: CALLBACK(parse_if_id, bool, 1253: uint32_t *out, chunk_t v) 1254: { 1255: char buf[32]; 1256: 1257: if (!vici_stringify(v, buf, sizeof(buf))) 1258: { 1259: return FALSE; 1260: } 1261: return if_id_from_string(buf, out); 1262: } 1263: 1264: /** 1265: * Parse TFC padding option 1266: */ 1267: CALLBACK(parse_tfc, bool, 1268: uint32_t *out, chunk_t v) 1269: { 1270: if (chunk_equals(v, chunk_from_str("mtu"))) 1271: { 1272: *out = -1; 1273: return TRUE; 1274: } 1275: return parse_uint32(out, v); 1276: } 1277: 1278: /** 1279: * Parse 6-bit DSCP value 1280: */ 1281: CALLBACK(parse_dscp, bool, 1282: uint8_t *out, chunk_t v) 1283: { 1284: if (parse_uint32_bin(out, v)) 1285: { 1286: *out = *out & 0x3f; 1287: return TRUE; 1288: } 1289: return FALSE; 1290: } 1291: 1292: /** 1293: * Parse authentication config 1294: */ 1295: CALLBACK(parse_auth, bool, 1296: auth_cfg_t *cfg, chunk_t v) 1297: { 1298: char buf[64], *pos; 1299: eap_vendor_type_t *type; 1300: 1301: if (!vici_stringify(v, buf, sizeof(buf))) 1302: { 1303: return FALSE; 1304: } 1305: if (strpfx(buf, "ike:") || 1306: strpfx(buf, "pubkey") || 1307: strpfx(buf, "rsa") || 1308: strpfx(buf, "ecdsa") || 1309: strpfx(buf, "bliss")) 1310: { 1311: cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); 1312: cfg->add_pubkey_constraints(cfg, buf, TRUE); 1313: return TRUE; 1314: } 1315: if (strcaseeq(buf, "psk")) 1316: { 1317: cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); 1318: return TRUE; 1319: } 1320: if (strcasepfx(buf, "xauth")) 1321: { 1322: pos = strchr(buf, '-'); 1323: if (pos) 1324: { 1325: cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos)); 1326: } 1327: cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH); 1328: return TRUE; 1329: } 1330: if (strcasepfx(buf, "eap")) 1331: { 1332: char *pos; 1333: 1334: cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); 1335: 1336: pos = strchr(buf, ':'); 1337: if (pos) 1338: { 1339: *pos = 0; 1340: cfg->add_pubkey_constraints(cfg, pos + 1, FALSE); 1341: } 1342: type = eap_vendor_type_from_string(buf); 1343: if (type) 1344: { 1345: cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type); 1346: if (type->vendor) 1347: { 1348: cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor); 1349: } 1350: free(type); 1351: } 1352: return TRUE; 1353: } 1354: return FALSE; 1355: } 1356: 1357: /** 1358: * Parse identity; add as auth rule to config 1359: */ 1360: static bool parse_id(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v) 1361: { 1362: char buf[BUF_LEN]; 1363: 1364: if (!vici_stringify(v, buf, sizeof(buf))) 1365: { 1366: return FALSE; 1367: } 1368: cfg->add(cfg, rule, identification_create_from_string(buf)); 1369: return TRUE; 1370: } 1371: 1372: /** 1373: * Parse IKE identity 1374: */ 1375: CALLBACK(parse_ike_id, bool, 1376: auth_cfg_t *cfg, chunk_t v) 1377: { 1378: return parse_id(cfg, AUTH_RULE_IDENTITY, v); 1379: } 1380: 1381: /** 1382: * Parse CA identity constraint 1383: */ 1384: CALLBACK(parse_ca_id, bool, 1385: auth_cfg_t *cfg, chunk_t v) 1386: { 1387: return parse_id(cfg, AUTH_RULE_CA_IDENTITY, v); 1388: } 1389: 1390: /** 1391: * Parse AAA identity 1392: */ 1393: CALLBACK(parse_aaa_id, bool, 1394: auth_cfg_t *cfg, chunk_t v) 1395: { 1396: return parse_id(cfg, AUTH_RULE_AAA_IDENTITY, v); 1397: } 1398: 1399: /** 1400: * Parse EAP identity 1401: */ 1402: CALLBACK(parse_eap_id, bool, 1403: auth_cfg_t *cfg, chunk_t v) 1404: { 1405: return parse_id(cfg, AUTH_RULE_EAP_IDENTITY, v); 1406: } 1407: 1408: /** 1409: * Parse XAuth identity 1410: */ 1411: CALLBACK(parse_xauth_id, bool, 1412: auth_cfg_t *cfg, chunk_t v) 1413: { 1414: return parse_id(cfg, AUTH_RULE_XAUTH_IDENTITY, v); 1415: } 1416: 1417: /** 1418: * Parse group membership 1419: */ 1420: CALLBACK(parse_group, bool, 1421: auth_cfg_t *cfg, chunk_t v) 1422: { 1423: return parse_id(cfg, AUTH_RULE_GROUP, v); 1424: } 1425: 1426: /** 1427: * Parse certificate policy 1428: */ 1429: CALLBACK(parse_cert_policy, bool, 1430: auth_cfg_t *cfg, chunk_t v) 1431: { 1432: char buf[BUF_LEN]; 1433: 1434: if (!vici_stringify(v, buf, sizeof(buf))) 1435: { 1436: return FALSE; 1437: } 1438: cfg->add(cfg, AUTH_RULE_CERT_POLICY, strdup(buf)); 1439: return TRUE; 1440: } 1441: 1442: /** 1443: * Add a certificate as auth rule to config 1444: */ 1445: static bool add_cert(auth_data_t *auth, auth_rule_t rule, certificate_t *cert) 1446: { 1.1.1.2 ! misho 1447: vici_authority_t *authority; 1.1 misho 1448: vici_cred_t *cred; 1449: 1.1.1.2 ! misho 1450: if (rule == AUTH_RULE_CA_CERT) ! 1451: { ! 1452: authority = auth->request->this->authority; ! 1453: cert = authority->add_ca_cert(authority, cert); ! 1454: } ! 1455: else ! 1456: { ! 1457: cred = auth->request->this->cred; ! 1458: cert = cred->add_cert(cred, cert); ! 1459: } 1.1 misho 1460: auth->cfg->add(auth->cfg, rule, cert); 1461: return TRUE; 1462: } 1463: 1464: /** 1465: * Parse a certificate; add as auth rule to config 1466: */ 1467: static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v) 1468: { 1469: certificate_t *cert; 1470: 1471: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, 1472: BUILD_BLOB_PEM, v, BUILD_END); 1473: if (cert) 1474: { 1475: return add_cert(auth, rule, cert); 1476: } 1477: return FALSE; 1478: } 1479: 1480: /** 1481: * Parse subject certificates 1482: */ 1483: CALLBACK(parse_certs, bool, 1484: auth_data_t *auth, chunk_t v) 1485: { 1486: return parse_cert(auth, AUTH_RULE_SUBJECT_CERT, v); 1487: } 1488: 1489: /** 1490: * Parse CA certificates 1491: */ 1492: CALLBACK(parse_cacerts, bool, 1493: auth_data_t *auth, chunk_t v) 1494: { 1495: return parse_cert(auth, AUTH_RULE_CA_CERT, v); 1496: } 1497: 1498: /** 1499: * Parse raw public keys 1500: */ 1501: CALLBACK(parse_pubkeys, bool, 1502: auth_data_t *auth, chunk_t v) 1503: { 1504: certificate_t *cert; 1505: 1506: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY, 1507: BUILD_BLOB_PEM, v, BUILD_END); 1508: if (cert) 1509: { 1.1.1.2 ! misho 1510: return add_cert(auth, AUTH_RULE_SUBJECT_CERT, cert); 1.1 misho 1511: } 1512: return FALSE; 1513: } 1514: 1515: /** 1516: * Parse revocation status 1517: */ 1518: CALLBACK(parse_revocation, bool, 1519: auth_cfg_t *cfg, chunk_t v) 1520: { 1521: enum_map_t map[] = { 1522: { "strict", VALIDATION_GOOD }, 1523: { "ifuri", VALIDATION_SKIPPED }, 1524: { "relaxed", VALIDATION_FAILED }, 1525: }; 1526: int d; 1527: 1528: if (parse_map(map, countof(map), &d, v)) 1529: { 1530: if (d != VALIDATION_FAILED) 1531: { 1532: cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, d); 1533: } 1534: return TRUE; 1535: } 1536: return FALSE; 1537: } 1538: 1539: /** 1540: * Parse list items to comma separated strings 1541: */ 1542: CALLBACK(parse_stringlist, bool, 1543: char **out, chunk_t v) 1544: { 1545: char *current; 1546: 1547: if (!chunk_printable(v, NULL, ' ')) 1548: { 1549: return FALSE; 1550: } 1551: current = *out; 1552: if (current) 1553: { 1554: if (asprintf(out, "%s, %.*s", current, (int)v.len, v.ptr) == -1) 1555: { 1556: return FALSE; 1557: } 1558: free(current); 1559: } 1560: else 1561: { 1562: if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1) 1563: { 1564: return FALSE; 1565: } 1566: } 1567: return TRUE; 1568: } 1569: 1570: /** 1571: * Parse an fragmentation_t 1572: */ 1573: CALLBACK(parse_frag, bool, 1574: fragmentation_t *out, chunk_t v) 1575: { 1576: enum_map_t map[] = { 1577: { "yes", FRAGMENTATION_YES }, 1578: { "accept", FRAGMENTATION_ACCEPT }, 1579: { "no", FRAGMENTATION_NO }, 1580: { "force", FRAGMENTATION_FORCE }, 1581: }; 1582: int d; 1583: 1584: if (parse_map(map, countof(map), &d, v)) 1585: { 1586: *out = d; 1587: return TRUE; 1588: } 1589: return FALSE; 1590: } 1591: 1592: /** 1593: * Parse a childless_t 1594: */ 1595: CALLBACK(parse_childless, bool, 1596: childless_t *out, chunk_t v) 1597: { 1598: enum_map_t map[] = { 1599: { "allow", CHILDLESS_ALLOW }, 1600: { "never", CHILDLESS_NEVER }, 1601: { "force", CHILDLESS_FORCE }, 1602: }; 1603: int d; 1604: 1605: if (parse_map(map, countof(map), &d, v)) 1606: { 1607: *out = d; 1608: return TRUE; 1609: } 1610: return FALSE; 1611: } 1612: 1613: /** 1614: * Parse a cert_policy_t 1615: */ 1616: CALLBACK(parse_send_cert, bool, 1617: cert_policy_t *out, chunk_t v) 1618: { 1619: enum_map_t map[] = { 1620: { "ifasked", CERT_SEND_IF_ASKED }, 1621: { "always", CERT_ALWAYS_SEND }, 1622: { "never", CERT_NEVER_SEND }, 1623: }; 1624: int d; 1625: 1626: if (parse_map(map, countof(map), &d, v)) 1627: { 1628: *out = d; 1629: return TRUE; 1630: } 1631: return FALSE; 1632: } 1633: 1634: /** 1635: * Parse a unique_policy_t 1636: */ 1637: CALLBACK(parse_unique, bool, 1638: unique_policy_t *out, chunk_t v) 1639: { 1640: enum_map_t map[] = { 1641: { "never", UNIQUE_NEVER }, 1642: { "no", UNIQUE_NO }, 1643: { "replace", UNIQUE_REPLACE }, 1644: { "keep", UNIQUE_KEEP }, 1645: }; 1646: int d; 1647: 1648: if (parse_map(map, countof(map), &d, v)) 1649: { 1650: *out = d; 1651: return TRUE; 1652: } 1653: return FALSE; 1654: } 1655: 1656: /** 1657: * Parse host_t into a list 1658: */ 1659: CALLBACK(parse_hosts, bool, 1660: linked_list_t *list, chunk_t v) 1661: { 1662: char buf[64]; 1663: host_t *host; 1664: 1665: if (!vici_stringify(v, buf, sizeof(buf))) 1666: { 1667: return FALSE; 1668: } 1669: host = host_create_from_string(buf, 0); 1670: if (!host) 1671: { 1672: return FALSE; 1673: } 1674: list->insert_last(list, host); 1675: return TRUE; 1676: } 1677: 1678: /** 1679: * Parse peer/ppk ID 1680: */ 1681: CALLBACK(parse_peer_id, bool, 1682: identification_t **out, chunk_t v) 1683: { 1684: char buf[BUF_LEN]; 1685: 1686: if (!vici_stringify(v, buf, sizeof(buf))) 1687: { 1688: return FALSE; 1689: } 1690: *out = identification_create_from_string(buf); 1691: return TRUE; 1692: } 1693: 1694: 1695: CALLBACK(cert_kv, bool, 1696: cert_data_t *cert, vici_message_t *message, char *name, chunk_t value) 1697: { 1698: parse_rule_t rules[] = { 1699: { "handle", parse_string, &cert->handle }, 1700: { "slot", parse_uint32, &cert->slot }, 1701: { "module", parse_string, &cert->module }, 1702: { "file", parse_string, &cert->file }, 1703: }; 1704: 1705: return parse_rules(rules, countof(rules), name, value, 1706: &cert->request->reply); 1707: } 1708: 1709: CALLBACK(child_li, bool, 1710: child_data_t *child, vici_message_t *message, char *name, chunk_t value) 1711: { 1712: parse_rule_t rules[] = { 1713: { "ah_proposals", parse_ah_proposal, child->proposals }, 1714: { "esp_proposals", parse_esp_proposal, child->proposals }, 1715: { "local_ts", parse_ts, child->local_ts }, 1716: { "remote_ts", parse_ts, child->remote_ts }, 1717: }; 1718: 1719: return parse_rules(rules, countof(rules), name, value, 1720: &child->request->reply); 1721: } 1722: 1723: CALLBACK(child_kv, bool, 1724: child_data_t *child, vici_message_t *message, char *name, chunk_t value) 1725: { 1726: parse_rule_t rules[] = { 1727: { "updown", parse_string, &child->cfg.updown }, 1728: { "hostaccess", parse_opt_haccess, &child->cfg.options }, 1729: { "mode", parse_mode, &child->cfg }, 1730: { "policies", parse_opt_policies, &child->cfg.options }, 1731: { "policies_fwd_out", parse_opt_fwd_out, &child->cfg.options }, 1732: { "replay_window", parse_uint32, &child->replay_window }, 1733: { "rekey_time", parse_time, &child->cfg.lifetime.time.rekey }, 1734: { "life_time", parse_time, &child->cfg.lifetime.time.life }, 1735: { "rand_time", parse_time, &child->cfg.lifetime.time.jitter }, 1736: { "rekey_bytes", parse_bytes, &child->cfg.lifetime.bytes.rekey }, 1737: { "life_bytes", parse_bytes, &child->cfg.lifetime.bytes.life }, 1738: { "rand_bytes", parse_bytes, &child->cfg.lifetime.bytes.jitter }, 1739: { "rekey_packets", parse_uint64, &child->cfg.lifetime.packets.rekey }, 1740: { "life_packets", parse_uint64, &child->cfg.lifetime.packets.life }, 1741: { "rand_packets", parse_uint64, &child->cfg.lifetime.packets.jitter }, 1742: { "dpd_action", parse_action, &child->cfg.dpd_action }, 1743: { "start_action", parse_action, &child->cfg.start_action }, 1744: { "close_action", parse_action, &child->cfg.close_action }, 1745: { "ipcomp", parse_opt_ipcomp, &child->cfg.options }, 1746: { "inactivity", parse_time32, &child->cfg.inactivity }, 1747: { "reqid", parse_uint32, &child->cfg.reqid }, 1748: { "mark_in", parse_mark, &child->cfg.mark_in }, 1749: { "mark_in_sa", parse_opt_mark_in, &child->cfg.options }, 1750: { "mark_out", parse_mark, &child->cfg.mark_out }, 1751: { "set_mark_in", parse_set_mark, &child->cfg.set_mark_in }, 1752: { "set_mark_out", parse_set_mark, &child->cfg.set_mark_out }, 1753: { "tfc_padding", parse_tfc, &child->cfg.tfc }, 1754: { "priority", parse_uint32, &child->cfg.priority }, 1755: { "interface", parse_string, &child->cfg.interface }, 1756: { "hw_offload", parse_hw_offload, &child->cfg.hw_offload }, 1757: { "sha256_96", parse_opt_sha256_96,&child->cfg.options }, 1758: { "copy_df", parse_opt_copy_df, &child->cfg.options }, 1759: { "copy_ecn", parse_opt_copy_ecn, &child->cfg.options }, 1760: { "copy_dscp", parse_copy_dscp, &child->cfg.copy_dscp }, 1761: { "if_id_in", parse_if_id, &child->cfg.if_id_in }, 1762: { "if_id_out", parse_if_id, &child->cfg.if_id_out }, 1763: }; 1764: 1765: return parse_rules(rules, countof(rules), name, value, 1766: &child->request->reply); 1767: } 1768: 1769: CALLBACK(auth_li, bool, 1770: auth_data_t *auth, vici_message_t *message, char *name, chunk_t value) 1771: { 1772: parse_rule_t rules[] = { 1773: { "groups", parse_group, auth->cfg }, 1774: { "cert_policy", parse_cert_policy, auth->cfg }, 1775: { "certs", parse_certs, auth }, 1776: { "cacerts", parse_cacerts, auth }, 1777: { "pubkeys", parse_pubkeys, auth }, 1778: }; 1779: 1780: return parse_rules(rules, countof(rules), name, value, 1781: &auth->request->reply); 1782: } 1783: 1784: CALLBACK(auth_kv, bool, 1785: auth_data_t *auth, vici_message_t *message, char *name, chunk_t value) 1786: { 1787: parse_rule_t rules[] = { 1788: { "auth", parse_auth, auth->cfg }, 1789: { "id", parse_ike_id, auth->cfg }, 1790: { "ca_id", parse_ca_id, auth->cfg }, 1791: { "aaa_id", parse_aaa_id, auth->cfg }, 1792: { "eap_id", parse_eap_id, auth->cfg }, 1793: { "xauth_id", parse_xauth_id, auth->cfg }, 1794: { "revocation", parse_revocation, auth->cfg }, 1795: { "round", parse_uint32, &auth->round }, 1796: }; 1797: 1798: return parse_rules(rules, countof(rules), name, value, 1799: &auth->request->reply); 1800: } 1801: 1802: CALLBACK(peer_li, bool, 1803: peer_data_t *peer, vici_message_t *message, char *name, chunk_t value) 1804: { 1805: parse_rule_t rules[] = { 1806: { "local_addrs", parse_stringlist, &peer->local_addrs }, 1807: { "remote_addrs", parse_stringlist, &peer->remote_addrs }, 1808: { "proposals", parse_ike_proposal, peer->proposals }, 1809: { "vips", parse_hosts, peer->vips }, 1810: { "pools", parse_stringlist, &peer->pools }, 1811: }; 1812: 1813: return parse_rules(rules, countof(rules), name, value, 1814: &peer->request->reply); 1815: } 1816: 1817: CALLBACK(peer_kv, bool, 1818: peer_data_t *peer, vici_message_t *message, char *name, chunk_t value) 1819: { 1820: parse_rule_t rules[] = { 1821: { "version", parse_uint32, &peer->version }, 1822: { "aggressive", parse_bool, &peer->aggressive }, 1823: { "pull", parse_bool, &peer->pull }, 1824: { "dscp", parse_dscp, &peer->dscp }, 1825: { "encap", parse_bool, &peer->encap }, 1826: { "mobike", parse_bool, &peer->mobike }, 1827: { "dpd_delay", parse_time, &peer->dpd_delay }, 1828: { "dpd_timeout", parse_time, &peer->dpd_timeout }, 1829: { "fragmentation", parse_frag, &peer->fragmentation }, 1830: { "childless", parse_childless, &peer->childless }, 1831: { "send_certreq", parse_bool, &peer->send_certreq }, 1832: { "send_cert", parse_send_cert, &peer->send_cert }, 1833: { "keyingtries", parse_uint32, &peer->keyingtries }, 1834: { "unique", parse_unique, &peer->unique }, 1835: { "local_port", parse_uint32, &peer->local_port }, 1836: { "remote_port", parse_uint32, &peer->remote_port }, 1837: { "reauth_time", parse_time, &peer->reauth_time }, 1838: { "rekey_time", parse_time, &peer->rekey_time }, 1839: { "over_time", parse_time, &peer->over_time }, 1840: { "rand_time", parse_time, &peer->rand_time }, 1841: { "ppk_id", parse_peer_id, &peer->ppk_id }, 1842: { "ppk_required", parse_bool, &peer->ppk_required }, 1843: { "if_id_in", parse_if_id, &peer->if_id_in }, 1844: { "if_id_out", parse_if_id, &peer->if_id_out }, 1845: #ifdef ME 1846: { "mediation", parse_bool, &peer->mediation }, 1847: { "mediated_by", parse_string, &peer->mediated_by }, 1848: { "mediation_peer", parse_peer_id, &peer->peer_id }, 1849: #endif /* ME */ 1850: }; 1851: 1852: return parse_rules(rules, countof(rules), name, value, 1853: &peer->request->reply); 1854: } 1855: 1856: CALLBACK(auth_sn, bool, 1857: auth_data_t *auth, vici_message_t *message, vici_parse_context_t *ctx, 1858: char *name) 1859: { 1860: if (strcasepfx(name, "cert") || 1861: strcasepfx(name, "cacert")) 1862: { 1863: cert_data_t *data; 1864: auth_rule_t rule; 1865: certificate_t *cert; 1866: chunk_t handle; 1867: 1868: INIT(data, 1869: .request = auth->request, 1870: .slot = -1, 1871: ); 1872: 1873: if (!message->parse(message, ctx, NULL, cert_kv, NULL, data)) 1874: { 1875: free_cert_data(data); 1876: return FALSE; 1877: } 1878: if (!data->handle && !data->file) 1879: { 1880: auth->request->reply = create_reply("handle or file path missing: " 1881: "%s", name); 1882: free_cert_data(data); 1883: return FALSE; 1884: } 1885: else if (data->handle && data->file) 1886: { 1887: auth->request->reply = create_reply("handle and file path given: " 1888: "%s", name); 1889: free_cert_data(data); 1890: return FALSE; 1891: } 1892: 1893: if (data->file) 1894: { 1895: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, 1896: BUILD_FROM_FILE, data->file, BUILD_END); 1897: } 1898: else 1899: { 1900: handle = chunk_from_hex(chunk_from_str(data->handle), NULL); 1901: if (data->slot != -1) 1902: { 1903: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, 1904: CERT_X509, BUILD_PKCS11_KEYID, handle, 1905: BUILD_PKCS11_SLOT, data->slot, 1906: data->module ? BUILD_PKCS11_MODULE : BUILD_END, 1907: data->module, BUILD_END); 1908: } 1909: else 1910: { 1911: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, 1912: CERT_X509, BUILD_PKCS11_KEYID, handle, 1913: data->module ? BUILD_PKCS11_MODULE : BUILD_END, 1914: data->module, BUILD_END); 1915: } 1916: chunk_free(&handle); 1917: } 1918: free_cert_data(data); 1919: if (!cert) 1920: { 1921: auth->request->reply = create_reply("unable to load certificate: " 1922: "%s", name); 1923: return FALSE; 1924: } 1925: rule = strcasepfx(name, "cert") ? AUTH_RULE_SUBJECT_CERT 1926: : AUTH_RULE_CA_CERT; 1927: return add_cert(auth, rule, cert); 1928: } 1929: auth->request->reply = create_reply("invalid section: %s", name); 1930: return FALSE; 1931: } 1932: 1933: /** 1934: * Check and update lifetimes 1935: */ 1936: static void check_lifetimes(lifetime_cfg_t *lft) 1937: { 1938: /* if no hard lifetime specified, add one at soft lifetime + 10% */ 1939: if (lft->time.life == LFT_UNDEFINED) 1940: { 1941: lft->time.life = lft->time.rekey * 110 / 100; 1942: } 1943: if (lft->bytes.life == LFT_UNDEFINED) 1944: { 1945: lft->bytes.life = lft->bytes.rekey * 110 / 100; 1946: } 1947: if (lft->packets.life == LFT_UNDEFINED) 1948: { 1949: lft->packets.life = lft->packets.rekey * 110 / 100; 1950: } 1951: /* if no rand time defined, use difference of hard and soft */ 1952: if (lft->time.jitter == LFT_UNDEFINED) 1953: { 1954: lft->time.jitter = lft->time.life - 1955: min(lft->time.life, lft->time.rekey); 1956: } 1957: if (lft->bytes.jitter == LFT_UNDEFINED) 1958: { 1959: lft->bytes.jitter = lft->bytes.life - 1960: min(lft->bytes.life, lft->bytes.rekey); 1961: } 1962: if (lft->packets.jitter == LFT_UNDEFINED) 1963: { 1964: lft->packets.jitter = lft->packets.life - 1965: min(lft->packets.life, lft->packets.rekey); 1966: } 1967: } 1968: 1969: CALLBACK(children_sn, bool, 1970: peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx, 1971: char *name) 1972: { 1973: child_data_t child = { 1974: .request = peer->request, 1975: .proposals = linked_list_create(), 1976: .local_ts = linked_list_create(), 1977: .remote_ts = linked_list_create(), 1978: .replay_window = REPLAY_UNDEFINED, 1979: .cfg = { 1980: .mode = MODE_TUNNEL, 1981: .lifetime = { 1982: .time = { 1983: .rekey = LFT_DEFAULT_CHILD_REKEY_TIME, 1984: .life = LFT_UNDEFINED, 1985: .jitter = LFT_UNDEFINED, 1986: }, 1987: .bytes = { 1988: .rekey = LFT_DEFAULT_CHILD_REKEY_BYTES, 1989: .life = LFT_UNDEFINED, 1990: .jitter = LFT_UNDEFINED, 1991: }, 1992: .packets = { 1993: .rekey = LFT_DEFAULT_CHILD_REKEY_PACKETS, 1994: .life = LFT_UNDEFINED, 1995: .jitter = LFT_UNDEFINED, 1996: }, 1997: }, 1998: }, 1999: }; 2000: child_cfg_t *cfg; 2001: proposal_t *proposal; 2002: traffic_selector_t *ts; 2003: 2004: if (!message->parse(message, ctx, NULL, child_kv, child_li, &child)) 2005: { 2006: free_child_data(&child); 2007: return FALSE; 2008: } 2009: 2010: if (child.local_ts->get_count(child.local_ts) == 0) 2011: { 2012: child.local_ts->insert_last(child.local_ts, 2013: traffic_selector_create_dynamic(0, 0, 65535)); 2014: } 2015: if (child.remote_ts->get_count(child.remote_ts) == 0) 2016: { 2017: child.remote_ts->insert_last(child.remote_ts, 2018: traffic_selector_create_dynamic(0, 0, 65535)); 2019: } 2020: if (child.proposals->get_count(child.proposals) == 0) 2021: { 1.1.1.2 ! misho 2022: proposal = proposal_create_default_aead(PROTO_ESP); 1.1 misho 2023: if (proposal) 2024: { 2025: child.proposals->insert_last(child.proposals, proposal); 2026: } 1.1.1.2 ! misho 2027: proposal = proposal_create_default(PROTO_ESP); 1.1 misho 2028: if (proposal) 2029: { 2030: child.proposals->insert_last(child.proposals, proposal); 2031: } 2032: } 2033: 2034: check_lifetimes(&child.cfg.lifetime); 2035: 2036: log_child_data(&child, name); 2037: 2038: cfg = child_cfg_create(name, &child.cfg); 2039: 2040: if (child.replay_window != REPLAY_UNDEFINED) 2041: { 2042: cfg->set_replay_window(cfg, child.replay_window); 2043: } 2044: while (child.local_ts->remove_first(child.local_ts, 2045: (void**)&ts) == SUCCESS) 2046: { 2047: cfg->add_traffic_selector(cfg, TRUE, ts); 2048: } 2049: while (child.remote_ts->remove_first(child.remote_ts, 2050: (void**)&ts) == SUCCESS) 2051: { 2052: cfg->add_traffic_selector(cfg, FALSE, ts); 2053: } 2054: while (child.proposals->remove_first(child.proposals, 2055: (void**)&proposal) == SUCCESS) 2056: { 2057: cfg->add_proposal(cfg, proposal); 2058: } 2059: 2060: peer->children->insert_last(peer->children, cfg); 2061: 2062: free_child_data(&child); 2063: 2064: return TRUE; 2065: } 2066: 2067: CALLBACK(peer_sn, bool, 2068: peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx, 2069: char *name) 2070: { 2071: if (strcaseeq(name, "children")) 2072: { 2073: return message->parse(message, ctx, children_sn, NULL, NULL, peer); 2074: } 2075: if (strcasepfx(name, "local") || 2076: strcasepfx(name, "remote")) 2077: { 2078: enumerator_t *enumerator; 2079: linked_list_t *auths; 2080: auth_data_t *auth, *current; 2081: auth_rule_t rule; 2082: certificate_t *cert; 2083: pubkey_cert_t *pubkey_cert; 2084: identification_t *id; 2085: bool default_id = FALSE; 2086: 2087: INIT(auth, 2088: .request = peer->request, 2089: .cfg = auth_cfg_create(), 2090: ); 2091: 2092: if (!message->parse(message, ctx, auth_sn, auth_kv, auth_li, auth)) 2093: { 2094: free_auth_data(auth); 2095: return FALSE; 2096: } 2097: id = auth->cfg->get(auth->cfg, AUTH_RULE_IDENTITY); 2098: 2099: enumerator = auth->cfg->create_enumerator(auth->cfg); 2100: while (enumerator->enumerate(enumerator, &rule, &cert)) 2101: { 2102: if (rule == AUTH_RULE_SUBJECT_CERT && !default_id) 2103: { 2104: if (id == NULL) 2105: { 2106: id = cert->get_subject(cert); 2107: DBG1(DBG_CFG, " id not specified, defaulting to" 2108: " cert subject '%Y'", id); 2109: auth->cfg->add(auth->cfg, AUTH_RULE_IDENTITY, id->clone(id)); 2110: default_id = TRUE; 2111: } 2112: else if (cert->get_type(cert) == CERT_TRUSTED_PUBKEY && 2113: id->get_type != ID_ANY) 2114: { 2115: /* set the subject of all raw public keys to the id */ 2116: pubkey_cert = (pubkey_cert_t*)cert; 2117: pubkey_cert->set_subject(pubkey_cert, id); 2118: } 2119: } 2120: } 2121: enumerator->destroy(enumerator); 2122: 2123: auths = strcasepfx(name, "local") ? peer->local : peer->remote; 2124: enumerator = auths->create_enumerator(auths); 2125: while (enumerator->enumerate(enumerator, ¤t)) 2126: { 2127: if (auth->round < current->round) 2128: { 2129: break; 2130: } 2131: } 2132: auths->insert_before(auths, enumerator, auth); 2133: enumerator->destroy(enumerator); 2134: return TRUE; 2135: } 2136: peer->request->reply = create_reply("invalid section: %s", name); 2137: return FALSE; 2138: } 2139: 2140: /** 2141: * Perform start actions associated with a child config 2142: */ 2143: static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg, 2144: child_cfg_t *child_cfg) 2145: { 2146: switch (child_cfg->get_start_action(child_cfg)) 2147: { 2148: case ACTION_RESTART: 2149: DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg)); 2150: charon->controller->initiate(charon->controller, 2151: peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg), 2152: NULL, NULL, 0, FALSE); 2153: break; 2154: case ACTION_ROUTE: 2155: DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg)); 2156: switch (child_cfg->get_mode(child_cfg)) 2157: { 2158: case MODE_PASS: 2159: case MODE_DROP: 2160: charon->shunts->install(charon->shunts, 2161: peer_cfg->get_name(peer_cfg), child_cfg); 2162: break; 2163: default: 2164: charon->traps->install(charon->traps, peer_cfg, child_cfg); 2165: break; 2166: } 2167: break; 2168: default: 2169: break; 2170: } 2171: } 2172: 2173: /** 2174: * Undo start actions associated with a child config 2175: */ 2176: static void clear_start_action(private_vici_config_t *this, char *peer_name, 2177: child_cfg_t *child_cfg) 2178: { 2179: enumerator_t *enumerator, *children; 2180: child_sa_t *child_sa; 2181: ike_sa_t *ike_sa; 2182: uint32_t id = 0, others; 2183: array_t *ids = NULL, *ikeids = NULL; 2184: char *name; 2185: 2186: name = child_cfg->get_name(child_cfg); 2187: 2188: switch (child_cfg->get_start_action(child_cfg)) 2189: { 2190: case ACTION_RESTART: 2191: enumerator = charon->controller->create_ike_sa_enumerator( 2192: charon->controller, TRUE); 2193: while (enumerator->enumerate(enumerator, &ike_sa)) 2194: { 2195: if (!streq(ike_sa->get_name(ike_sa), peer_name)) 2196: { 2197: continue; 2198: } 2199: others = id = 0; 2200: children = ike_sa->create_child_sa_enumerator(ike_sa); 2201: while (children->enumerate(children, &child_sa)) 2202: { 2203: if (child_sa->get_state(child_sa) != CHILD_DELETING && 2204: child_sa->get_state(child_sa) != CHILD_DELETED) 2205: { 2206: if (streq(name, child_sa->get_name(child_sa))) 2207: { 2208: id = child_sa->get_unique_id(child_sa); 2209: } 2210: else 2211: { 2212: others++; 2213: } 2214: } 2215: } 2216: children->destroy(children); 2217: 1.1.1.2 ! misho 2218: if (!ike_sa->get_child_count(ike_sa) || (id && !others)) 1.1 misho 2219: { 1.1.1.2 ! misho 2220: /* found no children or only matching, delete IKE_SA */ 1.1 misho 2221: id = ike_sa->get_unique_id(ike_sa); 2222: array_insert_create_value(&ikeids, sizeof(id), 2223: ARRAY_TAIL, &id); 2224: } 2225: else 2226: { 2227: children = ike_sa->create_child_sa_enumerator(ike_sa); 2228: while (children->enumerate(children, &child_sa)) 2229: { 2230: if (streq(name, child_sa->get_name(child_sa))) 2231: { 2232: id = child_sa->get_unique_id(child_sa); 2233: array_insert_create_value(&ids, sizeof(id), 2234: ARRAY_TAIL, &id); 2235: } 2236: } 2237: children->destroy(children); 2238: } 2239: } 2240: enumerator->destroy(enumerator); 2241: 2242: if (array_count(ids)) 2243: { 2244: while (array_remove(ids, ARRAY_HEAD, &id)) 2245: { 2246: DBG1(DBG_CFG, "closing '%s' #%u", name, id); 2247: charon->controller->terminate_child(charon->controller, 2248: id, NULL, NULL, 0); 2249: } 2250: array_destroy(ids); 2251: } 2252: if (array_count(ikeids)) 2253: { 2254: while (array_remove(ikeids, ARRAY_HEAD, &id)) 2255: { 2256: DBG1(DBG_CFG, "closing IKE_SA #%u", id); 2257: charon->controller->terminate_ike(charon->controller, id, 2258: FALSE, NULL, NULL, 0); 2259: } 2260: array_destroy(ikeids); 2261: } 2262: break; 2263: case ACTION_ROUTE: 2264: DBG1(DBG_CFG, "uninstalling '%s'", name); 2265: switch (child_cfg->get_mode(child_cfg)) 2266: { 2267: case MODE_PASS: 2268: case MODE_DROP: 2269: charon->shunts->uninstall(charon->shunts, peer_name, name); 2270: break; 2271: default: 2272: charon->traps->uninstall(charon->traps, peer_name, name); 2273: break; 2274: } 2275: break; 2276: default: 2277: break; 2278: } 2279: } 2280: 2281: /** 2282: * Run or undo a start actions associated with a child config 2283: */ 2284: static void handle_start_action(private_vici_config_t *this, 2285: peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, 2286: bool undo) 2287: { 2288: this->handling_actions = TRUE; 2289: this->lock->unlock(this->lock); 2290: 2291: if (undo) 2292: { 2293: clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg); 2294: } 2295: else 2296: { 2297: run_start_action(this, peer_cfg, child_cfg); 2298: } 2299: 2300: this->lock->write_lock(this->lock); 2301: this->handling_actions = FALSE; 2302: } 2303: 2304: /** 2305: * Run or undo start actions associated with all child configs of a peer config 2306: */ 2307: static void handle_start_actions(private_vici_config_t *this, 2308: peer_cfg_t *peer_cfg, bool undo) 2309: { 2310: enumerator_t *enumerator; 2311: child_cfg_t *child_cfg; 2312: 2313: this->handling_actions = TRUE; 2314: this->lock->unlock(this->lock); 2315: 2316: enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); 2317: while (enumerator->enumerate(enumerator, &child_cfg)) 2318: { 2319: if (undo) 2320: { 2321: clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg); 2322: } 2323: else 2324: { 2325: run_start_action(this, peer_cfg, child_cfg); 2326: } 2327: } 2328: enumerator->destroy(enumerator); 2329: 2330: this->lock->write_lock(this->lock); 2331: this->handling_actions = FALSE; 2332: } 2333: 2334: /** 2335: * Replace children of a peer config by a new config 2336: */ 2337: static void replace_children(private_vici_config_t *this, 2338: peer_cfg_t *from, peer_cfg_t *to) 2339: { 2340: enumerator_t *enumerator; 2341: child_cfg_t *child; 2342: bool added; 2343: 2344: enumerator = to->replace_child_cfgs(to, from); 2345: while (enumerator->enumerate(enumerator, &child, &added)) 2346: { 2347: handle_start_action(this, to, child, !added); 2348: } 2349: enumerator->destroy(enumerator); 2350: } 2351: 2352: /** 2353: * Merge/replace a peer config with existing configs 2354: */ 2355: static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg) 2356: { 1.1.1.2 ! misho 2357: peer_cfg_t *found; 1.1 misho 2358: ike_cfg_t *ike_cfg; 2359: 2360: this->lock->write_lock(this->lock); 2361: while (this->handling_actions) 2362: { 2363: this->condvar->wait(this->condvar, this->lock); 2364: } 2365: 1.1.1.2 ! misho 2366: found = this->conns->get(this->conns, peer_cfg->get_name(peer_cfg)); ! 2367: if (found) 1.1 misho 2368: { 1.1.1.2 ! misho 2369: ike_cfg = found->get_ike_cfg(found); ! 2370: if (peer_cfg->equals(peer_cfg, found) && ! 2371: ike_cfg->equals(ike_cfg, peer_cfg->get_ike_cfg(peer_cfg))) ! 2372: { ! 2373: DBG1(DBG_CFG, "updated vici connection: %s", ! 2374: peer_cfg->get_name(peer_cfg)); ! 2375: replace_children(this, peer_cfg, found); ! 2376: peer_cfg->destroy(peer_cfg); ! 2377: } ! 2378: else 1.1 misho 2379: { 1.1.1.2 ! misho 2380: DBG1(DBG_CFG, "replaced vici connection: %s", ! 2381: peer_cfg->get_name(peer_cfg)); ! 2382: this->conns->put(this->conns, peer_cfg->get_name(peer_cfg), ! 2383: peer_cfg); ! 2384: handle_start_actions(this, found, TRUE); ! 2385: handle_start_actions(this, peer_cfg, FALSE); ! 2386: found->destroy(found); 1.1 misho 2387: } 2388: } 1.1.1.2 ! misho 2389: else 1.1 misho 2390: { 2391: DBG1(DBG_CFG, "added vici connection: %s", peer_cfg->get_name(peer_cfg)); 1.1.1.2 ! misho 2392: this->conns->put(this->conns, peer_cfg->get_name(peer_cfg), peer_cfg); 1.1 misho 2393: handle_start_actions(this, peer_cfg, FALSE); 2394: } 2395: this->condvar->signal(this->condvar); 2396: this->lock->unlock(this->lock); 2397: } 2398: 2399: CALLBACK(config_sn, bool, 2400: request_data_t *request, vici_message_t *message, 2401: vici_parse_context_t *ctx, char *name) 2402: { 2403: peer_data_t peer = { 2404: .request = request, 2405: .local = linked_list_create(), 2406: .remote = linked_list_create(), 2407: .vips = linked_list_create(), 2408: .children = linked_list_create(), 2409: .proposals = linked_list_create(), 2410: .mobike = TRUE, 2411: .send_certreq = TRUE, 2412: .pull = TRUE, 2413: .send_cert = CERT_SEND_IF_ASKED, 2414: .version = IKE_ANY, 2415: .remote_port = IKEV2_UDP_PORT, 2416: .fragmentation = FRAGMENTATION_YES, 2417: .unique = UNIQUE_NO, 2418: .keyingtries = 1, 2419: .rekey_time = LFT_UNDEFINED, 2420: .reauth_time = LFT_UNDEFINED, 2421: .over_time = LFT_UNDEFINED, 2422: .rand_time = LFT_UNDEFINED, 2423: }; 2424: enumerator_t *enumerator; 2425: peer_cfg_create_t cfg; 2426: peer_cfg_t *peer_cfg; 2427: ike_cfg_create_t ike; 2428: ike_cfg_t *ike_cfg; 2429: child_cfg_t *child_cfg; 2430: auth_data_t *auth; 2431: proposal_t *proposal; 2432: host_t *host; 2433: char *str; 2434: 2435: DBG2(DBG_CFG, " conn %s:", name); 2436: 2437: if (!message->parse(message, ctx, peer_sn, peer_kv, peer_li, &peer)) 2438: { 2439: free_peer_data(&peer); 2440: return FALSE; 2441: } 2442: 2443: if (peer.local->get_count(peer.local) == 0) 2444: { 2445: INIT(auth, 2446: .cfg = auth_cfg_create(), 2447: ); 2448: peer.local->insert_last(peer.local, auth); 2449: } 2450: if (peer.remote->get_count(peer.remote) == 0) 2451: { 2452: INIT(auth, 2453: .cfg = auth_cfg_create(), 2454: ); 2455: peer.remote->insert_last(peer.remote, auth); 2456: } 2457: if (peer.proposals->get_count(peer.proposals) == 0) 2458: { 2459: proposal = proposal_create_default(PROTO_IKE); 2460: if (proposal) 2461: { 2462: peer.proposals->insert_last(peer.proposals, proposal); 2463: } 2464: proposal = proposal_create_default_aead(PROTO_IKE); 2465: if (proposal) 2466: { 2467: peer.proposals->insert_last(peer.proposals, proposal); 2468: } 2469: } 2470: if (!peer.local_addrs) 2471: { 2472: peer.local_addrs = strdup("%any"); 2473: } 2474: if (!peer.remote_addrs) 2475: { 2476: peer.remote_addrs = strdup("%any"); 2477: } 2478: if (!peer.local_port) 2479: { 2480: peer.local_port = charon->socket->get_port(charon->socket, FALSE); 2481: } 2482: 2483: if (peer.rekey_time == LFT_UNDEFINED && peer.reauth_time == LFT_UNDEFINED) 2484: { 2485: /* apply a default rekey time if no rekey/reauth time set */ 2486: peer.rekey_time = LFT_DEFAULT_IKE_REKEY_TIME; 2487: peer.reauth_time = 0; 2488: } 2489: if (peer.rekey_time == LFT_UNDEFINED) 2490: { 2491: peer.rekey_time = 0; 2492: } 2493: if (peer.reauth_time == LFT_UNDEFINED) 2494: { 2495: peer.reauth_time = 0; 2496: } 2497: if (peer.over_time == LFT_UNDEFINED) 2498: { 2499: /* default over_time to 10% of rekey/reauth time if not given */ 2500: peer.over_time = max(peer.rekey_time, peer.reauth_time) / 10; 2501: } 2502: if (peer.rand_time == LFT_UNDEFINED) 2503: { 2504: /* default rand_time to over_time if not given, but don't make it 2505: * longer than half of rekey/rauth time */ 2506: if (peer.rekey_time && peer.reauth_time) 2507: { 2508: peer.rand_time = min(peer.rekey_time, peer.reauth_time); 2509: } 2510: else 2511: { 2512: peer.rand_time = max(peer.rekey_time, peer.reauth_time); 2513: } 2514: peer.rand_time = min(peer.over_time, peer.rand_time / 2); 2515: } 2516: 2517: #ifdef ME 2518: if (peer.mediation && peer.mediated_by) 2519: { 2520: DBG1(DBG_CFG, "a mediation connection cannot be a mediated connection " 2521: "at the same time, config discarded"); 2522: free_peer_data(&peer); 2523: return FALSE; 2524: } 2525: if (peer.mediation) 2526: { /* force unique connections for mediation connections */ 2527: peer.unique = UNIQUE_REPLACE; 2528: } 2529: else if (peer.mediated_by) 2530: { /* fallback to remote identity of first auth round if peer_id is not 2531: * given explicitly */ 2532: auth_cfg_t *cfg; 2533: 2534: if (!peer.peer_id && 2535: peer.remote->get_first(peer.remote, (void**)&cfg) == SUCCESS) 2536: { 2537: peer.peer_id = cfg->get(cfg, AUTH_RULE_IDENTITY); 2538: if (peer.peer_id) 2539: { 2540: peer.peer_id = peer.peer_id->clone(peer.peer_id); 2541: } 2542: else 2543: { 2544: DBG1(DBG_CFG, "mediation peer missing for mediated connection, " 2545: "config discarded"); 2546: free_peer_data(&peer); 2547: return FALSE; 2548: } 2549: } 2550: } 2551: #endif /* ME */ 2552: 2553: log_peer_data(&peer); 2554: 2555: ike = (ike_cfg_create_t){ 2556: .version = peer.version, 2557: .local = peer.local_addrs, 2558: .local_port = peer.local_port, 2559: .remote = peer.remote_addrs, 2560: .remote_port = peer.remote_port, 2561: .no_certreq = !peer.send_certreq, 2562: .force_encap = peer.encap, 2563: .fragmentation = peer.fragmentation, 2564: .childless = peer.childless, 2565: .dscp = peer.dscp, 2566: }; 2567: ike_cfg = ike_cfg_create(&ike); 2568: 2569: cfg = (peer_cfg_create_t){ 2570: .cert_policy = peer.send_cert, 2571: .unique = peer.unique, 2572: .keyingtries = peer.keyingtries, 2573: .rekey_time = peer.rekey_time, 2574: .reauth_time = peer.reauth_time, 2575: .jitter_time = peer.rand_time, 2576: .over_time = peer.over_time, 2577: .no_mobike = !peer.mobike, 2578: .aggressive = peer.aggressive, 2579: .push_mode = !peer.pull, 2580: .dpd = peer.dpd_delay, 2581: .dpd_timeout = peer.dpd_timeout, 2582: .ppk_id = peer.ppk_id ? peer.ppk_id->clone(peer.ppk_id) : NULL, 2583: .ppk_required = peer.ppk_required, 2584: .if_id_in = peer.if_id_in, 2585: .if_id_out = peer.if_id_out, 2586: }; 2587: #ifdef ME 2588: cfg.mediation = peer.mediation; 2589: if (peer.mediated_by) 2590: { 2591: cfg.mediated_by = peer.mediated_by; 2592: if (peer.peer_id) 2593: { 2594: cfg.peer_id = peer.peer_id->clone(peer.peer_id); 2595: } 2596: } 2597: #endif /* ME */ 2598: peer_cfg = peer_cfg_create(name, ike_cfg, &cfg); 2599: 2600: while (peer.local->remove_first(peer.local, 2601: (void**)&auth) == SUCCESS) 2602: { 2603: peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, TRUE); 2604: auth->cfg = NULL; 2605: free_auth_data(auth); 2606: } 2607: while (peer.remote->remove_first(peer.remote, 2608: (void**)&auth) == SUCCESS) 2609: { 2610: peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, FALSE); 2611: auth->cfg = NULL; 2612: free_auth_data(auth); 2613: } 2614: while (peer.children->remove_first(peer.children, 2615: (void**)&child_cfg) == SUCCESS) 2616: { 2617: peer_cfg->add_child_cfg(peer_cfg, child_cfg); 2618: } 2619: while (peer.proposals->remove_first(peer.proposals, 2620: (void**)&proposal) == SUCCESS) 2621: { 2622: ike_cfg->add_proposal(ike_cfg, proposal); 2623: } 2624: while (peer.vips->remove_first(peer.vips, (void**)&host) == SUCCESS) 2625: { 2626: peer_cfg->add_virtual_ip(peer_cfg, host); 2627: } 2628: if (peer.pools) 2629: { 2630: enumerator = enumerator_create_token(peer.pools, ",", " "); 2631: while (enumerator->enumerate(enumerator, &str)) 2632: { 2633: peer_cfg->add_pool(peer_cfg, str); 2634: } 2635: enumerator->destroy(enumerator); 2636: } 2637: 2638: free_peer_data(&peer); 2639: 2640: merge_config(request->this, peer_cfg); 2641: 2642: return TRUE; 2643: } 2644: 2645: CALLBACK(load_conn, vici_message_t*, 2646: private_vici_config_t *this, char *name, u_int id, vici_message_t *message) 2647: { 2648: request_data_t request = { 2649: .this = this, 2650: }; 2651: 2652: if (!message->parse(message, NULL, config_sn, NULL, NULL, &request)) 2653: { 2654: if (request.reply) 2655: { 2656: return request.reply; 2657: } 2658: return create_reply("parsing request failed"); 2659: } 2660: return create_reply(NULL); 2661: } 2662: 2663: CALLBACK(unload_conn, vici_message_t*, 2664: private_vici_config_t *this, char *name, u_int id, vici_message_t *message) 2665: { 2666: peer_cfg_t *cfg; 2667: char *conn_name; 2668: 2669: conn_name = message->get_str(message, NULL, "name"); 2670: if (!conn_name) 2671: { 2672: return create_reply("unload: missing connection name"); 2673: } 2674: 2675: this->lock->write_lock(this->lock); 2676: while (this->handling_actions) 2677: { 2678: this->condvar->wait(this->condvar, this->lock); 2679: } 1.1.1.2 ! misho 2680: cfg = this->conns->remove(this->conns, conn_name); ! 2681: if (cfg) 1.1 misho 2682: { 1.1.1.2 ! misho 2683: handle_start_actions(this, cfg, TRUE); ! 2684: cfg->destroy(cfg); 1.1 misho 2685: } 2686: this->condvar->signal(this->condvar); 2687: this->lock->unlock(this->lock); 2688: 1.1.1.2 ! misho 2689: if (!cfg) 1.1 misho 2690: { 2691: return create_reply("unload: connection '%s' not found", conn_name); 2692: } 2693: return create_reply(NULL); 2694: } 2695: 2696: CALLBACK(get_conns, vici_message_t*, 2697: private_vici_config_t *this, char *name, u_int id, vici_message_t *message) 2698: { 2699: vici_builder_t *builder; 2700: enumerator_t *enumerator; 2701: peer_cfg_t *cfg; 2702: 2703: builder = vici_builder_create(); 2704: builder->begin_list(builder, "conns"); 2705: 2706: this->lock->read_lock(this->lock); 2707: enumerator = this->conns->create_enumerator(this->conns); 1.1.1.2 ! misho 2708: while (enumerator->enumerate(enumerator, NULL, &cfg)) 1.1 misho 2709: { 2710: builder->add_li(builder, "%s", cfg->get_name(cfg)); 2711: } 2712: enumerator->destroy(enumerator); 2713: this->lock->unlock(this->lock); 2714: 2715: builder->end_list(builder); 2716: 2717: return builder->finalize(builder); 2718: } 2719: 2720: static void manage_command(private_vici_config_t *this, 2721: char *name, vici_command_cb_t cb, bool reg) 2722: { 2723: this->dispatcher->manage_command(this->dispatcher, name, 2724: reg ? cb : NULL, this); 2725: } 2726: 2727: /** 2728: * (Un-)register dispatcher functions 2729: */ 2730: static void manage_commands(private_vici_config_t *this, bool reg) 2731: { 2732: manage_command(this, "load-conn", load_conn, reg); 2733: manage_command(this, "unload-conn", unload_conn, reg); 2734: manage_command(this, "get-conns", get_conns, reg); 2735: } 2736: 1.1.1.2 ! misho 2737: CALLBACK(destroy_conn, void, ! 2738: peer_cfg_t *cfg, const void *key) ! 2739: { ! 2740: cfg->destroy(cfg); ! 2741: } ! 2742: 1.1 misho 2743: METHOD(vici_config_t, destroy, void, 2744: private_vici_config_t *this) 2745: { 2746: manage_commands(this, FALSE); 1.1.1.2 ! misho 2747: this->conns->destroy_function(this->conns, destroy_conn); 1.1 misho 2748: this->condvar->destroy(this->condvar); 2749: this->lock->destroy(this->lock); 2750: free(this); 2751: } 2752: 2753: /** 2754: * See header 2755: */ 2756: vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher, 2757: vici_authority_t *authority, 2758: vici_cred_t *cred) 2759: { 2760: private_vici_config_t *this; 2761: 2762: INIT(this, 2763: .public = { 2764: .backend = { 2765: .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, 2766: .create_ike_cfg_enumerator = _create_ike_cfg_enumerator, 2767: .get_peer_cfg_by_name = _get_peer_cfg_by_name, 2768: }, 2769: .destroy = _destroy, 2770: }, 2771: .dispatcher = dispatcher, 1.1.1.2 ! misho 2772: .conns = hashtable_create(hashtable_hash_str, hashtable_equals_str, 32), 1.1 misho 2773: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), 2774: .condvar = rwlock_condvar_create(), 2775: .authority = authority, 2776: .cred = cred, 2777: ); 2778: 2779: manage_commands(this, TRUE); 2780: 2781: return &this->public; 2782: }