Return to config.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / conftest |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2010 Martin Willi ! 3: * Copyright (C) 2010 revosec AG ! 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 "config.h" ! 17: ! 18: #include <daemon.h> ! 19: #include <conftest.h> ! 20: ! 21: typedef struct private_config_t private_config_t; ! 22: ! 23: /** ! 24: * Private data of an config_t object. ! 25: */ ! 26: struct private_config_t { ! 27: ! 28: /** ! 29: * Public config_t interface. ! 30: */ ! 31: config_t public; ! 32: ! 33: /** ! 34: * List of loaded peer configs ! 35: */ ! 36: linked_list_t *configs; ! 37: }; ! 38: ! 39: CALLBACK(ike_filter, bool, ! 40: void *data, enumerator_t *orig, va_list args) ! 41: { ! 42: peer_cfg_t *cfg; ! 43: ike_cfg_t **out; ! 44: ! 45: VA_ARGS_VGET(args, out); ! 46: ! 47: if (orig->enumerate(orig, &cfg)) ! 48: { ! 49: *out = cfg->get_ike_cfg(cfg); ! 50: return TRUE; ! 51: } ! 52: return FALSE; ! 53: } ! 54: ! 55: METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, ! 56: private_config_t *this, host_t *me, host_t *other) ! 57: { ! 58: ! 59: return enumerator_create_filter( ! 60: this->configs->create_enumerator(this->configs), ! 61: ike_filter, NULL, NULL); ! 62: } ! 63: ! 64: METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, ! 65: private_config_t *this, identification_t *me, identification_t *other) ! 66: { ! 67: return this->configs->create_enumerator(this->configs); ! 68: } ! 69: ! 70: METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, ! 71: private_config_t *this, char *name) ! 72: { ! 73: enumerator_t *e1, *e2; ! 74: peer_cfg_t *current, *found = NULL; ! 75: child_cfg_t *child; ! 76: ! 77: e1 = this->configs->create_enumerator(this->configs); ! 78: while (e1->enumerate(e1, ¤t)) ! 79: { ! 80: e2 = current->create_child_cfg_enumerator(current); ! 81: while (e2->enumerate(e2, &child)) ! 82: { ! 83: if (streq(child->get_name(child), name)) ! 84: { ! 85: found = current; ! 86: found->get_ref(found); ! 87: break; ! 88: } ! 89: } ! 90: e2->destroy(e2); ! 91: if (found) ! 92: { ! 93: break; ! 94: } ! 95: } ! 96: e1->destroy(e1); ! 97: return found; ! 98: } ! 99: ! 100: /** ! 101: * Load IKE config for a given section name ! 102: */ ! 103: static ike_cfg_t *load_ike_config(private_config_t *this, ! 104: settings_t *settings, char *config) ! 105: { ! 106: enumerator_t *enumerator; ! 107: ike_cfg_t *ike_cfg; ! 108: proposal_t *proposal; ! 109: char *token; ! 110: ike_cfg_create_t ike = { ! 111: .version = IKEV2, ! 112: .local = settings->get_str(settings, "configs.%s.lhost", ! 113: "%any", config), ! 114: .local_port = settings->get_int(settings, "configs.%s.lport", ! 115: 500, config), ! 116: .remote = settings->get_str(settings, "configs.%s.rhost", ! 117: "%any", config), ! 118: .remote_port = settings->get_int(settings, "configs.%s.rport", ! 119: 500, config), ! 120: .force_encap = settings->get_bool(settings, "configs.%s.fake_nat", ! 121: FALSE, config), ! 122: }; ! 123: ! 124: ike_cfg = ike_cfg_create(&ike); ! 125: token = settings->get_str(settings, "configs.%s.proposal", NULL, config); ! 126: if (token) ! 127: { ! 128: enumerator = enumerator_create_token(token, ",", " "); ! 129: while (enumerator->enumerate(enumerator, &token)) ! 130: { ! 131: proposal = proposal_create_from_string(PROTO_IKE, token); ! 132: if (proposal) ! 133: { ! 134: ike_cfg->add_proposal(ike_cfg, proposal); ! 135: } ! 136: else ! 137: { ! 138: DBG1(DBG_CFG, "parsing proposal '%s' failed, skipped", token); ! 139: } ! 140: } ! 141: enumerator->destroy(enumerator); ! 142: } ! 143: else ! 144: { ! 145: ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); ! 146: ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE)); ! 147: } ! 148: return ike_cfg; ! 149: } ! 150: /** ! 151: * Load CHILD config for given section names ! 152: */ ! 153: static child_cfg_t *load_child_config(private_config_t *this, ! 154: settings_t *settings, char *config, char *child) ! 155: { ! 156: child_cfg_create_t data = { ! 157: .mode = MODE_TUNNEL, ! 158: }; ! 159: child_cfg_t *child_cfg; ! 160: enumerator_t *enumerator; ! 161: proposal_t *proposal; ! 162: traffic_selector_t *ts; ! 163: char *token; ! 164: ! 165: if (settings->get_bool(settings, "configs.%s.%s.transport", ! 166: FALSE, config, child)) ! 167: { ! 168: data.mode = MODE_TRANSPORT; ! 169: } ! 170: data.tfc = settings->get_int(settings, "configs.%s.%s.tfc_padding", ! 171: 0, config, child); ! 172: child_cfg = child_cfg_create(child, &data); ! 173: ! 174: token = settings->get_str(settings, "configs.%s.%s.proposal", ! 175: NULL, config, child); ! 176: if (token) ! 177: { ! 178: enumerator = enumerator_create_token(token, ",", " "); ! 179: while (enumerator->enumerate(enumerator, &token)) ! 180: { ! 181: proposal = proposal_create_from_string(PROTO_ESP, token); ! 182: if (proposal) ! 183: { ! 184: child_cfg->add_proposal(child_cfg, proposal); ! 185: } ! 186: else ! 187: { ! 188: DBG1(DBG_CFG, "parsing proposal '%s' failed, skipped", token); ! 189: } ! 190: } ! 191: enumerator->destroy(enumerator); ! 192: } ! 193: else ! 194: { ! 195: child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); ! 196: child_cfg->add_proposal(child_cfg, ! 197: proposal_create_default_aead(PROTO_ESP)); ! 198: } ! 199: ! 200: token = settings->get_str(settings, "configs.%s.%s.lts", NULL, config, child); ! 201: if (token) ! 202: { ! 203: enumerator = enumerator_create_token(token, ",", " "); ! 204: while (enumerator->enumerate(enumerator, &token)) ! 205: { ! 206: ts = traffic_selector_create_from_cidr(token, 0, 0, 65535); ! 207: if (ts) ! 208: { ! 209: child_cfg->add_traffic_selector(child_cfg, TRUE, ts); ! 210: } ! 211: else ! 212: { ! 213: DBG1(DBG_CFG, "invalid local ts: %s, skipped", token); ! 214: } ! 215: } ! 216: enumerator->destroy(enumerator); ! 217: } ! 218: else ! 219: { ! 220: ts = traffic_selector_create_dynamic(0, 0, 65535); ! 221: child_cfg->add_traffic_selector(child_cfg, TRUE, ts); ! 222: } ! 223: ! 224: token = settings->get_str(settings, "configs.%s.%s.rts", NULL, config, child); ! 225: if (token) ! 226: { ! 227: enumerator = enumerator_create_token(token, ",", " "); ! 228: while (enumerator->enumerate(enumerator, &token)) ! 229: { ! 230: ts = traffic_selector_create_from_cidr(token, 0, 0, 65535); ! 231: if (ts) ! 232: { ! 233: child_cfg->add_traffic_selector(child_cfg, FALSE, ts); ! 234: } ! 235: else ! 236: { ! 237: DBG1(DBG_CFG, "invalid remote ts: %s, skipped", token); ! 238: } ! 239: } ! 240: enumerator->destroy(enumerator); ! 241: } ! 242: else ! 243: { ! 244: ts = traffic_selector_create_dynamic(0, 0, 65535); ! 245: child_cfg->add_traffic_selector(child_cfg, FALSE, ts); ! 246: } ! 247: return child_cfg; ! 248: } ! 249: ! 250: /** ! 251: * Load peer config for a given section name ! 252: */ ! 253: static peer_cfg_t *load_peer_config(private_config_t *this, ! 254: settings_t *settings, char *config) ! 255: { ! 256: ike_cfg_t *ike_cfg; ! 257: peer_cfg_t *peer_cfg; ! 258: auth_cfg_t *auth; ! 259: child_cfg_t *child_cfg; ! 260: enumerator_t *enumerator; ! 261: identification_t *lid, *rid; ! 262: char *child, *policy, *pool; ! 263: uintptr_t strength; ! 264: peer_cfg_create_t peer = { ! 265: .cert_policy = CERT_ALWAYS_SEND, ! 266: .unique = UNIQUE_NO, ! 267: .keyingtries = 1, ! 268: .no_mobike = TRUE, ! 269: }; ! 270: ! 271: ike_cfg = load_ike_config(this, settings, config); ! 272: peer_cfg = peer_cfg_create(config, ike_cfg, &peer); ! 273: ! 274: auth = auth_cfg_create(); ! 275: auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); ! 276: lid = identification_create_from_string( ! 277: settings->get_str(settings, "configs.%s.lid", "%any", config)); ! 278: auth->add(auth, AUTH_RULE_IDENTITY, lid); ! 279: peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); ! 280: ! 281: auth = auth_cfg_create(); ! 282: auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); ! 283: rid = identification_create_from_string( ! 284: settings->get_str(settings, "configs.%s.rid", "%any", config)); ! 285: strength = settings->get_int(settings, "configs.%s.rsa_strength", 0, config); ! 286: if (strength) ! 287: { ! 288: auth->add(auth, AUTH_RULE_RSA_STRENGTH, strength); ! 289: } ! 290: strength = settings->get_int(settings, "configs.%s.ecdsa_strength", 0, config); ! 291: if (strength) ! 292: { ! 293: auth->add(auth, AUTH_RULE_ECDSA_STRENGTH, strength); ! 294: } ! 295: policy = settings->get_str(settings, "configs.%s.cert_policy", NULL, config); ! 296: if (policy) ! 297: { ! 298: auth->add(auth, AUTH_RULE_CERT_POLICY, strdup(policy)); ! 299: } ! 300: auth->add(auth, AUTH_RULE_IDENTITY, rid); ! 301: peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); ! 302: pool = settings->get_str(settings, "configs.%s.named_pool", NULL, config); ! 303: if (pool) ! 304: { ! 305: peer_cfg->add_pool(peer_cfg, pool); ! 306: } ! 307: ! 308: DBG1(DBG_CFG, "loaded config %s: %Y - %Y", config, lid, rid); ! 309: ! 310: enumerator = settings->create_section_enumerator(settings, ! 311: "configs.%s", config); ! 312: while (enumerator->enumerate(enumerator, &child)) ! 313: { ! 314: child_cfg = load_child_config(this, settings, config, child); ! 315: peer_cfg->add_child_cfg(peer_cfg, child_cfg); ! 316: } ! 317: enumerator->destroy(enumerator); ! 318: return peer_cfg; ! 319: } ! 320: ! 321: METHOD(config_t, load, void, ! 322: private_config_t *this, settings_t *settings) ! 323: { ! 324: enumerator_t *enumerator; ! 325: char *config; ! 326: ! 327: enumerator = settings->create_section_enumerator(settings, "configs"); ! 328: while (enumerator->enumerate(enumerator, &config)) ! 329: { ! 330: this->configs->insert_last(this->configs, ! 331: load_peer_config(this, settings, config)); ! 332: } ! 333: enumerator->destroy(enumerator); ! 334: } ! 335: ! 336: METHOD(config_t, destroy, void, ! 337: private_config_t *this) ! 338: { ! 339: this->configs->destroy_offset(this->configs, offsetof(peer_cfg_t, destroy)); ! 340: free(this); ! 341: } ! 342: ! 343: /** ! 344: * See header ! 345: */ ! 346: config_t *config_create() ! 347: { ! 348: private_config_t *this; ! 349: ! 350: INIT(this, ! 351: .public = { ! 352: .backend = { ! 353: .create_ike_cfg_enumerator = _create_ike_cfg_enumerator, ! 354: .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, ! 355: .get_peer_cfg_by_name = _get_peer_cfg_by_name, ! 356: }, ! 357: .load = _load, ! 358: .destroy = _destroy, ! 359: }, ! 360: .configs = linked_list_create(), ! 361: ); ! 362: ! 363: return &this->public; ! 364: }