From: Tobias Brunner Date: Tue, 9 Apr 2019 17:13:53 +0000 (+0200) Subject: child-create: Make sure the mode selected by the responder is acceptable X-Git-Tag: 5.8.0rc1~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a3885b86e6de2e1220ae3bacfe39b2d56b3c7a4c;p=thirdparty%2Fstrongswan.git child-create: Make sure the mode selected by the responder is acceptable Previously, the initiator would install the SA in transport mode if the peer sent back the USE_TRANSPORT_MODE notify, even if that was not requested originally. --- diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index d74013b8ff..b80e71d542 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -489,6 +489,45 @@ static linked_list_t* narrow_ts(private_child_create_t *this, bool local, return ts; } +/** + * Check if requested mode is acceptable + */ +static bool check_mode(private_child_create_t *this, host_t *i, host_t *r) +{ + switch (this->mode) + { + case MODE_TRANSPORT: + if (!this->config->has_option(this->config, OPT_PROXY_MODE) && + (!ts_list_is_host(this->tsi, i) || + !ts_list_is_host(this->tsr, r)) + ) + { + DBG1(DBG_IKE, "not using transport mode, not host-to-host"); + return FALSE; + } + if (this->config->get_mode(this->config) != MODE_TRANSPORT) + { + return FALSE; + } + break; + case MODE_BEET: + if (!ts_list_is_host(this->tsi, NULL) || + !ts_list_is_host(this->tsr, NULL)) + { + DBG1(DBG_IKE, "not using BEET mode, not host-to-host"); + return FALSE; + } + if (this->config->get_mode(this->config) != MODE_BEET) + { + return FALSE; + } + break; + default: + break; + } + return TRUE; +} + /** * Install a CHILD_SA for usage, return value: * - FAILED: no acceptable proposal @@ -616,47 +655,27 @@ static status_t select_and_install(private_child_create_t *this, { this->tsi = my_ts; this->tsr = other_ts; + + if (!check_mode(this, me, other)) + { + DBG1(DBG_IKE, "%N mode requested by responder is unacceptable", + ipsec_mode_names, this->mode); + return FAILED; + } } else { this->tsr = my_ts; this->tsi = other_ts; + + if (!check_mode(this, other, me)) + { + this->mode = MODE_TUNNEL; + } } if (!this->initiator) { - /* check if requested mode is acceptable, downgrade if required */ - switch (this->mode) - { - case MODE_TRANSPORT: - if (!this->config->has_option(this->config, OPT_PROXY_MODE) && - (!ts_list_is_host(this->tsi, other) || - !ts_list_is_host(this->tsr, me)) - ) - { - this->mode = MODE_TUNNEL; - DBG1(DBG_IKE, "not using transport mode, not host-to-host"); - } - if (this->config->get_mode(this->config) != MODE_TRANSPORT) - { - this->mode = MODE_TUNNEL; - } - break; - case MODE_BEET: - if (!ts_list_is_host(this->tsi, NULL) || - !ts_list_is_host(this->tsr, NULL)) - { - this->mode = MODE_TUNNEL; - DBG1(DBG_IKE, "not using BEET mode, not host-to-host"); - } - if (this->config->get_mode(this->config) != MODE_BEET) - { - this->mode = MODE_TUNNEL; - } - break; - default: - break; - } /* use a copy of the traffic selectors, as the POST hook should not * change payloads */ my_ts = this->tsr->clone_offset(this->tsr,