154a8e800ea0648a23280173590e085d9c1ef308
[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 use_natt);
306 this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
307 if (this->child_sa->alloc(this->child_sa, proposals) != SUCCESS)
308 {
309 this->logger->log(this->logger, ERROR,
310 "could not install CHILD_SA, CHILD_SA creation aborted");
311 return FAILED;
312 }
313 sa_payload = sa_payload_create_from_proposal_list(proposals);
314 destroy_proposal_list(proposals);
315 request->add_payload(request, (payload_t*)sa_payload);
316 }
317
318 { /* build the NONCE payload for us (initiator) */
319 nonce_payload_t *nonce_payload;
320
321 if (this->randomizer->allocate_pseudo_random_bytes(this->randomizer,
322 NONCE_SIZE, &this->nonce_i) != SUCCESS)
323 {
324 return FAILED;
325 }
326 nonce_payload = nonce_payload_create();
327 nonce_payload->set_nonce(nonce_payload, this->nonce_i);
328 request->add_payload(request, (payload_t*)nonce_payload);
329 }
330
331 { /* build TSi payload */
332 linked_list_t *ts_list;
333 ts_payload_t *ts_payload;
334
335 ts_list = this->policy->get_my_traffic_selectors(this->policy, me);
336 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list);
337 destroy_ts_list(ts_list);
338 request->add_payload(request, (payload_t*)ts_payload);
339 }
340
341 { /* build TSr payload */
342 linked_list_t *ts_list;
343 ts_payload_t *ts_payload;
344
345 ts_list = this->policy->get_other_traffic_selectors(this->policy, other);
346 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list);
347 destroy_ts_list(ts_list);
348 request->add_payload(request, (payload_t*)ts_payload);
349 }
350
351 if (this->rekeyed_sa)
352 { /* add REKEY_SA notify if we are rekeying */
353 notify_payload_t *notify;
354 protocol_id_t protocol;
355
356 protocol = this->rekeyed_sa->get_protocol(this->rekeyed_sa);
357 notify = notify_payload_create_from_protocol_and_type(protocol, REKEY_SA);
358 notify->set_spi(notify, this->rekeyed_sa->get_spi(this->rekeyed_sa, TRUE));
359 request->add_payload(request, (payload_t*)notify);
360
361 /* register us as rekeying to detect multiple rekeying */
362 this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, &this->public);
363 }
364
365 this->message_id = this->ike_sa->get_next_message_id(this->ike_sa);
366 request->set_message_id(request, this->message_id);
367
368 return SUCCESS;
369 }
370
371 /**
372 * Handle all kind of notifys
373 */
374 static status_t process_notifys(private_create_child_sa_t *this, notify_payload_t *notify_payload)
375 {
376 notify_type_t notify_type = notify_payload->get_notify_type(notify_payload);
377
378 this->logger->log(this->logger, CONTROL|LEVEL1, "process notify type %s",
379 mapping_find(notify_type_m, notify_type));
380
381 switch (notify_type)
382 {
383 case SINGLE_PAIR_REQUIRED:
384 {
385 this->logger->log(this->logger, AUDIT,
386 "received a SINGLE_PAIR_REQUIRED notify");
387 return FAILED;
388 }
389 case TS_UNACCEPTABLE:
390 {
391 this->logger->log(this->logger, CONTROL,
392 "received TS_UNACCEPTABLE notify");
393 return FAILED;
394 }
395 case NO_PROPOSAL_CHOSEN:
396 {
397 this->logger->log(this->logger, CONTROL,
398 "received NO_PROPOSAL_CHOSEN notify");
399 return FAILED;
400 }
401 case REKEY_SA:
402 {
403 u_int32_t spi;
404 protocol_id_t protocol;
405
406 protocol = notify_payload->get_protocol_id(notify_payload);
407 switch (protocol)
408 {
409 case PROTO_AH:
410 case PROTO_ESP:
411 spi = notify_payload->get_spi(notify_payload);
412 this->rekeyed_sa = this->ike_sa->get_child_sa(this->ike_sa,
413 protocol, spi,
414 FALSE);
415 break;
416 default:
417 break;
418 }
419 return SUCCESS;
420 }
421 default:
422 {
423 if (notify_type < 16383)
424 {
425 this->logger->log(this->logger, AUDIT,
426 "received %s notify error (%d), CHILD_SA creation failed",
427 mapping_find(notify_type_m, notify_type),
428 notify_type);
429 return FAILED;
430 }
431 else
432 {
433 this->logger->log(this->logger, CONTROL,
434 "received %s notify (%d), ignored",
435 mapping_find(notify_type_m, notify_type),
436 notify_type);
437 return SUCCESS;
438 }
439 }
440 }
441 }
442
443 /**
444 * Build a notify message.
445 */
446 static void build_notify(notify_type_t type, chunk_t data, message_t *message, bool flush_message)
447 {
448 notify_payload_t *notify;
449
450 if (flush_message)
451 {
452 payload_t *payload;
453 iterator_t *iterator = message->get_payload_iterator(message);
454 while (iterator->iterate(iterator, (void**)&payload))
455 {
456 payload->destroy(payload);
457 iterator->remove(iterator);
458 }
459 iterator->destroy(iterator);
460 }
461
462 notify = notify_payload_create();
463 notify->set_notify_type(notify, type);
464 notify->set_notification_data(notify, data);
465 message->add_payload(message, (payload_t*)notify);
466 }
467
468 /**
469 * Install a CHILD_SA for usage
470 */
471 static status_t install_child_sa(private_create_child_sa_t *this, bool initiator)
472 {
473 prf_plus_t *prf_plus;
474 chunk_t seed;
475 status_t status;
476
477 seed = chunk_alloc(this->nonce_i.len + this->nonce_r.len);
478 memcpy(seed.ptr, this->nonce_i.ptr, this->nonce_i.len);
479 memcpy(seed.ptr + this->nonce_i.len, this->nonce_r.ptr, this->nonce_r.len);
480 prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
481 chunk_free(&seed);
482
483 if (initiator)
484 {
485 status = this->child_sa->update(this->child_sa, this->proposal, prf_plus);
486 }
487 else
488 {
489 status = this->child_sa->add(this->child_sa, this->proposal, prf_plus);
490 }
491 prf_plus->destroy(prf_plus);
492 if (status != SUCCESS)
493 {
494 return DESTROY_ME;
495 }
496 if (initiator)
497 {
498 status = this->child_sa->add_policies(this->child_sa, this->tsi, this->tsr);
499 }
500 else
501 {
502 status = this->child_sa->add_policies(this->child_sa, this->tsr, this->tsi);
503 }
504 if (status != SUCCESS)
505 {
506 return DESTROY_ME;
507 }
508
509 /* add to IKE_SA, and remove from transaction */
510 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
511 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
512 this->child_sa = NULL;
513 return SUCCESS;
514 }
515
516 /**
517 * Implementation of transaction_t.get_response.
518 */
519 static status_t get_response(private_create_child_sa_t *this, message_t *request,
520 message_t **result, transaction_t **next)
521 {
522 host_t *me, *other;
523 identification_t *my_id, *other_id;
524 message_t *response;
525 status_t status;
526 iterator_t *payloads;
527 sa_payload_t *sa_request = NULL;
528 nonce_payload_t *nonce_request = NULL;
529 ts_payload_t *tsi_request = NULL;
530 ts_payload_t *tsr_request = NULL;
531 nonce_payload_t *nonce_response;
532
533 /* check if we already have built a response (retransmission) */
534 if (this->message)
535 {
536 *result = this->message;
537 return SUCCESS;
538 }
539
540 me = this->ike_sa->get_my_host(this->ike_sa);
541 other = this->ike_sa->get_other_host(this->ike_sa);
542 my_id = this->ike_sa->get_my_id(this->ike_sa);
543 other_id = this->ike_sa->get_other_id(this->ike_sa);
544 this->message_id = request->get_message_id(request);
545
546 /* set up response */
547 response = message_create();
548 response->set_source(response, me->clone(me));
549 response->set_destination(response, other->clone(other));
550 response->set_exchange_type(response, CREATE_CHILD_SA);
551 response->set_request(response, FALSE);
552 response->set_message_id(response, this->message_id);
553 response->set_ike_sa_id(response, this->ike_sa->get_id(this->ike_sa));
554 this->message = response;
555 *result = response;
556
557 /* check message type */
558 if (request->get_exchange_type(request) != CREATE_CHILD_SA)
559 {
560 this->logger->log(this->logger, ERROR,
561 "CREATE_CHILD_SA response of invalid type, aborted");
562 return FAILED;
563 }
564
565 /* we do not allow the creation of new CHILDren/rekeying when IKE_SA is
566 * rekeying */
567 if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING ||
568 this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
569 {
570 build_notify(NO_ADDITIONAL_SAS, CHUNK_INITIALIZER, response, TRUE);
571 this->logger->log(this->logger, AUDIT,
572 "unable to create new CHILD_SAs, as rekeying in progress");
573 return FAILED;
574 }
575
576 /* Iterate over all payloads. */
577 payloads = request->get_payload_iterator(request);
578 while (payloads->has_next(payloads))
579 {
580 payload_t *payload;
581 payloads->current(payloads, (void**)&payload);
582 switch (payload->get_type(payload))
583 {
584 case SECURITY_ASSOCIATION:
585 sa_request = (sa_payload_t*)payload;
586 break;
587 case NONCE:
588 nonce_request = (nonce_payload_t*)payload;
589 break;
590 case TRAFFIC_SELECTOR_INITIATOR:
591 tsi_request = (ts_payload_t*)payload;
592 break;
593 case TRAFFIC_SELECTOR_RESPONDER:
594 tsr_request = (ts_payload_t*)payload;
595 break;
596 case KEY_EXCHANGE:
597 {
598 u_int8_t dh_buffer[] = {0x00, 0x00}; /* MODP_NONE */
599 chunk_t group = chunk_from_buf(dh_buffer);
600 build_notify(INVALID_KE_PAYLOAD, group, response, TRUE);
601 this->logger->log(this->logger, CONTROL,
602 "CREATE_CHILD_SA used PFS, sending INVALID_KE_PAYLOAD");
603 return FAILED;
604 }
605 case NOTIFY:
606 {
607 status = process_notifys(this, (notify_payload_t*)payload);
608 if (status != SUCCESS)
609 {
610 payloads->destroy(payloads);
611 return status;
612 }
613 break;
614 }
615 default:
616 {
617 this->logger->log(this->logger, ERROR, "ignoring %s payload (%d)",
618 mapping_find(payload_type_m, payload->get_type(payload)),
619 payload->get_type(payload));
620 break;
621 }
622 }
623 }
624 payloads->destroy(payloads);
625
626 /* check if we have all payloads */
627 if (!(sa_request && nonce_request && tsi_request && tsr_request))
628 {
629 build_notify(INVALID_SYNTAX, CHUNK_INITIALIZER, response, TRUE);
630 this->logger->log(this->logger, AUDIT,
631 "request message incomplete, no CHILD_SA created");
632 return FAILED;
633 }
634
635 { /* process nonce payload */
636 this->nonce_i = nonce_request->get_nonce(nonce_request);
637 if (this->randomizer->allocate_pseudo_random_bytes(this->randomizer,
638 NONCE_SIZE, &this->nonce_r) != SUCCESS)
639 {
640 build_notify(NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER, response, TRUE);
641 return FAILED;
642 }
643 nonce_response = nonce_payload_create();
644 nonce_response->set_nonce(nonce_response, this->nonce_r);
645 }
646
647 { /* get a policy and process traffic selectors */
648 identification_t *my_id, *other_id;
649 linked_list_t *my_ts, *other_ts;
650
651 my_id = this->ike_sa->get_my_id(this->ike_sa);
652 other_id = this->ike_sa->get_other_id(this->ike_sa);
653
654 my_ts = tsr_request->get_traffic_selectors(tsr_request);
655 other_ts = tsi_request->get_traffic_selectors(tsi_request);
656
657 this->policy = charon->policies->get_policy(charon->policies,
658 my_id, other_id,
659 my_ts, other_ts,
660 me, other);
661 if (this->policy)
662 {
663 this->tsr = this->policy->select_my_traffic_selectors(this->policy, my_ts, me);
664 this->tsi = this->policy->select_other_traffic_selectors(this->policy, other_ts, other);
665 }
666 destroy_ts_list(my_ts);
667 destroy_ts_list(other_ts);
668
669 if (this->policy == NULL)
670 {
671 this->logger->log(this->logger, AUDIT,
672 "no acceptable policy found, adding TS_UNACCEPTABLE notify");
673 build_notify(TS_UNACCEPTABLE, CHUNK_INITIALIZER, response, TRUE);
674 return FAILED;
675 }
676 }
677
678 { /* process SA payload */
679 linked_list_t *proposal_list;
680 sa_payload_t *sa_response;
681 ts_payload_t *ts_response;
682 bool use_natt;
683 u_int32_t soft_lifetime, hard_lifetime;
684
685 sa_response = sa_payload_create();
686 /* get proposals from request, and select one with ours */
687 proposal_list = sa_request->get_proposals(sa_request);
688 this->logger->log(this->logger, CONTROL|LEVEL1, "selecting proposals:");
689 this->proposal = this->policy->select_proposal(this->policy, proposal_list);
690 destroy_proposal_list(proposal_list);
691
692 /* do we have a proposal? */
693 if (this->proposal == NULL)
694 {
695 this->logger->log(this->logger, AUDIT,
696 "CHILD_SA proposals unacceptable, adding NO_PROPOSAL_CHOSEN notify");
697 build_notify(NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER, response, TRUE);
698 return FAILED;
699 }
700 /* do we have traffic selectors? */
701 else if (this->tsi->get_count(this->tsi) == 0 || this->tsr->get_count(this->tsr) == 0)
702 {
703 this->logger->log(this->logger, AUDIT,
704 "CHILD_SA traffic selectors unacceptable, adding TS_UNACCEPTABLE notify");
705 build_notify(TS_UNACCEPTABLE, CHUNK_INITIALIZER, response, TRUE);
706 return FAILED;
707 }
708 else
709 { /* create child sa */
710 if (this->rekeyed_sa)
711 {
712 this->reqid = this->rekeyed_sa->get_reqid(this->rekeyed_sa);
713 }
714 soft_lifetime = this->policy->get_soft_lifetime(this->policy);
715 hard_lifetime = this->policy->get_hard_lifetime(this->policy);
716 use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
717 this->child_sa = child_sa_create(this->reqid, me, other, my_id, other_id,
718 soft_lifetime, hard_lifetime,
719 this->policy->get_updown(this->policy),
720 use_natt);
721 this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
722 if (install_child_sa(this, FALSE) != SUCCESS)
723 {
724 this->logger->log(this->logger, ERROR,
725 "installing CHILD_SA failed, adding NO_PROPOSAL_CHOSEN notify");
726 build_notify(NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER, response, TRUE);
727 return FAILED;
728 }
729 /* add proposal to sa payload */
730 sa_response->add_proposal(sa_response, this->proposal);
731 }
732 response->add_payload(response, (payload_t*)sa_response);
733
734 /* add nonce/ts payload after sa payload */
735 response->add_payload(response, (payload_t *)nonce_response);
736 ts_response = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
737 response->add_payload(response, (payload_t*)ts_response);
738 ts_response = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
739 response->add_payload(response, (payload_t*)ts_response);
740 }
741 /* CHILD_SA successfully created. If another transaction is already rekeying
742 * this SA, our lower nonce must be registered for a later nonce compare. */
743 if (this->rekeyed_sa)
744 {
745 private_create_child_sa_t *other;
746
747 other = this->rekeyed_sa->get_rekeying_transaction(this->rekeyed_sa);
748 if (other)
749 {
750 /* store our lower nonce in the simultaneus transaction, it
751 * will later compare it against his nonces when it calls conclude().
752 */
753 if (memcmp(this->nonce_i.ptr, this->nonce_r.ptr,
754 min(this->nonce_i.len, this->nonce_r.len)) < 0)
755 {
756 other->nonce_s = chunk_clone(this->nonce_i);
757 }
758 else
759 {
760 other->nonce_s = chunk_clone(this->nonce_r);
761 }
762 }
763 this->rekeyed_sa->set_state(this->rekeyed_sa, CHILD_REKEYING);
764 }
765 return SUCCESS;
766 }
767
768 /**
769 * Implementation of transaction_t.conclude
770 */
771 static status_t conclude(private_create_child_sa_t *this, message_t *response,
772 transaction_t **next)
773 {
774 iterator_t *payloads;
775 host_t *me, *other;
776 sa_payload_t *sa_payload = NULL;
777 nonce_payload_t *nonce_payload = NULL;
778 ts_payload_t *tsi_payload = NULL;
779 ts_payload_t *tsr_payload = NULL;
780 status_t status;
781 child_sa_t *new_child = NULL;
782 delete_child_sa_t *delete_child_sa;
783
784 /* check message type */
785 if (response->get_exchange_type(response) != CREATE_CHILD_SA)
786 {
787 this->logger->log(this->logger, ERROR,
788 "CREATE_CHILD_SA response of invalid type, aborting");
789 return FAILED;
790 }
791
792 me = this->ike_sa->get_my_host(this->ike_sa);
793 other = this->ike_sa->get_other_host(this->ike_sa);
794
795 /* Iterate over all payloads to collect them */
796 payloads = response->get_payload_iterator(response);
797 while (payloads->has_next(payloads))
798 {
799 payload_t *payload;
800 payloads->current(payloads, (void**)&payload);
801 switch (payload->get_type(payload))
802 {
803 case SECURITY_ASSOCIATION:
804 sa_payload = (sa_payload_t*)payload;
805 break;
806 case NONCE:
807 nonce_payload = (nonce_payload_t*)payload;
808 break;
809 case TRAFFIC_SELECTOR_INITIATOR:
810 tsi_payload = (ts_payload_t*)payload;
811 break;
812 case TRAFFIC_SELECTOR_RESPONDER:
813 tsr_payload = (ts_payload_t*)payload;
814 break;
815 case NOTIFY:
816 {
817 status = process_notifys(this, (notify_payload_t*)payload);
818 if (status != SUCCESS)
819 {
820 payloads->destroy(payloads);
821 return status;
822 }
823 break;
824 }
825 default:
826 {
827 this->logger->log(this->logger, ERROR, "ignoring %s payload (%d)",
828 mapping_find(payload_type_m, payload->get_type(payload)),
829 payload->get_type(payload));
830 break;
831 }
832 }
833 }
834 payloads->destroy(payloads);
835
836 if (!(sa_payload && nonce_payload && tsi_payload && tsr_payload))
837 {
838 this->logger->log(this->logger, AUDIT, "response message incomplete, no CHILD_SA built");
839 return FAILED;
840 }
841
842 { /* process NONCE payload */
843 this->nonce_r = nonce_payload->get_nonce(nonce_payload);
844 }
845
846 { /* process traffic selectors for us */
847 linked_list_t *ts_received = tsi_payload->get_traffic_selectors(tsi_payload);
848 this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received, me);
849 destroy_ts_list(ts_received);
850 }
851
852 { /* process traffic selectors for other */
853 linked_list_t *ts_received = tsr_payload->get_traffic_selectors(tsr_payload);
854 this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received, other);
855 destroy_ts_list(ts_received);
856 }
857
858 { /* process sa payload */
859 linked_list_t *proposal_list;
860
861 proposal_list = sa_payload->get_proposals(sa_payload);
862 /* we have to re-check here if other's selection is valid */
863 this->proposal = this->policy->select_proposal(this->policy, proposal_list);
864 destroy_proposal_list(proposal_list);
865
866 /* everything fine to create CHILD? */
867 if (this->proposal == NULL ||
868 this->tsi->get_count(this->tsi) == 0 ||
869 this->tsr->get_count(this->tsr) == 0)
870 {
871 this->logger->log(this->logger, AUDIT, "CHILD_SA creation failed");
872 return FAILED;
873 }
874 new_child = this->child_sa;
875 if (install_child_sa(this, TRUE) != SUCCESS)
876 {
877 this->logger->log(this->logger, ERROR,
878 "installing CHILD_SA failed, no CHILD_SA built");
879 return FAILED;
880 }
881 }
882 /* CHILD_SA successfully created. If the other peer initiated rekeying
883 * in the meantime, we detect this by comparing the rekeying_transaction
884 * of the SA. If it changed, we are not alone. Then we must compare the nonces.
885 * If no simultaneous rekeying is going on, we just initiate the delete of
886 * the superseded SA. */
887 if (this->rekeyed_sa)
888 {
889 /* rekeying finished, update SA status */
890 this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, NULL);
891
892 if (this->nonce_s.ptr)
893 { /* simlutaneous rekeying is going on, not so good */
894 chunk_t this_lowest;
895
896 /* first get our lowest nonce */
897 if (memcmp(this->nonce_i.ptr, this->nonce_r.ptr,
898 min(this->nonce_i.len, this->nonce_r.len)) < 0)
899 {
900 this_lowest = this->nonce_i;
901 }
902 else
903 {
904 this_lowest = this->nonce_r;
905 }
906 /* then compare against other lowest nonce */
907 if (memcmp(this_lowest.ptr, this->nonce_s.ptr,
908 min(this_lowest.len, this->nonce_s.len)) < 0)
909 {
910 this->logger->log(this->logger, ERROR,
911 "detected simultaneous CHILD_SA rekeying, deleting ours");
912 this->lost = TRUE;
913 }
914 else
915 {
916 this->logger->log(this->logger, ERROR,
917 "detected simultaneous CHILD_SA rekeying, but ours is preferred");
918 }
919 }
920 /* delete the old SA if we have won the rekeying nonce compare*/
921 if (!this->lost)
922 {
923 delete_child_sa = delete_child_sa_create(this->ike_sa);
924 delete_child_sa->set_child_sa(delete_child_sa, this->rekeyed_sa);
925 *next = (transaction_t*)delete_child_sa;
926 }
927 }
928 if (this->lost)
929 {
930 /* we have lost simlutaneous rekeying, delete the CHILD_SA we just have created */
931 delete_child_sa = delete_child_sa_create(this->ike_sa);
932 delete_child_sa->set_child_sa(delete_child_sa, new_child);
933 *next = (transaction_t*)delete_child_sa;
934 }
935 return SUCCESS;
936 }
937
938 /**
939 * implements transaction_t.destroy
940 */
941 static void destroy(private_create_child_sa_t *this)
942 {
943 DESTROY_IF(this->message);
944 DESTROY_IF(this->proposal);
945 DESTROY_IF(this->child_sa);
946 DESTROY_IF(this->policy);
947 destroy_ts_list(this->tsi);
948 destroy_ts_list(this->tsr);
949 chunk_free(&this->nonce_i);
950 chunk_free(&this->nonce_r);
951 chunk_free(&this->nonce_s);
952 this->randomizer->destroy(this->randomizer);
953 free(this);
954 }
955
956 /*
957 * Described in header.
958 */
959 create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa)
960 {
961 private_create_child_sa_t *this = malloc_thing(private_create_child_sa_t);
962
963 /* transaction interface functions */
964 this->public.transaction.get_request = (status_t(*)(transaction_t*,message_t**))get_request;
965 this->public.transaction.get_response = (status_t(*)(transaction_t*,message_t*,message_t**,transaction_t**))get_response;
966 this->public.transaction.conclude = (status_t(*)(transaction_t*,message_t*,transaction_t**))conclude;
967 this->public.transaction.get_message_id = (u_int32_t(*)(transaction_t*))get_message_id;
968 this->public.transaction.requested = (u_int32_t(*)(transaction_t*))requested;
969 this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
970
971 /* public functions */
972 this->public.set_policy = (void(*)(create_child_sa_t*,policy_t*))set_policy;
973 this->public.set_reqid = (void(*)(create_child_sa_t*,u_int32_t))set_reqid;
974 this->public.rekeys_child = (void(*)(create_child_sa_t*,child_sa_t*))rekeys_child;
975 this->public.cancel = (void(*)(create_child_sa_t*))cancel;
976
977 /* private data */
978 this->ike_sa = ike_sa;
979 this->message_id = 0;
980 this->message = NULL;
981 this->requested = 0;
982 this->rekey_spi = 0;
983 this->reqid = 0;
984 this->nonce_i = CHUNK_INITIALIZER;
985 this->nonce_r = CHUNK_INITIALIZER;
986 this->nonce_s = CHUNK_INITIALIZER;
987 this->child_sa = NULL;
988 this->rekeyed_sa = NULL;
989 this->lost = FALSE;
990 this->proposal = NULL;
991 this->policy = NULL;
992 this->tsi = NULL;
993 this->tsr = NULL;
994 this->randomizer = randomizer_create();
995 this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
996
997 return &this->public;
998 }