added hostaccess support
[strongswan.git] / src / charon / sa / transactions / create_child_sa.c
1 /**
2 * @file create_child_sa.c
3 *
4 * @brief Implementation of create_child_sa_t transaction.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include "create_child_sa.h"
24
25 #include <string.h>
26
27 #include <daemon.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/nonce_payload.h>
30 #include <encoding/payloads/ts_payload.h>
31 #include <sa/transactions/delete_child_sa.h>
32 #include <utils/randomizer.h>
33
34
35 typedef struct private_create_child_sa_t private_create_child_sa_t;
36
37 /**
38 * Private members of a create_child_sa_t object..
39 */
40 struct private_create_child_sa_t {
41
42 /**
43 * Public methods and transaction_t interface.
44 */
45 create_child_sa_t public;
46
47 /**
48 * Assigned IKE_SA.
49 */
50 ike_sa_t *ike_sa;
51
52 /**
53 * Message sent by our peer, if already generated
54 */
55 message_t *message;
56
57 /**
58 * Message ID this transaction uses
59 */
60 u_int32_t message_id;
61
62 /**
63 * Times we did send the request
64 */
65 u_int32_t requested;
66
67 /**
68 * initiators inbound SPI of the CHILD_SA which gets rekeyed
69 */
70 u_int32_t rekey_spi;
71
72 /**
73 * reqid to use for new CHILD_SA
74 */
75 u_int32_t reqid;
76
77 /**
78 * policy definition used
79 */
80 policy_t *policy;
81
82 /**
83 * Negotiated proposal used for CHILD_SA
84 */
85 proposal_t *proposal;
86
87 /**
88 * initiator chosen nonce
89 */
90 chunk_t nonce_i;
91
92 /**
93 * responder chosen nonce
94 */
95 chunk_t nonce_r;
96
97 /**
98 * lower of the nonces of a simultaneus rekeying request
99 */
100 chunk_t nonce_s;
101
102 /**
103 * Negotiated traffic selectors for initiator
104 */
105 linked_list_t *tsi;
106
107 /**
108 * Negotiated traffic selectors for responder
109 */
110 linked_list_t *tsr;
111
112 /**
113 * CHILD_SA created by this transaction
114 */
115 child_sa_t *child_sa;
116
117 /**
118 * CHILD_SA rekeyed if we are rekeying
119 */
120 child_sa_t *rekeyed_sa;
121
122 /**
123 * Have we lost the simultaneous rekeying nonce compare?
124 */
125 bool lost;
126
127 /**
128 * source of randomness
129 */
130 randomizer_t *randomizer;
131
132 /**
133 * Assigned logger.
134 */
135 logger_t *logger;
136 };
137
138 /**
139 * Implementation of transaction_t.get_message_id.
140 */
141 static u_int32_t get_message_id(private_create_child_sa_t *this)
142 {
143 return this->message_id;
144 }
145
146 /**
147 * Implementation of transaction_t.requested.
148 */
149 static u_int32_t requested(private_create_child_sa_t *this)
150 {
151 return this->requested++;
152 }
153
154 /**
155 * Implementation of create_child_sa_t.set_policy.
156 */
157 static void set_policy(private_create_child_sa_t *this, policy_t *policy)
158 {
159 this->policy = policy;
160 }
161
162 /**
163 * Implementation of create_child_sa_t.set_reqid.
164 */
165 static void set_reqid(private_create_child_sa_t *this, u_int32_t reqid)
166 {
167 this->reqid = reqid;
168 }
169
170 /**
171 * Implementation of create_child_sa_t.rekeys_child.
172 */
173 static void rekeys_child(private_create_child_sa_t *this, child_sa_t *child_sa)
174 {
175 this->rekeyed_sa = child_sa;
176 }
177
178 /**
179 * Implementation of create_child_sa_t.cancel.
180 */
181 static void cancel(private_create_child_sa_t *this)
182 {
183 this->rekeyed_sa = NULL;
184 this->lost = TRUE;
185 }
186
187 /**
188 * destroy a list of traffic selectors
189 */
190 static void destroy_ts_list(linked_list_t *list)
191 {
192 if (list)
193 {
194 traffic_selector_t *ts;
195 while (list->remove_last(list, (void**)&ts) == SUCCESS)
196 {
197 ts->destroy(ts);
198 }
199 list->destroy(list);
200 }
201 }
202
203 /**
204 * destroy a list of proposals
205 */
206 static void destroy_proposal_list(linked_list_t *list)
207 {
208 proposal_t *proposal;
209
210 while (list->remove_last(list, (void**)&proposal) == SUCCESS)
211 {
212 proposal->destroy(proposal);
213 }
214 list->destroy(list);
215 }
216
217 /**
218 * Implementation of transaction_t.get_request.
219 */
220 static status_t get_request(private_create_child_sa_t *this, message_t **result)
221 {
222 message_t *request;
223 host_t *me, *other;
224 identification_t *my_id, *other_id;
225
226 /* check if we already have built a message (retransmission) */
227 if (this->message)
228 {
229 *result = this->message;
230 return SUCCESS;
231 }
232
233 /* check if we are not already rekeying */
234 if (this->rekeyed_sa)
235 {
236 switch (this->rekeyed_sa->get_state(this->rekeyed_sa))
237 {
238 case CHILD_REKEYING:
239 this->logger->log(this->logger, ERROR,
240 "rekeying a CHILD_SA which is already rekeying, aborted");
241 return FAILED;
242 case CHILD_DELETING:
243 this->logger->log(this->logger, ERROR,
244 "rekeying a CHILD_SA which is deleting, aborted");
245 return FAILED;
246 default:
247 break;
248 }
249 this->rekeyed_sa->set_state(this->rekeyed_sa, CHILD_REKEYING);
250 }
251
252 me = this->ike_sa->get_my_host(this->ike_sa);
253 other = this->ike_sa->get_other_host(this->ike_sa);
254 my_id = this->ike_sa->get_my_id(this->ike_sa);
255 other_id = this->ike_sa->get_other_id(this->ike_sa);
256
257 /* build the request */
258 request = message_create();
259 request->set_source(request, me->clone(me));
260 request->set_destination(request, other->clone(other));
261 request->set_exchange_type(request, CREATE_CHILD_SA);
262 request->set_request(request, TRUE);
263 request->set_ike_sa_id(request, this->ike_sa->get_id(this->ike_sa));
264 *result = request;
265 this->message = request;
266
267 { /* build SA payload */
268 sa_payload_t *sa_payload;
269 linked_list_t *proposals;
270 bool use_natt;
271
272 /* get a policy, if we are rekeying */
273 if (this->rekeyed_sa)
274 {
275 linked_list_t *my_ts, *other_ts;
276 identification_t *my_id, *other_id;
277
278 my_ts = this->rekeyed_sa->get_my_traffic_selectors(this->rekeyed_sa);
279 other_ts = this->rekeyed_sa->get_other_traffic_selectors(this->rekeyed_sa);
280 my_id = this->ike_sa->get_my_id(this->ike_sa);
281 other_id = this->ike_sa->get_other_id(this->ike_sa);
282
283 this->policy = charon->policies->get_policy(charon->policies,
284 my_id, other_id,
285 my_ts, other_ts,
286 me, other);
287
288 this->reqid = this->rekeyed_sa->get_reqid(this->rekeyed_sa);
289
290 if (this->policy == NULL)
291 {
292 this->logger->log(this->logger, ERROR,
293 "no policy found to rekey CHILD_SA with reqid %d",
294 this->reqid);
295 return FAILED;
296 }
297 }
298
299 proposals = this->policy->get_proposals(this->policy);
300 use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
301 this->child_sa = child_sa_create(this->reqid, me, other, my_id, other_id,
302 this->policy->get_soft_lifetime(this->policy),
303 this->policy->get_hard_lifetime(this->policy),
304 this->policy->get_updown(this->policy),
305 this->policy->get_hostaccess(this->policy),
306 use_natt);
307 this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
308 if (this->child_sa->alloc(this->child_sa, proposals) != SUCCESS)
309 {
310 this->logger->log(this->logger, ERROR,
311 "could not install CHILD_SA, CHILD_SA creation aborted");
312 return FAILED;
313 }
314 sa_payload = sa_payload_create_from_proposal_list(proposals);
315 destroy_proposal_list(proposals);
316 request->add_payload(request, (payload_t*)sa_payload);
317 }
318
319 { /* build the NONCE payload for us (initiator) */
320 nonce_payload_t *nonce_payload;
321
322 if (this->randomizer->allocate_pseudo_random_bytes(this->randomizer,
323 NONCE_SIZE, &this->nonce_i) != SUCCESS)
324 {
325 return FAILED;
326 }
327 nonce_payload = nonce_payload_create();
328 nonce_payload->set_nonce(nonce_payload, this->nonce_i);
329 request->add_payload(request, (payload_t*)nonce_payload);
330 }
331
332 { /* build TSi payload */
333 linked_list_t *ts_list;
334 ts_payload_t *ts_payload;
335
336 ts_list = this->policy->get_my_traffic_selectors(this->policy, me);
337 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list);
338 destroy_ts_list(ts_list);
339 request->add_payload(request, (payload_t*)ts_payload);
340 }
341
342 { /* build TSr payload */
343 linked_list_t *ts_list;
344 ts_payload_t *ts_payload;
345
346 ts_list = this->policy->get_other_traffic_selectors(this->policy, other);
347 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list);
348 destroy_ts_list(ts_list);
349 request->add_payload(request, (payload_t*)ts_payload);
350 }
351
352 if (this->rekeyed_sa)
353 { /* add REKEY_SA notify if we are rekeying */
354 notify_payload_t *notify;
355 protocol_id_t protocol;
356
357 protocol = this->rekeyed_sa->get_protocol(this->rekeyed_sa);
358 notify = notify_payload_create_from_protocol_and_type(protocol, REKEY_SA);
359 notify->set_spi(notify, this->rekeyed_sa->get_spi(this->rekeyed_sa, TRUE));
360 request->add_payload(request, (payload_t*)notify);
361
362 /* register us as rekeying to detect multiple rekeying */
363 this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, &this->public);
364 }
365
366 this->message_id = this->ike_sa->get_next_message_id(this->ike_sa);
367 request->set_message_id(request, this->message_id);
368
369 return SUCCESS;
370 }
371
372 /**
373 * Handle all kind of notifys
374 */
375 static status_t process_notifys(private_create_child_sa_t *this, notify_payload_t *notify_payload)
376 {
377 notify_type_t notify_type = notify_payload->get_notify_type(notify_payload);
378
379 this->logger->log(this->logger, CONTROL|LEVEL1, "process notify type %s",
380 mapping_find(notify_type_m, notify_type));
381
382 switch (notify_type)
383 {
384 case SINGLE_PAIR_REQUIRED:
385 {
386 this->logger->log(this->logger, AUDIT,
387 "received a SINGLE_PAIR_REQUIRED notify");
388 return FAILED;
389 }
390 case TS_UNACCEPTABLE:
391 {
392 this->logger->log(this->logger, CONTROL,
393 "received TS_UNACCEPTABLE notify");
394 return FAILED;
395 }
396 case NO_PROPOSAL_CHOSEN:
397 {
398 this->logger->log(this->logger, CONTROL,
399 "received NO_PROPOSAL_CHOSEN notify");
400 return FAILED;
401 }
402 case REKEY_SA:
403 {
404 u_int32_t spi;
405 protocol_id_t protocol;
406
407 protocol = notify_payload->get_protocol_id(notify_payload);
408 switch (protocol)
409 {
410 case PROTO_AH:
411 case PROTO_ESP:
412 spi = notify_payload->get_spi(notify_payload);
413 this->rekeyed_sa = this->ike_sa->get_child_sa(this->ike_sa,
414 protocol, spi,
415 FALSE);
416 break;
417 default:
418 break;
419 }
420 return SUCCESS;
421 }
422 default:
423 {
424 if (notify_type < 16383)
425 {
426 this->logger->log(this->logger, AUDIT,
427 "received %s notify error (%d), CHILD_SA creation failed",
428 mapping_find(notify_type_m, notify_type),
429 notify_type);
430 return FAILED;
431 }
432 else
433 {
434 this->logger->log(this->logger, CONTROL,
435 "received %s notify (%d), ignored",
436 mapping_find(notify_type_m, notify_type),
437 notify_type);
438 return SUCCESS;
439 }
440 }
441 }
442 }
443
444 /**
445 * Build a notify message.
446 */
447 static void build_notify(notify_type_t type, chunk_t data, message_t *message, bool flush_message)
448 {
449 notify_payload_t *notify;
450
451 if (flush_message)
452 {
453 payload_t *payload;
454 iterator_t *iterator = message->get_payload_iterator(message);
455 while (iterator->iterate(iterator, (void**)&payload))
456 {
457 payload->destroy(payload);
458 iterator->remove(iterator);
459 }
460 iterator->destroy(iterator);
461 }
462
463 notify = notify_payload_create();
464 notify->set_notify_type(notify, type);
465 notify->set_notification_data(notify, data);
466 message->add_payload(message, (payload_t*)notify);
467 }
468
469 /**
470 * Install a CHILD_SA for usage
471 */
472 static status_t install_child_sa(private_create_child_sa_t *this, bool initiator)
473 {
474 prf_plus_t *prf_plus;
475 chunk_t seed;
476 status_t status;
477
478 seed = chunk_alloc(this->nonce_i.len + this->nonce_r.len);
479 memcpy(seed.ptr, this->nonce_i.ptr, this->nonce_i.len);
480 memcpy(seed.ptr + this->nonce_i.len, this->nonce_r.ptr, this->nonce_r.len);
481 prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
482 chunk_free(&seed);
483
484 if (initiator)
485 {
486 status = this->child_sa->update(this->child_sa, this->proposal, prf_plus);
487 }
488 else
489 {
490 status = this->child_sa->add(this->child_sa, this->proposal, prf_plus);
491 }
492 prf_plus->destroy(prf_plus);
493 if (status != SUCCESS)
494 {
495 return DESTROY_ME;
496 }
497 if (initiator)
498 {
499 status = this->child_sa->add_policies(this->child_sa, this->tsi, this->tsr);
500 }
501 else
502 {
503 status = this->child_sa->add_policies(this->child_sa, this->tsr, this->tsi);
504 }
505 if (status != SUCCESS)
506 {
507 return DESTROY_ME;
508 }
509
510 /* add to IKE_SA, and remove from transaction */
511 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
512 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
513 this->child_sa = NULL;
514 return SUCCESS;
515 }
516
517 /**
518 * Implementation of transaction_t.get_response.
519 */
520 static status_t get_response(private_create_child_sa_t *this, message_t *request,
521 message_t **result, transaction_t **next)
522 {
523 host_t *me, *other;
524 identification_t *my_id, *other_id;
525 message_t *response;
526 status_t status;
527 iterator_t *payloads;
528 sa_payload_t *sa_request = NULL;
529 nonce_payload_t *nonce_request = NULL;
530 ts_payload_t *tsi_request = NULL;
531 ts_payload_t *tsr_request = NULL;
532 nonce_payload_t *nonce_response;
533
534 /* check if we already have built a response (retransmission) */
535 if (this->message)
536 {
537 *result = this->message;
538 return SUCCESS;
539 }
540
541 me = this->ike_sa->get_my_host(this->ike_sa);
542 other = this->ike_sa->get_other_host(this->ike_sa);
543 my_id = this->ike_sa->get_my_id(this->ike_sa);
544 other_id = this->ike_sa->get_other_id(this->ike_sa);
545 this->message_id = request->get_message_id(request);
546
547 /* set up response */
548 response = message_create();
549 response->set_source(response, me->clone(me));
550 response->set_destination(response, other->clone(other));
551 response->set_exchange_type(response, CREATE_CHILD_SA);
552 response->set_request(response, FALSE);
553 response->set_message_id(response, this->message_id);
554 response->set_ike_sa_id(response, this->ike_sa->get_id(this->ike_sa));
555 this->message = response;
556 *result = response;
557
558 /* check message type */
559 if (request->get_exchange_type(request) != CREATE_CHILD_SA)
560 {
561 this->logger->log(this->logger, ERROR,
562 "CREATE_CHILD_SA response of invalid type, aborted");
563 return FAILED;
564 }
565
566 /* we do not allow the creation of new CHILDren/rekeying when IKE_SA is
567 * rekeying */
568 if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING ||
569 this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
570 {
571 build_notify(NO_ADDITIONAL_SAS, CHUNK_INITIALIZER, response, TRUE);
572 this->logger->log(this->logger, AUDIT,
573 "unable to create new CHILD_SAs, as rekeying in progress");
574 return FAILED;
575 }
576
577 /* Iterate over all payloads. */
578 payloads = request->get_payload_iterator(request);
579 while (payloads->has_next(payloads))
580 {
581 payload_t *payload;
582 payloads->current(payloads, (void**)&payload);
583 switch (payload->get_type(payload))
584 {
585 case SECURITY_ASSOCIATION:
586 sa_request = (sa_payload_t*)payload;
587 break;
588 case NONCE:
589 nonce_request = (nonce_payload_t*)payload;
590 break;
591 case TRAFFIC_SELECTOR_INITIATOR:
592 tsi_request = (ts_payload_t*)payload;
593 break;
594 case TRAFFIC_SELECTOR_RESPONDER:
595 tsr_request = (ts_payload_t*)payload;
596 break;
597 case KEY_EXCHANGE:
598 {
599 u_int8_t dh_buffer[] = {0x00, 0x00}; /* MODP_NONE */
600 chunk_t group = chunk_from_buf(dh_buffer);
601 build_notify(INVALID_KE_PAYLOAD, group, response, TRUE);
602 this->logger->log(this->logger, CONTROL,
603 "CREATE_CHILD_SA used PFS, sending INVALID_KE_PAYLOAD");
604 return FAILED;
605 }
606 case NOTIFY:
607 {
608 status = process_notifys(this, (notify_payload_t*)payload);
609 if (status != SUCCESS)
610 {
611 payloads->destroy(payloads);
612 return status;
613 }
614 break;
615 }
616 default:
617 {
618 this->logger->log(this->logger, ERROR, "ignoring %s payload (%d)",
619 mapping_find(payload_type_m, payload->get_type(payload)),
620 payload->get_type(payload));
621 break;
622 }
623 }
624 }
625 payloads->destroy(payloads);
626
627 /* check if we have all payloads */
628 if (!(sa_request && nonce_request && tsi_request && tsr_request))
629 {
630 build_notify(INVALID_SYNTAX, CHUNK_INITIALIZER, response, TRUE);
631 this->logger->log(this->logger, AUDIT,
632 "request message incomplete, no CHILD_SA created");
633 return FAILED;
634 }
635
636 { /* process nonce payload */
637 this->nonce_i = nonce_request->get_nonce(nonce_request);
638 if (this->randomizer->allocate_pseudo_random_bytes(this->randomizer,
639 NONCE_SIZE, &this->nonce_r) != SUCCESS)
640 {
641 build_notify(NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER, response, TRUE);
642 return FAILED;
643 }
644 nonce_response = nonce_payload_create();
645 nonce_response->set_nonce(nonce_response, this->nonce_r);
646 }
647
648 { /* get a policy and process traffic selectors */
649 identification_t *my_id, *other_id;
650 linked_list_t *my_ts, *other_ts;
651
652 my_id = this->ike_sa->get_my_id(this->ike_sa);
653 other_id = this->ike_sa->get_other_id(this->ike_sa);
654
655 my_ts = tsr_request->get_traffic_selectors(tsr_request);
656 other_ts = tsi_request->get_traffic_selectors(tsi_request);
657
658 this->policy = charon->policies->get_policy(charon->policies,
659 my_id, other_id,
660 my_ts, other_ts,
661 me, other);
662 if (this->policy)
663 {
664 this->tsr = this->policy->select_my_traffic_selectors(this->policy, my_ts, me);
665 this->tsi = this->policy->select_other_traffic_selectors(this->policy, other_ts, other);
666 }
667 destroy_ts_list(my_ts);
668 destroy_ts_list(other_ts);
669
670 if (this->policy == NULL)
671 {
672 this->logger->log(this->logger, AUDIT,
673 "no acceptable policy found, adding TS_UNACCEPTABLE notify");
674 build_notify(TS_UNACCEPTABLE, CHUNK_INITIALIZER, response, TRUE);
675 return FAILED;
676 }
677 }
678
679 { /* process SA payload */
680 linked_list_t *proposal_list;
681 sa_payload_t *sa_response;
682 ts_payload_t *ts_response;
683 bool use_natt;
684 u_int32_t soft_lifetime, hard_lifetime;
685
686 sa_response = sa_payload_create();
687 /* get proposals from request, and select one with ours */
688 proposal_list = sa_request->get_proposals(sa_request);
689 this->logger->log(this->logger, CONTROL|LEVEL1, "selecting proposals:");
690 this->proposal = this->policy->select_proposal(this->policy, proposal_list);
691 destroy_proposal_list(proposal_list);
692
693 /* do we have a proposal? */
694 if (this->proposal == NULL)
695 {
696 this->logger->log(this->logger, AUDIT,
697 "CHILD_SA proposals unacceptable, adding NO_PROPOSAL_CHOSEN notify");
698 build_notify(NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER, response, TRUE);
699 return FAILED;
700 }
701 /* do we have traffic selectors? */
702 else if (this->tsi->get_count(this->tsi) == 0 || this->tsr->get_count(this->tsr) == 0)
703 {
704 this->logger->log(this->logger, AUDIT,
705 "CHILD_SA traffic selectors unacceptable, adding TS_UNACCEPTABLE notify");
706 build_notify(TS_UNACCEPTABLE, CHUNK_INITIALIZER, response, TRUE);
707 return FAILED;
708 }
709 else
710 { /* create child sa */
711 if (this->rekeyed_sa)
712 {
713 this->reqid = this->rekeyed_sa->get_reqid(this->rekeyed_sa);
714 }
715 soft_lifetime = this->policy->get_soft_lifetime(this->policy);
716 hard_lifetime = this->policy->get_hard_lifetime(this->policy);
717 use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
718 this->child_sa = child_sa_create(this->reqid, me, other, my_id, other_id,
719 soft_lifetime, hard_lifetime,
720 this->policy->get_updown(this->policy),
721 this->policy->get_hostaccess(this->policy),
722 use_natt);
723 this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
724 if (install_child_sa(this, FALSE) != SUCCESS)
725 {
726 this->logger->log(this->logger, ERROR,
727 "installing CHILD_SA failed, adding NO_PROPOSAL_CHOSEN notify");
728 build_notify(NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER, response, TRUE);
729 return FAILED;
730 }
731 /* add proposal to sa payload */
732 sa_response->add_proposal(sa_response, this->proposal);
733 }
734 response->add_payload(response, (payload_t*)sa_response);
735
736 /* add nonce/ts payload after sa payload */
737 response->add_payload(response, (payload_t *)nonce_response);
738 ts_response = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
739 response->add_payload(response, (payload_t*)ts_response);
740 ts_response = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
741 response->add_payload(response, (payload_t*)ts_response);
742 }
743 /* CHILD_SA successfully created. If another transaction is already rekeying
744 * this SA, our lower nonce must be registered for a later nonce compare. */
745 if (this->rekeyed_sa)
746 {
747 private_create_child_sa_t *other;
748
749 other = this->rekeyed_sa->get_rekeying_transaction(this->rekeyed_sa);
750 if (other)
751 {
752 /* store our lower nonce in the simultaneus transaction, it
753 * will later compare it against his nonces when it calls conclude().
754 */
755 if (memcmp(this->nonce_i.ptr, this->nonce_r.ptr,
756 min(this->nonce_i.len, this->nonce_r.len)) < 0)
757 {
758 other->nonce_s = chunk_clone(this->nonce_i);
759 }
760 else
761 {
762 other->nonce_s = chunk_clone(this->nonce_r);
763 }
764 }
765 this->rekeyed_sa->set_state(this->rekeyed_sa, CHILD_REKEYING);
766 }
767 return SUCCESS;
768 }
769
770 /**
771 * Implementation of transaction_t.conclude
772 */
773 static status_t conclude(private_create_child_sa_t *this, message_t *response,
774 transaction_t **next)
775 {
776 iterator_t *payloads;
777 host_t *me, *other;
778 sa_payload_t *sa_payload = NULL;
779 nonce_payload_t *nonce_payload = NULL;
780 ts_payload_t *tsi_payload = NULL;
781 ts_payload_t *tsr_payload = NULL;
782 status_t status;
783 child_sa_t *new_child = NULL;
784 delete_child_sa_t *delete_child_sa;
785
786 /* check message type */
787 if (response->get_exchange_type(response) != CREATE_CHILD_SA)
788 {
789 this->logger->log(this->logger, ERROR,
790 "CREATE_CHILD_SA response of invalid type, aborting");
791 return FAILED;
792 }
793
794 me = this->ike_sa->get_my_host(this->ike_sa);
795 other = this->ike_sa->get_other_host(this->ike_sa);
796
797 /* Iterate over all payloads to collect them */
798 payloads = response->get_payload_iterator(response);
799 while (payloads->has_next(payloads))
800 {
801 payload_t *payload;
802 payloads->current(payloads, (void**)&payload);
803 switch (payload->get_type(payload))
804 {
805 case SECURITY_ASSOCIATION:
806 sa_payload = (sa_payload_t*)payload;
807 break;
808 case NONCE:
809 nonce_payload = (nonce_payload_t*)payload;
810 break;
811 case TRAFFIC_SELECTOR_INITIATOR:
812 tsi_payload = (ts_payload_t*)payload;
813 break;
814 case TRAFFIC_SELECTOR_RESPONDER:
815 tsr_payload = (ts_payload_t*)payload;
816 break;
817 case NOTIFY:
818 {
819 status = process_notifys(this, (notify_payload_t*)payload);
820 if (status != SUCCESS)
821 {
822 payloads->destroy(payloads);
823 return status;
824 }
825 break;
826 }
827 default:
828 {
829 this->logger->log(this->logger, ERROR, "ignoring %s payload (%d)",
830 mapping_find(payload_type_m, payload->get_type(payload)),
831 payload->get_type(payload));
832 break;
833 }
834 }
835 }
836 payloads->destroy(payloads);
837
838 if (!(sa_payload && nonce_payload && tsi_payload && tsr_payload))
839 {
840 this->logger->log(this->logger, AUDIT, "response message incomplete, no CHILD_SA built");
841 return FAILED;
842 }
843
844 { /* process NONCE payload */
845 this->nonce_r = nonce_payload->get_nonce(nonce_payload);
846 }
847
848 { /* process traffic selectors for us */
849 linked_list_t *ts_received = tsi_payload->get_traffic_selectors(tsi_payload);
850 this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received, me);
851 destroy_ts_list(ts_received);
852 }
853
854 { /* process traffic selectors for other */
855 linked_list_t *ts_received = tsr_payload->get_traffic_selectors(tsr_payload);
856 this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received, other);
857 destroy_ts_list(ts_received);
858 }
859
860 { /* process sa payload */
861 linked_list_t *proposal_list;
862
863 proposal_list = sa_payload->get_proposals(sa_payload);
864 /* we have to re-check here if other's selection is valid */
865 this->proposal = this->policy->select_proposal(this->policy, proposal_list);
866 destroy_proposal_list(proposal_list);
867
868 /* everything fine to create CHILD? */
869 if (this->proposal == NULL ||
870 this->tsi->get_count(this->tsi) == 0 ||
871 this->tsr->get_count(this->tsr) == 0)
872 {
873 this->logger->log(this->logger, AUDIT, "CHILD_SA creation failed");
874 return FAILED;
875 }
876 new_child = this->child_sa;
877 if (install_child_sa(this, TRUE) != SUCCESS)
878 {
879 this->logger->log(this->logger, ERROR,
880 "installing CHILD_SA failed, no CHILD_SA built");
881 return FAILED;
882 }
883 }
884 /* CHILD_SA successfully created. If the other peer initiated rekeying
885 * in the meantime, we detect this by comparing the rekeying_transaction
886 * of the SA. If it changed, we are not alone. Then we must compare the nonces.
887 * If no simultaneous rekeying is going on, we just initiate the delete of
888 * the superseded SA. */
889 if (this->rekeyed_sa)
890 {
891 /* rekeying finished, update SA status */
892 this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, NULL);
893
894 if (this->nonce_s.ptr)
895 { /* simlutaneous rekeying is going on, not so good */
896 chunk_t this_lowest;
897
898 /* first get our lowest nonce */
899 if (memcmp(this->nonce_i.ptr, this->nonce_r.ptr,
900 min(this->nonce_i.len, this->nonce_r.len)) < 0)
901 {
902 this_lowest = this->nonce_i;
903 }
904 else
905 {
906 this_lowest = this->nonce_r;
907 }
908 /* then compare against other lowest nonce */
909 if (memcmp(this_lowest.ptr, this->nonce_s.ptr,
910 min(this_lowest.len, this->nonce_s.len)) < 0)
911 {
912 this->logger->log(this->logger, ERROR,
913 "detected simultaneous CHILD_SA rekeying, deleting ours");
914 this->lost = TRUE;
915 }
916 else
917 {
918 this->logger->log(this->logger, ERROR,
919 "detected simultaneous CHILD_SA rekeying, but ours is preferred");
920 }
921 }
922 /* delete the old SA if we have won the rekeying nonce compare*/
923 if (!this->lost)
924 {
925 delete_child_sa = delete_child_sa_create(this->ike_sa);
926 delete_child_sa->set_child_sa(delete_child_sa, this->rekeyed_sa);
927 *next = (transaction_t*)delete_child_sa;
928 }
929 }
930 if (this->lost)
931 {
932 /* we have lost simlutaneous rekeying, delete the CHILD_SA we just have created */
933 delete_child_sa = delete_child_sa_create(this->ike_sa);
934 delete_child_sa->set_child_sa(delete_child_sa, new_child);
935 *next = (transaction_t*)delete_child_sa;
936 }
937 return SUCCESS;
938 }
939
940 /**
941 * implements transaction_t.destroy
942 */
943 static void destroy(private_create_child_sa_t *this)
944 {
945 DESTROY_IF(this->message);
946 DESTROY_IF(this->proposal);
947 DESTROY_IF(this->child_sa);
948 DESTROY_IF(this->policy);
949 destroy_ts_list(this->tsi);
950 destroy_ts_list(this->tsr);
951 chunk_free(&this->nonce_i);
952 chunk_free(&this->nonce_r);
953 chunk_free(&this->nonce_s);
954 this->randomizer->destroy(this->randomizer);
955 free(this);
956 }
957
958 /*
959 * Described in header.
960 */
961 create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa)
962 {
963 private_create_child_sa_t *this = malloc_thing(private_create_child_sa_t);
964
965 /* transaction interface functions */
966 this->public.transaction.get_request = (status_t(*)(transaction_t*,message_t**))get_request;
967 this->public.transaction.get_response = (status_t(*)(transaction_t*,message_t*,message_t**,transaction_t**))get_response;
968 this->public.transaction.conclude = (status_t(*)(transaction_t*,message_t*,transaction_t**))conclude;
969 this->public.transaction.get_message_id = (u_int32_t(*)(transaction_t*))get_message_id;
970 this->public.transaction.requested = (u_int32_t(*)(transaction_t*))requested;
971 this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
972
973 /* public functions */
974 this->public.set_policy = (void(*)(create_child_sa_t*,policy_t*))set_policy;
975 this->public.set_reqid = (void(*)(create_child_sa_t*,u_int32_t))set_reqid;
976 this->public.rekeys_child = (void(*)(create_child_sa_t*,child_sa_t*))rekeys_child;
977 this->public.cancel = (void(*)(create_child_sa_t*))cancel;
978
979 /* private data */
980 this->ike_sa = ike_sa;
981 this->message_id = 0;
982 this->message = NULL;
983 this->requested = 0;
984 this->rekey_spi = 0;
985 this->reqid = 0;
986 this->nonce_i = CHUNK_INITIALIZER;
987 this->nonce_r = CHUNK_INITIALIZER;
988 this->nonce_s = CHUNK_INITIALIZER;
989 this->child_sa = NULL;
990 this->rekeyed_sa = NULL;
991 this->lost = FALSE;
992 this->proposal = NULL;
993 this->policy = NULL;
994 this->tsi = NULL;
995 this->tsr = NULL;
996 this->randomizer = randomizer_create();
997 this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
998
999 return &this->public;
1000 }