Annotation of embedaddon/strongswan/src/libcharon/plugins/unity/unity_narrow.c, revision 1.1.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>