ipsec status lists IPCOMP CPIs
[strongswan.git] / src / charon / sa / tasks / child_create.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2007 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 *
17 * $Id$
18 */
19
20 #include "child_create.h"
21
22 #include <daemon.h>
23 #include <crypto/diffie_hellman.h>
24 #include <encoding/payloads/sa_payload.h>
25 #include <encoding/payloads/ke_payload.h>
26 #include <encoding/payloads/ts_payload.h>
27 #include <encoding/payloads/nonce_payload.h>
28 #include <encoding/payloads/notify_payload.h>
29 #include <processing/jobs/delete_ike_sa_job.h>
30
31
32 typedef struct private_child_create_t private_child_create_t;
33
34 /**
35 * Private members of a child_create_t task.
36 */
37 struct private_child_create_t {
38
39 /**
40 * Public methods and task_t interface.
41 */
42 child_create_t public;
43
44 /**
45 * Assigned IKE_SA.
46 */
47 ike_sa_t *ike_sa;
48
49 /**
50 * Are we the initiator?
51 */
52 bool initiator;
53
54 /**
55 * nonce chosen by us
56 */
57 chunk_t my_nonce;
58
59 /**
60 * nonce chosen by peer
61 */
62 chunk_t other_nonce;
63
64 /**
65 * config to create the CHILD_SA from
66 */
67 child_cfg_t *config;
68
69 /**
70 * list of proposal candidates
71 */
72 linked_list_t *proposals;
73
74 /**
75 * selected proposal to use for CHILD_SA
76 */
77 proposal_t *proposal;
78
79 /**
80 * traffic selectors for initiators side
81 */
82 linked_list_t *tsi;
83
84 /**
85 * traffic selectors for responders side
86 */
87 linked_list_t *tsr;
88
89 /**
90 * optional diffie hellman exchange
91 */
92 diffie_hellman_t *dh;
93
94 /**
95 * group used for DH exchange
96 */
97 diffie_hellman_group_t dh_group;
98
99 /**
100 * mode the new CHILD_SA uses (transport/tunnel/beet)
101 */
102 mode_t mode;
103
104 /**
105 * IPComp transform to use
106 */
107 ipcomp_transform_t ipcomp;
108
109 /**
110 * IPComp transform proposed or accepted by the other peer
111 */
112 ipcomp_transform_t ipcomp_received;
113
114 /**
115 * Other Compression Parameter Index (CPI)
116 */
117 u_int16_t other_cpi;
118
119 /**
120 * reqid to use if we are rekeying
121 */
122 u_int32_t reqid;
123
124 /**
125 * CHILD_SA which gets established
126 */
127 child_sa_t *child_sa;
128
129 /**
130 * successfully established the CHILD?
131 */
132 bool established;
133 };
134
135 /**
136 * get the nonce from a message
137 */
138 static status_t get_nonce(message_t *message, chunk_t *nonce)
139 {
140 nonce_payload_t *payload;
141
142 payload = (nonce_payload_t*)message->get_payload(message, NONCE);
143 if (payload == NULL)
144 {
145 return FAILED;
146 }
147 *nonce = payload->get_nonce(payload);
148 return NEED_MORE;
149 }
150
151 /**
152 * generate a new nonce to include in a CREATE_CHILD_SA message
153 */
154 static status_t generate_nonce(chunk_t *nonce)
155 {
156 rng_t *rng;
157
158 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
159 if (!rng)
160 {
161 DBG1(DBG_IKE, "error generating nonce value, no RNG found");
162 return FAILED;
163 }
164 rng->allocate_bytes(rng, NONCE_SIZE, nonce);
165 rng->destroy(rng);
166 return SUCCESS;
167 }
168
169 /**
170 * Check a list of traffic selectors if any selector belongs to host
171 */
172 static bool ts_list_is_host(linked_list_t *list, host_t *host)
173 {
174 traffic_selector_t *ts;
175 bool is_host = TRUE;
176 iterator_t *iterator = list->create_iterator(list, TRUE);
177
178 while (is_host && iterator->iterate(iterator, (void**)&ts))
179 {
180 is_host = is_host && ts->is_host(ts, host);
181 }
182 iterator->destroy(iterator);
183 return is_host;
184 }
185
186 /**
187 * Install a CHILD_SA for usage, return value:
188 * - FAILED: no acceptable proposal
189 * - INVALID_ARG: diffie hellman group inacceptable
190 * - NOT_FOUND: TS inacceptable
191 */
192 static status_t select_and_install(private_child_create_t *this, bool no_dh)
193 {
194 prf_plus_t *prf_plus;
195 status_t status;
196 chunk_t nonce_i, nonce_r, secret, seed;
197 linked_list_t *my_ts, *other_ts;
198 host_t *me, *other, *other_vip, *my_vip;
199
200 if (this->proposals == NULL)
201 {
202 SIG_CHD(UP_FAILED, this->child_sa, "SA payload missing in message");
203 return FAILED;
204 }
205 if (this->tsi == NULL || this->tsr == NULL)
206 {
207 SIG_CHD(UP_FAILED, this->child_sa, "TS payloads missing in message");
208 return NOT_FOUND;
209 }
210
211 if (this->initiator)
212 {
213 nonce_i = this->my_nonce;
214 nonce_r = this->other_nonce;
215 my_ts = this->tsi;
216 other_ts = this->tsr;
217 }
218 else
219 {
220 nonce_r = this->my_nonce;
221 nonce_i = this->other_nonce;
222 my_ts = this->tsr;
223 other_ts = this->tsi;
224 }
225
226 me = this->ike_sa->get_my_host(this->ike_sa);
227 other = this->ike_sa->get_other_host(this->ike_sa);
228 my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
229 other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
230
231 this->proposal = this->config->select_proposal(this->config, this->proposals,
232 no_dh);
233 if (this->proposal == NULL)
234 {
235 SIG_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found");
236 return FAILED;
237 }
238
239 if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
240 {
241 u_int16_t group;
242
243 if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
244 &group, NULL))
245 {
246 SIG_CHD(UP_FAILED, this->child_sa, "DH group %N inacceptable, "
247 "requesting %N", diffie_hellman_group_names, this->dh_group,
248 diffie_hellman_group_names, group);
249 this->dh_group = group;
250 return INVALID_ARG;
251 }
252 else
253 {
254 SIG_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found");
255 return FAILED;
256 }
257 }
258
259 if (my_vip == NULL)
260 {
261 my_vip = me;
262 }
263 else if (this->initiator)
264 {
265 /* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
266 this->child_sa->set_virtual_ip(this->child_sa, my_vip);
267 }
268 if (other_vip == NULL)
269 {
270 other_vip = other;
271 }
272
273 my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
274 my_vip);
275 other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
276 other_vip);
277
278 if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
279 {
280 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
281 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
282 SIG_CHD(UP_FAILED, this->child_sa, "no acceptable traffic selectors found");
283 return NOT_FOUND;
284 }
285
286 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
287 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
288 if (this->initiator)
289 {
290 this->tsi = my_ts;
291 this->tsr = other_ts;
292 }
293 else
294 {
295 this->tsr = my_ts;
296 this->tsi = other_ts;
297 }
298
299 if (!this->initiator)
300 {
301 /* check if requested mode is acceptable, downgrade if required */
302 switch (this->mode)
303 {
304 case MODE_TRANSPORT:
305 if (!ts_list_is_host(this->tsi, other) ||
306 !ts_list_is_host(this->tsr, me))
307 {
308 this->mode = MODE_TUNNEL;
309 DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
310 }
311 else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
312 {
313 this->mode = MODE_TUNNEL;
314 DBG1(DBG_IKE, "not using tranport mode, connection NATed");
315 }
316 break;
317 case MODE_BEET:
318 if (!ts_list_is_host(this->tsi, NULL) ||
319 !ts_list_is_host(this->tsr, NULL))
320 {
321 this->mode = MODE_TUNNEL;
322 DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
323 }
324 break;
325 default:
326 break;
327 }
328 }
329
330 if (this->dh)
331 {
332 if (this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
333 {
334 SIG_CHD(UP_FAILED, this->child_sa, "DH exchange incomplete");
335 return FAILED;
336 }
337 DBG3(DBG_IKE, "DH secret %B", &secret);
338 seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
339 }
340 else
341 {
342 seed = chunk_cata("cc", nonce_i, nonce_r);
343 }
344
345 if (this->ipcomp != IPCOMP_NONE)
346 {
347 this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
348 this->other_cpi);
349 }
350
351 status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
352 this->mode, this->proposal->get_protocol(this->proposal));
353 if (status != SUCCESS)
354 {
355 SIG_CHD(UP_FAILED, this->child_sa,
356 "unable to install IPsec policies (SPD) in kernel");
357 return NOT_FOUND;
358 }
359
360 prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
361 if (this->initiator)
362 {
363 status = this->child_sa->update(this->child_sa, this->proposal,
364 this->mode, prf_plus);
365 }
366 else
367 {
368 status = this->child_sa->add(this->child_sa, this->proposal,
369 this->mode, prf_plus);
370 }
371 prf_plus->destroy(prf_plus);
372
373 if (status != SUCCESS)
374 {
375 SIG_CHD(UP_FAILED, this->child_sa,
376 "unable to install IPsec SA (SAD) in kernel");
377 return FAILED;
378 }
379 /* add to IKE_SA, and remove from task */
380 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
381 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
382 this->established = TRUE;
383 return SUCCESS;
384 }
385
386 /**
387 * build the payloads for the message
388 */
389 static void build_payloads(private_child_create_t *this, message_t *message)
390 {
391 sa_payload_t *sa_payload;
392 nonce_payload_t *nonce_payload;
393 ke_payload_t *ke_payload;
394 ts_payload_t *ts_payload;
395
396 /* add SA payload */
397 if (this->initiator)
398 {
399 sa_payload = sa_payload_create_from_proposal_list(this->proposals);
400 }
401 else
402 {
403 sa_payload = sa_payload_create_from_proposal(this->proposal);
404 }
405 message->add_payload(message, (payload_t*)sa_payload);
406
407 /* add nonce payload if not in IKE_AUTH */
408 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
409 {
410 nonce_payload = nonce_payload_create();
411 nonce_payload->set_nonce(nonce_payload, this->my_nonce);
412 message->add_payload(message, (payload_t*)nonce_payload);
413 }
414
415 /* diffie hellman exchange, if PFS enabled */
416 if (this->dh)
417 {
418 ke_payload = ke_payload_create_from_diffie_hellman(this->dh);
419 message->add_payload(message, (payload_t*)ke_payload);
420 }
421
422 /* add TSi/TSr payloads */
423 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
424 message->add_payload(message, (payload_t*)ts_payload);
425 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
426 message->add_payload(message, (payload_t*)ts_payload);
427
428 /* add a notify if we are not in tunnel mode */
429 switch (this->mode)
430 {
431 case MODE_TRANSPORT:
432 message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
433 break;
434 case MODE_BEET:
435 message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
436 break;
437 default:
438 break;
439 }
440 }
441
442 /**
443 * Adds an IPCOMP_SUPPORTED notify to the message, if possible
444 */
445 static void build_ipcomp_supported_notify(private_child_create_t *this,
446 message_t *message)
447 {
448 u_int16_t cpi;
449 u_int8_t tid;
450
451 if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
452 {
453 DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, "
454 "IPComp disabled");
455 this->ipcomp = IPCOMP_NONE;
456 return;
457 }
458
459 cpi = this->child_sa->allocate_cpi(this->child_sa);
460 tid = this->ipcomp;
461 if (cpi)
462 {
463 message->add_notify(message, FALSE, IPCOMP_SUPPORTED,
464 chunk_cata("cc", chunk_from_thing(cpi), chunk_from_thing(tid)));
465 }
466 else
467 {
468 DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
469 this->ipcomp = IPCOMP_NONE;
470 }
471 }
472
473 /**
474 * Read payloads from message
475 */
476 static void process_payloads(private_child_create_t *this, message_t *message)
477 {
478 iterator_t *iterator;
479 payload_t *payload;
480 sa_payload_t *sa_payload;
481 ke_payload_t *ke_payload;
482 ts_payload_t *ts_payload;
483 notify_payload_t *notify_payload;
484
485 /* defaults to TUNNEL mode */
486 this->mode = MODE_TUNNEL;
487
488 iterator = message->get_payload_iterator(message);
489 while (iterator->iterate(iterator, (void**)&payload))
490 {
491 switch (payload->get_type(payload))
492 {
493 case SECURITY_ASSOCIATION:
494 sa_payload = (sa_payload_t*)payload;
495 this->proposals = sa_payload->get_proposals(sa_payload);
496 break;
497 case KEY_EXCHANGE:
498 ke_payload = (ke_payload_t*)payload;
499 if (!this->initiator)
500 {
501 this->dh_group = ke_payload->get_dh_group_number(ke_payload);
502 this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
503 }
504 if (this->dh)
505 {
506 this->dh->set_other_public_value(this->dh,
507 ke_payload->get_key_exchange_data(ke_payload));
508 }
509 break;
510 case TRAFFIC_SELECTOR_INITIATOR:
511 ts_payload = (ts_payload_t*)payload;
512 this->tsi = ts_payload->get_traffic_selectors(ts_payload);
513 break;
514 case TRAFFIC_SELECTOR_RESPONDER:
515 ts_payload = (ts_payload_t*)payload;
516 this->tsr = ts_payload->get_traffic_selectors(ts_payload);
517 break;
518 case NOTIFY:
519 notify_payload = (notify_payload_t*)payload;
520 switch (notify_payload ->get_notify_type(notify_payload ))
521 {
522 case USE_TRANSPORT_MODE:
523 this->mode = MODE_TRANSPORT;
524 break;
525 case USE_BEET_MODE:
526 this->mode = MODE_BEET;
527 break;
528 case IPCOMP_SUPPORTED:
529 {
530 chunk_t data = notify_payload->get_notification_data(notify_payload);
531 u_int16_t cpi = *(u_int16_t*)data.ptr;
532 ipcomp_transform_t ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
533 switch(ipcomp)
534 {
535 case IPCOMP_DEFLATE:
536 this->other_cpi = cpi;
537 this->ipcomp_received = ipcomp;
538 break;
539 case IPCOMP_LZS:
540 case IPCOMP_LZJH:
541 default:
542 DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a transform"
543 " ID we don't support %N", ipcomp_transform_names, ipcomp);
544 break;
545 }
546 }
547 default:
548 break;
549 }
550 break;
551 default:
552 break;
553 }
554 }
555 iterator->destroy(iterator);
556 }
557
558 /**
559 * Implementation of task_t.build for initiator
560 */
561 static status_t build_i(private_child_create_t *this, message_t *message)
562 {
563 host_t *me, *other, *vip;
564 bool propose_all = FALSE;
565 peer_cfg_t *peer_cfg;
566
567 switch (message->get_exchange_type(message))
568 {
569 case IKE_SA_INIT:
570 return get_nonce(message, &this->my_nonce);
571 case CREATE_CHILD_SA:
572 if (generate_nonce(&this->my_nonce) != SUCCESS)
573 {
574 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
575 return SUCCESS;
576 }
577 if (this->dh_group == MODP_NONE)
578 {
579 this->dh_group = this->config->get_dh_group(this->config);
580 }
581 break;
582 case IKE_AUTH:
583 if (!message->get_payload(message, ID_INITIATOR))
584 {
585 /* send only in the first request, not in subsequent EAP */
586 return NEED_MORE;
587 }
588 break;
589 default:
590 break;
591 }
592
593 SIG_CHD(UP_START, NULL, "establishing CHILD_SA '%s'",
594 this->config->get_name(this->config));
595
596 /* reuse virtual IP if we already have one */
597 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
598 if (me == NULL)
599 {
600 me = this->ike_sa->get_my_host(this->ike_sa);
601 }
602 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
603 if (other == NULL)
604 {
605 other = this->ike_sa->get_other_host(this->ike_sa);
606 }
607
608 /* check if we want a virtual IP, but don't have one */
609 if (!this->reqid)
610 {
611 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
612 vip = peer_cfg->get_virtual_ip(peer_cfg);
613 if (vip)
614 {
615 propose_all = TRUE;
616 }
617 }
618
619 if (propose_all)
620 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
621 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
622 NULL, NULL);
623 }
624 else
625 { /* but shorten a 0.0.0.0/0 subnet for host2host/we already have a vip */
626 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
627 NULL, me);
628 }
629 this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
630 NULL, other);
631
632 this->proposals = this->config->get_proposals(this->config,
633 this->dh_group == MODP_NONE);
634 this->mode = this->config->get_mode(this->config);
635
636 this->child_sa = child_sa_create(
637 this->ike_sa->get_my_host(this->ike_sa),
638 this->ike_sa->get_other_host(this->ike_sa),
639 this->ike_sa->get_my_id(this->ike_sa),
640 this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
641 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
642
643 if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
644 {
645 SIG_CHD(UP_FAILED, this->child_sa,
646 "unable to allocate SPIs from kernel");
647 return FAILED;
648 }
649
650 if (this->dh_group != MODP_NONE)
651 {
652 this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
653 }
654
655 if (this->config->use_ipcomp(this->config)) {
656 /* IPCOMP_DEFLATE is the only transform we support at the moment */
657 this->ipcomp = IPCOMP_DEFLATE;
658 build_ipcomp_supported_notify(this, message);
659 }
660
661 build_payloads(this, message);
662
663 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
664 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
665 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
666 this->tsi = NULL;
667 this->tsr = NULL;
668 this->proposals = NULL;
669
670 return NEED_MORE;
671 }
672
673 /**
674 * Implementation of task_t.process for initiator
675 */
676 static status_t process_r(private_child_create_t *this, message_t *message)
677 {
678 peer_cfg_t *peer_cfg;
679
680 switch (message->get_exchange_type(message))
681 {
682 case IKE_SA_INIT:
683 return get_nonce(message, &this->other_nonce);
684 case CREATE_CHILD_SA:
685 get_nonce(message, &this->other_nonce);
686 break;
687 case IKE_AUTH:
688 if (message->get_payload(message, ID_INITIATOR) == NULL)
689 {
690 /* wait until extensible authentication completed, if used */
691 return NEED_MORE;
692 }
693 default:
694 break;
695 }
696
697 process_payloads(this, message);
698
699 if (this->tsi == NULL || this->tsr == NULL)
700 {
701 DBG1(DBG_IKE, "TS payload missing in message");
702 return NEED_MORE;
703 }
704
705 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
706 if (peer_cfg)
707 {
708 host_t *me, *other;
709
710 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
711 if (me == NULL)
712 {
713 me = this->ike_sa->get_my_host(this->ike_sa);
714 }
715 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
716 if (other == NULL)
717 {
718 other = this->ike_sa->get_other_host(this->ike_sa);
719 }
720
721 this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
722 this->tsi, me, other);
723 }
724 return NEED_MORE;
725 }
726
727 /**
728 * handle CHILD_SA setup failure
729 */
730 static void handle_child_sa_failure(private_child_create_t *this,
731 message_t *message)
732 {
733 if (message->get_exchange_type(message) == IKE_AUTH &&
734 lib->settings->get_bool(lib->settings,
735 "charon.close_ike_on_child_failure", FALSE))
736 {
737 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
738 * first */
739 DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
740 charon->scheduler->schedule_job(charon->scheduler, (job_t*)
741 delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
742 100);
743 }
744 }
745
746 /**
747 * Implementation of task_t.build for responder
748 */
749 static status_t build_r(private_child_create_t *this, message_t *message)
750 {
751 payload_t *payload;
752 iterator_t *iterator;
753 bool no_dh = TRUE;
754
755 switch (message->get_exchange_type(message))
756 {
757 case IKE_SA_INIT:
758 return get_nonce(message, &this->my_nonce);
759 case CREATE_CHILD_SA:
760 if (generate_nonce(&this->my_nonce) != SUCCESS)
761 {
762 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
763 chunk_empty);
764 return SUCCESS;
765 }
766 no_dh = FALSE;
767 break;
768 case IKE_AUTH:
769 if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
770 {
771 /* wait until extensible authentication completed, if used */
772 return NEED_MORE;
773 }
774 default:
775 break;
776 }
777
778 if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
779 {
780 SIG_CHD(UP_FAILED, NULL,
781 "unable to create CHILD_SA while rekeying IKE_SA");
782 message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
783 return SUCCESS;
784 }
785
786 if (this->config == NULL)
787 {
788 SIG_CHD(UP_FAILED, NULL, "traffic selectors %#R=== %#R inacceptable",
789 this->tsr, this->tsi);
790 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
791 handle_child_sa_failure(this, message);
792 return SUCCESS;
793 }
794
795 /* check if ike_config_t included non-critical error notifies */
796 iterator = message->get_payload_iterator(message);
797 while (iterator->iterate(iterator, (void**)&payload))
798 {
799 if (payload->get_type(payload) == NOTIFY)
800 {
801 notify_payload_t *notify = (notify_payload_t*)payload;
802
803 switch (notify->get_notify_type(notify))
804 {
805 case INTERNAL_ADDRESS_FAILURE:
806 case FAILED_CP_REQUIRED:
807 {
808 SIG_CHD(UP_FAILED, NULL, "configuration payload negotation "
809 "failed, no CHILD_SA built");
810 iterator->destroy(iterator);
811 handle_child_sa_failure(this, message);
812 return SUCCESS;
813 }
814 default:
815 break;
816 }
817 }
818 }
819 iterator->destroy(iterator);
820
821 this->child_sa = child_sa_create(
822 this->ike_sa->get_my_host(this->ike_sa),
823 this->ike_sa->get_other_host(this->ike_sa),
824 this->ike_sa->get_my_id(this->ike_sa),
825 this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
826 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
827
828 if (this->config->use_ipcomp(this->config) &&
829 this->ipcomp_received != IPCOMP_NONE)
830 {
831 this->ipcomp = this->ipcomp_received;
832 build_ipcomp_supported_notify(this, message);
833 }
834 else if (this->ipcomp_received != IPCOMP_NONE)
835 {
836 DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
837 notify_type_names, IPCOMP_SUPPORTED);
838 }
839
840 switch (select_and_install(this, no_dh))
841 {
842 case SUCCESS:
843 break;
844 case NOT_FOUND:
845 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
846 handle_child_sa_failure(this, message);
847 return SUCCESS;
848 case INVALID_ARG:
849 {
850 u_int16_t group = htons(this->dh_group);
851 message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
852 chunk_from_thing(group));
853 handle_child_sa_failure(this, message);
854 return SUCCESS;
855 }
856 case FAILED:
857 default:
858 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
859 handle_child_sa_failure(this, message);
860 return SUCCESS;
861 }
862
863 build_payloads(this, message);
864
865 SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA '%s{%d}' established "
866 "with ts %#R=== %#R",
867 this->child_sa->get_name(this->child_sa),
868 this->child_sa->get_reqid(this->child_sa),
869 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
870 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
871
872 return SUCCESS;
873 }
874
875 /**
876 * Implementation of task_t.process for initiator
877 */
878 static status_t process_i(private_child_create_t *this, message_t *message)
879 {
880 iterator_t *iterator;
881 payload_t *payload;
882 bool no_dh = TRUE;
883
884 switch (message->get_exchange_type(message))
885 {
886 case IKE_SA_INIT:
887 return get_nonce(message, &this->other_nonce);
888 case CREATE_CHILD_SA:
889 get_nonce(message, &this->other_nonce);
890 no_dh = FALSE;
891 break;
892 case IKE_AUTH:
893 if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
894 {
895 /* wait until extensible authentication completed, if used */
896 return NEED_MORE;
897 }
898 default:
899 break;
900 }
901
902 /* check for erronous notifies */
903 iterator = message->get_payload_iterator(message);
904 while (iterator->iterate(iterator, (void**)&payload))
905 {
906 if (payload->get_type(payload) == NOTIFY)
907 {
908 notify_payload_t *notify = (notify_payload_t*)payload;
909 notify_type_t type = notify->get_notify_type(notify);
910
911 switch (type)
912 {
913 /* handle notify errors related to CHILD_SA only */
914 case NO_PROPOSAL_CHOSEN:
915 case SINGLE_PAIR_REQUIRED:
916 case NO_ADDITIONAL_SAS:
917 case INTERNAL_ADDRESS_FAILURE:
918 case FAILED_CP_REQUIRED:
919 case TS_UNACCEPTABLE:
920 case INVALID_SELECTORS:
921 {
922 SIG_CHD(UP_FAILED, this->child_sa, "received %N notify, "
923 "no CHILD_SA built", notify_type_names, type);
924 iterator->destroy(iterator);
925 handle_child_sa_failure(this, message);
926 /* an error in CHILD_SA creation is not critical */
927 return SUCCESS;
928 }
929 case INVALID_KE_PAYLOAD:
930 {
931 chunk_t data;
932 diffie_hellman_group_t bad_group;
933
934 bad_group = this->dh_group;
935 data = notify->get_notification_data(notify);
936 this->dh_group = ntohs(*((u_int16_t*)data.ptr));
937 DBG1(DBG_IKE, "peer didn't accept DH group %N, "
938 "it requested %N", diffie_hellman_group_names,
939 bad_group, diffie_hellman_group_names, this->dh_group);
940
941 this->public.task.migrate(&this->public.task, this->ike_sa);
942 iterator->destroy(iterator);
943 return NEED_MORE;
944 }
945 default:
946 break;
947 }
948 }
949 }
950 iterator->destroy(iterator);
951
952 process_payloads(this, message);
953
954 if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
955 {
956 SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
957 " but we did not send one previously, no CHILD_SA built");
958 handle_child_sa_failure(this, message);
959 return SUCCESS;
960 }
961 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
962 {
963 DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
964 "IPComp is disabled");
965 this->ipcomp = IPCOMP_NONE;
966 }
967 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
968 {
969 SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
970 " for a transform we did not propose, no CHILD_SA built");
971 handle_child_sa_failure(this, message);
972 return SUCCESS;
973 }
974
975 if (select_and_install(this, no_dh) == SUCCESS)
976 {
977 SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA '%s{%d}' established "
978 "with ts %#R=== %#R",
979 this->child_sa->get_name(this->child_sa),
980 this->child_sa->get_reqid(this->child_sa),
981 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
982 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
983 }
984 else
985 {
986 handle_child_sa_failure(this, message);
987 }
988 return SUCCESS;
989 }
990
991 /**
992 * Implementation of task_t.get_type
993 */
994 static task_type_t get_type(private_child_create_t *this)
995 {
996 return CHILD_CREATE;
997 }
998
999 /**
1000 * Implementation of child_create_t.use_reqid
1001 */
1002 static void use_reqid(private_child_create_t *this, u_int32_t reqid)
1003 {
1004 this->reqid = reqid;
1005 }
1006
1007 /**
1008 * Implementation of child_create_t.get_child
1009 */
1010 static child_sa_t* get_child(private_child_create_t *this)
1011 {
1012 return this->child_sa;
1013 }
1014
1015 /**
1016 * Implementation of child_create_t.get_lower_nonce
1017 */
1018 static chunk_t get_lower_nonce(private_child_create_t *this)
1019 {
1020 if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1021 min(this->my_nonce.len, this->other_nonce.len)) < 0)
1022 {
1023 return this->my_nonce;
1024 }
1025 else
1026 {
1027 return this->other_nonce;
1028 }
1029 }
1030
1031 /**
1032 * Implementation of task_t.migrate
1033 */
1034 static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
1035 {
1036 chunk_free(&this->my_nonce);
1037 chunk_free(&this->other_nonce);
1038 if (this->tsi)
1039 {
1040 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1041 }
1042 if (this->tsr)
1043 {
1044 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1045 }
1046 DESTROY_IF(this->child_sa);
1047 DESTROY_IF(this->proposal);
1048 DESTROY_IF(this->dh);
1049 if (this->proposals)
1050 {
1051 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1052 }
1053
1054 this->ike_sa = ike_sa;
1055 this->proposals = NULL;
1056 this->tsi = NULL;
1057 this->tsr = NULL;
1058 this->dh = NULL;
1059 this->child_sa = NULL;
1060 this->mode = MODE_TUNNEL;
1061 this->ipcomp = IPCOMP_NONE;
1062 this->ipcomp_received = IPCOMP_NONE;
1063 this->other_cpi = 0;
1064 this->reqid = 0;
1065 this->established = FALSE;
1066 }
1067
1068 /**
1069 * Implementation of task_t.destroy
1070 */
1071 static void destroy(private_child_create_t *this)
1072 {
1073 chunk_free(&this->my_nonce);
1074 chunk_free(&this->other_nonce);
1075 if (this->tsi)
1076 {
1077 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1078 }
1079 if (this->tsr)
1080 {
1081 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1082 }
1083 if (!this->established)
1084 {
1085 DESTROY_IF(this->child_sa);
1086 }
1087 DESTROY_IF(this->proposal);
1088 DESTROY_IF(this->dh);
1089 if (this->proposals)
1090 {
1091 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1092 }
1093
1094 DESTROY_IF(this->config);
1095 free(this);
1096 }
1097
1098 /*
1099 * Described in header.
1100 */
1101 child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
1102 {
1103 private_child_create_t *this = malloc_thing(private_child_create_t);
1104
1105 this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child;
1106 this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce;
1107 this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
1108 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
1109 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
1110 this->public.task.destroy = (void(*)(task_t*))destroy;
1111 if (config)
1112 {
1113 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
1114 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
1115 this->initiator = TRUE;
1116 config->get_ref(config);
1117 }
1118 else
1119 {
1120 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
1121 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
1122 this->initiator = FALSE;
1123 }
1124
1125 this->ike_sa = ike_sa;
1126 this->config = config;
1127 this->my_nonce = chunk_empty;
1128 this->other_nonce = chunk_empty;
1129 this->proposals = NULL;
1130 this->proposal = NULL;
1131 this->tsi = NULL;
1132 this->tsr = NULL;
1133 this->dh = NULL;
1134 this->dh_group = MODP_NONE;
1135 this->child_sa = NULL;
1136 this->mode = MODE_TUNNEL;
1137 this->ipcomp = IPCOMP_NONE;
1138 this->ipcomp_received = IPCOMP_NONE;
1139 this->other_cpi = 0;
1140 this->reqid = 0;
1141 this->established = FALSE;
1142
1143 return &this->public;
1144 }