Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_config.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2007 Martin Willi
3: * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include "ike_config.h"
18:
19: #include <daemon.h>
20: #include <encoding/payloads/cp_payload.h>
21:
22: typedef struct private_ike_config_t private_ike_config_t;
23:
24: /**
25: * Private members of a ike_config_t task.
26: */
27: struct private_ike_config_t {
28:
29: /**
30: * Public methods and task_t interface.
31: */
32: ike_config_t public;
33:
34: /**
35: * Assigned IKE_SA.
36: */
37: ike_sa_t *ike_sa;
38:
39: /**
40: * Are we the initiator?
41: */
42: bool initiator;
43:
44: /**
45: * Did we request a virtual IP?
46: */
47: bool vip_requested;
48:
49: /**
50: * Received list of virtual IPs, host_t*
51: */
52: linked_list_t *vips;
53:
54: /**
55: * list of attributes requested and its handler, entry_t
56: */
57: linked_list_t *requested;
58: };
59:
60: /**
61: * Entry for a requested attribute and the requesting handler
62: */
63: typedef struct {
64: /** attribute requested */
65: configuration_attribute_type_t type;
66: /** handler requesting this attribute */
67: attribute_handler_t *handler;
68: } entry_t;
69:
70: /**
71: * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
72: */
73: static configuration_attribute_t *build_vip(host_t *vip)
74: {
75: configuration_attribute_type_t type;
76: chunk_t chunk, prefix;
77:
78: if (vip->get_family(vip) == AF_INET)
79: {
80: type = INTERNAL_IP4_ADDRESS;
81: if (vip->is_anyaddr(vip))
82: {
83: chunk = chunk_empty;
84: }
85: else
86: {
87: chunk = vip->get_address(vip);
88: }
89: }
90: else
91: {
92: type = INTERNAL_IP6_ADDRESS;
93: if (vip->is_anyaddr(vip))
94: {
95: chunk = chunk_empty;
96: }
97: else
98: {
99: prefix = chunk_alloca(1);
100: *prefix.ptr = 64;
101: chunk = vip->get_address(vip);
102: chunk = chunk_cata("cc", chunk, prefix);
103: }
104: }
105: return configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE,
106: type, chunk);
107: }
108:
109: /**
110: * Handle a received attribute as initiator
111: */
112: static void handle_attribute(private_ike_config_t *this,
113: configuration_attribute_t *ca)
114: {
115: attribute_handler_t *handler = NULL;
116: enumerator_t *enumerator;
117: entry_t *entry;
118:
119: /* find the handler which requested this attribute */
120: enumerator = this->requested->create_enumerator(this->requested);
121: while (enumerator->enumerate(enumerator, &entry))
122: {
123: if (entry->type == ca->get_type(ca))
124: {
125: handler = entry->handler;
126: this->requested->remove_at(this->requested, enumerator);
127: free(entry);
128: break;
129: }
130: }
131: enumerator->destroy(enumerator);
132:
133: /* and pass it to the handle function */
134: handler = charon->attributes->handle(charon->attributes,
135: this->ike_sa, handler, ca->get_type(ca), ca->get_chunk(ca));
136: this->ike_sa->add_configuration_attribute(this->ike_sa,
137: handler, ca->get_type(ca), ca->get_chunk(ca));
138: }
139:
140: /**
141: * process a single configuration attribute
142: */
143: static void process_attribute(private_ike_config_t *this,
144: configuration_attribute_t *ca)
145: {
146: host_t *ip;
147: chunk_t addr;
148: int family = AF_INET6;
149:
150: switch (ca->get_type(ca))
151: {
152: case INTERNAL_IP4_ADDRESS:
153: family = AF_INET;
154: /* fall */
155: case INTERNAL_IP6_ADDRESS:
156: {
157: if (this->initiator && !this->vip_requested)
158: {
159: handle_attribute(this, ca);
160: return;
161: }
162:
163: addr = ca->get_chunk(ca);
164: if (addr.len == 0)
165: {
166: ip = host_create_any(family);
167: }
168: else
169: {
170: /* skip prefix byte in IPv6 payload*/
171: if (family == AF_INET6)
172: {
173: addr.len--;
174: }
175: ip = host_create_from_chunk(family, addr, 0);
176: }
177: if (ip)
178: {
179: this->vips->insert_last(this->vips, ip);
180: }
181: break;
182: }
183: case INTERNAL_IP4_SERVER:
184: case INTERNAL_IP6_SERVER:
185: /* assume it's a Windows client if we see proprietary attributes */
186: this->ike_sa->enable_extension(this->ike_sa, EXT_MS_WINDOWS);
187: /* fall */
188: default:
189: {
190: if (this->initiator)
191: {
192: handle_attribute(this, ca);
193: }
194: }
195: }
196: }
197:
198: /**
199: * Scan for configuration payloads and attributes
200: */
201: static void process_payloads(private_ike_config_t *this, message_t *message)
202: {
203: enumerator_t *enumerator, *attributes;
204: payload_t *payload;
205:
206: enumerator = message->create_payload_enumerator(message);
207: while (enumerator->enumerate(enumerator, &payload))
208: {
209: if (payload->get_type(payload) == PLV2_CONFIGURATION)
210: {
211: cp_payload_t *cp = (cp_payload_t*)payload;
212: configuration_attribute_t *ca;
213:
214: switch (cp->get_type(cp))
215: {
216: case CFG_REQUEST:
217: case CFG_REPLY:
218: {
219: attributes = cp->create_attribute_enumerator(cp);
220: while (attributes->enumerate(attributes, &ca))
221: {
222: DBG2(DBG_IKE, "processing %N attribute",
223: configuration_attribute_type_names, ca->get_type(ca));
224: process_attribute(this, ca);
225: }
226: attributes->destroy(attributes);
227: break;
228: }
229: default:
230: DBG1(DBG_IKE, "ignoring %N config payload",
231: config_type_names, cp->get_type(cp));
232: break;
233: }
234: }
235: }
236: enumerator->destroy(enumerator);
237: }
238:
239: METHOD(task_t, build_i, status_t,
240: private_ike_config_t *this, message_t *message)
241: {
242: if (message->get_message_id(message) == 1)
243: { /* in first IKE_AUTH only */
244: cp_payload_t *cp = NULL;
245: enumerator_t *enumerator;
246: attribute_handler_t *handler;
247: peer_cfg_t *config;
248: configuration_attribute_type_t type;
249: chunk_t data;
250: linked_list_t *vips;
251: host_t *host;
252:
253: vips = linked_list_create();
254:
255: /* reuse virtual IP if we already have one */
256: enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
257: TRUE);
258: while (enumerator->enumerate(enumerator, &host))
259: {
260: vips->insert_last(vips, host);
261: }
262: enumerator->destroy(enumerator);
263:
264: if (vips->get_count(vips) == 0)
265: {
266: config = this->ike_sa->get_peer_cfg(this->ike_sa);
267: enumerator = config->create_virtual_ip_enumerator(config);
268: while (enumerator->enumerate(enumerator, &host))
269: {
270: vips->insert_last(vips, host);
271: }
272: enumerator->destroy(enumerator);
273: }
274:
275: if (vips->get_count(vips))
276: {
277: cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REQUEST);
278: enumerator = vips->create_enumerator(vips);
279: while (enumerator->enumerate(enumerator, &host))
280: {
281: cp->add_attribute(cp, build_vip(host));
282: }
283: enumerator->destroy(enumerator);
284: this->vip_requested = TRUE;
285: }
286:
287: enumerator = charon->attributes->create_initiator_enumerator(
288: charon->attributes, this->ike_sa, vips);
289: while (enumerator->enumerate(enumerator, &handler, &type, &data))
290: {
291: configuration_attribute_t *ca;
292: entry_t *entry;
293:
294: /* create configuration attribute */
295: DBG2(DBG_IKE, "building %N attribute",
296: configuration_attribute_type_names, type);
297: ca = configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE,
298: type, data);
299: if (!cp)
300: {
301: cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REQUEST);
302: }
303: cp->add_attribute(cp, ca);
304:
305: /* save handler along with requested type */
306: entry = malloc_thing(entry_t);
307: entry->type = type;
308: entry->handler = handler;
309:
310: this->requested->insert_last(this->requested, entry);
311: }
312: enumerator->destroy(enumerator);
313:
314: vips->destroy(vips);
315:
316: if (cp)
317: {
318: message->add_payload(message, (payload_t*)cp);
319: }
320: else
321: { /* we don't expect a CFG_REPLY */
322: return SUCCESS;
323: }
324: }
325: return NEED_MORE;
326: }
327:
328: METHOD(task_t, process_r, status_t,
329: private_ike_config_t *this, message_t *message)
330: {
331: if (message->get_message_id(message) == 1)
332: { /* in first IKE_AUTH only */
333: process_payloads(this, message);
334: }
335: return NEED_MORE;
336: }
337:
338: METHOD(task_t, build_r, status_t,
339: private_ike_config_t *this, message_t *message)
340: {
341: if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
342: { /* in last IKE_AUTH exchange */
343: enumerator_t *enumerator;
344: configuration_attribute_type_t type;
345: chunk_t value;
346: cp_payload_t *cp = NULL;
347: peer_cfg_t *config;
348: identification_t *id;
349: linked_list_t *vips, *pools;
350: host_t *requested;
351:
352: if (this->ike_sa->has_condition(this->ike_sa, COND_REDIRECTED))
353: { /* don't assign attributes for redirected SAs */
354: return SUCCESS;
355: }
356:
357: id = this->ike_sa->get_other_eap_id(this->ike_sa);
358: config = this->ike_sa->get_peer_cfg(this->ike_sa);
359: vips = linked_list_create();
360: pools = linked_list_create_from_enumerator(
361: config->create_pool_enumerator(config));
362:
363: this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
364:
365: enumerator = this->vips->create_enumerator(this->vips);
366: while (enumerator->enumerate(enumerator, &requested))
367: {
368: host_t *found = NULL;
369:
370: /* query all pools until we get an address */
371: DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
372:
373: found = charon->attributes->acquire_address(charon->attributes,
374: pools, this->ike_sa, requested);
375: if (found)
376: {
377: DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
378: this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
379: if (!cp)
380: {
381: cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REPLY);
382: }
383: cp->add_attribute(cp, build_vip(found));
384: vips->insert_last(vips, found);
385: }
386: else
387: {
388: DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
389: requested, id);
390: }
391: }
392: enumerator->destroy(enumerator);
393:
394: if (this->vips->get_count(this->vips) && !vips->get_count(vips))
395: {
396: DBG1(DBG_IKE, "no virtual IP found, sending %N",
397: notify_type_names, INTERNAL_ADDRESS_FAILURE);
398: charon->bus->alert(charon->bus, ALERT_VIP_FAILURE, this->vips);
399: message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
400: chunk_empty);
401: vips->destroy_offset(vips, offsetof(host_t, destroy));
402: pools->destroy(pools);
403: return SUCCESS;
404: }
405: charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE);
406:
407: if (pools->get_count(pools) && !this->vips->get_count(this->vips))
408: {
409: DBG1(DBG_IKE, "expected a virtual IP request, sending %N",
410: notify_type_names, FAILED_CP_REQUIRED);
411: charon->bus->alert(charon->bus, ALERT_VIP_FAILURE, this->vips);
412: message->add_notify(message, FALSE, FAILED_CP_REQUIRED, chunk_empty);
413: vips->destroy_offset(vips, offsetof(host_t, destroy));
414: pools->destroy(pools);
415: return SUCCESS;
416: }
417:
418: /* query registered providers for additional attributes to include */
419: enumerator = charon->attributes->create_responder_enumerator(
420: charon->attributes, pools, this->ike_sa, vips);
421: while (enumerator->enumerate(enumerator, &type, &value))
422: {
423: if (!cp)
424: {
425: cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REPLY);
426: }
427: DBG2(DBG_IKE, "building %N attribute",
428: configuration_attribute_type_names, type);
429: cp->add_attribute(cp,
430: configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE,
431: type, value));
432: }
433: enumerator->destroy(enumerator);
434: vips->destroy_offset(vips, offsetof(host_t, destroy));
435: pools->destroy(pools);
436:
437: if (cp)
438: {
439: message->add_payload(message, (payload_t*)cp);
440: }
441: return SUCCESS;
442: }
443: return NEED_MORE;
444: }
445:
446: METHOD(task_t, process_i, status_t,
447: private_ike_config_t *this, message_t *message)
448: {
449: if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
450: { /* in last IKE_AUTH exchange */
451: enumerator_t *enumerator;
452: host_t *host;
453:
454: process_payloads(this, message);
455:
456: this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE);
457:
458: enumerator = this->vips->create_enumerator(this->vips);
459: while (enumerator->enumerate(enumerator, &host))
460: {
461: if (!host->is_anyaddr(host))
462: {
463: this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
464: }
465: }
466: enumerator->destroy(enumerator);
467:
468: charon->bus->handle_vips(charon->bus, this->ike_sa, TRUE);
469: return SUCCESS;
470: }
471: return NEED_MORE;
472: }
473:
474: METHOD(task_t, get_type, task_type_t,
475: private_ike_config_t *this)
476: {
477: return TASK_IKE_CONFIG;
478: }
479:
480: METHOD(task_t, migrate, void,
481: private_ike_config_t *this, ike_sa_t *ike_sa)
482: {
483: this->ike_sa = ike_sa;
484: this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
485: this->vips = linked_list_create();
486: this->requested->destroy_function(this->requested, free);
487: this->requested = linked_list_create();
488: }
489:
490: METHOD(task_t, destroy, void,
491: private_ike_config_t *this)
492: {
493: this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
494: this->requested->destroy_function(this->requested, free);
495: free(this);
496: }
497:
498: /*
499: * Described in header.
500: */
501: ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
502: {
503: private_ike_config_t *this;
504:
505: INIT(this,
506: .public = {
507: .task = {
508: .get_type = _get_type,
509: .migrate = _migrate,
510: .destroy = _destroy,
511: },
512: },
513: .initiator = initiator,
514: .ike_sa = ike_sa,
515: .vips = linked_list_create(),
516: .requested = linked_list_create(),
517: );
518:
519: if (initiator)
520: {
521: this->public.task.build = _build_i;
522: this->public.task.process = _process_i;
523: }
524: else
525: {
526: this->public.task.build = _build_r;
527: this->public.task.process = _process_r;
528: }
529:
530: return &this->public;
531: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>