71dc4461c9608b940391104691fb1dd551b35799
[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 if (this->reqid)
594 {
595 SIG_CHD(UP_START, NULL, "establishing CHILD_SA %s{%d}",
596 this->config->get_name(this->config), this->reqid);
597 }
598 else
599 {
600 SIG_CHD(UP_START, NULL, "establishing CHILD_SA %s{?}",
601 this->config->get_name(this->config));
602 }
603
604 /* reuse virtual IP if we already have one */
605 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
606 if (me == NULL)
607 {
608 me = this->ike_sa->get_my_host(this->ike_sa);
609 }
610 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
611 if (other == NULL)
612 {
613 other = this->ike_sa->get_other_host(this->ike_sa);
614 }
615
616 /* check if we want a virtual IP, but don't have one */
617 if (!this->reqid)
618 {
619 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
620 vip = peer_cfg->get_virtual_ip(peer_cfg);
621 if (vip)
622 {
623 propose_all = TRUE;
624 }
625 }
626
627 if (propose_all)
628 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
629 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
630 NULL, NULL);
631 }
632 else
633 { /* but shorten a 0.0.0.0/0 subnet for host2host/we already have a vip */
634 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
635 NULL, me);
636 }
637 this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
638 NULL, other);
639
640 this->proposals = this->config->get_proposals(this->config,
641 this->dh_group == MODP_NONE);
642 this->mode = this->config->get_mode(this->config);
643
644 this->child_sa = child_sa_create(
645 this->ike_sa->get_my_host(this->ike_sa),
646 this->ike_sa->get_other_host(this->ike_sa),
647 this->ike_sa->get_my_id(this->ike_sa),
648 this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
649 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
650
651 if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
652 {
653 SIG_CHD(UP_FAILED, this->child_sa,
654 "unable to allocate SPIs from kernel");
655 return FAILED;
656 }
657
658 if (this->dh_group != MODP_NONE)
659 {
660 this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
661 }
662
663 if (this->config->use_ipcomp(this->config)) {
664 /* IPCOMP_DEFLATE is the only transform we support at the moment */
665 this->ipcomp = IPCOMP_DEFLATE;
666 build_ipcomp_supported_notify(this, message);
667 }
668
669 build_payloads(this, message);
670
671 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
672 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
673 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
674 this->tsi = NULL;
675 this->tsr = NULL;
676 this->proposals = NULL;
677
678 return NEED_MORE;
679 }
680
681 /**
682 * Implementation of task_t.process for initiator
683 */
684 static status_t process_r(private_child_create_t *this, message_t *message)
685 {
686 peer_cfg_t *peer_cfg;
687
688 switch (message->get_exchange_type(message))
689 {
690 case IKE_SA_INIT:
691 return get_nonce(message, &this->other_nonce);
692 case CREATE_CHILD_SA:
693 get_nonce(message, &this->other_nonce);
694 break;
695 case IKE_AUTH:
696 if (message->get_payload(message, ID_INITIATOR) == NULL)
697 {
698 /* wait until extensible authentication completed, if used */
699 return NEED_MORE;
700 }
701 default:
702 break;
703 }
704
705 process_payloads(this, message);
706
707 if (this->tsi == NULL || this->tsr == NULL)
708 {
709 DBG1(DBG_IKE, "TS payload missing in message");
710 return NEED_MORE;
711 }
712
713 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
714 if (peer_cfg)
715 {
716 host_t *me, *other;
717
718 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
719 if (me == NULL)
720 {
721 me = this->ike_sa->get_my_host(this->ike_sa);
722 }
723 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
724 if (other == NULL)
725 {
726 other = this->ike_sa->get_other_host(this->ike_sa);
727 }
728
729 this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
730 this->tsi, me, other);
731 }
732 return NEED_MORE;
733 }
734
735 /**
736 * handle CHILD_SA setup failure
737 */
738 static void handle_child_sa_failure(private_child_create_t *this,
739 message_t *message)
740 {
741 if (message->get_exchange_type(message) == IKE_AUTH &&
742 lib->settings->get_bool(lib->settings,
743 "charon.close_ike_on_child_failure", FALSE))
744 {
745 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
746 * first */
747 DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
748 charon->scheduler->schedule_job(charon->scheduler, (job_t*)
749 delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
750 100);
751 }
752 }
753
754 /**
755 * Implementation of task_t.build for responder
756 */
757 static status_t build_r(private_child_create_t *this, message_t *message)
758 {
759 payload_t *payload;
760 iterator_t *iterator;
761 bool no_dh = TRUE;
762
763 switch (message->get_exchange_type(message))
764 {
765 case IKE_SA_INIT:
766 return get_nonce(message, &this->my_nonce);
767 case CREATE_CHILD_SA:
768 if (generate_nonce(&this->my_nonce) != SUCCESS)
769 {
770 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
771 chunk_empty);
772 return SUCCESS;
773 }
774 no_dh = FALSE;
775 break;
776 case IKE_AUTH:
777 if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
778 {
779 /* wait until extensible authentication completed, if used */
780 return NEED_MORE;
781 }
782 default:
783 break;
784 }
785
786 if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
787 {
788 SIG_CHD(UP_FAILED, NULL,
789 "unable to create CHILD_SA while rekeying IKE_SA");
790 message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
791 return SUCCESS;
792 }
793
794 if (this->config == NULL)
795 {
796 SIG_CHD(UP_FAILED, NULL, "traffic selectors %#R=== %#R inacceptable",
797 this->tsr, this->tsi);
798 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
799 handle_child_sa_failure(this, message);
800 return SUCCESS;
801 }
802
803 /* check if ike_config_t included non-critical error notifies */
804 iterator = message->get_payload_iterator(message);
805 while (iterator->iterate(iterator, (void**)&payload))
806 {
807 if (payload->get_type(payload) == NOTIFY)
808 {
809 notify_payload_t *notify = (notify_payload_t*)payload;
810
811 switch (notify->get_notify_type(notify))
812 {
813 case INTERNAL_ADDRESS_FAILURE:
814 case FAILED_CP_REQUIRED:
815 {
816 SIG_CHD(UP_FAILED, NULL, "configuration payload negotation "
817 "failed, no CHILD_SA built");
818 iterator->destroy(iterator);
819 handle_child_sa_failure(this, message);
820 return SUCCESS;
821 }
822 default:
823 break;
824 }
825 }
826 }
827 iterator->destroy(iterator);
828
829 this->child_sa = child_sa_create(
830 this->ike_sa->get_my_host(this->ike_sa),
831 this->ike_sa->get_other_host(this->ike_sa),
832 this->ike_sa->get_my_id(this->ike_sa),
833 this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
834 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
835
836 if (this->config->use_ipcomp(this->config) &&
837 this->ipcomp_received != IPCOMP_NONE)
838 {
839 this->ipcomp = this->ipcomp_received;
840 build_ipcomp_supported_notify(this, message);
841 }
842 else if (this->ipcomp_received != IPCOMP_NONE)
843 {
844 DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
845 notify_type_names, IPCOMP_SUPPORTED);
846 }
847
848 switch (select_and_install(this, no_dh))
849 {
850 case SUCCESS:
851 break;
852 case NOT_FOUND:
853 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
854 handle_child_sa_failure(this, message);
855 return SUCCESS;
856 case INVALID_ARG:
857 {
858 u_int16_t group = htons(this->dh_group);
859 message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
860 chunk_from_thing(group));
861 handle_child_sa_failure(this, message);
862 return SUCCESS;
863 }
864 case FAILED:
865 default:
866 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
867 handle_child_sa_failure(this, message);
868 return SUCCESS;
869 }
870
871 build_payloads(this, message);
872
873 SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA %s{%d} established "
874 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
875 this->child_sa->get_name(this->child_sa),
876 this->child_sa->get_reqid(this->child_sa),
877 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
878 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
879 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
880 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
881
882 return SUCCESS;
883 }
884
885 /**
886 * Implementation of task_t.process for initiator
887 */
888 static status_t process_i(private_child_create_t *this, message_t *message)
889 {
890 iterator_t *iterator;
891 payload_t *payload;
892 bool no_dh = TRUE;
893
894 switch (message->get_exchange_type(message))
895 {
896 case IKE_SA_INIT:
897 return get_nonce(message, &this->other_nonce);
898 case CREATE_CHILD_SA:
899 get_nonce(message, &this->other_nonce);
900 no_dh = FALSE;
901 break;
902 case IKE_AUTH:
903 if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
904 {
905 /* wait until extensible authentication completed, if used */
906 return NEED_MORE;
907 }
908 default:
909 break;
910 }
911
912 /* check for erronous notifies */
913 iterator = message->get_payload_iterator(message);
914 while (iterator->iterate(iterator, (void**)&payload))
915 {
916 if (payload->get_type(payload) == NOTIFY)
917 {
918 notify_payload_t *notify = (notify_payload_t*)payload;
919 notify_type_t type = notify->get_notify_type(notify);
920
921 switch (type)
922 {
923 /* handle notify errors related to CHILD_SA only */
924 case NO_PROPOSAL_CHOSEN:
925 case SINGLE_PAIR_REQUIRED:
926 case NO_ADDITIONAL_SAS:
927 case INTERNAL_ADDRESS_FAILURE:
928 case FAILED_CP_REQUIRED:
929 case TS_UNACCEPTABLE:
930 case INVALID_SELECTORS:
931 {
932 SIG_CHD(UP_FAILED, this->child_sa, "received %N notify, "
933 "no CHILD_SA built", notify_type_names, type);
934 iterator->destroy(iterator);
935 handle_child_sa_failure(this, message);
936 /* an error in CHILD_SA creation is not critical */
937 return SUCCESS;
938 }
939 case INVALID_KE_PAYLOAD:
940 {
941 chunk_t data;
942 diffie_hellman_group_t bad_group;
943
944 bad_group = this->dh_group;
945 data = notify->get_notification_data(notify);
946 this->dh_group = ntohs(*((u_int16_t*)data.ptr));
947 DBG1(DBG_IKE, "peer didn't accept DH group %N, "
948 "it requested %N", diffie_hellman_group_names,
949 bad_group, diffie_hellman_group_names, this->dh_group);
950
951 this->public.task.migrate(&this->public.task, this->ike_sa);
952 iterator->destroy(iterator);
953 return NEED_MORE;
954 }
955 default:
956 break;
957 }
958 }
959 }
960 iterator->destroy(iterator);
961
962 process_payloads(this, message);
963
964 if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
965 {
966 SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
967 " but we did not send one previously, no CHILD_SA built");
968 handle_child_sa_failure(this, message);
969 return SUCCESS;
970 }
971 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
972 {
973 DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
974 "IPComp is disabled");
975 this->ipcomp = IPCOMP_NONE;
976 }
977 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
978 {
979 SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
980 " for a transform we did not propose, no CHILD_SA built");
981 handle_child_sa_failure(this, message);
982 return SUCCESS;
983 }
984
985 if (select_and_install(this, no_dh) == SUCCESS)
986 {
987 SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA %s{%d} established "
988 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
989 this->child_sa->get_name(this->child_sa),
990 this->child_sa->get_reqid(this->child_sa),
991 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
992 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
993 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
994 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
995 }
996 else
997 {
998 handle_child_sa_failure(this, message);
999 }
1000 return SUCCESS;
1001 }
1002
1003 /**
1004 * Implementation of task_t.get_type
1005 */
1006 static task_type_t get_type(private_child_create_t *this)
1007 {
1008 return CHILD_CREATE;
1009 }
1010
1011 /**
1012 * Implementation of child_create_t.use_reqid
1013 */
1014 static void use_reqid(private_child_create_t *this, u_int32_t reqid)
1015 {
1016 this->reqid = reqid;
1017 }
1018
1019 /**
1020 * Implementation of child_create_t.get_child
1021 */
1022 static child_sa_t* get_child(private_child_create_t *this)
1023 {
1024 return this->child_sa;
1025 }
1026
1027 /**
1028 * Implementation of child_create_t.get_lower_nonce
1029 */
1030 static chunk_t get_lower_nonce(private_child_create_t *this)
1031 {
1032 if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1033 min(this->my_nonce.len, this->other_nonce.len)) < 0)
1034 {
1035 return this->my_nonce;
1036 }
1037 else
1038 {
1039 return this->other_nonce;
1040 }
1041 }
1042
1043 /**
1044 * Implementation of task_t.migrate
1045 */
1046 static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
1047 {
1048 chunk_free(&this->my_nonce);
1049 chunk_free(&this->other_nonce);
1050 if (this->tsi)
1051 {
1052 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1053 }
1054 if (this->tsr)
1055 {
1056 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1057 }
1058 DESTROY_IF(this->child_sa);
1059 DESTROY_IF(this->proposal);
1060 DESTROY_IF(this->dh);
1061 if (this->proposals)
1062 {
1063 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1064 }
1065
1066 this->ike_sa = ike_sa;
1067 this->proposals = NULL;
1068 this->tsi = NULL;
1069 this->tsr = NULL;
1070 this->dh = NULL;
1071 this->child_sa = NULL;
1072 this->mode = MODE_TUNNEL;
1073 this->ipcomp = IPCOMP_NONE;
1074 this->ipcomp_received = IPCOMP_NONE;
1075 this->other_cpi = 0;
1076 this->reqid = 0;
1077 this->established = FALSE;
1078 }
1079
1080 /**
1081 * Implementation of task_t.destroy
1082 */
1083 static void destroy(private_child_create_t *this)
1084 {
1085 chunk_free(&this->my_nonce);
1086 chunk_free(&this->other_nonce);
1087 if (this->tsi)
1088 {
1089 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1090 }
1091 if (this->tsr)
1092 {
1093 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1094 }
1095 if (!this->established)
1096 {
1097 DESTROY_IF(this->child_sa);
1098 }
1099 DESTROY_IF(this->proposal);
1100 DESTROY_IF(this->dh);
1101 if (this->proposals)
1102 {
1103 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1104 }
1105
1106 DESTROY_IF(this->config);
1107 free(this);
1108 }
1109
1110 /*
1111 * Described in header.
1112 */
1113 child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
1114 {
1115 private_child_create_t *this = malloc_thing(private_child_create_t);
1116
1117 this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child;
1118 this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce;
1119 this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
1120 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
1121 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
1122 this->public.task.destroy = (void(*)(task_t*))destroy;
1123 if (config)
1124 {
1125 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
1126 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
1127 this->initiator = TRUE;
1128 config->get_ref(config);
1129 }
1130 else
1131 {
1132 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
1133 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
1134 this->initiator = FALSE;
1135 }
1136
1137 this->ike_sa = ike_sa;
1138 this->config = config;
1139 this->my_nonce = chunk_empty;
1140 this->other_nonce = chunk_empty;
1141 this->proposals = NULL;
1142 this->proposal = NULL;
1143 this->tsi = NULL;
1144 this->tsr = NULL;
1145 this->dh = NULL;
1146 this->dh_group = MODP_NONE;
1147 this->child_sa = NULL;
1148 this->mode = MODE_TUNNEL;
1149 this->ipcomp = IPCOMP_NONE;
1150 this->ipcomp_received = IPCOMP_NONE;
1151 this->other_cpi = 0;
1152 this->reqid = 0;
1153 this->established = FALSE;
1154
1155 return &this->public;
1156 }