2 * Copyright (C) 2008-2019 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * HSR Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 #include <bio/bio_reader.h>
24 #include <bio/bio_writer.h>
25 #include <sa/ikev2/keymat_v2.h>
26 #include <crypto/diffie_hellman.h>
27 #include <crypto/hashers/hash_algorithm_set.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/ke_payload.h>
30 #include <encoding/payloads/nonce_payload.h>
32 /** maximum retries to do with cookies/other dh groups */
35 typedef struct private_ike_init_t private_ike_init_t
;
38 * Private members of a ike_init_t task.
40 struct private_ike_init_t
{
43 * Public methods and task_t interface.
53 * Are we the initiator?
58 * diffie hellman group to use
60 diffie_hellman_group_t dh_group
;
63 * diffie hellman key exchange
68 * Applying DH public value failed?
73 * Keymat derivation (from IKE_SA)
83 * nonce chosen by peer
93 * Negotiated proposal used for IKE_SA
98 * Old IKE_SA which gets rekeyed
103 * cookie received from responder
108 * retries done so far after failure (cookie or bad dh group)
113 * Whether to use Signature Authentication as per RFC 7427
115 bool signature_authentication
;
118 * Whether to follow IKEv2 redirects as per RFC 5685
120 bool follow_redirects
;
124 * Allocate our own nonce value
126 static bool generate_nonce(private_ike_init_t
*this)
130 DBG1(DBG_IKE
, "no nonce generator found to create nonce");
133 if (!this->nonceg
->allocate_nonce(this->nonceg
, NONCE_SIZE
,
136 DBG1(DBG_IKE
, "nonce allocation failed");
143 * Notify the peer about the hash algorithms we support or expect,
146 static void send_supported_hash_algorithms(private_ike_init_t
*this,
149 hash_algorithm_set_t
*algos
;
150 enumerator_t
*enumerator
, *rounds
;
151 bio_writer_t
*writer
;
152 hash_algorithm_t hash
;
156 signature_params_t
*config
;
158 size_t len
= BUF_LEN
;
163 algos
= hash_algorithm_set_create();
164 peer
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
167 rounds
= peer
->create_auth_cfg_enumerator(peer
, FALSE
);
168 while (rounds
->enumerate(rounds
, &auth
))
170 enumerator
= auth
->create_enumerator(auth
);
171 while (enumerator
->enumerate(enumerator
, &rule
, &config
))
173 if (rule
== AUTH_RULE_IKE_SIGNATURE_SCHEME
)
175 hash
= hasher_from_signature_scheme(config
->scheme
,
177 if (hasher_algorithm_for_ikev2(hash
))
179 algos
->add(algos
, hash
);
183 enumerator
->destroy(enumerator
);
185 rounds
->destroy(rounds
);
188 if (!algos
->count(algos
))
190 enumerator
= lib
->crypto
->create_hasher_enumerator(lib
->crypto
);
191 while (enumerator
->enumerate(enumerator
, &hash
, &plugin_name
))
193 if (hasher_algorithm_for_ikev2(hash
))
195 algos
->add(algos
, hash
);
198 enumerator
->destroy(enumerator
);
201 if (algos
->count(algos
))
203 writer
= bio_writer_create(0);
204 enumerator
= algos
->create_enumerator(algos
);
205 while (enumerator
->enumerate(enumerator
, &hash
))
207 writer
->write_uint16(writer
, hash
);
209 /* generate debug output */
210 written
= snprintf(pos
, len
, " %N", hash_algorithm_short_names
,
212 if (written
> 0 && written
< len
)
218 enumerator
->destroy(enumerator
);
219 message
->add_notify(message
, FALSE
, SIGNATURE_HASH_ALGORITHMS
,
220 writer
->get_buf(writer
));
221 writer
->destroy(writer
);
224 DBG2(DBG_CFG
, "sending supported signature hash algorithms:%s", buf
);
226 algos
->destroy(algos
);
230 * Store algorithms supported by other peer
232 static void handle_supported_hash_algorithms(private_ike_init_t
*this,
233 notify_payload_t
*notify
)
235 bio_reader_t
*reader
;
238 size_t len
= BUF_LEN
;
243 reader
= bio_reader_create(notify
->get_notification_data(notify
));
244 while (reader
->remaining(reader
) >= 2 && reader
->read_uint16(reader
, &algo
))
246 if (hasher_algorithm_for_ikev2(algo
))
248 this->keymat
->add_hash_algorithm(this->keymat
, algo
);
251 /* generate debug output */
252 written
= snprintf(pos
, len
, " %N", hash_algorithm_short_names
,
254 if (written
> 0 && written
< len
)
261 reader
->destroy(reader
);
264 DBG2(DBG_CFG
, "received supported signature hash algorithms:%s", buf
);
268 this->ike_sa
->enable_extension(this->ike_sa
, EXT_SIGNATURE_AUTH
);
273 * Check whether to send a USE_PPK notify
275 static bool send_use_ppk(private_ike_init_t
*this)
280 bool use_ppk
= FALSE
;
284 peer
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
285 if (peer
->get_ppk_id(peer
))
290 else if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_PPK
))
292 /* check if we have at least one PPK available */
293 keys
= lib
->credmgr
->create_shared_enumerator(lib
->credmgr
, SHARED_PPK
,
295 if (keys
->enumerate(keys
, &key
, NULL
, NULL
))
305 * build the payloads for the message
307 static bool build_payloads(private_ike_init_t
*this, message_t
*message
)
309 sa_payload_t
*sa_payload
;
310 ke_payload_t
*ke_payload
;
311 nonce_payload_t
*nonce_payload
;
312 linked_list_t
*proposal_list
, *other_dh_groups
;
314 proposal_t
*proposal
;
315 enumerator_t
*enumerator
;
318 id
= this->ike_sa
->get_id(this->ike_sa
);
320 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
324 proposal_list
= ike_cfg
->get_proposals(ike_cfg
);
325 other_dh_groups
= linked_list_create();
326 enumerator
= proposal_list
->create_enumerator(proposal_list
);
327 while (enumerator
->enumerate(enumerator
, (void**)&proposal
))
329 /* include SPI of new IKE_SA when we are rekeying */
332 proposal
->set_spi(proposal
, id
->get_initiator_spi(id
));
334 /* move the selected DH group to the front of the proposal */
335 if (!proposal
->promote_dh_group(proposal
, this->dh_group
))
336 { /* the proposal does not include the group, move to the back */
337 proposal_list
->remove_at(proposal_list
, enumerator
);
338 other_dh_groups
->insert_last(other_dh_groups
, proposal
);
341 enumerator
->destroy(enumerator
);
342 /* add proposals that don't contain the selected group */
343 enumerator
= other_dh_groups
->create_enumerator(other_dh_groups
);
344 while (enumerator
->enumerate(enumerator
, (void**)&proposal
))
345 { /* no need to remove from the list as we destroy it anyway*/
346 proposal_list
->insert_last(proposal_list
, proposal
);
348 enumerator
->destroy(enumerator
);
349 other_dh_groups
->destroy(other_dh_groups
);
351 sa_payload
= sa_payload_create_from_proposals_v2(proposal_list
);
352 proposal_list
->destroy_offset(proposal_list
, offsetof(proposal_t
, destroy
));
358 /* include SPI of new IKE_SA when we are rekeying */
359 this->proposal
->set_spi(this->proposal
, id
->get_responder_spi(id
));
361 sa_payload
= sa_payload_create_from_proposal_v2(this->proposal
);
363 message
->add_payload(message
, (payload_t
*)sa_payload
);
365 ke_payload
= ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE
,
369 DBG1(DBG_IKE
, "creating KE payload failed");
372 nonce_payload
= nonce_payload_create(PLV2_NONCE
);
373 nonce_payload
->set_nonce(nonce_payload
, this->my_nonce
);
376 { /* payload order differs if we are rekeying */
377 message
->add_payload(message
, (payload_t
*)nonce_payload
);
378 message
->add_payload(message
, (payload_t
*)ke_payload
);
382 message
->add_payload(message
, (payload_t
*)ke_payload
);
383 message
->add_payload(message
, (payload_t
*)nonce_payload
);
386 /* negotiate fragmentation if we are not rekeying */
388 ike_cfg
->fragmentation(ike_cfg
) != FRAGMENTATION_NO
)
390 if (this->initiator
||
391 this->ike_sa
->supports_extension(this->ike_sa
,
392 EXT_IKE_FRAGMENTATION
))
394 message
->add_notify(message
, FALSE
, FRAGMENTATION_SUPPORTED
,
398 /* submit supported hash algorithms for signature authentication */
399 if (!this->old_sa
&& this->signature_authentication
)
401 if (this->initiator
||
402 this->ike_sa
->supports_extension(this->ike_sa
,
405 send_supported_hash_algorithms(this, message
);
408 /* notify other peer if we support redirection */
409 if (!this->old_sa
&& this->initiator
&& this->follow_redirects
)
411 identification_t
*gateway
;
415 from
= this->ike_sa
->get_redirected_from(this->ike_sa
);
418 gateway
= identification_create_from_sockaddr(
419 from
->get_sockaddr(from
));
420 data
= redirect_data_create(gateway
, chunk_empty
);
421 message
->add_notify(message
, FALSE
, REDIRECTED_FROM
, data
);
423 gateway
->destroy(gateway
);
427 message
->add_notify(message
, FALSE
, REDIRECT_SUPPORTED
,
431 /* notify the peer if we want to use/support PPK */
432 if (!this->old_sa
&& send_use_ppk(this))
434 message
->add_notify(message
, FALSE
, USE_PPK
, chunk_empty
);
436 /* notify the peer if we accept childless IKE_SAs */
437 if (!this->old_sa
&& !this->initiator
&&
438 ike_cfg
->childless(ike_cfg
) != CHILDLESS_NEVER
)
440 message
->add_notify(message
, FALSE
, CHILDLESS_IKEV2_SUPPORTED
,
447 * Process the SA payload and select a proposal
449 static void process_sa_payload(private_ike_init_t
*this, message_t
*message
,
450 sa_payload_t
*sa_payload
)
452 ike_cfg_t
*ike_cfg
, *cfg
, *alt_cfg
= NULL
;
453 enumerator_t
*enumerator
;
454 linked_list_t
*proposal_list
;
456 proposal_selection_flag_t flags
= 0;
458 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
460 proposal_list
= sa_payload
->get_proposals(sa_payload
);
461 if (!this->ike_sa
->supports_extension(this->ike_sa
, EXT_STRONGSWAN
) &&
462 !lib
->settings
->get_bool(lib
->settings
, "%s.accept_private_algs",
465 flags
|= PROPOSAL_SKIP_PRIVATE
;
467 if (!lib
->settings
->get_bool(lib
->settings
,
468 "%s.prefer_configured_proposals", TRUE
, lib
->ns
))
470 flags
|= PROPOSAL_PREFER_SUPPLIED
;
472 this->proposal
= ike_cfg
->select_proposal(ike_cfg
, proposal_list
, flags
);
475 if (!this->initiator
&& !this->old_sa
)
477 me
= message
->get_destination(message
);
478 other
= message
->get_source(message
);
479 enumerator
= charon
->backends
->create_ike_cfg_enumerator(
480 charon
->backends
, me
, other
, IKEV2
);
481 while (enumerator
->enumerate(enumerator
, &cfg
))
484 { /* already tried and failed */
487 DBG1(DBG_IKE
, "no matching proposal found, trying alternative "
489 this->proposal
= cfg
->select_proposal(cfg
, proposal_list
,
493 alt_cfg
= cfg
->get_ref(cfg
);
497 enumerator
->destroy(enumerator
);
501 this->ike_sa
->set_ike_cfg(this->ike_sa
, alt_cfg
);
502 alt_cfg
->destroy(alt_cfg
);
506 charon
->bus
->alert(charon
->bus
, ALERT_PROPOSAL_MISMATCH_IKE
,
510 proposal_list
->destroy_offset(proposal_list
,
511 offsetof(proposal_t
, destroy
));
515 * Read payloads from message
517 static void process_payloads(private_ike_init_t
*this, message_t
*message
)
519 enumerator_t
*enumerator
;
521 ke_payload_t
*ke_payload
= NULL
;
523 enumerator
= message
->create_payload_enumerator(message
);
524 while (enumerator
->enumerate(enumerator
, &payload
))
526 switch (payload
->get_type(payload
))
528 case PLV2_SECURITY_ASSOCIATION
:
530 process_sa_payload(this, message
, (sa_payload_t
*)payload
);
533 case PLV2_KEY_EXCHANGE
:
535 ke_payload
= (ke_payload_t
*)payload
;
537 this->dh_group
= ke_payload
->get_dh_group_number(ke_payload
);
542 nonce_payload_t
*nonce_payload
= (nonce_payload_t
*)payload
;
544 this->other_nonce
= nonce_payload
->get_nonce(nonce_payload
);
549 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
551 switch (notify
->get_notify_type(notify
))
553 case FRAGMENTATION_SUPPORTED
:
554 this->ike_sa
->enable_extension(this->ike_sa
,
555 EXT_IKE_FRAGMENTATION
);
557 case SIGNATURE_HASH_ALGORITHMS
:
558 if (this->signature_authentication
)
560 handle_supported_hash_algorithms(this, notify
);
566 this->ike_sa
->enable_extension(this->ike_sa
,
570 case REDIRECTED_FROM
:
572 identification_t
*gateway
;
575 data
= notify
->get_notification_data(notify
);
576 gateway
= redirect_data_parse(data
, NULL
);
579 DBG1(DBG_IKE
, "received invalid REDIRECTED_FROM "
583 DBG1(DBG_IKE
, "client got redirected from %Y", gateway
);
584 gateway
->destroy(gateway
);
587 case REDIRECT_SUPPORTED
:
590 this->ike_sa
->enable_extension(this->ike_sa
,
591 EXT_IKE_REDIRECTION
);
594 case CHILDLESS_IKEV2_SUPPORTED
:
595 if (this->initiator
&& !this->old_sa
)
597 this->ike_sa
->enable_extension(this->ike_sa
,
602 /* other notifies are handled elsewhere */
611 enumerator
->destroy(enumerator
);
615 this->ike_sa
->set_proposal(this->ike_sa
, this->proposal
);
618 if (ke_payload
&& this->proposal
&&
619 this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
621 if (!this->initiator
)
623 this->dh
= this->keymat
->keymat
.create_dh(
624 &this->keymat
->keymat
, this->dh_group
);
628 this->dh_failed
= this->dh
->get_dh_group(this->dh
) != this->dh_group
;
630 if (this->dh
&& !this->dh_failed
)
632 this->dh_failed
= !this->dh
->set_other_public_value(this->dh
,
633 ke_payload
->get_key_exchange_data(ke_payload
));
638 METHOD(task_t
, build_i
, status_t
,
639 private_ike_init_t
*this, message_t
*message
)
643 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
645 DBG0(DBG_IKE
, "initiating IKE_SA %s[%d] to %H",
646 this->ike_sa
->get_name(this->ike_sa
),
647 this->ike_sa
->get_unique_id(this->ike_sa
),
648 this->ike_sa
->get_other_host(this->ike_sa
));
649 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
651 if (this->retry
>= MAX_RETRIES
)
653 DBG1(DBG_IKE
, "giving up after %d retries", MAX_RETRIES
);
657 /* if we are retrying after an INVALID_KE_PAYLOAD we already have one */
660 if (this->old_sa
&& lib
->settings
->get_bool(lib
->settings
,
661 "%s.prefer_previous_dh_group", TRUE
, lib
->ns
))
662 { /* reuse the DH group we used for the old IKE_SA when rekeying */
663 proposal_t
*proposal
;
666 proposal
= this->old_sa
->get_proposal(this->old_sa
);
667 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
,
670 this->dh_group
= dh_group
;
673 { /* this shouldn't happen, but let's be safe */
674 this->dh_group
= ike_cfg
->get_dh_group(ike_cfg
);
679 this->dh_group
= ike_cfg
->get_dh_group(ike_cfg
);
681 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
685 DBG1(DBG_IKE
, "configured DH group %N not supported",
686 diffie_hellman_group_names
, this->dh_group
);
690 else if (this->dh
->get_dh_group(this->dh
) != this->dh_group
)
691 { /* reset DH instance if group changed (INVALID_KE_PAYLOAD) */
692 this->dh
->destroy(this->dh
);
693 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
697 DBG1(DBG_IKE
, "requested DH group %N not supported",
698 diffie_hellman_group_names
, this->dh_group
);
703 /* generate nonce only when we are trying the first time */
704 if (this->my_nonce
.ptr
== NULL
)
706 if (!generate_nonce(this))
712 if (this->cookie
.ptr
)
714 message
->add_notify(message
, FALSE
, COOKIE
, this->cookie
);
717 if (!build_payloads(this, message
))
724 chunk_t connect_id
= this->ike_sa
->get_connect_id(this->ike_sa
);
727 message
->add_notify(message
, FALSE
, ME_CONNECTID
, connect_id
);
735 METHOD(task_t
, process_r
, status_t
,
736 private_ike_init_t
*this, message_t
*message
)
738 DBG0(DBG_IKE
, "%H is initiating an IKE_SA", message
->get_source(message
));
739 this->ike_sa
->set_state(this->ike_sa
, IKE_CONNECTING
);
741 if (!generate_nonce(this))
748 notify_payload_t
*notify
= message
->get_notify(message
, ME_CONNECTID
);
751 chunk_t connect_id
= notify
->get_notification_data(notify
);
752 DBG2(DBG_IKE
, "received ME_CONNECTID %#B", &connect_id
);
753 charon
->connect_manager
->stop_checks(charon
->connect_manager
,
759 process_payloads(this, message
);
765 * Derive the keymat for the IKE_SA
767 static bool derive_keys(private_ike_init_t
*this,
768 chunk_t nonce_i
, chunk_t nonce_r
)
770 keymat_v2_t
*old_keymat
;
771 pseudo_random_function_t prf_alg
= PRF_UNDEFINED
;
772 chunk_t skd
= chunk_empty
;
775 id
= this->ike_sa
->get_id(this->ike_sa
);
778 /* rekeying: Include old SKd, use old PRF, apply SPI */
779 old_keymat
= (keymat_v2_t
*)this->old_sa
->get_keymat(this->old_sa
);
780 prf_alg
= old_keymat
->get_skd(old_keymat
, &skd
);
783 id
->set_responder_spi(id
, this->proposal
->get_spi(this->proposal
));
787 id
->set_initiator_spi(id
, this->proposal
->get_spi(this->proposal
));
790 if (!this->keymat
->derive_ike_keys(this->keymat
, this->proposal
, this->dh
,
791 nonce_i
, nonce_r
, id
, prf_alg
, skd
))
795 charon
->bus
->ike_keys(charon
->bus
, this->ike_sa
, this->dh
, chunk_empty
,
796 nonce_i
, nonce_r
, this->old_sa
, NULL
, AUTH_NONE
);
800 METHOD(task_t
, build_r
, status_t
,
801 private_ike_init_t
*this, message_t
*message
)
803 identification_t
*gateway
;
805 /* check if we have everything we need */
806 if (this->proposal
== NULL
||
807 this->other_nonce
.len
== 0 || this->my_nonce
.len
== 0)
809 DBG1(DBG_IKE
, "received proposals unacceptable");
810 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
814 /* check if we'd have to redirect the client */
816 this->ike_sa
->supports_extension(this->ike_sa
, EXT_IKE_REDIRECTION
) &&
817 charon
->redirect
->redirect_on_init(charon
->redirect
, this->ike_sa
,
822 DBG1(DBG_IKE
, "redirecting peer to %Y", gateway
);
823 data
= redirect_data_create(gateway
, this->other_nonce
);
824 message
->add_notify(message
, TRUE
, REDIRECT
, data
);
825 gateway
->destroy(gateway
);
830 if (this->dh
== NULL
||
831 !this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
835 if (this->proposal
->get_algorithm(this->proposal
, DIFFIE_HELLMAN_GROUP
,
838 DBG1(DBG_IKE
, "DH group %N unacceptable, requesting %N",
839 diffie_hellman_group_names
, this->dh_group
,
840 diffie_hellman_group_names
, group
);
841 this->dh_group
= group
;
842 group
= htons(group
);
843 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
844 chunk_from_thing(group
));
848 DBG1(DBG_IKE
, "no acceptable proposal found");
849 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
856 DBG1(DBG_IKE
, "applying DH public value failed");
857 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
861 if (!derive_keys(this, this->other_nonce
, this->my_nonce
))
863 DBG1(DBG_IKE
, "key derivation failed");
864 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
867 if (!build_payloads(this, message
))
869 message
->add_notify(message
, TRUE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
876 * Raise alerts for received notify errors
878 static void raise_alerts(private_ike_init_t
*this, notify_type_t type
)
885 case NO_PROPOSAL_CHOSEN
:
886 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
887 list
= ike_cfg
->get_proposals(ike_cfg
);
888 charon
->bus
->alert(charon
->bus
, ALERT_PROPOSAL_MISMATCH_IKE
, list
);
889 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
896 METHOD(task_t
, pre_process_i
, status_t
,
897 private_ike_init_t
*this, message_t
*message
)
899 enumerator_t
*enumerator
;
902 /* check for erroneous notifies */
903 enumerator
= message
->create_payload_enumerator(message
);
904 while (enumerator
->enumerate(enumerator
, &payload
))
906 if (payload
->get_type(payload
) == PLV2_NOTIFY
)
908 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
909 notify_type_t type
= notify
->get_notify_type(notify
);
917 cookie
= notify
->get_notification_data(notify
);
918 if (chunk_equals(cookie
, this->cookie
))
920 DBG1(DBG_IKE
, "ignore response with duplicate COOKIE "
922 enumerator
->destroy(enumerator
);
929 identification_t
*gateway
;
930 chunk_t data
, nonce
= chunk_empty
;
931 status_t status
= SUCCESS
;
937 data
= notify
->get_notification_data(notify
);
938 gateway
= redirect_data_parse(data
, &nonce
);
939 if (!gateway
|| !chunk_equals(nonce
, this->my_nonce
))
941 DBG1(DBG_IKE
, "received invalid REDIRECT notify");
946 enumerator
->destroy(enumerator
);
954 enumerator
->destroy(enumerator
);
958 METHOD(task_t
, process_i
, status_t
,
959 private_ike_init_t
*this, message_t
*message
)
961 enumerator_t
*enumerator
;
964 /* check for erroneous notifies */
965 enumerator
= message
->create_payload_enumerator(message
);
966 while (enumerator
->enumerate(enumerator
, &payload
))
968 if (payload
->get_type(payload
) == PLV2_NOTIFY
)
970 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
971 notify_type_t type
= notify
->get_notify_type(notify
);
975 case INVALID_KE_PAYLOAD
:
978 diffie_hellman_group_t bad_group
;
980 bad_group
= this->dh_group
;
981 data
= notify
->get_notification_data(notify
);
982 this->dh_group
= ntohs(*((uint16_t*)data
.ptr
));
983 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
984 "it requested %N", diffie_hellman_group_names
,
985 bad_group
, diffie_hellman_group_names
, this->dh_group
);
987 if (this->old_sa
== NULL
)
988 { /* reset the IKE_SA if we are not rekeying */
989 this->ike_sa
->reset(this->ike_sa
, FALSE
);
992 enumerator
->destroy(enumerator
);
996 case NAT_DETECTION_SOURCE_IP
:
997 case NAT_DETECTION_DESTINATION_IP
:
998 /* skip, handled in ike_natd_t */
1000 case MULTIPLE_AUTH_SUPPORTED
:
1001 /* handled in ike_auth_t */
1005 chunk_free(&this->cookie
);
1006 this->cookie
= chunk_clone(notify
->get_notification_data(notify
));
1007 this->ike_sa
->reset(this->ike_sa
, FALSE
);
1008 enumerator
->destroy(enumerator
);
1009 DBG2(DBG_IKE
, "received %N notify", notify_type_names
, type
);
1015 identification_t
*gateway
;
1016 chunk_t data
, nonce
= chunk_empty
;
1017 status_t status
= FAILED
;
1021 DBG1(DBG_IKE
, "received REDIRECT notify during rekeying"
1025 data
= notify
->get_notification_data(notify
);
1026 gateway
= redirect_data_parse(data
, &nonce
);
1027 if (this->ike_sa
->handle_redirect(this->ike_sa
, gateway
))
1031 DESTROY_IF(gateway
);
1033 enumerator
->destroy(enumerator
);
1040 DBG1(DBG_IKE
, "received %N notify error",
1041 notify_type_names
, type
);
1042 enumerator
->destroy(enumerator
);
1043 raise_alerts(this, type
);
1046 DBG2(DBG_IKE
, "received %N notify",
1047 notify_type_names
, type
);
1053 enumerator
->destroy(enumerator
);
1055 process_payloads(this, message
);
1057 /* check if we have everything */
1058 if (this->proposal
== NULL
||
1059 this->other_nonce
.len
== 0 || this->my_nonce
.len
== 0)
1061 DBG1(DBG_IKE
, "peers proposal selection invalid");
1065 if (this->dh
== NULL
||
1066 !this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
1068 DBG1(DBG_IKE
, "peer DH group selection invalid");
1072 if (this->dh_failed
)
1074 DBG1(DBG_IKE
, "applying DH public value failed");
1078 if (!derive_keys(this, this->my_nonce
, this->other_nonce
))
1080 DBG1(DBG_IKE
, "key derivation failed");
1086 METHOD(task_t
, get_type
, task_type_t
,
1087 private_ike_init_t
*this)
1089 return TASK_IKE_INIT
;
1092 METHOD(task_t
, migrate
, void,
1093 private_ike_init_t
*this, ike_sa_t
*ike_sa
)
1095 DESTROY_IF(this->proposal
);
1096 chunk_free(&this->other_nonce
);
1098 this->ike_sa
= ike_sa
;
1099 this->keymat
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
1100 this->proposal
= NULL
;
1101 this->dh_failed
= FALSE
;
1104 METHOD(task_t
, destroy
, void,
1105 private_ike_init_t
*this)
1107 DESTROY_IF(this->dh
);
1108 DESTROY_IF(this->proposal
);
1109 DESTROY_IF(this->nonceg
);
1110 chunk_free(&this->my_nonce
);
1111 chunk_free(&this->other_nonce
);
1112 chunk_free(&this->cookie
);
1116 METHOD(ike_init_t
, get_lower_nonce
, chunk_t
,
1117 private_ike_init_t
*this)
1119 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
1120 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
1122 return this->my_nonce
;
1126 return this->other_nonce
;
1131 * Described in header.
1133 ike_init_t
*ike_init_create(ike_sa_t
*ike_sa
, bool initiator
, ike_sa_t
*old_sa
)
1135 private_ike_init_t
*this;
1140 .get_type
= _get_type
,
1141 .migrate
= _migrate
,
1142 .destroy
= _destroy
,
1144 .get_lower_nonce
= _get_lower_nonce
,
1147 .initiator
= initiator
,
1148 .dh_group
= MODP_NONE
,
1149 .keymat
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
),
1151 .signature_authentication
= lib
->settings
->get_bool(lib
->settings
,
1152 "%s.signature_authentication", TRUE
, lib
->ns
),
1153 .follow_redirects
= lib
->settings
->get_bool(lib
->settings
,
1154 "%s.follow_redirects", TRUE
, lib
->ns
),
1156 this->nonceg
= this->keymat
->keymat
.create_nonce_gen(&this->keymat
->keymat
);
1160 this->public.task
.build
= _build_i
;
1161 this->public.task
.process
= _process_i
;
1162 this->public.task
.pre_process
= _pre_process_i
;
1166 this->public.task
.build
= _build_r
;
1167 this->public.task
.process
= _process_r
;
1169 return &this->public;