aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/sa/transactions/ike_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/transactions/ike_auth.c')
-rw-r--r--src/charon/sa/transactions/ike_auth.c184
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;
}