Return to unity_narrow.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / unity |
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: }