Annotation of embedaddon/strongswan/src/libcharon/plugins/unity/unity_narrow.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2014 Tobias Brunner
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * Copyright (C) 2012 Martin Willi
! 6: * Copyright (C) 2012 revosec AG
! 7: *
! 8: * This program is free software; you can redistribute it and/or modify it
! 9: * under the terms of the GNU General Public License as published by the
! 10: * Free Software Foundation; either version 2 of the License, or (at your
! 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 12: *
! 13: * This program is distributed in the hope that it will be useful, but
! 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 16: * for more details.
! 17: */
! 18:
! 19: #include "unity_narrow.h"
! 20:
! 21: #include <daemon.h>
! 22: #include <encoding/payloads/id_payload.h>
! 23: #include <collections/hashtable.h>
! 24:
! 25: typedef struct private_unity_narrow_t private_unity_narrow_t;
! 26:
! 27: /**
! 28: * Private data of an unity_narrow_t object.
! 29: */
! 30: struct private_unity_narrow_t {
! 31:
! 32: /**
! 33: * Public unity_narrow_t interface.
! 34: */
! 35: unity_narrow_t public;
! 36:
! 37: /**
! 38: * Unity attribute handler
! 39: */
! 40: unity_handler_t *handler;
! 41:
! 42: /**
! 43: * IKE_SAs for which we received 0.0.0.0/0 as remote traffic selector
! 44: */
! 45: hashtable_t *wildcard_ts;
! 46: };
! 47:
! 48: /**
! 49: * Narrow the given received traffic selector with the child configuration and
! 50: * put them into the given list of TS
! 51: */
! 52: static void narrow_ts(child_cfg_t *cfg, traffic_selector_t *ts,
! 53: linked_list_t *list)
! 54: {
! 55: linked_list_t *received, *selected;
! 56:
! 57: received = linked_list_create();
! 58: received->insert_last(received, ts);
! 59: selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL, FALSE);
! 60: while (selected->remove_first(selected, (void**)&ts) == SUCCESS)
! 61: {
! 62: list->insert_last(list, ts);
! 63: }
! 64: selected->destroy(selected);
! 65: received->destroy(received);
! 66: }
! 67:
! 68: /**
! 69: * Narrow TS as initiator to Unity Split-Include/Local-LAN
! 70: */
! 71: static void narrow_initiator(private_unity_narrow_t *this, ike_sa_t *ike_sa,
! 72: child_cfg_t *cfg, linked_list_t *remote)
! 73: {
! 74: traffic_selector_t *current, *orig = NULL;
! 75: enumerator_t *enumerator;
! 76:
! 77: enumerator = this->handler->create_include_enumerator(this->handler,
! 78: ike_sa->get_id(ike_sa));
! 79: while (enumerator->enumerate(enumerator, ¤t))
! 80: {
! 81: if (orig == NULL)
! 82: { /* got one, replace original TS */
! 83: if (remote->remove_first(remote, (void**)&orig) != SUCCESS)
! 84: {
! 85: break;
! 86: }
! 87: }
! 88: narrow_ts(cfg, current, remote);
! 89: }
! 90: enumerator->destroy(enumerator);
! 91: if (orig)
! 92: {
! 93: DBG1(DBG_CFG, "narrowed CHILD_SA to %N %#R",
! 94: configuration_attribute_type_names,
! 95: UNITY_SPLIT_INCLUDE, remote);
! 96: orig->destroy(orig);
! 97: }
! 98: else
! 99: { /* since we originally changed the traffic selector to 0.0.0.0/0 local
! 100: * narrowing is not applied if no Split-Include attrs are received */
! 101: if (remote->remove_first(remote, (void**)&orig) == SUCCESS)
! 102: {
! 103: narrow_ts(cfg, orig, remote);
! 104: orig->destroy(orig);
! 105: }
! 106: }
! 107: }
! 108:
! 109: /**
! 110: * As initiator and responder, bump up TS to 0.0.0.0/0 for on-the-wire bits
! 111: */
! 112: static void narrow_pre(linked_list_t *list, char *side)
! 113: {
! 114: traffic_selector_t *ts;
! 115:
! 116: while (list->remove_first(list, (void**)&ts) == SUCCESS)
! 117: {
! 118: ts->destroy(ts);
! 119: }
! 120: ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
! 121: "0.0.0.0", 0,
! 122: "255.255.255.255", 65535);
! 123: if (ts)
! 124: {
! 125: DBG2(DBG_CFG, "changing proposed traffic selectors for %s:", side);
! 126: DBG2(DBG_CFG, " %R", ts);
! 127: list->insert_last(list, ts);
! 128: }
! 129: }
! 130:
! 131: /**
! 132: * As responder, narrow down TS to configuration for installation
! 133: */
! 134: static void narrow_responder_post(child_cfg_t *child_cfg, linked_list_t *local)
! 135: {
! 136: traffic_selector_t *ts;
! 137: linked_list_t *configured;
! 138:
! 139: while (local->remove_first(local, (void**)&ts) == SUCCESS)
! 140: {
! 141: ts->destroy(ts);
! 142: }
! 143: configured = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL,
! 144: FALSE);
! 145:
! 146: while (configured->remove_first(configured, (void**)&ts) == SUCCESS)
! 147: {
! 148: local->insert_last(local, ts);
! 149: }
! 150: configured->destroy(configured);
! 151: }
! 152:
! 153: /**
! 154: * Check if any Split-Include attributes are active on this IKE_SA
! 155: */
! 156: static bool has_split_includes(private_unity_narrow_t *this, ike_sa_t *ike_sa)
! 157: {
! 158: enumerator_t *enumerator;
! 159: traffic_selector_t *ts;
! 160: bool has;
! 161:
! 162: enumerator = this->handler->create_include_enumerator(this->handler,
! 163: ike_sa->get_id(ike_sa));
! 164: has = enumerator->enumerate(enumerator, &ts);
! 165: enumerator->destroy(enumerator);
! 166:
! 167: return has;
! 168: }
! 169:
! 170: METHOD(listener_t, narrow, bool,
! 171: private_unity_narrow_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
! 172: narrow_hook_t type, linked_list_t *local, linked_list_t *remote)
! 173: {
! 174: if (ike_sa->get_version(ike_sa) == IKEV1 &&
! 175: ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
! 176: {
! 177: /* depending on who initiates a rekeying the hooks will not match the
! 178: * roles in the IKE_SA */
! 179: if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
! 180: {
! 181: switch (type)
! 182: {
! 183: case NARROW_INITIATOR_PRE_AUTH:
! 184: case NARROW_RESPONDER:
! 185: if (has_split_includes(this, ike_sa))
! 186: {
! 187: narrow_pre(remote, "other");
! 188: }
! 189: break;
! 190: case NARROW_INITIATOR_POST_AUTH:
! 191: case NARROW_RESPONDER_POST:
! 192: narrow_initiator(this, ike_sa,
! 193: child_sa->get_config(child_sa), remote);
! 194: break;
! 195: default:
! 196: break;
! 197: }
! 198: }
! 199: else
! 200: {
! 201: switch (type)
! 202: {
! 203: case NARROW_INITIATOR_PRE_AUTH:
! 204: case NARROW_RESPONDER:
! 205: if (this->wildcard_ts->get(this->wildcard_ts, ike_sa))
! 206: {
! 207: narrow_pre(local, "us");
! 208:
! 209: }
! 210: break;
! 211: case NARROW_INITIATOR_POST_AUTH:
! 212: case NARROW_RESPONDER_POST:
! 213: if (this->wildcard_ts->get(this->wildcard_ts, ike_sa))
! 214: {
! 215: narrow_responder_post(child_sa->get_config(child_sa),
! 216: local);
! 217: }
! 218: break;
! 219: default:
! 220: break;
! 221: }
! 222: }
! 223: }
! 224: return TRUE;
! 225: }
! 226:
! 227: METHOD(listener_t, message, bool,
! 228: private_unity_narrow_t *this, ike_sa_t *ike_sa, message_t *message,
! 229: bool incoming, bool plain)
! 230: {
! 231: traffic_selector_t *tsr = NULL, *wildcard;
! 232: enumerator_t *enumerator;
! 233: id_payload_t *id_payload;
! 234: payload_t *payload;
! 235: bool first = TRUE;
! 236:
! 237: if (!incoming || !plain ||
! 238: message->get_exchange_type(message) != QUICK_MODE ||
! 239: !ike_sa || !ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
! 240: {
! 241: return TRUE;
! 242: }
! 243: enumerator = message->create_payload_enumerator(message);
! 244: while (enumerator->enumerate(enumerator, &payload))
! 245: {
! 246: if (payload->get_type(payload) == PLV1_ID)
! 247: {
! 248: if (!first)
! 249: {
! 250: id_payload = (id_payload_t*)payload;
! 251: tsr = id_payload->get_ts(id_payload);
! 252: break;
! 253: }
! 254: first = FALSE;
! 255: }
! 256: }
! 257: enumerator->destroy(enumerator);
! 258: if (!tsr)
! 259: {
! 260: return TRUE;
! 261: }
! 262: wildcard = traffic_selector_create_from_cidr("0.0.0.0/0", 0, 0, 65535);
! 263: if (tsr->equals(tsr, wildcard))
! 264: {
! 265: this->wildcard_ts->put(this->wildcard_ts, ike_sa, ike_sa);
! 266: }
! 267: else
! 268: {
! 269: this->wildcard_ts->remove(this->wildcard_ts, ike_sa);
! 270: }
! 271: wildcard->destroy(wildcard);
! 272: tsr->destroy(tsr);
! 273: return TRUE;
! 274: }
! 275:
! 276: METHOD(listener_t, ike_updown, bool,
! 277: private_unity_narrow_t *this, ike_sa_t *ike_sa, bool up)
! 278: {
! 279: if (!up)
! 280: {
! 281: this->wildcard_ts->remove(this->wildcard_ts, ike_sa);
! 282: }
! 283: return TRUE;
! 284: }
! 285:
! 286: METHOD(unity_narrow_t, destroy, void,
! 287: private_unity_narrow_t *this)
! 288: {
! 289: this->wildcard_ts->destroy(this->wildcard_ts);
! 290: free(this);
! 291: }
! 292:
! 293: /**
! 294: * See header
! 295: */
! 296: unity_narrow_t *unity_narrow_create(unity_handler_t *handler)
! 297: {
! 298: private_unity_narrow_t *this;
! 299:
! 300: INIT(this,
! 301: .public = {
! 302: .listener = {
! 303: .narrow = _narrow,
! 304: .message = _message,
! 305: .ike_updown = _ike_updown,
! 306: },
! 307: .destroy = _destroy,
! 308: },
! 309: .handler = handler,
! 310: .wildcard_ts = hashtable_create(hashtable_hash_ptr,
! 311: hashtable_equals_ptr, 4),
! 312: );
! 313:
! 314: return &this->public;
! 315: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>