4 * @brief Implementation of ike_sa_init_t transaction.
9 * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
10 * Copyright (C) 2005-2006 Martin Willi
11 * Copyright (C) 2005 Jan Hutter
12 * Hochschule fuer Technik Rapperswil
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include "ike_sa_init.h"
30 #include <crypto/diffie_hellman.h>
31 #include <crypto/hashers/hasher.h>
32 #include <encoding/payloads/sa_payload.h>
33 #include <encoding/payloads/ke_payload.h>
34 #include <encoding/payloads/nonce_payload.h>
35 #include <sa/transactions/ike_auth.h>
36 #include <queues/jobs/delete_ike_sa_job.h>
37 #include <queues/jobs/rekey_ike_sa_job.h>
40 typedef struct private_ike_sa_init_t private_ike_sa_init_t
;
43 * Private members of a ike_sa_init_t object..
45 struct private_ike_sa_init_t
{
48 * Public methods and transaction_t interface.
58 * Message sent by our peer, if already generated
63 * Message ID this transaction uses
68 * Times we did send the request
73 * Next transaction followed to this one. May be IKE_AUTH,
74 * or a IKE_SA_INIT retry
79 * Diffie hellman object used to generate public DH value.
81 diffie_hellman_t
*diffie_hellman
;
84 * initiator chosen nonce
89 * responder chosen nonce
94 * connection definition used for initiation
96 connection_t
*connection
;
99 * policy definition forwarded to ike_auth transaction
104 * Negotiated proposal used for IKE_SA
106 proposal_t
*proposal
;
109 * Reqid to pass to IKE_AUTH, used for created CHILD_SA
114 * Unique ID for to enumerate all IKE_SAs in its name
119 * Randomizer to generate nonces
121 randomizer_t
*randomizer
;
124 * Hasher used to build NAT detection hashes
126 hasher_t
*nat_hasher
;
129 * Precomputed NAT hash for source address
131 chunk_t natd_src_hash
;
134 * Precomputed NAT hash for destination address
136 chunk_t natd_dst_hash
;
139 * Did we process any NAT detection notifys for a source address?
144 * Did we process any NAT detection notifys for a destination address?
149 * Have we found a matching source address NAT hash?
151 bool natd_src_matched
;
154 * Have we found a matching destination address NAT hash?
156 bool natd_dst_matched
;
160 * Implementation of ike_sa_init_t.use_dh_group.
162 static bool use_dh_group(private_ike_sa_init_t
*this, diffie_hellman_group_t dh_group
)
164 if (this->connection
->check_dh_group(this->connection
, dh_group
))
166 this->diffie_hellman
= diffie_hellman_create(dh_group
);
167 if (this->diffie_hellman
)
176 * Implementation of ike_sa_init_t.set_config.
178 static void set_config(private_ike_sa_init_t
*this,
179 connection_t
*connection
, policy_t
*policy
)
181 this->connection
= connection
;
182 this->policy
= policy
;
186 * Implementation of ike_sa_init_t.set_reqid.
188 static void set_reqid(private_ike_sa_init_t
*this, u_int32_t reqid
)
194 * Implementation of transaction_t.get_message_id.
196 static u_int32_t
get_message_id(private_ike_sa_init_t
*this)
198 return this->message_id
;
202 * Implementation of transaction_t.requested.
204 static u_int32_t
requested(private_ike_sa_init_t
*this)
206 return this->requested
++;
210 * Build NAT detection hash for a host
212 static chunk_t
generate_natd_hash(private_ike_sa_init_t
*this,
213 ike_sa_id_t
* ike_sa_id
, host_t
*host
)
215 chunk_t natd_chunk
, spi_i_chunk
, spi_r_chunk
, addr_chunk
, port_chunk
;
217 u_int64_t spi_i
, spi_r
;
220 /* prepare all requred chunks */
221 spi_i
= ike_sa_id
->get_initiator_spi(ike_sa_id
);
222 spi_r
= ike_sa_id
->get_responder_spi(ike_sa_id
);
223 spi_i_chunk
.ptr
= (void*)&spi_i
;
224 spi_i_chunk
.len
= sizeof(spi_i
);
225 spi_r_chunk
.ptr
= (void*)&spi_r
;
226 spi_r_chunk
.len
= sizeof(spi_r
);
227 port
= htons(host
->get_port(host
));
228 port_chunk
.ptr
= (void*)&port
;
229 port_chunk
.len
= sizeof(port
);
230 addr_chunk
= host
->get_address(host
);
232 /* natd_hash = SHA1( spi_i | spi_r | address | port ) */
233 natd_chunk
= chunk_cat("cccc", spi_i_chunk
, spi_r_chunk
, addr_chunk
, port_chunk
);
234 this->nat_hasher
->allocate_hash(this->nat_hasher
, natd_chunk
, &natd_hash
);
235 DBG3(DBG_IKE
, "natd_chunk %B", &natd_chunk
);
236 DBG3(DBG_IKE
, "natd_hash %B", &natd_hash
);
238 chunk_free(&natd_chunk
);
243 * Build a NAT detection notify payload.
245 static notify_payload_t
*build_natd_payload(private_ike_sa_init_t
*this,
246 notify_type_t type
, host_t
*host
)
249 notify_payload_t
*notify
;
250 ike_sa_id_t
*ike_sa_id
;
252 ike_sa_id
= this->ike_sa
->get_id(this->ike_sa
);
253 notify
= notify_payload_create();
254 notify
->set_notify_type(notify
, type
);
255 hash
= generate_natd_hash(this, ike_sa_id
, host
);
256 notify
->set_notification_data(notify
, hash
);
263 * Implementation of transaction_t.get_request.
265 static status_t
get_request(private_ike_sa_init_t
*this, message_t
**result
)
269 identification_t
*my_id
, *other_id
;
272 /* check if we already have built a message (retransmission) */
275 *result
= this->message
;
279 me
= this->connection
->get_my_host(this->connection
);
280 other
= this->connection
->get_other_host(this->connection
);
282 /* we already set up the IDs. Mine is already fully qualified, other
283 * will be updated in the ike_auth transaction */
284 my_id
= this->policy
->get_my_id(this->policy
);
285 other_id
= this->policy
->get_other_id(this->policy
);
286 this->ike_sa
->set_my_id(this->ike_sa
, my_id
->clone(my_id
));
287 this->ike_sa
->set_other_id(this->ike_sa
, other_id
->clone(other_id
));
288 if (snprintf(name
, sizeof(name
), "%s{%d}",
289 this->connection
->get_name(this->connection
),
290 this->unique_id
) > 0)
292 this->ike_sa
->set_name(this->ike_sa
, name
);
295 /* setting up a IKE_SA implicitly requires setup of a CHILD_SA */
296 SIG(IKE_UP_START
, "initiating IKE_SA '%s' between %H[%D]...%H[%D]",
297 this->connection
->get_name(this->connection
), me
, my_id
, other
, other_id
);
298 SIG(CHILD_UP_START
, "establishing CHILD_SA '%s' along with IKE_SA",
299 this->policy
->get_name(this->policy
));
301 /* build the request */
302 request
= message_create();
303 request
->set_source(request
, me
->clone(me
));
304 request
->set_destination(request
, other
->clone(other
));
305 request
->set_exchange_type(request
, IKE_SA_INIT
);
306 request
->set_request(request
, TRUE
);
307 request
->set_message_id(request
, this->message_id
);
308 request
->set_ike_sa_id(request
, this->ike_sa
->get_id(this->ike_sa
));
309 /* apply for caller */
311 /* store for retransmission */
312 this->message
= request
;
314 /* if the DH group is set via use_dh_group(), we already have a DH object */
315 if (!this->diffie_hellman
)
317 diffie_hellman_group_t dh_group
;
319 dh_group
= this->connection
->get_dh_group(this->connection
);
320 this->diffie_hellman
= diffie_hellman_create(dh_group
);
321 if (this->diffie_hellman
== NULL
)
323 SIG(IKE_UP_FAILED
, "DH group %N not supported, aborting",
324 diffie_hellman_group_names
, dh_group
);
326 "initiating CHILD_SA failed, unable to create IKE_SA");
331 { /* build the SA payload from proposals */
332 sa_payload_t
*sa_payload
;
333 linked_list_t
*proposal_list
;
335 proposal_list
= this->connection
->get_proposals(this->connection
);
336 sa_payload
= sa_payload_create_from_proposal_list(proposal_list
);
337 proposal_list
->destroy_offset(proposal_list
, offsetof(proposal_t
, destroy
));
339 request
->add_payload(request
, (payload_t
*)sa_payload
);
342 { /* build the KE payload from the DH object */
343 ke_payload_t
*ke_payload
;
345 ke_payload
= ke_payload_create_from_diffie_hellman(this->diffie_hellman
);
347 request
->add_payload(request
, (payload_t
*)ke_payload
);
350 { /* build the NONCE payload for us (initiator) */
351 nonce_payload_t
*nonce_payload
;
353 if (this->randomizer
->allocate_pseudo_random_bytes(this->randomizer
,
354 NONCE_SIZE
, &this->nonce_i
) != SUCCESS
)
356 SIG(IKE_UP_FAILED
, "could not generate nonce, aborting");
358 "initiating CHILD_SA failed, unable to create IKE_SA");
361 nonce_payload
= nonce_payload_create();
362 nonce_payload
->set_nonce(nonce_payload
, this->nonce_i
);
364 request
->add_payload(request
, (payload_t
*)nonce_payload
);
367 { /* build NAT_DETECTION notifys */
368 notify_payload_t
*notify
;
372 /* N(NAT_DETECTION_SOURCE_IP)+ */
373 list
= charon
->socket
->create_local_address_list(charon
->socket
);
374 while (list
->remove_first(list
, (void**)&host
) == SUCCESS
)
376 /* TODO: should we only include NAT payloads for addresses
377 * of used address family? */
378 notify
= build_natd_payload(this, NAT_DETECTION_SOURCE_IP
, host
);
380 request
->add_payload(request
, (payload_t
*)notify
);
384 /* N(NAT_DETECTION_DESTINATION_IP) */
385 notify
= build_natd_payload(this, NAT_DETECTION_DESTINATION_IP
, other
);
386 request
->add_payload(request
, (payload_t
*)notify
);
389 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
394 * Handle all kind of notifys
396 static status_t
process_notifys(private_ike_sa_init_t
*this, notify_payload_t
*notify_payload
)
398 chunk_t notification_data
;
399 notify_type_t notify_type
= notify_payload
->get_notify_type(notify_payload
);
401 DBG2(DBG_IKE
, "process notify type %N", notify_type_names
, notify_type
);
405 case NO_PROPOSAL_CHOSEN
:
408 "received a NO_PROPOSAL_CHOSEN notify, deleting IKE_SA");
411 case INVALID_MAJOR_VERSION
:
414 "received a INVALID_MAJOR_VERSION notify, deleting IKE_SA");
417 case INVALID_KE_PAYLOAD
:
420 diffie_hellman_group_t dh_group
, old_dh_group
;
421 ike_sa_init_t
*retry
;
423 old_dh_group
= this->connection
->get_dh_group(this->connection
);
424 notify_data
= notify_payload
->get_notification_data(notify_payload
);
425 dh_group
= ntohs(*((u_int16_t
*)notify_data
.ptr
));
427 DBG1(DBG_IKE
, "peer didn't accept DH group %N, it requested %N",
428 diffie_hellman_group_names
, old_dh_group
,
429 diffie_hellman_group_names
, dh_group
);
430 if (!this->connection
->check_dh_group(this->connection
, dh_group
))
432 SIG(IKE_UP_FAILED
, "DH group %N not acceptable, aborting",
433 diffie_hellman_group_names
, dh_group
);
436 retry
= ike_sa_init_create(this->ike_sa
);
437 retry
->set_config(retry
, this->connection
, this->policy
);
438 this->connection
= NULL
;
440 retry
->use_dh_group(retry
, dh_group
);
441 *this->next
= (transaction_t
*)retry
;
444 case NAT_DETECTION_DESTINATION_IP
:
446 this->natd_dst_seen
= TRUE
;
447 if (this->natd_dst_matched
)
451 notification_data
= notify_payload
->get_notification_data(notify_payload
);
452 if (chunk_equals(notification_data
, this->natd_dst_hash
))
454 this->natd_dst_matched
= TRUE
;
455 DBG2(DBG_IKE
, "NAT-D dst hash match");
459 DBG2(DBG_IKE
, "NAT-D dst hash mismatch");
463 case NAT_DETECTION_SOURCE_IP
:
465 this->natd_src_seen
= TRUE
;;
466 if (this->natd_src_matched
)
470 notification_data
= notify_payload
->get_notification_data(notify_payload
);
471 if (chunk_equals(notification_data
, this->natd_src_hash
))
473 this->natd_src_matched
= TRUE
;
474 DBG2(DBG_IKE
, "NAT-D src hash match");
478 DBG2(DBG_IKE
, "NAT-D src hash mismatch");
484 if (notify_type
< 16383)
486 SIG(IKE_UP_FAILED
, "received %N notify error, deleting IKE_SA",
487 notify_type_names
, notify_type
);
492 DBG1(DBG_IKE
, "received %N notify, ignored",
493 notify_type_names
, notify_type
);
501 * Implementation of transaction_t.get_response.
503 static status_t
get_response(private_ike_sa_init_t
*this,
504 message_t
*request
, message_t
**result
,
505 transaction_t
**next
)
510 iterator_t
*payloads
;
512 sa_payload_t
*sa_request
= NULL
;
513 ke_payload_t
*ke_request
= NULL
;
514 nonce_payload_t
*nonce_request
= NULL
;
515 ike_sa_id_t
*ike_sa_id
;
519 /* check if we already have built a response (retransmission) */
522 *result
= this->message
;
526 me
= request
->get_destination(request
);
527 other
= request
->get_source(request
);
528 this->message_id
= request
->get_message_id(request
);
530 SIG(IKE_UP_START
, "establishing IKE_SA between %H...%H", me
, other
);
532 /* set up response */
533 response
= message_create();
534 response
->set_source(response
, me
->clone(me
));
535 response
->set_destination(response
, other
->clone(other
));
536 response
->set_exchange_type(response
, IKE_SA_INIT
);
537 response
->set_request(response
, FALSE
);
538 response
->set_message_id(response
, this->message_id
);
539 response
->set_ike_sa_id(response
, this->ike_sa
->get_id(this->ike_sa
));
540 this->message
= response
;
543 /* check message type */
544 if (request
->get_exchange_type(request
) != IKE_SA_INIT
)
546 SIG(IKE_UP_FAILED
, "IKE_SA_INIT request of invalid type, deleting IKE_SA");
550 /* this is the first message to process, find a connection for IKE_SA */
551 this->connection
= charon
->connections
->get_connection_by_hosts(
552 charon
->connections
, me
, other
);
553 if (this->connection
== NULL
)
555 notify_payload_t
*notify
= notify_payload_create();
556 notify
->set_notify_type(notify
, NO_PROPOSAL_CHOSEN
);
557 response
->add_payload(response
, (payload_t
*)notify
);
559 SIG(IKE_UP_FAILED
, "no connection for hosts %H...%H found, "
560 "deleting IKE_SA", me
, other
);
564 if (snprintf(name
, sizeof(name
), "%s{%d}",
565 this->connection
->get_name(this->connection
),
566 this->unique_id
) > 0)
568 this->ike_sa
->set_name(this->ike_sa
, name
);
570 this->ike_sa
->apply_connection(this->ike_sa
, this->connection
);
572 /* Precompute NAT-D hashes for incoming NAT notify comparison */
573 ike_sa_id
= request
->get_ike_sa_id(request
);
574 this->natd_dst_hash
= generate_natd_hash(this, ike_sa_id
, me
);
575 this->natd_src_hash
= generate_natd_hash(this, ike_sa_id
, other
);
577 /* Iterate over all payloads. */
578 payloads
= request
->get_payload_iterator(request
);
579 while (payloads
->iterate(payloads
, (void**)&payload
))
581 switch (payload
->get_type(payload
))
583 case SECURITY_ASSOCIATION
:
584 sa_request
= (sa_payload_t
*)payload
;
587 ke_request
= (ke_payload_t
*)payload
;
590 nonce_request
= (nonce_payload_t
*)payload
;
594 status
= process_notifys(this, (notify_payload_t
*)payload
);
595 if (status
== FAILED
)
597 payloads
->destroy(payloads
);
598 /* we return SUCCESS, returned FAILED means do next transaction */
601 if (status
== DESTROY_ME
)
603 payloads
->destroy(payloads
);
610 DBG2(DBG_IKE
, "ignoring %N payload",
611 payload_type_names
, payload
->get_type(payload
));
616 payloads
->destroy(payloads
);
618 /* check if we have all payloads */
619 if (!(sa_request
&& ke_request
&& nonce_request
))
621 notify_payload_t
*notify
= notify_payload_create();
622 notify
->set_notify_type(notify
, INVALID_SYNTAX
);
623 response
->add_payload(response
, (payload_t
*)notify
);
624 SIG(IKE_UP_FAILED
, "received request message incomplete, deleting IKE_SA");
628 { /* process SA payload:
629 * -------------------
630 * - extract proposals
631 * - select our most preferred proposal found in extracted
632 * - if no matches, return NO_PROPOSAL_CHOSEN
633 * - add sa payload with selected proposal
635 sa_payload_t
* sa_response
;
636 linked_list_t
*proposal_list
;
638 proposal_list
= sa_request
->get_proposals(sa_request
);
639 this->proposal
= this->connection
->select_proposal(this->connection
, proposal_list
);
640 proposal_list
->destroy_offset(proposal_list
, offsetof(proposal_t
, destroy
));
641 if (this->proposal
== NULL
)
643 notify_payload_t
*notify
= notify_payload_create();
644 notify
->set_notify_type(notify
, NO_PROPOSAL_CHOSEN
);
645 response
->add_payload(response
, (payload_t
*)notify
);
646 SIG(IKE_UP_FAILED
, "request did not contain any acceptable "
647 "proposals, deleting IKE_SA");
650 sa_response
= sa_payload_create_from_proposal(this->proposal
);
651 response
->add_payload(response
, (payload_t
*)sa_response
);
654 { /* process KE payload:
655 * --------------------
656 * - check if used group match the selected proposal
657 * - if not, stop with INVALID_KE_PAYLOAD
658 * - apply others public value to complete diffie hellman exchange
659 * - add our public value to response
661 diffie_hellman_group_t used_group
;
662 ke_payload_t
*ke_response
;
664 used_group
= ke_request
->get_dh_group_number(ke_request
);
666 if (!this->connection
->check_dh_group(this->connection
, used_group
) ||
667 (this->diffie_hellman
= diffie_hellman_create(used_group
)) == NULL
)
669 u_int16_t notify_group
;
670 chunk_t notify_chunk
;
671 notify_payload_t
*notify
;
672 iterator_t
*iterator
;
675 notify_group
= this->connection
->get_dh_group(this->connection
);
676 SIG(IKE_UP_FAILED
, "request used inacceptable DH group %N, sending "
677 "INVALID_KE_PAYLOAD with %N, deleting IKE_SA",
678 diffie_hellman_group_names
, used_group
,
679 diffie_hellman_group_names
, notify_group
);
681 /* remove already added payloads */
682 iterator
= response
->get_payload_iterator(response
);
683 while (iterator
->iterate(iterator
, (void**)&payload
))
685 iterator
->remove(iterator
);
686 payload
->destroy(payload
);
688 iterator
->destroy(iterator
);
690 notify_group
= htons(notify_group
);
691 notify_chunk
.ptr
= (u_int8_t
*)¬ify_group
;
692 notify_chunk
.len
= sizeof(notify_group
);
693 notify
= notify_payload_create();
694 notify
->set_notify_type(notify
, INVALID_KE_PAYLOAD
);
695 notify
->set_notification_data(notify
, notify_chunk
);
696 response
->add_payload(response
, (payload_t
*)notify
);
699 this->diffie_hellman
->set_other_public_value(this->diffie_hellman
,
700 ke_request
->get_key_exchange_data(ke_request
));
703 ke_response
= ke_payload_create_from_diffie_hellman(this->diffie_hellman
);
704 response
->add_payload(response
, (payload_t
*)ke_response
);
707 { /* process nonce payload:
708 * ----------------------
709 * - get nonce from payload
710 * - generate own nonce and add to reply
712 nonce_payload_t
*nonce_response
;
714 this->nonce_i
= nonce_request
->get_nonce(nonce_request
);
716 /* build response nonce */
717 if (this->randomizer
->allocate_pseudo_random_bytes(this->randomizer
,
718 NONCE_SIZE
, &this->nonce_r
) != SUCCESS
)
720 notify_payload_t
*notify
= notify_payload_create();
721 notify
->set_notify_type(notify
, NO_PROPOSAL_CHOSEN
);
722 response
->add_payload(response
, (payload_t
*)notify
);
723 SIG(IKE_UP_FAILED
, "could not create nonce, deleting IKE_SA");
726 nonce_response
= nonce_payload_create();
727 nonce_response
->set_nonce(nonce_response
, this->nonce_r
);
728 response
->add_payload(response
, (payload_t
*)nonce_response
);
731 { /* processs NATT stuff:
732 * --------------------
733 * - check if we or other is behind NAT
734 * - enable NATT if so
735 * - build NAT detection notifys for reply
737 notify_payload_t
*notify
;
739 if ((!this->natd_src_seen
&& this->natd_dst_seen
) ||
740 (this->natd_src_seen
&& !this->natd_dst_seen
))
742 notify
= notify_payload_create();
743 notify
->set_notify_type(notify
, INVALID_SYNTAX
);
744 response
->add_payload(response
, (payload_t
*)notify
);
745 SIG(IKE_UP_FAILED
, "request contained invalid number of NAT-D"
746 "payloads, deleting IKE_SA");
749 if (this->natd_dst_seen
&& !this->natd_dst_matched
)
751 this->ike_sa
->enable_natt(this->ike_sa
, TRUE
);
753 if (this->natd_src_seen
&& !this->natd_src_matched
)
755 this->ike_sa
->enable_natt(this->ike_sa
, FALSE
);
757 /* build response NAT DETECTION notifys, if remote supports it */
758 if (this->natd_src_seen
|| this->natd_dst_seen
)
760 /* N(NAT_DETECTION_SOURCE_IP) */
761 notify
= build_natd_payload(this, NAT_DETECTION_SOURCE_IP
, me
);
762 response
->add_payload(response
, (payload_t
*)notify
);
764 /* N(NAT_DETECTION_DESTINATION_IP) */
765 notify
= build_natd_payload(this, NAT_DETECTION_DESTINATION_IP
, other
);
766 response
->add_payload(response
, (payload_t
*)notify
);
770 /* derive all the keys used in the IKE_SA */
771 if (this->ike_sa
->derive_keys(this->ike_sa
, this->proposal
,
772 this->diffie_hellman
,
773 this->nonce_i
, this->nonce_r
,
774 FALSE
, NULL
, NULL
) != SUCCESS
)
776 notify_payload_t
*notify
= notify_payload_create();
777 notify
->set_notify_type(notify
, NO_PROPOSAL_CHOSEN
);
778 response
->add_payload(response
, (payload_t
*)notify
);
779 SIG(IKE_UP_FAILED
, "error creating transforms from proposal, deleting IKE_SA");
783 this->ike_sa
->set_lifetimes(this->ike_sa
,
784 this->connection
->get_soft_lifetime(this->connection
),
785 this->connection
->get_hard_lifetime(this->connection
));
787 { /* create ike_auth transaction, which will store informations for us */
788 packet_t
*response_packet
;
789 chunk_t request_chunk
, response_chunk
;
790 ike_auth_t
*ike_auth
;
792 /* we normally do not generate the message. But we need the generated message
793 * for authentication in the next state, so we do it here. This is not problematic,
794 * as we don't use a crypter/signer in ike_sa_init... */
795 if (response
->generate(response
, NULL
, NULL
, &response_packet
) != SUCCESS
)
797 SIG(IKE_UP_FAILED
, "error in response generation, deleting IKE_SA");
800 response_packet
->destroy(response_packet
);
801 request_chunk
= request
->get_packet_data(request
);
802 response_chunk
= response
->get_packet_data(response
);
804 /* create next transaction, for which we except a message */
805 ike_auth
= ike_auth_create(this->ike_sa
);
806 ike_auth
->set_config(ike_auth
, this->connection
, this->policy
);
807 ike_auth
->set_reqid(ike_auth
, this->reqid
);
808 this->connection
= NULL
;
810 ike_auth
->set_nonces(ike_auth
,
811 chunk_clone(this->nonce_i
),
812 chunk_clone(this->nonce_r
));
813 ike_auth
->set_init_messages(ike_auth
, request_chunk
, response_chunk
);
814 *next
= (transaction_t
*)ike_auth
;
817 /* everything went fine. Now we set a timeout to destroy half initiated IKE_SAs */
818 timeout
= charon
->configuration
->get_half_open_ike_sa_timeout(charon
->configuration
);
821 job_t
*job
= (job_t
*)delete_ike_sa_job_create(
822 this->ike_sa
->get_id(this->ike_sa
), FALSE
);
823 charon
->event_queue
->add_relative(charon
->event_queue
, job
, timeout
);
826 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
833 * Implementation of transaction_t.conclude
835 static status_t
conclude(private_ike_sa_init_t
*this, message_t
*response
,
836 transaction_t
**next
)
838 u_int64_t responder_spi
;
839 ike_sa_id_t
*ike_sa_id
;
840 iterator_t
*payloads
;
843 sa_payload_t
*sa_payload
= NULL
;
844 ke_payload_t
*ke_payload
= NULL
;
845 nonce_payload_t
*nonce_payload
= NULL
;
848 /* check message type */
849 if (response
->get_exchange_type(response
) != IKE_SA_INIT
)
851 SIG(IKE_UP_FAILED
, "IKE_SA_INIT response of invalid type, deleting IKE_SA");
852 SIG(CHILD_UP_FAILED
, "initiating CHILD_SA failed, unable to create IKE_SA");
856 /* allow setting of next transaction in other functions */
859 me
= this->connection
->get_my_host(this->connection
);
860 other
= this->connection
->get_other_host(this->connection
);
862 /* check if SPI has been updated, but apply only if all goes ok later */
863 responder_spi
= response
->get_responder_spi(response
);
864 if (responder_spi
== 0)
866 SIG(IKE_UP_FAILED
, "response contained a SPI of zero, deleting IKE_SA");
867 SIG(CHILD_UP_FAILED
, "initiating CHILD_SA failed, unable to create IKE_SA");
871 /* Precompute NAT-D hashes for later comparison */
872 ike_sa_id
= response
->get_ike_sa_id(response
);
873 this->natd_src_hash
= generate_natd_hash(this, ike_sa_id
, other
);
874 this->natd_dst_hash
= generate_natd_hash(this, ike_sa_id
, me
);
876 /* Iterate over all payloads to collect them */
877 payloads
= response
->get_payload_iterator(response
);
878 while (payloads
->iterate(payloads
, (void**)&payload
))
880 switch (payload
->get_type(payload
))
882 case SECURITY_ASSOCIATION
:
884 sa_payload
= (sa_payload_t
*)payload
;
889 ke_payload
= (ke_payload_t
*)payload
;
894 nonce_payload
= (nonce_payload_t
*)payload
;
899 status
= process_notifys(this, (notify_payload_t
*)payload
);
900 if (status
== FAILED
)
902 payloads
->destroy(payloads
);
903 /* we return SUCCESS, returned FAILED means do next transaction */
906 if (status
== DESTROY_ME
)
908 SIG(CHILD_UP_FAILED
, "initiating CHILD_SA failed, unable to create IKE_SA");
909 payloads
->destroy(payloads
);
916 DBG1(DBG_IKE
, "ignoring payload %N",
917 payload_type_names
, payload
->get_type(payload
));
922 payloads
->destroy(payloads
);
924 if (!(nonce_payload
&& sa_payload
&& ke_payload
))
926 SIG(IKE_UP_FAILED
, "response message incomplete, deleting IKE_SA");
927 SIG(CHILD_UP_FAILED
, "initiating CHILD_SA failed, unable to create IKE_SA");
931 { /* process SA payload:
932 * -------------------
933 * - get proposals from it
934 * - check if peer selected a proposal
935 * - verify it's selection againts our set
937 linked_list_t
*proposal_list
;
939 /* get the list of selected proposals, the peer has to select only one proposal */
940 proposal_list
= sa_payload
->get_proposals (sa_payload
);
941 if (proposal_list
->get_count(proposal_list
) != 1)
943 SIG(IKE_UP_FAILED
, "response did not contain a single proposal, deleting IKE_SA");
944 SIG(CHILD_UP_FAILED
, "initiating CHILD_SA failed, unable to create IKE_SA");
945 proposal_list
->destroy_offset(proposal_list
, offsetof(proposal_t
, destroy
));
949 /* we have to re-check if the others selection is valid */
950 this->proposal
= this->connection
->select_proposal(this->connection
, proposal_list
);
951 proposal_list
->destroy_offset(proposal_list
, offsetof(proposal_t
, destroy
));
953 if (this->proposal
== NULL
)
955 SIG(IKE_UP_FAILED
, "peer selected a proposal we did not offer, deleting IKE_SA");
956 SIG(CHILD_UP_FAILED
, "initiating CHILD_SA failed, unable to create IKE_SA");
961 { /* process KE payload:
962 * -------------------
963 * - extract others public value
964 * - complete diffie-hellman exchange
966 this->diffie_hellman
->set_other_public_value(this->diffie_hellman
,
967 ke_payload
->get_key_exchange_data(ke_payload
));
970 { /* process NONCE payload:
971 * ----------------------
972 * - extract nonce used for key derivation */
973 this->nonce_r
= nonce_payload
->get_nonce(nonce_payload
);
976 { /* process NATT stuff:
977 * -------------------
978 * - check if we or other is NATted
979 * - switch to port 4500 if so
981 if ((!this->natd_dst_seen
&& this->natd_src_seen
) ||
982 (this->natd_dst_seen
&& !this->natd_src_seen
))
984 SIG(IKE_UP_FAILED
, "request contained invalid number of NAT-D payloads, deleting IKE_SA");
985 SIG(CHILD_UP_FAILED
, "initiating CHILD_SA failed, unable to create IKE_SA");
988 if (this->natd_src_seen
&& !this->natd_src_matched
)
990 this->ike_sa
->enable_natt(this->ike_sa
, FALSE
);
992 if (this->natd_dst_seen
&& !this->natd_dst_matched
)
994 this->ike_sa
->enable_natt(this->ike_sa
, TRUE
);
996 if (this->ike_sa
->is_natt_enabled(this->ike_sa
))
998 me
= this->ike_sa
->get_my_host(this->ike_sa
);
999 me
->set_port(me
, IKEV2_NATT_PORT
);
1000 other
= this->ike_sa
->get_other_host(this->ike_sa
);
1001 other
->set_port(other
, IKEV2_NATT_PORT
);
1003 DBG2(DBG_IKE
, "switching to port %d", IKEV2_NATT_PORT
);
1007 /* because we are original initiator we have to update the responder SPI to the new one */
1008 ike_sa_id
= this->ike_sa
->get_id(this->ike_sa
);
1009 ike_sa_id
->set_responder_spi(ike_sa_id
, responder_spi
);
1011 /* derive all the keys used in the IKE_SA */
1012 if (this->ike_sa
->derive_keys(this->ike_sa
, this->proposal
,
1013 this->diffie_hellman
,
1014 this->nonce_i
, this->nonce_r
,
1015 TRUE
, NULL
, NULL
) != SUCCESS
)
1017 SIG(IKE_UP_FAILED
, "error creating transforms from proposal, deleting IKE_SA");
1018 SIG(CHILD_UP_FAILED
, "initiating CHILD_SA failed, unable to create IKE_SA");
1022 this->ike_sa
->set_lifetimes(this->ike_sa
,
1023 this->connection
->get_soft_lifetime(this->connection
),
1024 this->connection
->get_hard_lifetime(this->connection
));
1026 { /* create ike_auth transaction, which will continue IKE_SA setup */
1027 chunk_t request_chunk
, response_chunk
;
1028 ike_auth_t
*ike_auth
;
1030 request_chunk
= this->message
->get_packet_data(this->message
);
1031 response_chunk
= response
->get_packet_data(response
);
1033 /* create next transaction, for which we except a message */
1034 ike_auth
= ike_auth_create(this->ike_sa
);
1035 ike_auth
->set_config(ike_auth
, this->connection
, this->policy
);
1036 ike_auth
->set_reqid(ike_auth
, this->reqid
);
1037 this->connection
= NULL
;
1038 this->policy
= NULL
;
1039 ike_auth
->set_nonces(ike_auth
,
1040 chunk_clone(this->nonce_i
),
1041 chunk_clone(this->nonce_r
));
1042 ike_auth
->set_init_messages(ike_auth
, request_chunk
, response_chunk
);
1043 *next
= (transaction_t
*)ike_auth
;
1049 static void destroy(private_ike_sa_init_t
*this)
1051 DESTROY_IF(this->message
);
1052 DESTROY_IF(this->diffie_hellman
);
1053 DESTROY_IF(this->proposal
);
1054 DESTROY_IF(this->connection
);
1055 DESTROY_IF(this->policy
);
1056 chunk_free(&this->nonce_i
);
1057 chunk_free(&this->nonce_r
);
1058 this->randomizer
->destroy(this->randomizer
);
1059 this->nat_hasher
->destroy(this->nat_hasher
);
1060 chunk_free(&this->natd_src_hash
);
1061 chunk_free(&this->natd_dst_hash
);
1066 * Described in header.
1068 ike_sa_init_t
*ike_sa_init_create(ike_sa_t
*ike_sa
)
1070 static u_int unique_id
= 0;
1071 private_ike_sa_init_t
*this = malloc_thing(private_ike_sa_init_t
);
1073 /* transaction interface functions */
1074 this->public.transaction
.get_request
= (status_t(*)(transaction_t
*,message_t
**))get_request
;
1075 this->public.transaction
.get_response
= (status_t(*)(transaction_t
*,message_t
*,message_t
**,transaction_t
**))get_response
;
1076 this->public.transaction
.conclude
= (status_t(*)(transaction_t
*,message_t
*,transaction_t
**))conclude
;
1077 this->public.transaction
.get_message_id
= (u_int32_t(*)(transaction_t
*))get_message_id
;
1078 this->public.transaction
.requested
= (u_int32_t(*)(transaction_t
*))requested
;
1079 this->public.transaction
.destroy
= (void(*)(transaction_t
*))destroy
;
1081 /* public functions */
1082 this->public.set_config
= (void(*)(ike_sa_init_t
*,connection_t
*,policy_t
*))set_config
;
1083 this->public.set_reqid
= (void(*)(ike_sa_init_t
*,u_int32_t
))set_reqid
;
1084 this->public.use_dh_group
= (bool(*)(ike_sa_init_t
*,diffie_hellman_group_t
))use_dh_group
;
1087 this->ike_sa
= ike_sa
;
1088 this->message_id
= 0;
1089 this->message
= NULL
;
1090 this->requested
= 0;
1091 this->diffie_hellman
= NULL
;
1092 this->nonce_i
= CHUNK_INITIALIZER
;
1093 this->nonce_r
= CHUNK_INITIALIZER
;
1094 this->connection
= NULL
;
1095 this->policy
= NULL
;
1096 this->proposal
= NULL
;
1097 this->unique_id
= ++unique_id
;
1099 this->randomizer
= randomizer_create();
1100 this->nat_hasher
= hasher_create(HASH_SHA1
);
1101 this->natd_src_hash
= CHUNK_INITIALIZER
;
1102 this->natd_dst_hash
= CHUNK_INITIALIZER
;
1103 this->natd_src_seen
= FALSE
;
1104 this->natd_dst_seen
= FALSE
;
1105 this->natd_src_matched
= FALSE
;
1106 this->natd_dst_matched
= FALSE
;
1108 return &this->public;