165baa4beed891af063fdf53f9e10b4531ee8f79
[strongswan.git] / src / charon / sa / tasks / child_create.c
1 /**
2 * @file child_create.c
3 *
4 * @brief Implementation of the child_create task.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2007 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include "child_create.h"
25
26 #include <daemon.h>
27 #include <crypto/diffie_hellman.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/ts_payload.h>
30 #include <encoding/payloads/nonce_payload.h>
31 #include <encoding/payloads/notify_payload.h>
32
33
34 typedef struct private_child_create_t private_child_create_t;
35
36 /**
37 * Private members of a child_create_t task.
38 */
39 struct private_child_create_t {
40
41 /**
42 * Public methods and task_t interface.
43 */
44 child_create_t public;
45
46 /**
47 * Assigned IKE_SA.
48 */
49 ike_sa_t *ike_sa;
50
51 /**
52 * Are we the initiator?
53 */
54 bool initiator;
55
56 /**
57 * nonce chosen by us
58 */
59 chunk_t my_nonce;
60
61 /**
62 * nonce chosen by peer
63 */
64 chunk_t other_nonce;
65
66 /**
67 * policy to create the CHILD_SA from
68 */
69 policy_t *policy;
70
71 /**
72 * list of proposal candidates
73 */
74 linked_list_t *proposals;
75
76 /**
77 * selected proposal to use for CHILD_SA
78 */
79 proposal_t *proposal;
80
81 /**
82 * traffic selectors for initiators side
83 */
84 linked_list_t *tsi;
85
86 /**
87 * traffic selectors for responders side
88 */
89 linked_list_t *tsr;
90
91 /**
92 * mode the new CHILD_SA uses (transport/tunnel/beet)
93 */
94 mode_t mode;
95
96 /**
97 * reqid to use if we are rekeying
98 */
99 u_int32_t reqid;
100
101 /**
102 * CHILD_SA which gets established
103 */
104 child_sa_t *child_sa;
105 };
106
107 /**
108 * get the nonce from a message
109 */
110 static status_t get_nonce(message_t *message, chunk_t *nonce)
111 {
112 nonce_payload_t *payload;
113
114 payload = (nonce_payload_t*)message->get_payload(message, NONCE);
115 if (payload == NULL)
116 {
117 return FAILED;
118 }
119 *nonce = payload->get_nonce(payload);
120 return NEED_MORE;
121 }
122
123 /**
124 * generate a new nonce to include in a CREATE_CHILD_SA message
125 */
126 static status_t generate_nonce(chunk_t *nonce)
127 {
128 status_t status;
129 randomizer_t *randomizer = randomizer_create();
130
131 status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE,
132 nonce);
133 randomizer->destroy(randomizer);
134 if (status != SUCCESS)
135 {
136 DBG1(DBG_IKE, "error generating random nonce value");
137 return FAILED;
138 }
139 return SUCCESS;
140 }
141
142 /**
143 * Check a list of traffic selectors if any selector belongs to host
144 */
145 static bool ts_list_is_host(linked_list_t *list, host_t *host)
146 {
147 traffic_selector_t *ts;
148 bool is_host = TRUE;
149 iterator_t *iterator = list->create_iterator(list, TRUE);
150
151 while (is_host && iterator->iterate(iterator, (void**)&ts))
152 {
153 is_host = is_host && ts->is_host(ts, host);
154 }
155 iterator->destroy(iterator);
156 return is_host;
157 }
158
159 /**
160 * Install a CHILD_SA for usage
161 */
162 static status_t select_and_install(private_child_create_t *this)
163 {
164 prf_plus_t *prf_plus;
165 status_t status;
166 chunk_t nonce_i, nonce_r, seed;
167 linked_list_t *my_ts, *other_ts;
168 host_t *me, *other, *other_vip, *my_vip;
169
170 if (this->proposals == NULL || this->tsi == NULL || this->tsr == NULL)
171 {
172 SIG(CHILD_UP_FAILED, "SA/TS payloads missing in message");
173 return FAILED;
174 }
175
176 if (this->initiator)
177 {
178 nonce_i = this->my_nonce;
179 nonce_r = this->other_nonce;
180 my_ts = this->tsi;
181 other_ts = this->tsr;
182 }
183 else
184 {
185 nonce_r = this->my_nonce;
186 nonce_i = this->other_nonce;
187 my_ts = this->tsr;
188 other_ts = this->tsi;
189 }
190
191 me = this->ike_sa->get_my_host(this->ike_sa);
192 other = this->ike_sa->get_other_host(this->ike_sa);
193 my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
194 other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
195
196 this->proposal = this->policy->select_proposal(this->policy, this->proposals);
197
198 if (this->initiator && my_vip)
199 { /* if we have a virtual IP, shorten our TS to the minimum */
200 my_ts = this->policy->select_my_traffic_selectors(this->policy, my_ts,
201 my_vip);
202 }
203 else
204 { /* shorten in the host2host case only */
205 my_ts = this->policy->select_my_traffic_selectors(this->policy,
206 my_ts, me);
207 }
208 if (other_vip)
209 { /* if other has a virtual IP, shorten it's traffic selectors to it */
210 other_ts = this->policy->select_other_traffic_selectors(this->policy,
211 other_ts, other_vip);
212 }
213 else
214 { /* use his host for the host2host case */
215 other_ts = this->policy->select_other_traffic_selectors(this->policy,
216 other_ts, other);
217 }
218 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
219 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
220 if (this->initiator)
221 {
222 this->tsi = my_ts;
223 this->tsr = other_ts;
224 }
225 else
226 {
227 this->tsr = my_ts;
228 this->tsi = other_ts;
229 }
230
231 if (this->proposal == NULL ||
232 this->tsi->get_count(this->tsi) == 0 ||
233 this->tsr->get_count(this->tsr) == 0)
234 {
235 SIG(CHILD_UP_FAILED, "no acceptable proposal found");
236 return FAILED;
237 }
238
239 if (!this->initiator)
240 {
241 /* check if requested mode is acceptable, downgrade if required */
242 switch (this->mode)
243 {
244 case MODE_TRANSPORT:
245 if (!ts_list_is_host(this->tsi, other) ||
246 !ts_list_is_host(this->tsr, me))
247 {
248 this->mode = MODE_TUNNEL;
249 DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
250 }
251 else if (this->ike_sa->is_natt_enabled(this->ike_sa))
252 {
253 this->mode = MODE_TUNNEL;
254 DBG1(DBG_IKE, "not using tranport mode, connection NATed");
255 }
256 break;
257 case MODE_BEET:
258 if (!ts_list_is_host(this->tsi, NULL) ||
259 !ts_list_is_host(this->tsr, NULL))
260 {
261 this->mode = MODE_TUNNEL;
262 DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
263 }
264 break;
265 default:
266 break;
267 }
268 }
269
270 seed = chunk_cata("cc", nonce_i, nonce_r);
271 prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
272
273 if (this->initiator)
274 {
275 status = this->child_sa->update(this->child_sa, this->proposal,
276 this->mode, prf_plus);
277 }
278 else
279 {
280 status = this->child_sa->add(this->child_sa, this->proposal,
281 this->mode, prf_plus);
282 }
283 prf_plus->destroy(prf_plus);
284
285 if (status != SUCCESS)
286 {
287 SIG(CHILD_UP_FAILED, "unable to install IPsec SA (SAD) in kernel");
288 return status;
289 }
290
291 status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
292 this->mode);
293
294 if (status != SUCCESS)
295 {
296 SIG(CHILD_UP_FAILED, "unable to install IPsec policies (SPD) in kernel");
297 return status;
298 }
299 /* add to IKE_SA, and remove from task */
300 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
301 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
302 this->child_sa = NULL;
303 return SUCCESS;
304 }
305
306 /**
307 * build the payloads for the message
308 */
309 static void build_payloads(private_child_create_t *this, message_t *message)
310 {
311 sa_payload_t *sa_payload;
312 ts_payload_t *ts_payload;
313 nonce_payload_t *nonce_payload;
314
315 /* add SA payload */
316 if (this->initiator)
317 {
318 sa_payload = sa_payload_create_from_proposal_list(this->proposals);
319 }
320 else
321 {
322 sa_payload = sa_payload_create_from_proposal(this->proposal);
323 }
324 message->add_payload(message, (payload_t*)sa_payload);
325
326 /* add TSi/TSr payloads */
327 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
328 message->add_payload(message, (payload_t*)ts_payload);
329 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
330 message->add_payload(message, (payload_t*)ts_payload);
331
332 /* add nonce payload if not in IKE_AUTH */
333 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
334 {
335 nonce_payload = nonce_payload_create();
336 nonce_payload->set_nonce(nonce_payload, this->my_nonce);
337 message->add_payload(message, (payload_t*)nonce_payload);
338 }
339
340 /* add a notify if we are not in tunnel mode */
341 switch (this->mode)
342 {
343 case MODE_TRANSPORT:
344 message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
345 break;
346 case MODE_BEET:
347 message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
348 break;
349 default:
350 break;
351 }
352 }
353
354 /**
355 * Read payloads from message
356 */
357 static void process_payloads(private_child_create_t *this, message_t *message)
358 {
359 iterator_t *iterator;
360 payload_t *payload;
361 sa_payload_t *sa_payload;
362 ts_payload_t *ts_payload;
363 notify_payload_t *notify_payload;
364
365 /* defaults to TUNNEL mode */
366 this->mode = MODE_TUNNEL;
367
368 iterator = message->get_payload_iterator(message);
369 while (iterator->iterate(iterator, (void**)&payload))
370 {
371 switch (payload->get_type(payload))
372 {
373 case SECURITY_ASSOCIATION:
374 sa_payload = (sa_payload_t*)payload;
375 this->proposals = sa_payload->get_proposals(sa_payload);
376 break;
377 case TRAFFIC_SELECTOR_INITIATOR:
378 ts_payload = (ts_payload_t*)payload;
379 this->tsi = ts_payload->get_traffic_selectors(ts_payload);
380 break;
381 case TRAFFIC_SELECTOR_RESPONDER:
382 ts_payload = (ts_payload_t*)payload;
383 this->tsr = ts_payload->get_traffic_selectors(ts_payload);
384 break;
385 case NOTIFY:
386 notify_payload = (notify_payload_t*)payload;
387 switch (notify_payload ->get_notify_type(notify_payload ))
388 {
389 case USE_TRANSPORT_MODE:
390 this->mode = MODE_TRANSPORT;
391 break;
392 case USE_BEET_MODE:
393 this->mode = MODE_BEET;
394 break;
395 default:
396 break;
397 }
398 break;
399 default:
400 break;
401 }
402 }
403 iterator->destroy(iterator);
404 }
405
406 /**
407 * Implementation of task_t.build for initiator
408 */
409 static status_t build_i(private_child_create_t *this, message_t *message)
410 {
411 host_t *me, *other, *vip;
412
413 switch (message->get_exchange_type(message))
414 {
415 case IKE_SA_INIT:
416 return get_nonce(message, &this->my_nonce);
417 case CREATE_CHILD_SA:
418 if (generate_nonce(&this->my_nonce) != SUCCESS)
419 {
420 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
421 return SUCCESS;
422 }
423 break;
424 default:
425 break;
426 }
427
428 SIG(CHILD_UP_START, "establishing CHILD_SA");
429
430 me = this->ike_sa->get_my_host(this->ike_sa);
431 other = this->ike_sa->get_other_host(this->ike_sa);
432 vip = this->policy->get_virtual_ip(this->policy, NULL);
433
434 if (vip)
435 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
436 this->tsi = this->policy->get_my_traffic_selectors(this->policy, NULL);
437 vip->destroy(vip);
438 }
439 else
440 { /* but shorten a 0.0.0.0/0 subnet to the actual address if host2host */
441 this->tsi = this->policy->get_my_traffic_selectors(this->policy, me);
442 }
443 this->tsr = this->policy->get_other_traffic_selectors(this->policy, other);
444 this->proposals = this->policy->get_proposals(this->policy);
445 this->mode = this->policy->get_mode(this->policy);
446
447 this->child_sa = child_sa_create(me, other,
448 this->ike_sa->get_my_id(this->ike_sa),
449 this->ike_sa->get_other_id(this->ike_sa),
450 this->policy, this->reqid,
451 this->ike_sa->is_natt_enabled(this->ike_sa));
452
453 if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
454 {
455 SIG(CHILD_UP_FAILED, "unable to allocate SPIs from kernel");
456 return FAILED;
457 }
458
459 build_payloads(this, message);
460
461 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
462 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
463 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
464 this->tsi = NULL;
465 this->tsr = NULL;
466 this->proposals = NULL;
467
468 return NEED_MORE;
469 }
470
471 /**
472 * Implementation of task_t.process for initiator
473 */
474 static status_t process_r(private_child_create_t *this, message_t *message)
475 {
476 switch (message->get_exchange_type(message))
477 {
478 case IKE_SA_INIT:
479 return get_nonce(message, &this->other_nonce);
480 case CREATE_CHILD_SA:
481 get_nonce(message, &this->other_nonce);
482 break;
483 default:
484 break;
485 }
486
487 process_payloads(this, message);
488
489 if (this->tsi == NULL || this->tsr == NULL)
490 {
491 DBG1(DBG_IKE, "TS payload missing in message");
492 return NEED_MORE;
493 }
494
495 this->policy = charon->policies->get_policy(charon->policies,
496 this->ike_sa->get_my_id(this->ike_sa),
497 this->ike_sa->get_other_id(this->ike_sa),
498 this->tsr, this->tsi,
499 this->ike_sa->get_my_host(this->ike_sa),
500 this->ike_sa->get_other_host(this->ike_sa));
501
502 if (this->policy && this->ike_sa->get_policy(this->ike_sa) == NULL)
503 {
504 this->ike_sa->set_policy(this->ike_sa, this->policy);
505 }
506
507 return NEED_MORE;
508 }
509
510 /**
511 * Implementation of task_t.build for responder
512 */
513 static status_t build_r(private_child_create_t *this, message_t *message)
514 {
515 switch (message->get_exchange_type(message))
516 {
517 case IKE_SA_INIT:
518 return get_nonce(message, &this->my_nonce);
519 case CREATE_CHILD_SA:
520 if (generate_nonce(&this->my_nonce) != SUCCESS)
521 {
522 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
523 return SUCCESS;
524 }
525 break;
526 default:
527 break;
528 }
529
530 if (this->policy == NULL)
531 {
532 SIG(CHILD_UP_FAILED, "received traffic selectors inacceptable");
533 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
534 return SUCCESS;
535 }
536
537 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
538 this->ike_sa->get_other_host(this->ike_sa),
539 this->ike_sa->get_my_id(this->ike_sa),
540 this->ike_sa->get_other_id(this->ike_sa),
541 this->policy, this->reqid,
542 this->ike_sa->is_natt_enabled(this->ike_sa));
543
544 if (select_and_install(this) != SUCCESS)
545 {
546 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
547 return SUCCESS;
548 }
549
550 build_payloads(this, message);
551
552 SIG(CHILD_UP_SUCCESS, "established CHILD_SA successfully");
553
554 return SUCCESS;
555 }
556
557 /**
558 * Implementation of task_t.process for initiator
559 */
560 static status_t process_i(private_child_create_t *this, message_t *message)
561 {
562 iterator_t *iterator;
563 payload_t *payload;
564 status_t status;
565
566 switch (message->get_exchange_type(message))
567 {
568 case IKE_SA_INIT:
569 return get_nonce(message, &this->other_nonce);
570 case CREATE_CHILD_SA:
571 get_nonce(message, &this->other_nonce);
572 break;
573 default:
574 break;
575 }
576
577 /* check for erronous notifies */
578 iterator = message->get_payload_iterator(message);
579 while (iterator->iterate(iterator, (void**)&payload))
580 {
581 if (payload->get_type(payload) == NOTIFY)
582 {
583 notify_payload_t *notify = (notify_payload_t*)payload;
584 notify_type_t type = notify->get_notify_type(notify);
585
586 if (type < 16383)
587 {
588 SIG(CHILD_UP_FAILED, "received %N notify error",
589 notify_type_names, type);
590 iterator->destroy(iterator);
591 /* an error in CHILD_SA creation is not critical */
592 return SUCCESS;
593 }
594 }
595 }
596 iterator->destroy(iterator);
597
598 process_payloads(this, message);
599
600 status = select_and_install(this);
601
602 SIG(CHILD_UP_SUCCESS, "established CHILD_SA successfully");
603
604 return SUCCESS;
605 }
606
607 /**
608 * Implementation of task_t.get_type
609 */
610 static task_type_t get_type(private_child_create_t *this)
611 {
612 return CHILD_CREATE;
613 }
614
615 /**
616 * Implementation of child_create_t.use_reqid
617 */
618 static void use_reqid(private_child_create_t *this, u_int32_t reqid)
619 {
620 this->reqid = reqid;
621 }
622
623 /**
624 * Implementation of task_t.migrate
625 */
626 static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
627 {
628 chunk_free(&this->my_nonce);
629 chunk_free(&this->other_nonce);
630 if (this->tsi)
631 {
632 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
633 }
634 if (this->tsr)
635 {
636 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
637 }
638 DESTROY_IF(this->child_sa);
639 DESTROY_IF(this->proposal);
640 if (this->proposals)
641 {
642 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
643 }
644
645 this->ike_sa = ike_sa;
646 this->proposals = NULL;
647 this->tsi = NULL;
648 this->tsr = NULL;
649 this->child_sa = NULL;
650 this->mode = MODE_TUNNEL;
651 this->reqid = 0;
652 }
653
654 /**
655 * Implementation of task_t.destroy
656 */
657 static void destroy(private_child_create_t *this)
658 {
659 chunk_free(&this->my_nonce);
660 chunk_free(&this->other_nonce);
661 if (this->tsi)
662 {
663 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
664 }
665 if (this->tsr)
666 {
667 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
668 }
669 DESTROY_IF(this->child_sa);
670 DESTROY_IF(this->proposal);
671 if (this->proposals)
672 {
673 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
674 }
675
676 DESTROY_IF(this->policy);
677 free(this);
678 }
679
680 /*
681 * Described in header.
682 */
683 child_create_t *child_create_create(ike_sa_t *ike_sa, policy_t *policy)
684 {
685 private_child_create_t *this = malloc_thing(private_child_create_t);
686
687 this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
688 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
689 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
690 this->public.task.destroy = (void(*)(task_t*))destroy;
691 if (policy)
692 {
693 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
694 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
695 this->initiator = TRUE;
696 policy->get_ref(policy);
697 }
698 else
699 {
700 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
701 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
702 this->initiator = FALSE;
703 }
704
705 this->ike_sa = ike_sa;
706 this->policy = policy;
707 this->my_nonce = chunk_empty;
708 this->other_nonce = chunk_empty;
709 this->proposals = NULL;
710 this->proposal = NULL;
711 this->tsi = NULL;
712 this->tsr = NULL;
713 this->child_sa = NULL;
714 this->mode = MODE_TUNNEL;
715 this->reqid = 0;
716
717 return &this->public;
718 }