diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index f15455930..d507896de 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -167,6 +167,11 @@ enum ike_extension_t { * Responder accepts childless IKE_SAs, RFC 6023 */ EXT_IKE_CHILDLESS = (1<<16), + + /** + * IKE_INTERMEDIATE, draft-ietf-ipsecme-ikev2-intermediate + */ + EXT_IKE_INTERMEDIATE = (1<<17), }; /** diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c index efc8a381b..ef20f17ed 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_init.c +++ b/src/libcharon/sa/ikev2/tasks/ike_init.c @@ -346,6 +346,7 @@ static bool build_payloads(private_ike_init_t *this, message_t *message) proposal_t *proposal; enumerator_t *enumerator; ike_cfg_t *ike_cfg; + bool additional_ke = FALSE; id = this->ike_sa->get_id(this->ike_sa); @@ -370,6 +371,8 @@ static bool build_payloads(private_ike_init_t *this, message_t *message) proposal_list->remove_at(proposal_list, enumerator); other_dh_groups->insert_last(other_dh_groups, proposal); } + additional_ke = additional_ke || + proposal_has_additional_ke(proposal); } enumerator->destroy(enumerator); /* add proposals that don't contain the selected group */ @@ -392,6 +395,7 @@ static bool build_payloads(private_ike_init_t *this, message_t *message) this->proposal->set_spi(this->proposal, id->get_responder_spi(id)); } sa_payload = sa_payload_create_from_proposal_v2(this->proposal); + additional_ke = proposal_has_additional_ke(this->proposal); } message->add_payload(message, (payload_t*)sa_payload); @@ -465,6 +469,16 @@ static bool build_payloads(private_ike_init_t *this, message_t *message) message->add_notify(message, FALSE, CHILDLESS_IKEV2_SUPPORTED, chunk_empty); } + if (!this->old_sa && additional_ke) + { + if (this->initiator || + this->ike_sa->supports_extension(this->ike_sa, + EXT_IKE_INTERMEDIATE)) + { + message->add_notify(message, FALSE, INTERMEDIATE_EXCHANGE_SUPPORTED, + chunk_empty); + } + } return TRUE; } @@ -724,6 +738,13 @@ static void process_payloads(private_ike_init_t *this, message_t *message) EXT_IKE_CHILDLESS); } break; + case INTERMEDIATE_EXCHANGE_SUPPORTED: + if (!this->old_sa) + { + this->ike_sa->enable_extension(this->ike_sa, + EXT_IKE_INTERMEDIATE); + } + break; default: /* other notifies are handled elsewhere */ break;