diff options
Diffstat (limited to 'src/charon/sa/transactions/ike_auth.c')
-rw-r--r-- | src/charon/sa/transactions/ike_auth.c | 184 |
1 files changed, 156 insertions, 28 deletions
diff --git a/src/charon/sa/transactions/ike_auth.c b/src/charon/sa/transactions/ike_auth.c index ae155ec88..3ab4d8ae4 100644 --- a/src/charon/sa/transactions/ike_auth.c +++ b/src/charon/sa/transactions/ike_auth.c @@ -128,6 +128,11 @@ struct private_ike_auth_t { * reqid to use for CHILD_SA setup */ u_int32_t reqid; + + /** + * mode the CHILD_SA uses: tranport, tunnel, BEET + */ + mode_t mode; }; /** @@ -183,6 +188,30 @@ static void set_init_messages(private_ike_auth_t *this, chunk_t init_request, ch } /** + * Build a notify message. + */ +static void build_notify(notify_type_t type, message_t *message, bool flush_message) +{ + notify_payload_t *notify; + + if (flush_message) + { + payload_t *payload; + iterator_t *iterator = message->get_payload_iterator(message); + while (iterator->iterate(iterator, (void**)&payload)) + { + payload->destroy(payload); + iterator->remove(iterator); + } + iterator->destroy(iterator); + } + + notify = notify_payload_create(); + notify->set_notify_type(notify, type); + message->add_payload(message, (payload_t*)notify); +} + +/** * Implementation of transaction_t.get_request. */ static status_t get_request(private_ike_auth_t *this, message_t **result) @@ -319,6 +348,28 @@ static status_t get_request(private_ike_auth_t *this, message_t **result) request->add_payload(request, (payload_t*)sa_payload); } + /* notify for transport/BEET mode, we propose it + * independent of the traffic selectors */ + switch (this->policy->get_mode(this->policy)) + { + case MODE_TUNNEL: + /* is the default */ + break; + case MODE_TRANSPORT: + if (this->ike_sa->is_natt_enabled(this->ike_sa)) + { + DBG1(DBG_IKE, "not using tranport mode, as connection NATed"); + } + else + { + build_notify(USE_TRANSPORT_MODE, request, FALSE); + } + break; + case MODE_BEET: + build_notify(USE_BEET_MODE, request, FALSE); + break; + } + { /* build TSi payload */ linked_list_t *ts_list; ts_payload_t *ts_payload; @@ -376,6 +427,16 @@ static status_t process_notifies(private_ike_auth_t *this, notify_payload_t *not this->build_child = FALSE; return SUCCESS; } + case USE_TRANSPORT_MODE: + { + this->mode = MODE_TRANSPORT; + return SUCCESS; + } + case USE_BEET_MODE: + { + this->mode = MODE_BEET; + return SUCCESS; + } default: { if (notify_type < 16383) @@ -395,30 +456,6 @@ static status_t process_notifies(private_ike_auth_t *this, notify_payload_t *not } /** - * Build a notify message. - */ -static void build_notify(notify_type_t type, message_t *message, bool flush_message) -{ - notify_payload_t *notify; - - if (flush_message) - { - payload_t *payload; - iterator_t *iterator = message->get_payload_iterator(message); - while (iterator->iterate(iterator, (void**)&payload)) - { - payload->destroy(payload); - iterator->remove(iterator); - } - iterator->destroy(iterator); - } - - notify = notify_payload_create(); - notify->set_notify_type(notify, type); - message->add_payload(message, (payload_t*)notify); -} - -/** * Import certificate requests from a certreq payload */ static void add_certificate_request(certreq_payload_t *certreq_payload, @@ -502,6 +539,23 @@ static void import_certificate(cert_payload_t *cert_payload) } /** + * Check a list of traffic selectors if any selector belongs to host + */ +static bool ts_list_is_host(linked_list_t *list, host_t *host) +{ + traffic_selector_t *ts; + bool is_host = TRUE; + iterator_t *iterator = list->create_iterator(list, TRUE); + + while (is_host && iterator->iterate(iterator, (void**)&ts)) + { + is_host = is_host && ts->is_host(ts, host); + } + iterator->destroy(iterator); + return is_host; +} + +/** * Install a CHILD_SA for usage */ static status_t install_child_sa(private_ike_auth_t *this, bool initiator) @@ -518,11 +572,13 @@ static status_t install_child_sa(private_ike_auth_t *this, bool initiator) if (initiator) { - status = this->child_sa->update(this->child_sa, this->proposal, prf_plus); + status = this->child_sa->update(this->child_sa, this->proposal, + this->mode, prf_plus); } else { - status = this->child_sa->add(this->child_sa, this->proposal, prf_plus); + status = this->child_sa->add(this->child_sa, this->proposal, + this->mode, prf_plus); } prf_plus->destroy(prf_plus); if (status != SUCCESS) @@ -531,11 +587,13 @@ static status_t install_child_sa(private_ike_auth_t *this, bool initiator) } if (initiator) { - status = this->child_sa->add_policies(this->child_sa, this->tsi, this->tsr); + status = this->child_sa->add_policies(this->child_sa, this->tsi, + this->tsr, this->mode); } else { - status = this->child_sa->add_policies(this->child_sa, this->tsr, this->tsi); + status = this->child_sa->add_policies(this->child_sa, this->tsr, + this->tsi, this->mode); } if (status != SUCCESS) { @@ -850,6 +908,44 @@ static status_t get_response(private_ike_auth_t *this, message_t *request, this->policy->get_hostaccess(this->policy), use_natt); this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy)); + + /* check mode, and include notify into reply */ + switch (this->mode) + { + case MODE_TUNNEL: + /* is the default */ + break; + case MODE_TRANSPORT: + if (!ts_list_is_host(this->tsi, other) || + !ts_list_is_host(this->tsr, me)) + { + this->mode = MODE_TUNNEL; + DBG1(DBG_IKE, "not using tranport mode, not host-to-host"); + } + else if (this->ike_sa->is_natt_enabled(this->ike_sa)) + { + this->mode = MODE_TUNNEL; + DBG1(DBG_IKE, "not using tranport mode, as connection NATed"); + } + else + { + build_notify(USE_TRANSPORT_MODE, response, FALSE); + } + 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"); + } + else + { + build_notify(USE_BEET_MODE, response, FALSE); + } + break; + } + if (install_child_sa(this, FALSE) != SUCCESS) { SIG(CHILD_UP_FAILED, "installing CHILD_SA failed, no CHILD_SA created"); @@ -1048,6 +1144,37 @@ static status_t conclude(private_ike_auth_t *this, message_t *response, } else { + /* check mode if it is acceptable */ + switch (this->mode) + { + case MODE_TUNNEL: + /* is the default */ + break; + case MODE_TRANSPORT: + /* TODO: we should close the CHILD_SA if negotiated + * mode is not acceptable for us */ + if (!ts_list_is_host(this->tsi, me) || + !ts_list_is_host(this->tsr, other)) + { + this->mode = MODE_TUNNEL; + DBG1(DBG_IKE, "not using tranport mode, not host-to-host"); + } + else if (this->ike_sa->is_natt_enabled(this->ike_sa)) + { + this->mode = MODE_TUNNEL; + DBG1(DBG_IKE, "not using tranport mode, as connection NATed"); + } + 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"); + } + break; + } + if (install_child_sa(this, TRUE) != SUCCESS) { SIG(CHILD_UP_FAILED, "installing CHILD_SA failed, no CHILD_SA built"); @@ -1126,6 +1253,7 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa) this->tsr = NULL; this->build_child = TRUE; this->reqid = 0; + this->mode = MODE_TUNNEL; return &this->public; } |