re-established all previous AUD level messages
[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 ipsec_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 DBG1(DBG_IKE, "SA payload missing in message");
203 return FAILED;
204 }
205 if (this->tsi == NULL || this->tsr == NULL)
206 {
207 DBG1(DBG_IKE, "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 DBG1(DBG_IKE, "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 DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N",
247 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 DBG1(DBG_IKE, "no acceptable proposal found");
255 return FAILED;
256 }
257 }
258
259 if (my_vip == NULL)
260 {
261 my_vip = me;
262 }
263 if (other_vip == NULL)
264 {
265 other_vip = other;
266 }
267
268 my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
269 my_vip);
270 other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
271 other_vip);
272
273 if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
274 {
275 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
276 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
277 DBG1(DBG_IKE, "no acceptable traffic selectors found");
278 return NOT_FOUND;
279 }
280
281 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
282 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
283 if (this->initiator)
284 {
285 this->tsi = my_ts;
286 this->tsr = other_ts;
287 }
288 else
289 {
290 this->tsr = my_ts;
291 this->tsi = other_ts;
292 }
293
294 if (!this->initiator)
295 {
296 /* check if requested mode is acceptable, downgrade if required */
297 switch (this->mode)
298 {
299 case MODE_TRANSPORT:
300 if (!ts_list_is_host(this->tsi, other) ||
301 !ts_list_is_host(this->tsr, me))
302 {
303 this->mode = MODE_TUNNEL;
304 DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
305 }
306 else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
307 {
308 this->mode = MODE_TUNNEL;
309 DBG1(DBG_IKE, "not using tranport mode, connection NATed");
310 }
311 break;
312 case MODE_BEET:
313 if (!ts_list_is_host(this->tsi, NULL) ||
314 !ts_list_is_host(this->tsr, NULL))
315 {
316 this->mode = MODE_TUNNEL;
317 DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
318 }
319 break;
320 default:
321 break;
322 }
323 }
324
325 if (this->dh)
326 {
327 if (this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
328 {
329 DBG1(DBG_IKE, "DH exchange incomplete");
330 return FAILED;
331 }
332 DBG3(DBG_IKE, "DH secret %B", &secret);
333 seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
334 }
335 else
336 {
337 seed = chunk_cata("cc", nonce_i, nonce_r);
338 }
339
340 if (this->ipcomp != IPCOMP_NONE)
341 {
342 this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
343 this->other_cpi);
344 }
345
346 status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
347 this->mode, this->proposal->get_protocol(this->proposal));
348 if (status != SUCCESS)
349 {
350 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
351 return NOT_FOUND;
352 }
353
354 prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
355 if (this->initiator)
356 {
357 status = this->child_sa->update(this->child_sa, this->proposal,
358 this->mode, prf_plus);
359 }
360 else
361 {
362 status = this->child_sa->add(this->child_sa, this->proposal,
363 this->mode, prf_plus);
364 }
365 prf_plus->destroy(prf_plus);
366
367 if (status != SUCCESS)
368 {
369 DBG1(DBG_IKE, "unable to install IPsec SA (SAD) in kernel");
370 return FAILED;
371 }
372 /* add to IKE_SA, and remove from task */
373 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
374 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
375 this->established = TRUE;
376 return SUCCESS;
377 }
378
379 /**
380 * build the payloads for the message
381 */
382 static void build_payloads(private_child_create_t *this, message_t *message)
383 {
384 sa_payload_t *sa_payload;
385 nonce_payload_t *nonce_payload;
386 ke_payload_t *ke_payload;
387 ts_payload_t *ts_payload;
388
389 /* add SA payload */
390 if (this->initiator)
391 {
392 sa_payload = sa_payload_create_from_proposal_list(this->proposals);
393 }
394 else
395 {
396 sa_payload = sa_payload_create_from_proposal(this->proposal);
397 }
398 message->add_payload(message, (payload_t*)sa_payload);
399
400 /* add nonce payload if not in IKE_AUTH */
401 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
402 {
403 nonce_payload = nonce_payload_create();
404 nonce_payload->set_nonce(nonce_payload, this->my_nonce);
405 message->add_payload(message, (payload_t*)nonce_payload);
406 }
407
408 /* diffie hellman exchange, if PFS enabled */
409 if (this->dh)
410 {
411 ke_payload = ke_payload_create_from_diffie_hellman(this->dh);
412 message->add_payload(message, (payload_t*)ke_payload);
413 }
414
415 /* add TSi/TSr payloads */
416 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
417 message->add_payload(message, (payload_t*)ts_payload);
418 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
419 message->add_payload(message, (payload_t*)ts_payload);
420
421 /* add a notify if we are not in tunnel mode */
422 switch (this->mode)
423 {
424 case MODE_TRANSPORT:
425 message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
426 break;
427 case MODE_BEET:
428 message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
429 break;
430 default:
431 break;
432 }
433 }
434
435 /**
436 * Adds an IPCOMP_SUPPORTED notify to the message, if possible
437 */
438 static void build_ipcomp_supported_notify(private_child_create_t *this,
439 message_t *message)
440 {
441 u_int16_t cpi;
442 u_int8_t tid;
443
444 if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
445 {
446 DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, "
447 "IPComp disabled");
448 this->ipcomp = IPCOMP_NONE;
449 return;
450 }
451
452 cpi = this->child_sa->allocate_cpi(this->child_sa);
453 tid = this->ipcomp;
454 if (cpi)
455 {
456 message->add_notify(message, FALSE, IPCOMP_SUPPORTED,
457 chunk_cata("cc", chunk_from_thing(cpi), chunk_from_thing(tid)));
458 }
459 else
460 {
461 DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
462 this->ipcomp = IPCOMP_NONE;
463 }
464 }
465
466 /**
467 * Read payloads from message
468 */
469 static void process_payloads(private_child_create_t *this, message_t *message)
470 {
471 iterator_t *iterator;
472 payload_t *payload;
473 sa_payload_t *sa_payload;
474 ke_payload_t *ke_payload;
475 ts_payload_t *ts_payload;
476 notify_payload_t *notify_payload;
477
478 /* defaults to TUNNEL mode */
479 this->mode = MODE_TUNNEL;
480
481 iterator = message->get_payload_iterator(message);
482 while (iterator->iterate(iterator, (void**)&payload))
483 {
484 switch (payload->get_type(payload))
485 {
486 case SECURITY_ASSOCIATION:
487 sa_payload = (sa_payload_t*)payload;
488 this->proposals = sa_payload->get_proposals(sa_payload);
489 break;
490 case KEY_EXCHANGE:
491 ke_payload = (ke_payload_t*)payload;
492 if (!this->initiator)
493 {
494 this->dh_group = ke_payload->get_dh_group_number(ke_payload);
495 this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
496 }
497 if (this->dh)
498 {
499 this->dh->set_other_public_value(this->dh,
500 ke_payload->get_key_exchange_data(ke_payload));
501 }
502 break;
503 case TRAFFIC_SELECTOR_INITIATOR:
504 ts_payload = (ts_payload_t*)payload;
505 this->tsi = ts_payload->get_traffic_selectors(ts_payload);
506 break;
507 case TRAFFIC_SELECTOR_RESPONDER:
508 ts_payload = (ts_payload_t*)payload;
509 this->tsr = ts_payload->get_traffic_selectors(ts_payload);
510 break;
511 case NOTIFY:
512 notify_payload = (notify_payload_t*)payload;
513 switch (notify_payload ->get_notify_type(notify_payload ))
514 {
515 case USE_TRANSPORT_MODE:
516 this->mode = MODE_TRANSPORT;
517 break;
518 case USE_BEET_MODE:
519 this->mode = MODE_BEET;
520 break;
521 case IPCOMP_SUPPORTED:
522 {
523 chunk_t data = notify_payload->get_notification_data(notify_payload);
524 u_int16_t cpi = *(u_int16_t*)data.ptr;
525 ipcomp_transform_t ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
526 switch(ipcomp)
527 {
528 case IPCOMP_DEFLATE:
529 this->other_cpi = cpi;
530 this->ipcomp_received = ipcomp;
531 break;
532 case IPCOMP_LZS:
533 case IPCOMP_LZJH:
534 default:
535 DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a transform"
536 " ID we don't support %N", ipcomp_transform_names, ipcomp);
537 break;
538 }
539 }
540 default:
541 break;
542 }
543 break;
544 default:
545 break;
546 }
547 }
548 iterator->destroy(iterator);
549 }
550
551 /**
552 * Implementation of task_t.build for initiator
553 */
554 static status_t build_i(private_child_create_t *this, message_t *message)
555 {
556 host_t *me, *other, *vip;
557 bool propose_all = FALSE;
558 peer_cfg_t *peer_cfg;
559
560 switch (message->get_exchange_type(message))
561 {
562 case IKE_SA_INIT:
563 return get_nonce(message, &this->my_nonce);
564 case CREATE_CHILD_SA:
565 if (generate_nonce(&this->my_nonce) != SUCCESS)
566 {
567 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
568 return SUCCESS;
569 }
570 if (this->dh_group == MODP_NONE)
571 {
572 this->dh_group = this->config->get_dh_group(this->config);
573 }
574 break;
575 case IKE_AUTH:
576 if (!message->get_payload(message, ID_INITIATOR))
577 {
578 /* send only in the first request, not in subsequent EAP */
579 return NEED_MORE;
580 }
581 break;
582 default:
583 break;
584 }
585
586 if (this->reqid)
587 {
588 DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
589 this->config->get_name(this->config), this->reqid);
590 }
591 else
592 {
593 DBG0(DBG_IKE, "establishing CHILD_SA %s",
594 this->config->get_name(this->config));
595 }
596
597 /* reuse virtual IP if we already have one */
598 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
599 if (me == NULL)
600 {
601 me = this->ike_sa->get_my_host(this->ike_sa);
602 }
603 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
604 if (other == NULL)
605 {
606 other = this->ike_sa->get_other_host(this->ike_sa);
607 }
608
609 /* check if we want a virtual IP, but don't have one */
610 if (!this->reqid)
611 {
612 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
613 vip = peer_cfg->get_virtual_ip(peer_cfg);
614 if (vip)
615 {
616 propose_all = TRUE;
617 }
618 }
619
620 if (propose_all)
621 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
622 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
623 NULL, NULL);
624 }
625 else
626 { /* but shorten a 0.0.0.0/0 subnet for host2host/we already have a vip */
627 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
628 NULL, me);
629 }
630 this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
631 NULL, other);
632
633 this->proposals = this->config->get_proposals(this->config,
634 this->dh_group == MODP_NONE);
635 this->mode = this->config->get_mode(this->config);
636
637 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
638 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
639 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
640
641 if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
642 {
643 DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
644 return FAILED;
645 }
646
647 if (this->dh_group != MODP_NONE)
648 {
649 this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
650 }
651
652 if (this->config->use_ipcomp(this->config)) {
653 /* IPCOMP_DEFLATE is the only transform we support at the moment */
654 this->ipcomp = IPCOMP_DEFLATE;
655 build_ipcomp_supported_notify(this, message);
656 }
657
658 build_payloads(this, message);
659
660 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
661 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
662 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
663 this->tsi = NULL;
664 this->tsr = NULL;
665 this->proposals = NULL;
666
667 return NEED_MORE;
668 }
669
670 /**
671 * Implementation of task_t.process for initiator
672 */
673 static status_t process_r(private_child_create_t *this, message_t *message)
674 {
675 peer_cfg_t *peer_cfg;
676
677 switch (message->get_exchange_type(message))
678 {
679 case IKE_SA_INIT:
680 return get_nonce(message, &this->other_nonce);
681 case CREATE_CHILD_SA:
682 get_nonce(message, &this->other_nonce);
683 break;
684 case IKE_AUTH:
685 if (message->get_payload(message, ID_INITIATOR) == NULL)
686 {
687 /* wait until extensible authentication completed, if used */
688 return NEED_MORE;
689 }
690 default:
691 break;
692 }
693
694 process_payloads(this, message);
695
696 if (this->tsi == NULL || this->tsr == NULL)
697 {
698 DBG1(DBG_IKE, "TS payload missing in message");
699 return NEED_MORE;
700 }
701
702 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
703 if (peer_cfg)
704 {
705 host_t *me, *other;
706
707 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
708 if (me == NULL)
709 {
710 me = this->ike_sa->get_my_host(this->ike_sa);
711 }
712 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
713 if (other == NULL)
714 {
715 other = this->ike_sa->get_other_host(this->ike_sa);
716 }
717
718 this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
719 this->tsi, me, other);
720 }
721 return NEED_MORE;
722 }
723
724 /**
725 * handle CHILD_SA setup failure
726 */
727 static void handle_child_sa_failure(private_child_create_t *this,
728 message_t *message)
729 {
730 if (message->get_exchange_type(message) == IKE_AUTH &&
731 lib->settings->get_bool(lib->settings,
732 "charon.close_ike_on_child_failure", FALSE))
733 {
734 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
735 * first */
736 DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
737 charon->scheduler->schedule_job(charon->scheduler, (job_t*)
738 delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
739 100);
740 }
741 }
742
743 /**
744 * Implementation of task_t.build for responder
745 */
746 static status_t build_r(private_child_create_t *this, message_t *message)
747 {
748 payload_t *payload;
749 iterator_t *iterator;
750 bool no_dh = TRUE;
751
752 switch (message->get_exchange_type(message))
753 {
754 case IKE_SA_INIT:
755 return get_nonce(message, &this->my_nonce);
756 case CREATE_CHILD_SA:
757 if (generate_nonce(&this->my_nonce) != SUCCESS)
758 {
759 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
760 chunk_empty);
761 return SUCCESS;
762 }
763 no_dh = FALSE;
764 break;
765 case IKE_AUTH:
766 if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
767 {
768 /* wait until extensible authentication completed, if used */
769 return NEED_MORE;
770 }
771 default:
772 break;
773 }
774
775 if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
776 {
777 DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
778 message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
779 return SUCCESS;
780 }
781
782 if (this->config == NULL)
783 {
784 DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
785 this->tsr, this->tsi);
786 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
787 handle_child_sa_failure(this, message);
788 return SUCCESS;
789 }
790
791 /* check if ike_config_t included non-critical error notifies */
792 iterator = message->get_payload_iterator(message);
793 while (iterator->iterate(iterator, (void**)&payload))
794 {
795 if (payload->get_type(payload) == NOTIFY)
796 {
797 notify_payload_t *notify = (notify_payload_t*)payload;
798
799 switch (notify->get_notify_type(notify))
800 {
801 case INTERNAL_ADDRESS_FAILURE:
802 case FAILED_CP_REQUIRED:
803 {
804 DBG1(DBG_IKE,"configuration payload negotation "
805 "failed, no CHILD_SA built");
806 iterator->destroy(iterator);
807 handle_child_sa_failure(this, message);
808 return SUCCESS;
809 }
810 default:
811 break;
812 }
813 }
814 }
815 iterator->destroy(iterator);
816
817 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
818 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
819 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
820
821 if (this->config->use_ipcomp(this->config) &&
822 this->ipcomp_received != IPCOMP_NONE)
823 {
824 this->ipcomp = this->ipcomp_received;
825 build_ipcomp_supported_notify(this, message);
826 }
827 else if (this->ipcomp_received != IPCOMP_NONE)
828 {
829 DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
830 notify_type_names, IPCOMP_SUPPORTED);
831 }
832
833 switch (select_and_install(this, no_dh))
834 {
835 case SUCCESS:
836 break;
837 case NOT_FOUND:
838 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
839 handle_child_sa_failure(this, message);
840 return SUCCESS;
841 case INVALID_ARG:
842 {
843 u_int16_t group = htons(this->dh_group);
844 message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
845 chunk_from_thing(group));
846 handle_child_sa_failure(this, message);
847 return SUCCESS;
848 }
849 case FAILED:
850 default:
851 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
852 handle_child_sa_failure(this, message);
853 return SUCCESS;
854 }
855
856 build_payloads(this, message);
857
858 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
859 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
860 this->child_sa->get_name(this->child_sa),
861 this->child_sa->get_reqid(this->child_sa),
862 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
863 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
864 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
865 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
866
867 return SUCCESS;
868 }
869
870 /**
871 * Implementation of task_t.process for initiator
872 */
873 static status_t process_i(private_child_create_t *this, message_t *message)
874 {
875 iterator_t *iterator;
876 payload_t *payload;
877 bool no_dh = TRUE;
878
879 switch (message->get_exchange_type(message))
880 {
881 case IKE_SA_INIT:
882 return get_nonce(message, &this->other_nonce);
883 case CREATE_CHILD_SA:
884 get_nonce(message, &this->other_nonce);
885 no_dh = FALSE;
886 break;
887 case IKE_AUTH:
888 if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
889 {
890 /* wait until extensible authentication completed, if used */
891 return NEED_MORE;
892 }
893 default:
894 break;
895 }
896
897 /* check for erronous notifies */
898 iterator = message->get_payload_iterator(message);
899 while (iterator->iterate(iterator, (void**)&payload))
900 {
901 if (payload->get_type(payload) == NOTIFY)
902 {
903 notify_payload_t *notify = (notify_payload_t*)payload;
904 notify_type_t type = notify->get_notify_type(notify);
905
906 switch (type)
907 {
908 /* handle notify errors related to CHILD_SA only */
909 case NO_PROPOSAL_CHOSEN:
910 case SINGLE_PAIR_REQUIRED:
911 case NO_ADDITIONAL_SAS:
912 case INTERNAL_ADDRESS_FAILURE:
913 case FAILED_CP_REQUIRED:
914 case TS_UNACCEPTABLE:
915 case INVALID_SELECTORS:
916 {
917 DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
918 notify_type_names, type);
919 iterator->destroy(iterator);
920 handle_child_sa_failure(this, message);
921 /* an error in CHILD_SA creation is not critical */
922 return SUCCESS;
923 }
924 case INVALID_KE_PAYLOAD:
925 {
926 chunk_t data;
927 diffie_hellman_group_t bad_group;
928
929 bad_group = this->dh_group;
930 data = notify->get_notification_data(notify);
931 this->dh_group = ntohs(*((u_int16_t*)data.ptr));
932 DBG1(DBG_IKE, "peer didn't accept DH group %N, "
933 "it requested %N", diffie_hellman_group_names,
934 bad_group, diffie_hellman_group_names, this->dh_group);
935
936 this->public.task.migrate(&this->public.task, this->ike_sa);
937 iterator->destroy(iterator);
938 return NEED_MORE;
939 }
940 default:
941 break;
942 }
943 }
944 }
945 iterator->destroy(iterator);
946
947 process_payloads(this, message);
948
949 if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
950 {
951 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
952 " one, no CHILD_SA built");
953 handle_child_sa_failure(this, message);
954 return SUCCESS;
955 }
956 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
957 {
958 DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
959 "IPComp is disabled");
960 this->ipcomp = IPCOMP_NONE;
961 }
962 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
963 {
964 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
965 "no CHILD_SA built");
966 handle_child_sa_failure(this, message);
967 return SUCCESS;
968 }
969
970 if (select_and_install(this, no_dh) == SUCCESS)
971 {
972 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
973 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
974 this->child_sa->get_name(this->child_sa),
975 this->child_sa->get_reqid(this->child_sa),
976 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
977 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
978 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
979 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
980 }
981 else
982 {
983 handle_child_sa_failure(this, message);
984 }
985 return SUCCESS;
986 }
987
988 /**
989 * Implementation of task_t.get_type
990 */
991 static task_type_t get_type(private_child_create_t *this)
992 {
993 return CHILD_CREATE;
994 }
995
996 /**
997 * Implementation of child_create_t.use_reqid
998 */
999 static void use_reqid(private_child_create_t *this, u_int32_t reqid)
1000 {
1001 this->reqid = reqid;
1002 }
1003
1004 /**
1005 * Implementation of child_create_t.get_child
1006 */
1007 static child_sa_t* get_child(private_child_create_t *this)
1008 {
1009 return this->child_sa;
1010 }
1011
1012 /**
1013 * Implementation of child_create_t.get_lower_nonce
1014 */
1015 static chunk_t get_lower_nonce(private_child_create_t *this)
1016 {
1017 if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1018 min(this->my_nonce.len, this->other_nonce.len)) < 0)
1019 {
1020 return this->my_nonce;
1021 }
1022 else
1023 {
1024 return this->other_nonce;
1025 }
1026 }
1027
1028 /**
1029 * Implementation of task_t.migrate
1030 */
1031 static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
1032 {
1033 chunk_free(&this->my_nonce);
1034 chunk_free(&this->other_nonce);
1035 if (this->tsi)
1036 {
1037 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1038 }
1039 if (this->tsr)
1040 {
1041 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1042 }
1043 DESTROY_IF(this->child_sa);
1044 DESTROY_IF(this->proposal);
1045 DESTROY_IF(this->dh);
1046 if (this->proposals)
1047 {
1048 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1049 }
1050
1051 this->ike_sa = ike_sa;
1052 this->proposals = NULL;
1053 this->tsi = NULL;
1054 this->tsr = NULL;
1055 this->dh = NULL;
1056 this->child_sa = NULL;
1057 this->mode = MODE_TUNNEL;
1058 this->ipcomp = IPCOMP_NONE;
1059 this->ipcomp_received = IPCOMP_NONE;
1060 this->other_cpi = 0;
1061 this->reqid = 0;
1062 this->established = FALSE;
1063 }
1064
1065 /**
1066 * Implementation of task_t.destroy
1067 */
1068 static void destroy(private_child_create_t *this)
1069 {
1070 chunk_free(&this->my_nonce);
1071 chunk_free(&this->other_nonce);
1072 if (this->tsi)
1073 {
1074 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1075 }
1076 if (this->tsr)
1077 {
1078 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1079 }
1080 if (!this->established)
1081 {
1082 DESTROY_IF(this->child_sa);
1083 }
1084 DESTROY_IF(this->proposal);
1085 DESTROY_IF(this->dh);
1086 if (this->proposals)
1087 {
1088 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1089 }
1090
1091 DESTROY_IF(this->config);
1092 free(this);
1093 }
1094
1095 /*
1096 * Described in header.
1097 */
1098 child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
1099 {
1100 private_child_create_t *this = malloc_thing(private_child_create_t);
1101
1102 this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child;
1103 this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce;
1104 this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
1105 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
1106 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
1107 this->public.task.destroy = (void(*)(task_t*))destroy;
1108 if (config)
1109 {
1110 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
1111 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
1112 this->initiator = TRUE;
1113 config->get_ref(config);
1114 }
1115 else
1116 {
1117 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
1118 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
1119 this->initiator = FALSE;
1120 }
1121
1122 this->ike_sa = ike_sa;
1123 this->config = config;
1124 this->my_nonce = chunk_empty;
1125 this->other_nonce = chunk_empty;
1126 this->proposals = NULL;
1127 this->proposal = NULL;
1128 this->tsi = NULL;
1129 this->tsr = NULL;
1130 this->dh = NULL;
1131 this->dh_group = MODP_NONE;
1132 this->child_sa = NULL;
1133 this->mode = MODE_TUNNEL;
1134 this->ipcomp = IPCOMP_NONE;
1135 this->ipcomp_received = IPCOMP_NONE;
1136 this->other_cpi = 0;
1137 this->reqid = 0;
1138 this->established = FALSE;
1139
1140 return &this->public;
1141 }