aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/charon/config/connections/connection.c83
-rw-r--r--src/charon/config/connections/connection.h43
-rw-r--r--src/charon/config/connections/local_connection_store.c16
-rw-r--r--src/charon/config/policies/local_policy_store.c69
-rw-r--r--src/charon/config/policies/policy.c282
-rw-r--r--src/charon/config/policies/policy.h188
-rwxr-xr-xsrc/charon/config/policies/policy_store.h32
-rw-r--r--src/charon/config/traffic_selector.c17
-rw-r--r--src/charon/queues/jobs/initiate_ike_sa_job.c17
-rw-r--r--src/charon/queues/jobs/initiate_ike_sa_job.h8
-rw-r--r--src/charon/sa/authenticator.c14
-rw-r--r--src/charon/sa/authenticator.h3
-rw-r--r--src/charon/sa/child_sa.c35
-rw-r--r--src/charon/sa/child_sa.h18
-rw-r--r--src/charon/sa/ike_sa.c448
-rw-r--r--src/charon/sa/ike_sa.h131
-rw-r--r--src/charon/sa/ike_sa_manager.c10
-rw-r--r--src/charon/sa/transactions/create_child_sa.c167
-rw-r--r--src/charon/sa/transactions/create_child_sa.h19
-rw-r--r--src/charon/sa/transactions/dead_peer_detection.c17
-rw-r--r--src/charon/sa/transactions/delete_child_sa.c17
-rw-r--r--src/charon/sa/transactions/delete_ike_sa.c17
-rw-r--r--src/charon/sa/transactions/ike_auth.c156
-rw-r--r--src/charon/sa/transactions/ike_auth.h14
-rw-r--r--src/charon/sa/transactions/ike_sa_init.c58
-rw-r--r--src/charon/sa/transactions/ike_sa_init.h13
-rwxr-xr-xsrc/charon/threads/stroke_interface.c57
-rw-r--r--src/libstrongswan/definitions.h5
28 files changed, 1060 insertions, 894 deletions
diff --git a/src/charon/config/connections/connection.c b/src/charon/config/connections/connection.c
index 3de57ca80..e1ab0392d 100644
--- a/src/charon/config/connections/connection.c
+++ b/src/charon/config/connections/connection.c
@@ -59,6 +59,11 @@ struct private_connection_t {
* Public part
*/
connection_t public;
+
+ /**
+ * Number of references hold by others to this connection
+ */
+ u_int refcount;
/**
* Name of the connection
@@ -155,24 +160,6 @@ static host_t *get_other_host (private_connection_t *this)
}
/**
- * Implementation of connection_t.update_my_host.
- */
-static void update_my_host(private_connection_t *this, host_t *my_host)
-{
- this->my_host->destroy(this->my_host);
- this->my_host = my_host;
-}
-
-/**
- * Implementation of connection_t.update_other_host.
- */
-static void update_other_host(private_connection_t *this, host_t *other_host)
-{
- this->other_host->destroy(this->other_host);
- this->other_host = other_host;
-}
-
-/**
* Implementation of connection_t.get_proposals.
*/
static linked_list_t* get_proposals(private_connection_t *this)
@@ -288,31 +275,11 @@ static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh
}
/**
- * Implementation of connection_t.clone.
+ * Implementation of connection_t.get_ref.
*/
-static connection_t *clone(private_connection_t *this)
+static void get_ref(private_connection_t *this)
{
- iterator_t *iterator;
- proposal_t *proposal;
- private_connection_t *clone = (private_connection_t*)connection_create(
- this->name, this->ikev2,
- this->cert_policy,
- this->certreq_policy,
- this->my_host->clone(this->my_host),
- this->other_host->clone(this->other_host),
- this->auth_method);
-
- /* clone all proposals */
- iterator = this->proposals->create_iterator(this->proposals, TRUE);
- while (iterator->has_next(iterator))
- {
- iterator->current(iterator, (void**)&proposal);
- proposal = proposal->clone(proposal);
- clone->proposals->insert_last(clone->proposals, (void*)proposal);
- }
- iterator->destroy(iterator);
-
- return &clone->public;
+ this->refcount++;
}
/**
@@ -320,18 +287,21 @@ static connection_t *clone(private_connection_t *this)
*/
static void destroy(private_connection_t *this)
{
- proposal_t *proposal;
-
- while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
+ if (--this->refcount == 0)
{
- proposal->destroy(proposal);
+ proposal_t *proposal;
+
+ while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
+ {
+ proposal->destroy(proposal);
+ }
+ this->proposals->destroy(this->proposals);
+
+ this->my_host->destroy(this->my_host);
+ this->other_host->destroy(this->other_host);
+ free(this->name);
+ free(this);
}
- this->proposals->destroy(this->proposals);
-
- this->my_host->destroy(this->my_host);
- this->other_host->destroy(this->other_host);
- free(this->name);
- free(this);
}
/**
@@ -344,15 +314,13 @@ connection_t * connection_create(char *name, bool ikev2,
auth_method_t auth_method)
{
private_connection_t *this = malloc_thing(private_connection_t);
-
+
/* public functions */
this->public.get_name = (char*(*)(connection_t*))get_name;
this->public.is_ikev2 = (bool(*)(connection_t*))is_ikev2;
this->public.get_cert_policy = (cert_policy_t(*)(connection_t*))get_cert_policy;
this->public.get_certreq_policy = (cert_policy_t(*)(connection_t*))get_certreq_policy;
this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host;
- this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host;
- this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host;
this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host;
this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals;
this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal;
@@ -360,10 +328,11 @@ connection_t * connection_create(char *name, bool ikev2,
this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method;
this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group;
this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group;
- this->public.clone = (connection_t*(*)(connection_t*))clone;
+ this->public.get_ref = (void(*)(connection_t*))get_ref;
this->public.destroy = (void(*)(connection_t*))destroy;
/* private variables */
+ this->refcount = 1;
this->name = strdup(name);
this->ikev2 = ikev2;
this->cert_policy = cert_policy;
@@ -373,6 +342,6 @@ connection_t * connection_create(char *name, bool ikev2,
this->auth_method = auth_method;
this->proposals = linked_list_create();
-
- return (&this->public);
+
+ return &this->public;
}
diff --git a/src/charon/config/connections/connection.h b/src/charon/config/connections/connection.h
index dca570e05..111acd5e1 100644
--- a/src/charon/config/connections/connection.h
+++ b/src/charon/config/connections/connection.h
@@ -130,30 +130,6 @@ struct connection_t {
* @return host information as host_t object
*/
host_t *(*get_other_host) (connection_t *this);
-
- /**
- * @brief Update address of my host.
- *
- * It may be necessary to uptdate own address, as it
- * is set to the default route (0.0.0.0) in some cases.
- * Old host is destroyed, new one NOT cloned.
- *
- * @param this calling object
- * @param my_host new host to set as my_host
- */
- void (*update_my_host) (connection_t *this, host_t *my_host);
-
- /**
- * @brief Update address of remote host.
- *
- * It may be necessary to uptdate remote address, as a
- * connection may define %any (0.0.0.0) or a subnet.
- * Old host is destroyed, new one NOT cloned.
- *
- * @param this calling object
- * @param my_host new host to set as other_host
- */
- void (*update_other_host) (connection_t *this, host_t *other_host);
/**
* @brief Returns a list of all supported proposals.
@@ -227,7 +203,7 @@ struct connection_t {
* the peer. It should be ommited when CERT_SEND_NEVER, sended otherwise.
*
* @param this calling object
- * @return - TRUE, if certificate request should be sent
+ * @return certificate request sending policy
*/
cert_policy_t (*get_certreq_policy) (connection_t *this);
@@ -261,16 +237,21 @@ struct connection_t {
bool (*check_dh_group) (connection_t *this, diffie_hellman_group_t dh_group);
/**
- * @brief Clone a connection_t object.
- *
- * @param this connection to clone
- * @return clone of it
+ * @brief Get a new reference to this connection.
+ *
+ * Get a new reference to this connection by increasing
+ * it's internal reference counter.
+ *
+ * @param this calling object
*/
- connection_t *(*clone) (connection_t *this);
+ void (*get_ref) (connection_t *this);
/**
* @brief Destroys a connection_t object.
*
+ * Decrements the internal reference counter and
+ * destroys the connection when it reaches zero.
+ *
* @param this calling object
*/
void (*destroy) (connection_t *this);
@@ -278,7 +259,7 @@ struct connection_t {
/**
* @brief Creates a connection_t object.
- *
+ *
* Supplied hosts become owned by connection, so
* do not modify or destroy them after a call to
* connection_create(). Name gets cloned internally.
diff --git a/src/charon/config/connections/local_connection_store.c b/src/charon/config/connections/local_connection_store.c
index c6e982e23..1f961cbcc 100644
--- a/src/charon/config/connections/local_connection_store.c
+++ b/src/charon/config/connections/local_connection_store.c
@@ -116,7 +116,7 @@ static connection_t *get_connection_by_hosts(private_local_connection_store_t *t
{
found = candidate;
best_prio = prio;
- }
+ }
}
}
iterator->destroy(iterator);
@@ -132,13 +132,9 @@ static connection_t *get_connection_by_hosts(private_local_connection_store_t *t
found_my_host->get_string(found_my_host),
found_other_host->get_string(found_other_host),
best_prio);
-
- found = found->clone(found);
- if (best_prio & PRIO_ADDR_ANY)
- {
- /* replace %any by the peer's address */
- found->update_other_host(found, other_host->clone(other_host));
- }
+
+ /* give out a new reference to it */
+ found->get_ref(found);
}
pthread_mutex_unlock(&(this->mutex));
return found;
@@ -159,13 +155,15 @@ static connection_t *get_connection_by_name(private_local_connection_store_t *th
iterator->current(iterator, (void**)&current);
if (strcmp(name, current->get_name(current)) == 0)
{
- found = current->clone(current);
+ found = current;
break;
}
}
iterator->destroy(iterator);
pthread_mutex_unlock(&(this->mutex));
+ /* get a new reference for it */
+ found->get_ref(found);
return found;
}
diff --git a/src/charon/config/policies/local_policy_store.c b/src/charon/config/policies/local_policy_store.c
index 2054b9df5..0c3e0ee04 100644
--- a/src/charon/config/policies/local_policy_store.c
+++ b/src/charon/config/policies/local_policy_store.c
@@ -67,9 +67,42 @@ static void add_policy(private_local_policy_store_t *this, policy_t *policy)
}
/**
- * Implementation of policy_store_t.get_policy_by_ids.
+ * Check if a policy contains traffic selectors
*/
-static policy_t *get_policy_by_ids(private_local_policy_store_t *this, identification_t *my_id, identification_t *other_id)
+static bool contains_traffic_selectors(policy_t *policy, bool mine,
+ linked_list_t *ts, host_t *host)
+{
+ linked_list_t *selected;
+ bool contains = FALSE;
+ traffic_selector_t *to;
+
+ if (mine)
+ {
+ selected = policy->select_my_traffic_selectors(policy, ts, host);
+ }
+ else
+ {
+ selected = policy->select_other_traffic_selectors(policy, ts, host);
+ }
+ if (selected->get_count(selected))
+ {
+ contains = TRUE;
+ }
+ while (selected->remove_last(selected, (void**)&to) == SUCCESS)
+ {
+ to->destroy(to);
+ }
+ selected->destroy(selected);
+ return contains;
+}
+
+/**
+ * Implementation of policy_store_t.get_policy.
+ */
+static policy_t *get_policy(private_local_policy_store_t *this,
+ identification_t *my_id, identification_t *other_id,
+ linked_list_t *my_ts, linked_list_t *other_ts,
+ host_t *my_host, host_t *other_host)
{
typedef enum {
PRIO_UNDEFINED = 0x00,
@@ -111,9 +144,22 @@ static policy_t *get_policy_by_ids(private_local_policy_store_t *this, identific
{
prio = PRIO_ID_MATCH - wildcards;
}
+
+ /* only accept if traffic selectors match */
+ if (!contains_traffic_selectors(candidate, TRUE, my_ts, my_host) ||
+ !contains_traffic_selectors(candidate, FALSE, other_ts, other_host))
+ {
+ this->logger->log(this->logger, CONTROL|LEVEL2,
+ "candidate '%s' inacceptable due traffic selector mismatch",
+ candidate->get_name(candidate),
+ candidate_my_id->get_string(candidate_my_id),
+ candidate_other_id->get_string(candidate_other_id),
+ prio);
+ continue;
+ }
this->logger->log(this->logger, CONTROL|LEVEL2,
- "candidate policy \"%s\": %s...%s (prio=%d)",
+ "candidate policy '%s': %s...%s (prio=%d)",
candidate->get_name(candidate),
candidate_my_id->get_string(candidate_my_id),
candidate_other_id->get_string(candidate_other_id),
@@ -134,18 +180,13 @@ static policy_t *get_policy_by_ids(private_local_policy_store_t *this, identific
identification_t *found_other_id = found->get_other_id(found);
this->logger->log(this->logger, CONTROL|LEVEL1,
- "found matching policy \"%s\": %s...%s (prio=%d)",
+ "found matching policy '%s': %s...%s (prio=%d)",
found->get_name(found),
found_my_id->get_string(found_my_id),
found_other_id->get_string(found_other_id),
best_prio);
-
- found = found->clone(found);
- if (best_prio != PRIO_ID_MATCH)
- {
- /* replace %any/wildcards by the peer's address */
- found->update_other_id(found, other_id->clone(other_id));
- }
+ /* give out a new reference to it */
+ found->get_ref(found);
}
pthread_mutex_unlock(&(this->mutex));
return found;
@@ -168,12 +209,14 @@ static policy_t *get_policy_by_name(private_local_policy_store_t *this, char *na
iterator->current(iterator, (void **)&current);
if (strcmp(current->get_name(current), name) == 0)
{
- found = current->clone(current);
+ found = current;
}
}
iterator->destroy(iterator);
pthread_mutex_unlock(&(this->mutex));
+ /* give out a new reference */
+ found->get_ref(found);
return found;
}
@@ -234,7 +277,7 @@ local_policy_store_t *local_policy_store_create(void)
private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t);
this->public.policy_store.add_policy = (void(*)(policy_store_t*,policy_t*))add_policy;
- this->public.policy_store.get_policy_by_ids = (policy_t*(*)(policy_store_t*,identification_t*,identification_t*))get_policy_by_ids;
+ this->public.policy_store.get_policy = (policy_t*(*)(policy_store_t*,identification_t*,identification_t*,linked_list_t*,linked_list_t*,host_t*,host_t*))get_policy;
this->public.policy_store.get_policy_by_name = (policy_t*(*)(policy_store_t*,char*))get_policy_by_name;
this->public.policy_store.delete_policy = (status_t(*)(policy_store_t*,char*))delete_policy;
this->public.policy_store.destroy = (void(*)(policy_store_t*))destroy;
diff --git a/src/charon/config/policies/policy.c b/src/charon/config/policies/policy.c
index 152c157a8..a64af3271 100644
--- a/src/charon/config/policies/policy.c
+++ b/src/charon/config/policies/policy.c
@@ -44,6 +44,11 @@ struct private_policy_t {
policy_t public;
/**
+ * Number of references hold by others to this policy
+ */
+ u_int refcount;
+
+ /**
* Name of the policy, used to query it
*/
char *name;
@@ -135,76 +140,52 @@ static identification_t *get_other_id(private_policy_t *this)
}
/**
- * Implementation of policy_t.update_my_id
- */
-static void update_my_id(private_policy_t *this, identification_t *my_id)
-{
- this->my_id->destroy(this->my_id);
- this->my_id = my_id;
-}
-
-/**
- * Implementation of policy_t.update_other_id
- */
-static void update_other_id(private_policy_t *this, identification_t *other_id)
-{
- this->other_id->destroy(this->other_id);
- this->other_id = other_id;
-}
-
-/**
- * Helper function which does the work for policy_t.update_my_ts and update_other_ts
+ * Get traffic selectors, with wildcard-address update
*/
-static void update_ts(linked_list_t* list, host_t *new_host)
+static linked_list_t *get_traffic_selectors(private_policy_t *this, linked_list_t *list, host_t *host)
{
- traffic_selector_t *ts;
iterator_t *iterator;
-
+ traffic_selector_t *current;
+ linked_list_t *result = linked_list_create();
+
iterator = list->create_iterator(list, TRUE);
- while (iterator->has_next(iterator))
+
+ while (iterator->iterate(iterator, (void**)&current))
{
- iterator->current(iterator, (void**)&ts);
- ts->update_address_range(ts, new_host);
+ /* we make a copy of the TS, this allows us to update wildcard
+ * addresses in it. We won't pollute the shared policy. */
+ current = current->clone(current);
+ current->update_address_range(current, host);
+
+ result->insert_last(result, (void*)current);
}
iterator->destroy(iterator);
-}
-
-/**
- * Implementation of policy_t.update_my_id
- */
-static void update_my_ts(private_policy_t *this, host_t *my_host)
-{
- update_ts(this->my_ts, my_host);
-}
-
-/**
- * Implementation of policy_t.update_other_ts
- */
-static void update_other_ts(private_policy_t *this, host_t *my_host)
-{
- update_ts(this->other_ts, my_host);
+ return result;
}
/**
* Implementation of policy_t.get_my_traffic_selectors
*/
-static linked_list_t *get_my_traffic_selectors(private_policy_t *this)
+static linked_list_t *get_my_traffic_selectors(private_policy_t *this, host_t *me)
{
- return this->my_ts;
+ return get_traffic_selectors(this, this->my_ts, me);
}
/**
* Implementation of policy_t.get_other_traffic_selectors
*/
-static linked_list_t *get_other_traffic_selectors(private_policy_t *this, traffic_selector_t **traffic_selectors[])
+static linked_list_t *get_other_traffic_selectors(private_policy_t *this, host_t *other)
{
- return this->other_ts;
+ return get_traffic_selectors(this, this->other_ts, other);
}
/**
- * Implementation of private_policy_t.select_traffic_selectors
+ * Narrow traffic selectors, with wildcard-address update in "stored".
*/
-static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_list_t *stored, linked_list_t *supplied)
+static linked_list_t *select_traffic_selectors(private_policy_t *this,
+ linked_list_t *stored,
+ linked_list_t *supplied,
+ host_t *host)
{
iterator_t *supplied_iter, *stored_iter;
traffic_selector_t *supplied_ts, *stored_ts, *selected_ts;
@@ -218,16 +199,17 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_li
supplied_iter = supplied->create_iterator(supplied, TRUE);
/* iterate over all stored selectors */
- while (stored_iter->has_next(stored_iter))
+ while (stored_iter->iterate(stored_iter, (void**)&stored_ts))
{
- stored_iter->current(stored_iter, (void**)&stored_ts);
+ /* we make a copy of the TS, this allows us to update wildcard
+ * addresses in it. We won't pollute the shared policy. */
+ stored_ts = stored_ts->clone(stored_ts);
+ stored_ts->update_address_range(stored_ts, host);
supplied_iter->reset(supplied_iter);
/* iterate over all supplied traffic selectors */
- while (supplied_iter->has_next(supplied_iter))
+ while (supplied_iter->iterate(supplied_iter, (void**)&supplied_ts))
{
- supplied_iter->current(supplied_iter, (void**)&supplied_ts);
-
this->logger->log(this->logger, CONTROL|LEVEL2,
" stored %s <=> %s received",
stored_ts->get_string(stored_ts),
@@ -243,6 +225,7 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_li
selected_ts->get_string(selected_ts));
}
}
+ stored_ts->destroy(stored_ts);
}
stored_iter->destroy(stored_iter);
supplied_iter->destroy(supplied_iter);
@@ -253,17 +236,21 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_li
/**
* Implementation of private_policy_t.select_my_traffic_selectors
*/
-static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
+static linked_list_t *select_my_traffic_selectors(private_policy_t *this,
+ linked_list_t *supplied,
+ host_t *me)
{
- return select_traffic_selectors(this, this->my_ts, supplied);
+ return select_traffic_selectors(this, this->my_ts, supplied, me);
}
/**
* Implementation of private_policy_t.select_other_traffic_selectors
*/
-static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
+static linked_list_t *select_other_traffic_selectors(private_policy_t *this,
+ linked_list_t *supplied,
+ host_t* other)
{
- return select_traffic_selectors(this, this->other_ts, supplied);
+ return select_traffic_selectors(this, this->other_ts, supplied, other);
}
/**
@@ -322,11 +309,11 @@ static void add_authorities(private_policy_t *this, identification_t *my_ca, ide
}
/**
- * Implementation of policy_t.add_updown
+ * Implementation of policy_t.get_updown
*/
-static void add_updown(private_policy_t *this, char *updown)
+static char* get_updown(private_policy_t *this)
{
- this->updown = (updown == NULL)? NULL:strdup(updown);
+ return this->updown;
}
/**
@@ -375,118 +362,67 @@ static u_int32_t get_hard_lifetime(private_policy_t *this)
}
/**
- * Implements policy_t.clone.
+ * Implements policy_t.get_ref.
*/
-static policy_t *clone_(private_policy_t *this)
+static void get_ref(private_policy_t *this)
{
- private_policy_t *clone = (private_policy_t*)policy_create(this->name,
- this->my_id->clone(this->my_id),
- this->other_id->clone(this->other_id),
- this->hard_lifetime, this->soft_lifetime,
- this->jitter);
- iterator_t *iterator;
- proposal_t *proposal;
- traffic_selector_t *ts;
-
- /* clone the certification authorities */
- if (this->my_ca)
- {
- clone->my_ca = this->my_ca->clone(this->my_ca);
- }
- if (this->other_ca)
- {
- clone->other_ca = this->other_ca->clone(this->other_ca);
- }
-
- /* clone updown script */
- clone->updown = (this->updown == NULL)? NULL:strdup(this->updown);
-
- /* clone all proposals */
- iterator = this->proposals->create_iterator(this->proposals, TRUE);
- while (iterator->has_next(iterator))
- {
- iterator->current(iterator, (void**)&proposal);
- proposal = proposal->clone(proposal);
- clone->proposals->insert_last(clone->proposals, (void*)proposal);
- }
- iterator->destroy(iterator);
-
- /* clone all local traffic selectors */
- iterator = this->my_ts->create_iterator(this->my_ts, TRUE);
- while (iterator->has_next(iterator))
- {
- iterator->current(iterator, (void**)&ts);
- ts = ts->clone(ts);
- clone->my_ts->insert_last(clone->my_ts, (void*)ts);
- }
- iterator->destroy(iterator);
-
- /* clone all remote traffic selectors */
- iterator = this->other_ts->create_iterator(this->other_ts, TRUE);
- while (iterator->has_next(iterator))
- {
- iterator->current(iterator, (void**)&ts);
- ts = ts->clone(ts);
- clone->other_ts->insert_last(clone->other_ts, (void*)ts);
- }
- iterator->destroy(iterator);
-
- return &clone->public;
+ this->refcount++;
}
/**
* Implements policy_t.destroy.
*/
-static status_t destroy(private_policy_t *this)
-{
- proposal_t *proposal;
- traffic_selector_t *traffic_selector;
-
-
- /* delete proposals */
- while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
- {
- proposal->destroy(proposal);
- }
- this->proposals->destroy(this->proposals);
-
- /* delete traffic selectors */
- while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS)
- {
- traffic_selector->destroy(traffic_selector);
- }
- this->my_ts->destroy(this->my_ts);
-
- /* delete traffic selectors */
- while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS)
- {
- traffic_selector->destroy(traffic_selector);
- }
- this->other_ts->destroy(this->other_ts);
-
- /* delete certification authorities */
- if (this->my_ca)
- {
- this->my_ca->destroy(this->my_ca);
- }
- if (this->other_ca)
- {
- this->other_ca->destroy(this->other_ca);
- }
-
- /* delete updown script */
- if (this->updown)
+static void destroy(private_policy_t *this)
+{
+ if (--this->refcount == 0)
{
- free(this->updown);
+ proposal_t *proposal;
+ traffic_selector_t *traffic_selector;
+
+ /* delete proposals */
+ while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
+ {
+ proposal->destroy(proposal);
+ }
+ this->proposals->destroy(this->proposals);
+
+ /* delete traffic selectors */
+ while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS)
+ {
+ traffic_selector->destroy(traffic_selector);
+ }
+ this->my_ts->destroy(this->my_ts);
+
+ /* delete traffic selectors */
+ while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS)
+ {
+ traffic_selector->destroy(traffic_selector);
+ }
+ this->other_ts->destroy(this->other_ts);
+
+ /* delete certification authorities */
+ if (this->my_ca)
+ {
+ this->my_ca->destroy(this->my_ca);
+ }
+ if (this->other_ca)
+ {
+ this->other_ca->destroy(this->other_ca);
+ }
+
+ /* delete updown script */
+ if (this->updown)
+ {
+ free(this->updown);
+ }
+
+ /* delete ids */
+ this->my_id->destroy(this->my_id);
+ this->other_id->destroy(this->other_id);
+
+ free(this->name);
+ free(this);
}
-
- /* delete ids */
- this->my_id->destroy(this->my_id);
- this->other_id->destroy(this->other_id);
-
- free(this->name);
- free(this);
- return SUCCESS;
}
/*
@@ -494,7 +430,7 @@ static status_t destroy(private_policy_t *this)
*/
policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id,
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
- u_int32_t jitter)
+ u_int32_t jitter, char *updown)
{
private_policy_t *this = malloc_thing(private_policy_t);
@@ -502,24 +438,20 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
this->public.get_name = (char *(*)(policy_t*))get_name;
this->public.get_my_id = (identification_t*(*)(policy_t*))get_my_id;
this->public.get_other_id = (identification_t*(*)(policy_t*))get_other_id;
- this->public.update_my_id = (void(*)(policy_t*,identification_t*))update_my_id;
- this->public.update_other_id = (void(*)(policy_t*,identification_t*))update_other_id;
- this->public.update_my_ts = (void(*)(policy_t*,host_t*))update_my_ts;
- this->public.update_other_ts = (void(*)(policy_t*,host_t*))update_other_ts;
- this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*))get_my_traffic_selectors;
- this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_my_traffic_selectors;
- this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*))get_other_traffic_selectors;
- this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_other_traffic_selectors;
+ this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*,host_t*))get_my_traffic_selectors;
+ this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*,host_t*))get_other_traffic_selectors;
+ this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*,host_t*))select_my_traffic_selectors;
+ this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*,host_t*))select_other_traffic_selectors;
this->public.get_proposals = (linked_list_t*(*)(policy_t*))get_proposals;
this->public.select_proposal = (proposal_t*(*)(policy_t*,linked_list_t*))select_proposal;
this->public.add_my_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_my_traffic_selector;
this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector;
this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal;
this->public.add_authorities = (void(*)(policy_t*,identification_t*, identification_t*))add_authorities;
- this->public.add_updown = (void(*)(policy_t*,char*))add_updown;
+ this->public.get_updown = (char*(*)(policy_t*))get_updown;
this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
- this->public.clone = (policy_t*(*)(policy_t*))clone_;
+ this->public.get_ref = (void(*)(policy_t*))get_ref;
this->public.destroy = (void(*)(policy_t*))destroy;
/* apply init values */
@@ -529,8 +461,10 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
this->hard_lifetime = hard_lifetime;
this->soft_lifetime = soft_lifetime;
this->jitter = jitter;
+ this->updown = (updown == NULL) ? NULL : strdup(updown);
/* initialize private members*/
+ this->refcount = 1;
this->my_ca = NULL;
this->other_ca = NULL;
this->proposals = linked_list_create();
@@ -538,5 +472,5 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
this->other_ts = linked_list_create();
this->logger = logger_manager->get_logger(logger_manager, CONFIG);
- return (&this->public);
+ return &this->public;
}
diff --git a/src/charon/config/policies/policy.h b/src/charon/config/policies/policy.h
index 329a48ff3..1a539f5bc 100644
--- a/src/charon/config/policies/policy.h
+++ b/src/charon/config/policies/policy.h
@@ -75,145 +75,103 @@ struct policy_t {
* @return other id
*/
identification_t *(*get_other_id) (policy_t *this);
-
- /**
- * @brief Update own ID.
- *
- * It may be necessary to uptdate own ID, as it
- * is set to %any or to e.g. *@strongswan.org in
- * some cases.
- * Old ID is destroyed, new one NOT cloned.
- *
- * @param this calling object
- * @param my_id new ID to set as my_id
- */
- void (*update_my_id) (policy_t *this, identification_t *my_id);
-
- /**
- * @brief Update others ID.
- *
- * It may be necessary to uptdate others ID, as it
- * is set to %any or to e.g. *@strongswan.org in
- * some cases.
- * Old ID is destroyed, new one NOT cloned.
- *
- * @param this calling object
- * @param other_id new ID to set as other_id
- */
- void (*update_other_id) (policy_t *this, identification_t *other_id);
-
- /**
- * @brief Update own address in traffic selectors.
- *
- * Update own 0.0.0.0 address in traffic selectors
- * with supplied one. The size of the subnet will be
- * set to /32.
- *
- * @param this calling object
- * @param my_host new address to set in traffic selectors
- */
- void (*update_my_ts) (policy_t *this, host_t *my_host);
-
- /**
- * @brief Update others address in traffic selectors.
- *
- * Update remote 0.0.0.0 address in traffic selectors
- * with supplied one. The size of the subnet will be
- * set to /32.
- *
- * @param this calling object
- * @param other_host new address to set in traffic selectors
- */
- void (*update_other_ts) (policy_t *this, host_t *other_host);
/**
* @brief Get configured traffic selectors for our site.
*
* Returns a list with all traffic selectors for the local
- * site. List and items MUST NOT be freed nor modified.
+ * site. List and items must be destroyed after usage.
*
- * @param this calling object
- * @return list with traffic selectors
+ * @param this calling object
+ * @return list with traffic selectors
*/
- linked_list_t *(*get_my_traffic_selectors) (policy_t *this);
+ linked_list_t *(*get_my_traffic_selectors) (policy_t *this, host_t *me);
/**
* @brief Get configured traffic selectors for others site.
*
* Returns a list with all traffic selectors for the remote
- * site. List and items MUST NOT be freed nor modified.
+ * site. List and items must be destroyed after usage.
*
- * @param this calling object
- * @return list with traffic selectors
+ * @param this calling object
+ * @return list with traffic selectors
*/
- linked_list_t *(*get_other_traffic_selectors) (policy_t *this);
+ linked_list_t *(*get_other_traffic_selectors) (policy_t *this, host_t* other);
/**
* @brief Select traffic selectors from a supplied list for local site.
*
* Resulted list and traffic selectors must be destroyed after usage.
+ * As the traffic selectors may contain a wildcard address (0.0.0.0) for
+ * addresses we don't know in previous, an address may be supplied to
+ * replace these 0.0.0.0 addresses on-the-fly.
*
- * @param this calling object
- * @param supplied linked list with traffic selectors
- * @return list containing the selected traffic selectors
+ * @param this calling object
+ * @param supplied linked list with traffic selectors
+ * @param me host address used by us
+ * @return list containing the selected traffic selectors
*/
- linked_list_t *(*select_my_traffic_selectors) (policy_t *this, linked_list_t *supplied);
+ linked_list_t *(*select_my_traffic_selectors) (policy_t *this,
+ linked_list_t *supplied,
+ host_t *me);
/**
* @brief Select traffic selectors from a supplied list for remote site.
*
* Resulted list and traffic selectors must be destroyed after usage.
- *
- * @param this calling object
- * @param supplied linked list with traffic selectors
- * @return list containing the selected traffic selectors
+ * As the traffic selectors may contain a wildcard address (0.0.0.0) for
+ * addresses we don't know in previous, an address may be supplied to
+ * replace these 0.0.0.0 addresses on-the-fly.
+ *
+ * @param this calling object
+ * @param supplied linked list with traffic selectors
+ * @return list containing the selected traffic selectors
*/
- linked_list_t *(*select_other_traffic_selectors) (policy_t *this, linked_list_t *supplied);
+ linked_list_t *(*select_other_traffic_selectors) (policy_t *this,
+ linked_list_t *supplied,
+ host_t *other);
/**
* @brief Get the list of internally stored proposals.
*
- * Rembember: policy_t does store proposals for AH/ESP,
- * IKE proposals are in the connection_t
- *
- * @warning List and Items are still owned by policy and MUST NOT
- * be manipulated or freed!
- *
- * @param this calling object
- * @return lists with proposals
+ * policy_t does store proposals for AH/ESP, IKE proposals are in
+ * the connection_t.
+ * List and Items are still owned by policy and MUST NOT
+ * be manipulated or freed!
+ *
+ * @param this calling object
+ * @return lists with proposals
*/
linked_list_t *(*get_proposals) (policy_t *this);
/**
* @brief Select a proposal from a supplied list.
+ *
+ * Returned propsal is newly created and must be destroyed after usage.
*
- * @param this calling object
- * @param proposals list from from wich proposals are selected
- * @return selected proposal, or NULL if nothing matches
+ * @param this calling object
+ * @param proposals list from from wich proposals are selected
+ * @return selected proposal, or NULL if nothing matches
*/
proposal_t *(*select_proposal) (policy_t *this, linked_list_t *proposals);
/**
* @brief Add a traffic selector to the list for local site.
*
- * After add, proposal is owned by policy.
- *
- * @warning Do not add while other threads are reading.
+ * After add, traffic selector is owned by policy.
*
- * @param this calling object
- * @param traffic_selector traffic_selector to add
+ * @param this calling object
+ * @param traffic_selector traffic_selector to add
*/
void (*add_my_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector);
/**
* @brief Add a traffic selector to the list for remote site.
*
- * After add, proposal is owned by policy.
- *
- * @warning Do not add while other threads are reading.
+ * After add, traffic selector is owned by policy.
*
- * @param this calling object
- * @param traffic_selector traffic_selector to add
+ * @param this calling object
+ * @param traffic_selector traffic_selector to add
*/
void (*add_other_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector);
@@ -222,30 +180,29 @@ struct policy_t {
*
* The proposals are stored by priority, first added
* is the most prefered.
+ * After add, proposal is owned by policy.
*
- * @warning Do not add while other threads are reading.
- *
- * @param this calling object
- * @param proposal proposal to add
+ * @param this calling object
+ * @param proposal proposal to add
*/
void (*add_proposal) (policy_t *this, proposal_t *proposal);
/**
- * @brief Add certification authorities
+ * @brief Add certification authorities.
*
- * @param this calling object
- * @param my_ca issuer of my certificate
- * @param other_ca required issuer of the peer's certificate
+ * @param this calling object
+ * @param my_ca issuer of my certificate
+ * @param other_ca required issuer of the peer's certificate
*/
void (*add_authorities) (policy_t *this, identification_t *my_ca, identification_t *other_ca);
/**
- * @brief Add updown script
+ * @brief Get updown script
*
- * @param this calling object
- * @param updown updown script
+ * @param this calling object
+ * @return path to updown script
*/
- void (*add_updown) (policy_t *this, char *updown);
+ char* (*get_updown) (policy_t *this);
/**
* @brief Get the lifetime of a policy, before rekeying starts.
@@ -253,29 +210,34 @@ struct policy_t {
* A call to this function automatically adds a jitter to
* avoid simultanous rekeying.
*
- * @param this policy
- * @return lifetime in seconds
+ * @param this policy
+ * @return lifetime in seconds
*/
u_int32_t (*get_soft_lifetime) (policy_t *this);
/**
* @brief Get the lifetime of a policy, before SA gets deleted.
*
- * @param this policy
- * @return lifetime in seconds
+ * @param this policy
+ * @return lifetime in seconds
*/
u_int32_t (*get_hard_lifetime) (policy_t *this);
/**
- * @brief Clone a policy.
+ * @brief Get a new reference.
+ *
+ * Get a new reference to this policy by increasing
+ * it's internal reference counter.
*
- * @param this policy to clone
- * @return clone of it
+ * @param this calling object
*/
- policy_t *(*clone) (policy_t *this);
+ void (*get_ref) (policy_t *this);
/**
- * @brief Destroys the policy object
+ * @brief Destroys the policy object.
+ *
+ * Decrements the internal reference counter and
+ * destroys the policy when it reaches zero.
*
* @param this calling object
*/
@@ -291,6 +253,7 @@ struct policy_t {
* (soft_lifetime - random(0, jitter)). After a successful rekeying,
* the hard_lifetime limit counter is reset. You should specify
* hard_lifetime > soft_lifetime > jitter.
+ * After a call to create, a reference is obtained (refcount = 1).
*
* @param name name of the policy
* @param my_id identification_t for ourselves
@@ -298,11 +261,14 @@ struct policy_t {
* @param hard_lifetime lifetime before deleting an SA
* @param soft_lifetime lifetime before rekeying an SA
* @param jitter range of randomization time
+ * @param updown updown script to execute on up/down event
* @return policy_t object
*
* @ingroup config
*/
-policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id,
- u_int32_t hard_lifetime, u_int32_t soft_lifetime, u_int32_t jitter);
+policy_t *policy_create(char *name,
+ identification_t *my_id, identification_t *other_id,
+ u_int32_t hard_lifetime, u_int32_t soft_lifetime,
+ u_int32_t jitter, char *updown);
#endif /* POLICY_H_ */
diff --git a/src/charon/config/policies/policy_store.h b/src/charon/config/policies/policy_store.h
index 40cc87e2f..2ea57b8b4 100755
--- a/src/charon/config/policies/policy_store.h
+++ b/src/charon/config/policies/policy_store.h
@@ -25,13 +25,17 @@
#include <types.h>
#include <config/policies/policy.h>
+#include <utils/linked_list.h>
typedef struct policy_store_t policy_store_t;
/**
* @brief The interface for a store of policy_t's.
- *
+ *
+ * The store uses reference counting to manage their lifetime. Call
+ * destroy() for a policy which is returned from the store after usage.
+ *
* @b Constructors:
* - stroke_create()
*
@@ -40,28 +44,30 @@ typedef struct policy_store_t policy_store_t;
struct policy_store_t {
/**
- * @brief Returns a policy identified by two IDs.
+ * @brief Returns a policy identified by two IDs and a set of traffic selectors.
*
- * The returned policy gets created/cloned and therefore must be
- * destroyed by the caller.
* other_id must be fully qualified. my_id may be %any, as the
* other peer may not include an IDr Request.
*
- * @param this calling object
- * @param my_id own ID of the policy
- * @param other_id others ID of the policy
+ * @param this calling object
+ * @param my_id own ID of the policy
+ * @param other_id others ID of the policy
+ * @param my_ts traffic selectors requested for local host
+ * @param other_ts traffic selectors requested for remote host
+ * @param my_host host to use for wilcards in TS compare
+ * @param other_host host to use for wildcards in TS compare
* @return
- * - matching policy_t, if found
- * - NULL otherwise
+ * - matching policy_t, if found
+ * - NULL otherwise
*/
- policy_t *(*get_policy_by_ids) (policy_store_t *this, identification_t *my_id, identification_t *other_id);
+ policy_t *(*get_policy) (policy_store_t *this,
+ identification_t *my_id, identification_t *other_id,
+ linked_list_t *my_ts, linked_list_t *other_ts,
+ host_t *my_host, host_t* other_host);
/**
* @brief Returns a policy identified by a connection name.
*
- * The returned policy gets created/cloned and therefore must be
- * destroyed by the caller.
- *
* @param this calling object
* @param name name of the policy
* @return
diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c
index b0b0a13ce..3a9480f77 100644
--- a/src/charon/config/traffic_selector.c
+++ b/src/charon/config/traffic_selector.c
@@ -356,16 +356,18 @@ static void update_address_range(private_traffic_selector_t *this, host_t *host)
*/
static traffic_selector_t *clone_(private_traffic_selector_t *this)
{
- private_traffic_selector_t *clone = traffic_selector_create(this->protocol, this->type, this->from_port, this->to_port);
- clone->type = this->type;
- clone->string = strdup(this->string);
+ private_traffic_selector_t *clone;
+
+ clone = traffic_selector_create(this->protocol, this->type,
+ this->from_port, this->to_port);
switch (clone->type)
{
case TS_IPV4_ADDR_RANGE:
{
clone->from_addr_ipv4 = this->from_addr_ipv4;
clone->to_addr_ipv4 = this->to_addr_ipv4;
- return &(clone->public);
+ update_string(clone);
+ return &clone->public;
}
case TS_IPV6_ADDR_RANGE:
default:
@@ -391,8 +393,7 @@ static void destroy(private_traffic_selector_t *this)
traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_addr, u_int16_t from_port, chunk_t to_addr, u_int16_t to_port)
{
private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port);
-
- this->type = type;
+
switch (type)
{
case TS_IPV4_ADDR_RANGE:
@@ -400,12 +401,12 @@ traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_typ
if (from_addr.len != 4 || to_addr.len != 4)
{
free(this);
- return NULL;
+ return NULL;
}
/* chunk contains network order, convert! */
this->from_addr_ipv4 = ntohl(*((u_int32_t*)from_addr.ptr));
this->to_addr_ipv4 = ntohl(*((u_int32_t*)to_addr.ptr));
- break;
+ break;
}
case TS_IPV6_ADDR_RANGE:
default:
diff --git a/src/charon/queues/jobs/initiate_ike_sa_job.c b/src/charon/queues/jobs/initiate_ike_sa_job.c
index 6c753fd68..38108cab8 100644
--- a/src/charon/queues/jobs/initiate_ike_sa_job.c
+++ b/src/charon/queues/jobs/initiate_ike_sa_job.c
@@ -41,11 +41,16 @@ struct private_initiate_ike_sa_job_t {
initiate_ike_sa_job_t public;
/**
- * associated connection object to initiate
+ * associated connection to initiate
*/
connection_t *connection;
/**
+ * associated policy to initiate
+ */
+ policy_t *policy;
+
+ /**
* logger
*/
logger_t *logger;
@@ -75,7 +80,9 @@ static status_t execute(private_initiate_ike_sa_job_t *this)
this->logger->log(this->logger, CONTROL|LEVEL2, "Creating and checking out IKE SA");
charon->ike_sa_manager->create_and_checkout(charon->ike_sa_manager, &ike_sa);
- status = ike_sa->initiate(ike_sa, this->connection->clone(this->connection));
+ this->connection->get_ref(this->connection);
+ this->policy->get_ref(this->policy);
+ status = ike_sa->initiate(ike_sa, this->connection, this->policy);
if (status != SUCCESS)
{
this->logger->log(this->logger, ERROR,
@@ -95,13 +102,14 @@ static status_t execute(private_initiate_ike_sa_job_t *this)
static void destroy(private_initiate_ike_sa_job_t *this)
{
this->connection->destroy(this->connection);
+ this->policy->destroy(this->policy);
free(this);
}
/*
* Described in header
*/
-initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection)
+initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection, policy_t *policy)
{
private_initiate_ike_sa_job_t *this = malloc_thing(private_initiate_ike_sa_job_t);
@@ -112,7 +120,8 @@ initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection)
/* private variables */
this->connection = connection;
+ this->policy = policy;
this->logger = logger_manager->get_logger(logger_manager, WORKER);
- return &(this->public);
+ return &this->public;
}
diff --git a/src/charon/queues/jobs/initiate_ike_sa_job.h b/src/charon/queues/jobs/initiate_ike_sa_job.h
index fe81d31d6..c119cf3fc 100644
--- a/src/charon/queues/jobs/initiate_ike_sa_job.h
+++ b/src/charon/queues/jobs/initiate_ike_sa_job.h
@@ -26,6 +26,7 @@
#include <types.h>
#include <queues/jobs/job.h>
#include <config/connections/connection.h>
+#include <config/policies/policy.h>
typedef struct initiate_ike_sa_job_t initiate_ike_sa_job_t;
@@ -33,8 +34,7 @@ typedef struct initiate_ike_sa_job_t initiate_ike_sa_job_t;
/**
* @brief Class representing an INITIATE_IKE_SA Job.
*
- * This job is created if an IKE_SA should be iniated. This
- * happens via a user request, or via the kernel interface.
+ * This job is created if an IKE_SA should be iniated.
*
* @b Constructors:
* - initiate_ike_sa_job_create()
@@ -52,10 +52,12 @@ struct initiate_ike_sa_job_t {
* @brief Creates a job of type INITIATE_IKE_SA.
*
* @param connection connection_t to initializes
+ * @param policy policy to set up
* @return initiate_ike_sa_job_t object
*
* @ingroup jobs
*/
-initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection);
+initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection,
+ policy_t *policy);
#endif /*INITIATE_IKE_SA_JOB_H_*/
diff --git a/src/charon/sa/authenticator.c b/src/charon/sa/authenticator.c
index fb4bdde4e..8dcfc049f 100644
--- a/src/charon/sa/authenticator.c
+++ b/src/charon/sa/authenticator.c
@@ -51,6 +51,11 @@ struct private_authenticator_t {
ike_sa_t *ike_sa;
/**
+ * auth_method to create own signature/mac/whatever..
+ */
+ auth_method_t auth_method;
+
+ /**
* PRF taken from the IKE_SA.
*/
prf_t *prf;
@@ -294,10 +299,8 @@ static status_t compute_auth_data (private_authenticator_t *this,
chunk_t other_nonce,
id_payload_t *my_id_payload,
bool initiator)
-{
- connection_t *connection = this->ike_sa->get_connection(this->ike_sa);
-
- switch(connection->get_auth_method(connection))
+{
+ switch(this->auth_method)
{
case SHARED_KEY_MESSAGE_INTEGRITY_CODE:
{
@@ -405,7 +408,7 @@ static void destroy (private_authenticator_t *this)
/*
* Described in header.
*/
-authenticator_t *authenticator_create(ike_sa_t *ike_sa)
+authenticator_t *authenticator_create(ike_sa_t *ike_sa, auth_method_t auth_method)
{
private_authenticator_t *this = malloc_thing(private_authenticator_t);
@@ -420,6 +423,7 @@ authenticator_t *authenticator_create(ike_sa_t *ike_sa)
/* private data */
this->ike_sa = ike_sa;
+ this->auth_method = auth_method;
this->prf = this->ike_sa->get_prf(this->ike_sa);
this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
diff --git a/src/charon/sa/authenticator.h b/src/charon/sa/authenticator.h
index 99a56e2e4..645e39b81 100644
--- a/src/charon/sa/authenticator.h
+++ b/src/charon/sa/authenticator.h
@@ -122,11 +122,12 @@ struct authenticator_t {
* @brief Creates an authenticator object.
*
* @param ike_sa associated ike_sa
+ * @param auth_method authentication method to use for own signature/mac
*
* @return authenticator_t object
*
* @ingroup sa
*/
-authenticator_t *authenticator_create(ike_sa_t *ike_sa);
+authenticator_t *authenticator_create(ike_sa_t *ike_sa, auth_method_t auth_method);
#endif /* AUTHENTICATOR_H_ */
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index c9c6794b2..38b4fa87a 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -96,6 +96,16 @@ struct private_child_sa_t {
linked_list_t *policies;
/**
+ * Seperate list for local traffic selectors
+ */
+ linked_list_t *my_ts;
+
+ /**
+ * Seperate list for remote traffic selectors
+ */
+ linked_list_t *other_ts;
+
+ /**
* reqid used for this child_sa
*/
u_int32_t reqid;
@@ -473,6 +483,9 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
policy->my_ts = my_ts->clone(my_ts);
policy->other_ts = other_ts->clone(other_ts);
this->policies->insert_last(this->policies, (void*)policy);
+ /* add to separate list to query them via get_*_traffic_selectors() */
+ this->my_ts->insert_last(this->my_ts, (void*)policy->my_ts);
+ this->other_ts->insert_last(this->other_ts, (void*)policy->other_ts);
}
}
my_iter->destroy(my_iter);
@@ -481,6 +494,22 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
}
/**
+ * Implementation of child_sa_t.get_my_traffic_selectors.
+ */
+static linked_list_t *get_my_traffic_selectors(private_child_sa_t *this)
+{
+ return this->my_ts;
+}
+
+/**
+ * Implementation of child_sa_t.get_my_traffic_selectors.
+ */
+static linked_list_t *get_other_traffic_selectors(private_child_sa_t *this)
+{
+ return this->other_ts;
+}
+
+/**
* Implementation of child_sa_t.set_rekeying_transaction.
*/
static void set_rekeying_transaction(private_child_sa_t *this, void *transaction)
@@ -819,6 +848,8 @@ static void destroy(private_child_sa_t *this)
}
this->policies->destroy(this->policies);
+ this->my_ts->destroy(this->my_ts);
+ this->other_ts->destroy(this->other_ts);
this->me.addr->destroy(this->me.addr);
this->other.addr->destroy(this->other.addr);
free(this);
@@ -843,6 +874,8 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_diff_t,host_diff_t))update_hosts;
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
+ this->public.get_my_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_my_traffic_selectors;
+ this->public.get_other_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_other_traffic_selectors;
this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
this->public.set_rekeying_transaction = (void (*)(child_sa_t*,void*))set_rekeying_transaction;
this->public.get_rekeying_transaction = (void* (*)(child_sa_t*))get_rekeying_transaction;
@@ -866,6 +899,8 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
/* reuse old reqid if we are rekeying an existing CHILD_SA */
this->reqid = rekey ? rekey : ++reqid;
this->policies = linked_list_create();
+ this->my_ts = linked_list_create();
+ this->other_ts = linked_list_create();
this->protocol = PROTO_NONE;
this->rekeying_transaction = NULL;
diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h
index 33d06a70b..2a74a2a44 100644
--- a/src/charon/sa/child_sa.h
+++ b/src/charon/sa/child_sa.h
@@ -177,7 +177,7 @@ struct child_sa_t {
* @return SUCCESS or FAILED
*/
status_t (*update_hosts) (child_sa_t *this, host_t *new_me, host_t *new_other,
- host_diff_t my_diff, host_diff_t other_diff);
+ host_diff_t my_diff, host_diff_t other_diff);
/**
* @brief Install the policies using some traffic selectors.
@@ -193,6 +193,22 @@ struct child_sa_t {
status_t (*add_policies) (child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list);
/**
+ * @brief Get the traffic selectors of added policies of local host.
+ *
+ * @param this calling object
+ * @return list of traffic selectors
+ */
+ linked_list_t* (*get_my_traffic_selectors) (child_sa_t *this);
+
+ /**
+ * @brief Get the traffic selectors of added policies of remote host.
+ *
+ * @param this calling object
+ * @return list of traffic selectors
+ */
+ linked_list_t* (*get_other_traffic_selectors) (child_sa_t *this);
+
+ /**
* @brief Get the time of this child_sa_t's last use (i.e. last use of any of its policies)
*
* @param this calling object
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index c233afc37..569d8795e 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -86,24 +86,39 @@ struct private_ike_sa_t {
ike_sa_id_t *ike_sa_id;
/**
- * Linked List containing the child sa's of the current IKE_SA.
+ * Current state of the IKE_SA
*/
- linked_list_t *child_sas;
+ ike_sa_state_t state;
/**
- * Current state of the IKE_SA
+ * Name of the connection used by this IKE_SA
*/
- ike_sa_state_t state;
+ char *name;
+
+ /**
+ * Address of local host
+ */
+ host_t *my_host;
+
+ /**
+ * Address of remote host
+ */
+ host_t *other_host;
+
+ /**
+ * Identification used for us
+ */
+ identification_t *my_id;
/**
- * Connection definition used for this IKE_SA
+ * Identification used for other
*/
- connection_t *connection;
+ identification_t *other_id;
/**
- * Policy definition used for this IKE_SA
+ * Linked List containing the child sa's of the current IKE_SA.
*/
- policy_t *policy;
+ linked_list_t *child_sas;
/**
* crypter for inbound traffic
@@ -208,7 +223,7 @@ struct private_ike_sa_t {
/**
* get the time of the latest traffic processed by the kernel
*/
-static time_t get_esp_time(private_ike_sa_t* this, bool inbound)
+static time_t get_kernel_time(private_ike_sa_t* this, bool inbound)
{
iterator_t *iterator;
child_sa_t *child_sa;
@@ -232,7 +247,7 @@ static time_t get_esp_time(private_ike_sa_t* this, bool inbound)
*/
static time_t get_time_inbound(private_ike_sa_t *this)
{
- return max(this->time_inbound, get_esp_time(this, TRUE));
+ return max(this->time_inbound, get_kernel_time(this, TRUE));
}
/**
@@ -240,9 +255,41 @@ static time_t get_time_inbound(private_ike_sa_t *this)
*/
static time_t get_time_outbound(private_ike_sa_t *this)
{
- return max(this->time_outbound, get_esp_time(this, FALSE));
+ return max(this->time_outbound, get_kernel_time(this, FALSE));
}
+/**
+ * Implementation of ike_sa_t.get_name.
+ */
+static char *get_name(private_ike_sa_t *this)
+{
+ return this->name;
+}
+
+/**
+ * Implementation of ike_sa_t.set_name.
+ */
+static void set_name(private_ike_sa_t *this, char* name)
+{
+ free(this->name);
+ this->name = strdup(name);
+}
+
+/**
+ * Implementation of ike_sa_t.get_my_host.
+ */
+static host_t *get_my_host(private_ike_sa_t *this)
+{
+ return this->my_host;
+}
+
+/**
+ * Implementation of ike_sa_t.get_other_host.
+ */
+static host_t *get_other_host(private_ike_sa_t *this)
+{
+ return this->other_host;
+}
/**
* Update connection host, as addresses may change (NAT)
@@ -278,53 +325,58 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
* packet or any authenticated UDP-encapsulated ESP packet can be
* used to detect that the IP address or the port has changed.
*/
- host_t *old_other = NULL;
iterator_t *iterator = NULL;
child_sa_t *child_sa = NULL;
- int my_changes, other_changes;
-
- my_changes = me->get_differences(me, this->connection->get_my_host(this->connection));
-
- old_other = this->connection->get_other_host(this->connection);
- other_changes = other->get_differences(other, old_other);
-
- if (!my_changes && !other_changes)
+ host_diff_t my_diff, other_diff;
+
+ if (this->my_host == NULL || this->other_host == NULL)
+ {
+ /* on first received message */
+ this->my_host = me->clone(me);
+ this->other_host = other->clone(other);
+ return;
+ }
+
+ my_diff = me->get_differences(me, this->my_host);
+ other_diff = other->get_differences(other, this->other_host);
+
+ if (!my_diff && !other_diff)
{
return;
}
- if (my_changes)
+ if (my_diff)
{
- this->connection->update_my_host(this->connection, me->clone(me));
+ this->my_host->destroy(this->my_host);
+ this->my_host = me->clone(me);
}
if (!this->nat_here)
{
/* update without restrictions if we are not NATted */
- if (other_changes)
+ if (other_diff)
{
- this->connection->update_other_host(this->connection, other->clone(other));
+ this->other_host->destroy(this->other_host);
+ this->other_host = other->clone(other);
}
}
else
{
/* if we are natted, only port may change */
- if (other_changes & HOST_DIFF_ADDR)
+ if (other_diff & HOST_DIFF_ADDR)
{
return;
}
- else if (other_changes & HOST_DIFF_PORT)
+ else if (other_diff & HOST_DIFF_PORT)
{
- old_other->set_port(old_other, other->get_port(other));
+ this->other_host->set_port(this->other_host, other->get_port(other));
}
}
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_sa->update_hosts(child_sa,
- this->connection->get_my_host(this->connection),
- this->connection->get_other_host(this->connection),
- my_changes, other_changes);
+ child_sa->update_hosts(child_sa, this->my_host, this->other_host,
+ my_diff, other_diff);
/* TODO: what to do if update fails? Delete CHILD_SA? */
}
iterator->destroy(iterator);
@@ -705,7 +757,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
else
{
/* check if message is trustworthy, and update connection information */
- if ((this->state == IKE_CREATED && this->connection) ||
+ if (this->state == IKE_CREATED ||
message->get_exchange_type(message) != IKE_SA_INIT)
{
update_hosts(this, message->get_destination(message),
@@ -727,26 +779,60 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
/**
* Implementation of ike_sa_t.initiate.
*/
-static status_t initiate(private_ike_sa_t *this, connection_t *connection)
+static status_t initiate(private_ike_sa_t *this,
+ connection_t *connection, policy_t *policy)
{
ike_sa_init_t *ike_sa_init;
- /* set connection and policy */
- this->connection = connection;
- this->policy = charon->policies->get_policy_by_name(charon->policies,
- this->connection->get_name(this->connection));
- if (this->policy == NULL)
- {
- this->logger->log(this->logger, ERROR,
- "no policy found for connection %s, aborting",
- connection->get_name(connection));
- return DESTROY_ME;
- }
+ set_name(this, connection->get_name(connection));
+
+ /* apply hosts from connection */
+ this->my_host = connection->get_my_host(connection);
+ this->my_host = this->my_host->clone(this->my_host);
+ this->other_host = connection->get_other_host(connection);
+ this->other_host = this->other_host->clone(this->other_host);
+
this->message_id_out = 1;
ike_sa_init = ike_sa_init_create(&this->public);
+ ike_sa_init->set_config(ike_sa_init, connection, policy);
return queue_transaction(this, (transaction_t*)ike_sa_init, TRUE);
}
+
+/**
+ * Implementation of ike_sa_t.acquire.
+ */
+static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
+{
+ /* - get TS from child with reqid
+ * - get a policy from TS
+ * - get connection from policy
+ */
+ switch (this->state)
+ {
+ case IKE_CREATED:
+ /* ike_sa_init */
+ break;
+ case IKE_CONNECTING:
+ case IKE_ESTABLISHED:
+ /* queue create_child_sa */
+ break;
+ case IKE_DELETING:
+ /* deny */
+ break;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of ike_sa_t.route.
+ */
+static status_t route(private_ike_sa_t *this, policy_t *policy)
+{
+ /* TODO: create CHILD_SA, add policy */
+ return FAILED;
+}
+
/**
* Implementation of ike_sa_t.send_dpd
*/
@@ -803,15 +889,12 @@ static void send_keepalive(private_ike_sa_t *this)
if (diff >= interval)
{
- host_t *me, *other;
packet_t *packet;
chunk_t data;
packet = packet_create();
- me = this->connection->get_my_host(this->connection);
- other = this->connection->get_other_host(this->connection);
- packet->set_source(packet, me->clone(me));
- packet->set_destination(packet, other->clone(other));
+ packet->set_source(packet, this->my_host->clone(this->my_host));
+ packet->set_destination(packet, this->other_host->clone(this->other_host));
data.ptr = malloc(1);
data.ptr[0] = 0xFF;
data.len = 1;
@@ -843,17 +926,11 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
mapping_find(ike_sa_state_m, state));
if (state == IKE_ESTABLISHED)
{
- host_t *my_host, *other_host;
- identification_t *my_id, *other_id;
- my_host = this->connection->get_my_host(this->connection);
- other_host = this->connection->get_other_host(this->connection);
- my_id = this->policy->get_my_id(this->policy);
- other_id = this->policy->get_other_id(this->policy);
this->logger->log(this->logger, AUDIT, "IKE_SA established: %s[%s]...%s[%s]",
- my_host->get_string(my_host),
- my_id->get_string(my_id),
- other_host->get_string(other_host),
- other_id->get_string(other_id));
+ this->my_host->get_string(this->my_host),
+ this->my_id->get_string(this->my_id),
+ this->other_host->get_string(this->other_host),
+ this->other_id->get_string(this->other_id));
send_dpd(this);
}
@@ -861,74 +938,75 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
}
/**
- * Implementation of protected_ike_sa_t.get_connection.
+ * Implementation of protected_ike_sa_t.get_prf.
*/
-static connection_t *get_connection(private_ike_sa_t *this)
+static prf_t *get_prf(private_ike_sa_t *this)
{
- return this->connection;
+ return this->prf;
}
/**
- * Implementation of protected_ike_sa_t.set_connection.
+ * Implementation of protected_ike_sa_t.get_prf.
*/
-static void set_connection(private_ike_sa_t *this,connection_t * connection)
+static prf_t *get_child_prf(private_ike_sa_t *this)
{
- this->connection = connection;
+ return this->child_prf;
}
/**
- * Implementation of protected_ike_sa_t.get_policy.
+ * Implementation of protected_ike_sa_t.get_prf_auth_i.
*/
-static policy_t *get_policy(private_ike_sa_t *this)
+static prf_t *get_prf_auth_i(private_ike_sa_t *this)
{
- return this->policy;
+ return this->prf_auth_i;
}
/**
- * Implementation of protected_ike_sa_t.set_policy.
+ * Implementation of protected_ike_sa_t.get_prf_auth_r.
*/
-static void set_policy(private_ike_sa_t *this,policy_t * policy)
+static prf_t *get_prf_auth_r(private_ike_sa_t *this)
{
- this->policy = policy;
+ return this->prf_auth_r;
}
/**
- * Implementation of protected_ike_sa_t.get_prf.
+ * Implementation of ike_sa_t.get_id.
*/
-static prf_t *get_prf(private_ike_sa_t *this)
+static ike_sa_id_t* get_id(private_ike_sa_t *this)
{
- return this->prf;
+ return this->ike_sa_id;
}
/**
- * Implementation of protected_ike_sa_t.get_prf.
+ * Implementation of ike_sa_t.get_my_id.
*/
-static prf_t *get_child_prf(private_ike_sa_t *this)
+static identification_t* get_my_id(private_ike_sa_t *this)
{
- return this->child_prf;
+ return this->my_id;
}
/**
- * Implementation of protected_ike_sa_t.get_prf_auth_i.
+ * Implementation of ike_sa_t.set_my_id.
*/
-static prf_t *get_prf_auth_i(private_ike_sa_t *this)
+static void set_my_id(private_ike_sa_t *this, identification_t *me)
{
- return this->prf_auth_i;
+ this->my_id = me;
}
/**
- * Implementation of protected_ike_sa_t.get_prf_auth_r.
+ * Implementation of ike_sa_t.get_other_id.
*/
-static prf_t *get_prf_auth_r(private_ike_sa_t *this)
+static identification_t* get_other_id(private_ike_sa_t *this)
{
- return this->prf_auth_r;
+ return this->other_id;
}
+
/**
- * Implementation of ike_sa_t.get_id.
+ * Implementation of ike_sa_t.set_other_id.
*/
-static ike_sa_id_t* get_id(private_ike_sa_t *this)
+static void set_other_id(private_ike_sa_t *this, identification_t *other)
{
- return this->ike_sa_id;
+ this->other_id = other;
}
/**
@@ -1201,55 +1279,41 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name)
{
iterator_t *iterator;
child_sa_t *child_sa;
- host_t *my_host, *other_host;
- identification_t *my_id = NULL, *other_id = NULL;
+ char *my_host, *other_host, *my_id, *other_id;
- /* only log if name == NULL or name == connection_name */
- if (name)
+ if (name == NULL || streq(name, this->name))
{
- if (streq(this->connection->get_name(this->connection), name))
+ if (logger == NULL)
{
- return;
+ logger = this->logger;
}
+
+ my_host = this->my_host ?
+ this->my_host->get_string(this->my_host) : "(unknown)";
+ other_host = this->other_host ?
+ this->other_host->get_string(this->other_host) : "(unknown)";
+ my_id = this->my_id ?
+ this->my_id->get_string(this->my_id) : "(unknown)";
+ other_id = this->other_id ?
+ this->other_id->get_string(this->other_id) : "(unknown)";
+
+ logger->log(logger, CONTROL|LEVEL1,
+ " \"%s\": IKE_SA in state %s, SPIs: 0x%.16llx 0x%.16llx",
+ this->name,
+ mapping_find(ike_sa_state_m, this->state),
+ this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
+ this->ike_sa_id->get_responder_spi(this->ike_sa_id));
+ logger->log(logger, CONTROL, " \"%s\": %s[%s]...%s[%s]",
+ this->name, my_host, my_id, other_host, other_id);
+
+ iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+ while (iterator->has_next(iterator))
+ {
+ iterator->current(iterator, (void**)&child_sa);
+ child_sa->log_status(child_sa, logger, this->name);
+ }
+ iterator->destroy(iterator);
}
- my_host = this->connection->get_my_host(this->connection);
- other_host = this->connection->get_other_host(this->connection);
-
- /* use policy information, if available */
- if (this->policy)
- {
- my_id = this->policy->get_my_id(this->policy);
- other_id = this->policy->get_other_id(this->policy);
- name = this->policy->get_name(this->policy);
- }
- else
- {
- name = this->connection->get_name(this->connection);
- }
-
- if (logger == NULL)
- {
- logger = this->logger;
- }
- logger->log(logger, CONTROL|LEVEL1, " \"%s\": IKE_SA in state %s, SPIs: 0x%.16llx 0x%.16llx",
- name,
- mapping_find(ike_sa_state_m, this->state),
- this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
- this->ike_sa_id->get_responder_spi(this->ike_sa_id));
- logger->log(logger, CONTROL, " \"%s\": %s[%s]...%s[%s]",
- name,
- my_host->get_string(my_host),
- my_id ? my_id->get_string(my_id) : "(unknown)",
- other_host->get_string(other_host),
- other_id ? other_id->get_string(other_id) : "(unknown)");
-
- iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
- while (iterator->has_next(iterator))
- {
- iterator->current(iterator, (void**)&child_sa);
- child_sa->log_status(child_sa, logger, name);
- }
- iterator->destroy(iterator);
}
/**
@@ -1313,6 +1377,7 @@ static void destroy(private_ike_sa_t *this)
{
child_sa_t *child_sa;
transaction_t *transaction;
+ char *my_host, *other_host, *my_id, *other_id;
this->logger->log(this->logger, CONTROL|LEVEL2, "going to destroy IKE SA %llu:%llu, role %s",
this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
@@ -1336,73 +1401,38 @@ static void destroy(private_ike_sa_t *this)
transaction->destroy(transaction);
}
this->transaction_queue->destroy(this->transaction_queue);
- if (this->transaction_in)
- {
- this->transaction_in->destroy(this->transaction_in);
- }
- if (this->transaction_in_next)
- {
- this->transaction_in_next->destroy(this->transaction_in_next);
- }
- if (this->transaction_out)
- {
- this->transaction_out->destroy(this->transaction_out);
- }
- if (this->crypter_in)
- {
- this->crypter_in->destroy(this->crypter_in);
- }
- if (this->crypter_out)
- {
- this->crypter_out->destroy(this->crypter_out);
- }
- if (this->signer_in)
- {
- this->signer_in->destroy(this->signer_in);
- }
- if (this->signer_out)
- {
- this->signer_out->destroy(this->signer_out);
- }
- if (this->prf)
- {
- this->prf->destroy(this->prf);
- }
- if (this->child_prf)
- {
- this->child_prf->destroy(this->child_prf);
- }
- if (this->prf_auth_i)
- {
- this->prf_auth_i->destroy(this->prf_auth_i);
- }
- if (this->prf_auth_r)
- {
- this->prf_auth_r->destroy(this->prf_auth_r);
- }
- if (this->connection)
- {
- host_t *my_host, *other_host;
- identification_t *my_id = NULL, *other_id = NULL;
- my_host = this->connection->get_my_host(this->connection);
- other_host = this->connection->get_other_host(this->connection);
- if (this->policy)
- {
- my_id = this->policy->get_my_id(this->policy);
- other_id = this->policy->get_other_id(this->policy);
- }
-
- this->logger->log(this->logger, AUDIT, "IKE_SA deleted between %s[%s]...%s[%s]",
- my_host->get_string(my_host),
- my_id ? my_id->get_string(my_id) : "(unknown)",
- other_host->get_string(other_host),
- other_id ? other_id->get_string(other_id) : "(unknown)");
- this->connection->destroy(this->connection);
- }
- if (this->policy)
- {
- this->policy->destroy(this->policy);
- }
+
+ DESTROY_IF(this->transaction_in);
+ DESTROY_IF(this->transaction_in_next);
+ DESTROY_IF(this->transaction_out);
+ DESTROY_IF(this->crypter_in);
+ DESTROY_IF(this->crypter_out);
+ DESTROY_IF(this->signer_in);
+ DESTROY_IF(this->signer_out);
+ DESTROY_IF(this->prf);
+ DESTROY_IF(this->child_prf);
+ DESTROY_IF(this->prf_auth_i);
+ DESTROY_IF(this->prf_auth_r);
+
+ my_host = this->my_host ?
+ this->my_host->get_string(this->my_host) : "(unknown)";
+ other_host = this->other_host ?
+ this->other_host->get_string(this->other_host) : "(unknown)";
+ my_id = this->my_id ?
+ this->my_id->get_string(this->my_id) : "(unknown)";
+ other_id = this->other_id ?
+ this->other_id->get_string(this->other_id) : "(unknown)";
+
+ this->logger->log(this->logger, AUDIT,
+ "IKE_SA deleted between %s[%s]...%s[%s]",
+ my_host, my_id, other_host, other_id);
+
+ DESTROY_IF(this->my_host);
+ DESTROY_IF(this->other_host);
+ DESTROY_IF(this->my_id);
+ DESTROY_IF(this->other_id);
+
+ free(this->name);
this->ike_sa_id->destroy(this->ike_sa_id);
free(this);
}
@@ -1417,11 +1447,20 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
/* Public functions */
this->public.get_state = (ike_sa_state_t(*)(ike_sa_t*)) get_state;
this->public.set_state = (void(*)(ike_sa_t*,ike_sa_state_t)) set_state;
+ this->public.get_name = (char*(*)(ike_sa_t*))get_name;
+ this->public.set_name = (void(*)(ike_sa_t*,char*))set_name;
this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
- this->public.initiate = (status_t(*)(ike_sa_t*,connection_t*)) initiate;
+ this->public.initiate = (status_t(*)(ike_sa_t*,connection_t*,policy_t*)) initiate;
+ this->public.route = (status_t(*)(ike_sa_t*,policy_t*)) route;
+ this->public.acquire = (status_t(*)(ike_sa_t*,u_int32_t)) acquire;
this->public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
+ this->public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host;
+ this->public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host;
+ this->public.get_my_id = (identification_t*(*)(ike_sa_t*)) get_my_id;
+ this->public.set_my_id = (void(*)(ike_sa_t*,identification_t*)) set_my_id;
+ this->public.get_other_id = (identification_t*(*)(ike_sa_t*)) get_other_id;
+ this->public.set_other_id = (void(*)(ike_sa_t*,identification_t*)) set_other_id;
this->public.get_next_message_id = (u_int32_t(*)(ike_sa_t*)) get_next_message_id;
- this->public.get_connection = (connection_t*(*)(ike_sa_t*)) get_connection;
this->public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request;
this->public.log_status = (void (*) (ike_sa_t*,logger_t*,char*))log_status;
this->public.delete = (status_t(*)(ike_sa_t*))delete_;
@@ -1432,10 +1471,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.get_child_prf = (prf_t *(*) (ike_sa_t *)) get_child_prf;
this->public.get_prf_auth_i = (prf_t *(*) (ike_sa_t *)) get_prf_auth_i;
this->public.get_prf_auth_r = (prf_t *(*) (ike_sa_t *)) get_prf_auth_r;
- this->public.set_connection = (void (*) (ike_sa_t *,connection_t *)) set_connection;
- this->public.get_connection = (connection_t *(*) (ike_sa_t *)) get_connection;
- this->public.set_policy = (void (*) (ike_sa_t *,policy_t *)) set_policy;
- this->public.get_policy = (policy_t *(*) (ike_sa_t *)) get_policy;
this->public.build_transforms = (status_t (*) (ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t,bool)) build_transforms;
this->public.add_child_sa = (void (*) (ike_sa_t*,child_sa_t*)) add_child_sa;
this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa;
@@ -1448,7 +1483,12 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
/* initialize private fields */
this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+ this->name = strdup("(uninitialized)");
this->child_sas = linked_list_create();
+ this->my_host = NULL;
+ this->other_host = NULL;
+ this->my_id = NULL;
+ this->other_id = NULL;
this->crypter_in = NULL;
this->crypter_out = NULL;
this->signer_in = NULL;
@@ -1457,8 +1497,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->prf_auth_i = NULL;
this->prf_auth_r = NULL;
this->child_prf = NULL;
- this->connection = NULL;
- this->policy = NULL;
this->nat_here = FALSE;
this->nat_there = FALSE;
this->transaction_queue = linked_list_create();
diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h
index ab94505fd..f593e382a 100644
--- a/src/charon/sa/ike_sa.h
+++ b/src/charon/sa/ike_sa.h
@@ -152,20 +152,115 @@ struct ike_sa_t {
* @param state state to set for the IKE_SA
*/
void (*set_state) (ike_sa_t *this, ike_sa_state_t ike_sa);
+
+ /**
+ * @brief Get the name of the connection this IKE_SA uses.
+ *
+ * @param this calling object
+ * @return name
+ */
+ char* (*get_name) (ike_sa_t *this);
+
+ /**
+ * @brief Set the name of the connection this IKE_SA uses.
+ *
+ * @param this calling object
+ * @param name name, gets cloned
+ */
+ void (*set_name) (ike_sa_t *this, char* name);
+
+ /**
+ * @brief Get the own host address.
+ *
+ * @param this calling object
+ * @return host address
+ */
+ host_t* (*get_my_host) (ike_sa_t *this);
+
+ /**
+ * @brief Get the other peers host address.
+ *
+ * @param this calling object
+ * @return host address
+ */
+ host_t* (*get_other_host) (ike_sa_t *this);
+
+ /**
+ * @brief Get the own identification.
+ *
+ * @param this calling object
+ * @return identification
+ */
+ identification_t* (*get_my_id) (ike_sa_t *this);
+
+ /**
+ * @brief Set the own identification.
+ *
+ * @param this calling object
+ * @param me identification
+ */
+ void (*set_my_id) (ike_sa_t *this, identification_t *me);
+
+ /**
+ * @brief Get the other peers identification.
+ *
+ * @param this calling object
+ * @return identification
+ */
+ identification_t* (*get_other_id) (ike_sa_t *this);
+
+ /**
+ * @brief Set the other peers identification.
+ *
+ * @param this calling object
+ * @param other identification
+ */
+ void (*set_other_id) (ike_sa_t *this, identification_t *other);
/**
* @brief Initiate a new connection.
*
- * The connection_t object is owned by the IKE_SA after the call, so
+ * The policy/connection is owned by the IKE_SA after the call, so
* do not modify or destroy it.
*
* @param this calling object
* @param connection connection to initiate
+ * @param policy policy to set up
+ * @return
+ * - SUCCESS if initialization started
+ * - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
+ */
+ status_t (*initiate) (ike_sa_t *this, connection_t *connection, policy_t *policy);
+
+ /**
+ * @brief Route a policy in the kernel.
+ *
+ * Installs the policies in the kernel. If traffic matches,
+ * the kernel requests connection setup from the IKE_SA via acquire().
+ * The policy is owned by the IKE_SA after the call, so
+ * do not modify or destroy it.
+ *
+ * @param this calling object
+ * @param policy policy to route
+ * @return
+ * - SUCCESS if initialization started
+ * - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
+ */
+ status_t (*route) (ike_sa_t *this, policy_t *policy);
+
+ /**
+ * @brief Acquire connection setup for a policy.
+ *
+ * If an installed policy raises an acquire, the kernel calls
+ * this function to establsh the CHILD_SA (and maybe the IKE_SA).
+ *
+ * @param this calling object
+ * @param reqid reqid of the CHILD_SA the policy belongs to.
* @return
* - SUCCESS if initialization started
* - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
*/
- status_t (*initiate) (ike_sa_t *this, connection_t *connection);
+ status_t (*acquire) (ike_sa_t *this, u_int32_t reqid);
/**
* @brief Initiates the deletion of an IKE_SA.
@@ -280,38 +375,6 @@ struct ike_sa_t {
* @param name name of the connection
*/
void (*log_status) (ike_sa_t *this, logger_t *logger, char *name);
-
- /**
- * @brief Get the internal stored connection_t object.
- *
- * @param this calling object
- * @return pointer to the internal stored connection_t object
- */
- connection_t *(*get_connection) (ike_sa_t *this);
-
- /**
- * @brief Set the internal connection object.
- *
- * @param this calling object
- * @param connection object of type connection_t
- */
- void (*set_connection) (ike_sa_t *this, connection_t *connection);
-
- /**
- * @brief Get the internal stored policy object.
- *
- * @param this calling object
- * @return pointer to the internal stored policy_t object
- */
- policy_t *(*get_policy) (ike_sa_t *this);
-
- /**
- * @brief Set the internal policy_t object.
- *
- * @param this calling object
- * @param policy object of type policy_t
- */
- void (*set_policy) (ike_sa_t *this, policy_t *policy);
/**
* @brief Derive all keys and create the transforms for IKE communication.
diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c
index e6a738d50..b0822acb7 100644
--- a/src/charon/sa/ike_sa_manager.c
+++ b/src/charon/sa/ike_sa_manager.c
@@ -600,19 +600,15 @@ linked_list_t *get_ike_sa_list_by_name(private_ike_sa_manager_t* this, const cha
{
linked_list_t *list;
iterator_t *iterator;
+ ike_sa_entry_t *entry;
pthread_mutex_lock(&(this->mutex));
list = linked_list_create();
iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
- while (iterator->has_next(iterator))
+ while (iterator->iterate(iterator, (void**)&entry))
{
- ike_sa_entry_t *entry;
- connection_t *connection;
-
- iterator->current(iterator, (void**)&entry);
- connection = entry->ike_sa->get_connection(entry->ike_sa);
- if (strcmp(name, connection->get_name(connection)) == 0)
+ if (strcmp(name, entry->ike_sa->get_name(entry->ike_sa)) == 0)
{
list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id));
}
diff --git a/src/charon/sa/transactions/create_child_sa.c b/src/charon/sa/transactions/create_child_sa.c
index 14d1dab70..4c29cabd1 100644
--- a/src/charon/sa/transactions/create_child_sa.c
+++ b/src/charon/sa/transactions/create_child_sa.c
@@ -70,11 +70,6 @@ struct private_create_child_sa_t {
u_int32_t rekey_spi;
/**
- * connection of IKE_SA
- */
- connection_t *connection;
-
- /**
* policy definition used
*/
policy_t *policy;
@@ -152,6 +147,14 @@ static u_int32_t requested(private_create_child_sa_t *this)
}
/**
+ * Implementation of create_child_sa_t.set_policy.
+ */
+static void set_policy(private_create_child_sa_t *this, policy_t *policy)
+{
+ this->policy = policy;
+}
+
+/**
* Implementation of create_child_sa_t.rekeys_child.
*/
static void rekeys_child(private_create_child_sa_t *this, child_sa_t *child_sa)
@@ -169,6 +172,22 @@ static void cancel(private_create_child_sa_t *this)
}
/**
+ * destroy a list of traffic selectors
+ */
+static void destroy_ts_list(linked_list_t *list)
+{
+ if (list)
+ {
+ traffic_selector_t *ts;
+ while (list->remove_last(list, (void**)&ts) == SUCCESS)
+ {
+ ts->destroy(ts);
+ }
+ list->destroy(list);
+ }
+}
+
+/**
* Implementation of transaction_t.get_request.
*/
static status_t get_request(private_create_child_sa_t *this, message_t **result)
@@ -176,6 +195,13 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
message_t *request;
host_t *me, *other;
+ /* check if we already have built a message (retransmission) */
+ if (this->message)
+ {
+ *result = this->message;
+ return SUCCESS;
+ }
+
/* check if we are not already rekeying */
if (this->rekeyed_sa)
{
@@ -195,17 +221,8 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
this->rekeyed_sa->set_state(this->rekeyed_sa, CHILD_REKEYING);
}
- /* check if we already have built a message (retransmission) */
- if (this->message)
- {
- *result = this->message;
- return SUCCESS;
- }
-
- this->connection = this->ike_sa->get_connection(this->ike_sa);
- me = this->connection->get_my_host(this->connection);
- other = this->connection->get_other_host(this->connection);
- this->policy = this->ike_sa->get_policy(this->ike_sa);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
/* build the request */
request = message_create();
@@ -223,9 +240,31 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
bool use_natt;
u_int32_t reqid = 0;
+ /* get a policy, if we are rekeying */
if (this->rekeyed_sa)
{
+ linked_list_t *my_ts, *other_ts;
+ identification_t *my_id, *other_id;
+
+ my_ts = this->rekeyed_sa->get_my_traffic_selectors(this->rekeyed_sa);
+ other_ts = this->rekeyed_sa->get_other_traffic_selectors(this->rekeyed_sa);
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+
+ this->policy = charon->policies->get_policy(charon->policies,
+ my_id, other_id,
+ my_ts, other_ts,
+ me, other);
+
reqid = this->rekeyed_sa->get_reqid(this->rekeyed_sa);
+
+ if (this->policy == NULL)
+ {
+ this->logger->log(this->logger, ERROR,
+ "no policy found to rekey CHILD_SA with reqid %d",
+ reqid);
+ return FAILED;
+ }
}
proposals = this->policy->get_proposals(this->policy);
@@ -261,8 +300,9 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
linked_list_t *ts_list;
ts_payload_t *ts_payload;
- ts_list = this->policy->get_my_traffic_selectors(this->policy);
+ ts_list = this->policy->get_my_traffic_selectors(this->policy, me);
ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list);
+ destroy_ts_list(ts_list);
request->add_payload(request, (payload_t*)ts_payload);
}
@@ -270,8 +310,9 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
linked_list_t *ts_list;
ts_payload_t *ts_payload;
- ts_list = this->policy->get_other_traffic_selectors(this->policy);
+ ts_list = this->policy->get_other_traffic_selectors(this->policy, other);
ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list);
+ destroy_ts_list(ts_list);
request->add_payload(request, (payload_t*)ts_payload);
}
@@ -439,22 +480,6 @@ static status_t install_child_sa(private_create_child_sa_t *this, bool initiator
}
/**
- * destroy a list of traffic selectors
- */
-static void destroy_ts_list(linked_list_t *list)
-{
- if (list)
- {
- traffic_selector_t *ts;
- while (list->remove_last(list, (void**)&ts) == SUCCESS)
- {
- ts->destroy(ts);
- }
- list->destroy(list);
- }
-}
-
-/**
* Implementation of transaction_t.get_response.
*/
static status_t get_response(private_create_child_sa_t *this, message_t *request,
@@ -477,10 +502,8 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
return SUCCESS;
}
- this->connection = this->ike_sa->get_connection(this->ike_sa);
- me = this->connection->get_my_host(this->connection);
- other = this->connection->get_other_host(this->connection);
- this->policy = this->ike_sa->get_policy(this->ike_sa);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
this->message_id = request->get_message_id(request);
/* set up response */
@@ -573,16 +596,35 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
nonce_response->set_nonce(nonce_response, this->nonce_r);
}
- { /* process traffic selectors for other */
- linked_list_t *ts_received = tsi_request->get_traffic_selectors(tsi_request);
- this->tsi = this->policy->select_other_traffic_selectors(this->policy, ts_received);
- destroy_ts_list(ts_received);
- }
-
- { /* process traffic selectors for us */
- linked_list_t *ts_received = ts_received = tsr_request->get_traffic_selectors(tsr_request);
- this->tsr = this->policy->select_my_traffic_selectors(this->policy, ts_received);
- destroy_ts_list(ts_received);
+ { /* get a policy and process traffic selectors */
+ identification_t *my_id, *other_id;
+ linked_list_t *my_ts, *other_ts;
+
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+
+ my_ts = tsr_request->get_traffic_selectors(tsr_request);
+ other_ts = tsi_request->get_traffic_selectors(tsi_request);
+
+ this->policy = charon->policies->get_policy(charon->policies,
+ my_id, other_id,
+ my_ts, other_ts,
+ me, other);
+ if (this->policy)
+ {
+ this->tsr = this->policy->select_my_traffic_selectors(this->policy, my_ts, me);
+ this->tsi = this->policy->select_other_traffic_selectors(this->policy, other_ts, other);
+ }
+ destroy_ts_list(my_ts);
+ destroy_ts_list(other_ts);
+
+ if (this->policy == NULL)
+ {
+ this->logger->log(this->logger, AUDIT,
+ "no acceptable policy found, adding TS_UNACCEPTABLE notify");
+ build_notify(TS_UNACCEPTABLE, CHUNK_INITIALIZER, response, TRUE);
+ return FAILED;
+ }
}
{ /* process SA payload */
@@ -705,8 +747,8 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
return FAILED;
}
- me = this->connection->get_my_host(this->connection);
- other = this->connection->get_other_host(this->connection);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
/* Iterate over all payloads to collect them */
payloads = response->get_payload_iterator(response);
@@ -761,13 +803,13 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
{ /* process traffic selectors for us */
linked_list_t *ts_received = tsi_payload->get_traffic_selectors(tsi_payload);
- this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received);
+ this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received, me);
destroy_ts_list(ts_received);
}
{ /* process traffic selectors for other */
linked_list_t *ts_received = tsr_payload->get_traffic_selectors(tsr_payload);
- this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received);
+ this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received, other);
destroy_ts_list(ts_received);
}
@@ -790,8 +832,7 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
this->tsi->get_count(this->tsi) == 0 ||
this->tsr->get_count(this->tsr) == 0)
{
- this->logger->log(this->logger, AUDIT,
- "CHILD_SA creation failed");
+ this->logger->log(this->logger, AUDIT, "CHILD_SA creation failed");
return FAILED;
}
new_child = this->child_sa;
@@ -863,18 +904,10 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
*/
static void destroy(private_create_child_sa_t *this)
{
- if (this->message)
- {
- this->message->destroy(this->message);
- }
- if (this->proposal)
- {
- this->proposal->destroy(this->proposal);
- }
- if (this->child_sa)
- {
- this->child_sa->destroy(this->child_sa);
- }
+ DESTROY_IF(this->message);
+ DESTROY_IF(this->proposal);
+ DESTROY_IF(this->child_sa);
+ DESTROY_IF(this->policy);
destroy_ts_list(this->tsi);
destroy_ts_list(this->tsr);
chunk_free(&this->nonce_i);
@@ -900,6 +933,7 @@ create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa)
this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
/* public functions */
+ this->public.set_policy = (void(*)(create_child_sa_t*,policy_t*))set_policy;
this->public.rekeys_child = (void(*)(create_child_sa_t*,child_sa_t*))rekeys_child;
this->public.cancel = (void(*)(create_child_sa_t*))cancel;
@@ -916,6 +950,7 @@ create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa)
this->rekeyed_sa = NULL;
this->lost = FALSE;
this->proposal = NULL;
+ this->policy = NULL;
this->tsi = NULL;
this->tsr = NULL;
this->randomizer = randomizer_create();
diff --git a/src/charon/sa/transactions/create_child_sa.h b/src/charon/sa/transactions/create_child_sa.h
index df7a64fde..d45bfcc6b 100644
--- a/src/charon/sa/transactions/create_child_sa.h
+++ b/src/charon/sa/transactions/create_child_sa.h
@@ -33,6 +33,10 @@ typedef struct create_child_sa_t create_child_sa_t;
/**
* @brief A transaction to create a new or rekey an existing CHILD_SA.
*
+ * If the CHILD_SA is intended to create a new CHILD_SA, set the policy
+ * with set_policy(). If it is intended to rekey an existing CHILD_SA,
+ * set the appropriate CHILD_SA with rekeys_child().
+ *
* Rekeying of an CHILD_SA works the same way as creating a new one,
* but includes an additional REKEY_SA notify and deletes the old
* one (in a separate transaction).
@@ -68,10 +72,15 @@ struct create_child_sa_t {
transaction_t transaction;
/**
- * @brief Set the CHILD_SA which gets rekeyed by the new one.
+ * @brief Set the policy to use for creating a new CHILD_SA.
*
- * If this transaction is used for rekeying, set the inbound
- * SPI of the CHILD_SA which the new CHILD_SA rekeys.
+ * @param this calling object
+ * @param policy policy for CHILD_SA
+ */
+ void (*set_policy) (create_child_sa_t* this, policy_t *policy);
+
+ /**
+ * @brief Set the CHILD_SA which gets rekeyed by the new one.
*
* @param this calling object
* @param child_sa CHILD_SA to rekey
@@ -79,9 +88,9 @@ struct create_child_sa_t {
void (*rekeys_child) (create_child_sa_t* this, child_sa_t *child_sa);
/**
- * @brief Cancel a rekeying request.
+ * @brief Cancel the request.
*
- * Cancelling a rekeying request will set a flag in the transaction. When
+ * Cancelling the request will set a flag in the transaction. When
* the response for the transaction is received, the created CHILD_SA
* gets deleted afterwards.
*
diff --git a/src/charon/sa/transactions/dead_peer_detection.c b/src/charon/sa/transactions/dead_peer_detection.c
index c7f5db604..a0e687c32 100644
--- a/src/charon/sa/transactions/dead_peer_detection.c
+++ b/src/charon/sa/transactions/dead_peer_detection.c
@@ -85,7 +85,6 @@ static u_int32_t requested(private_dead_peer_detection_t *this)
static status_t get_request(private_dead_peer_detection_t *this, message_t **result)
{
message_t *request;
- connection_t *connection;
host_t *me, *other;
/* check if we already have built a message (retransmission) */
@@ -95,9 +94,8 @@ static status_t get_request(private_dead_peer_detection_t *this, message_t **res
return SUCCESS;
}
- connection = this->ike_sa->get_connection(this->ike_sa);
- me = connection->get_my_host(connection);
- other = connection->get_other_host(connection);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
/* build the request */
request = message_create();
@@ -124,7 +122,6 @@ static status_t get_response(private_dead_peer_detection_t *this, message_t *req
{
host_t *me, *other;
message_t *response;
- connection_t *connection;
/* check if we already have built a response (retransmission) */
if (this->message)
@@ -133,9 +130,8 @@ static status_t get_response(private_dead_peer_detection_t *this, message_t *req
return SUCCESS;
}
- connection = this->ike_sa->get_connection(this->ike_sa);
- me = connection->get_my_host(connection);
- other = connection->get_other_host(connection);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
this->message_id = request->get_message_id(request);
/* set up response */
@@ -167,10 +163,7 @@ static status_t conclude(private_dead_peer_detection_t *this, message_t *respons
*/
static void destroy(private_dead_peer_detection_t *this)
{
- if (this->message)
- {
- this->message->destroy(this->message);
- }
+ DESTROY_IF(this->message);
free(this);
}
diff --git a/src/charon/sa/transactions/delete_child_sa.c b/src/charon/sa/transactions/delete_child_sa.c
index e8ca4bbae..f8399628b 100644
--- a/src/charon/sa/transactions/delete_child_sa.c
+++ b/src/charon/sa/transactions/delete_child_sa.c
@@ -100,7 +100,6 @@ static void set_child_sa(private_delete_child_sa_t *this, child_sa_t *child_sa)
static status_t get_request(private_delete_child_sa_t *this, message_t **result)
{
message_t *request;
- connection_t *connection;
host_t *me, *other;
/* check if we already have built a message (retransmission) */
@@ -110,9 +109,8 @@ static status_t get_request(private_delete_child_sa_t *this, message_t **result)
return SUCCESS;
}
- connection = this->ike_sa->get_connection(this->ike_sa);
- me = connection->get_my_host(connection);
- other = connection->get_other_host(connection);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
/* build the request */
request = message_create();
@@ -228,7 +226,6 @@ static status_t get_response(private_delete_child_sa_t *this, message_t *request
host_t *me, *other;
message_t *response;
iterator_t *payloads;
- connection_t *connection;
/* check if we already have built a response (retransmission) */
if (this->message)
@@ -237,9 +234,8 @@ static status_t get_response(private_delete_child_sa_t *this, message_t *request
return SUCCESS;
}
- connection = this->ike_sa->get_connection(this->ike_sa);
- me = connection->get_my_host(connection);
- other = connection->get_other_host(connection);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
this->message_id = request->get_message_id(request);
/* set up response */
@@ -335,10 +331,7 @@ static status_t conclude(private_delete_child_sa_t *this, message_t *response,
*/
static void destroy(private_delete_child_sa_t *this)
{
- if (this->message)
- {
- this->message->destroy(this->message);
- }
+ DESTROY_IF(this->message);
free(this);
}
diff --git a/src/charon/sa/transactions/delete_ike_sa.c b/src/charon/sa/transactions/delete_ike_sa.c
index 95f9fc654..3ab89a45c 100644
--- a/src/charon/sa/transactions/delete_ike_sa.c
+++ b/src/charon/sa/transactions/delete_ike_sa.c
@@ -86,7 +86,6 @@ static u_int32_t requested(private_delete_ike_sa_t *this)
static status_t get_request(private_delete_ike_sa_t *this, message_t **result)
{
message_t *request;
- connection_t *connection;
host_t *me, *other;
delete_payload_t *delete_payload;
@@ -97,9 +96,8 @@ static status_t get_request(private_delete_ike_sa_t *this, message_t **result)
return SUCCESS;
}
- connection = this->ike_sa->get_connection(this->ike_sa);
- me = connection->get_my_host(connection);
- other = connection->get_other_host(connection);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
/* build the request */
request = message_create();
@@ -134,7 +132,6 @@ static status_t get_response(private_delete_ike_sa_t *this, message_t *request,
message_t *response;
iterator_t *payloads;
delete_payload_t *delete_request = NULL;
- connection_t *connection;
/* check if we already have built a response (retransmission)
* this only happens in special simultanous transaction cases,
@@ -145,9 +142,8 @@ static status_t get_response(private_delete_ike_sa_t *this, message_t *request,
return SUCCESS;
}
- connection = this->ike_sa->get_connection(this->ike_sa);
- me = connection->get_my_host(connection);
- other = connection->get_other_host(connection);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
this->message_id = request->get_message_id(request);
/* set up response */
@@ -240,10 +236,7 @@ static status_t conclude(private_delete_ike_sa_t *this, message_t *response,
*/
static void destroy(private_delete_ike_sa_t *this)
{
- if (this->message)
- {
- this->message->destroy(this->message);
- }
+ DESTROY_IF(this->message);
free(this);
}
diff --git a/src/charon/sa/transactions/ike_auth.c b/src/charon/sa/transactions/ike_auth.c
index 53ba6205c..2bf12f754 100644
--- a/src/charon/sa/transactions/ike_auth.c
+++ b/src/charon/sa/transactions/ike_auth.c
@@ -90,12 +90,12 @@ struct private_ike_auth_t {
chunk_t init_response;
/**
- * connection definition used
+ * connection definition used for IKE_SA setup
*/
connection_t *connection;
/**
- * policy definition used
+ * policy definition used CHILD_SA creation
*/
policy_t *policy;
@@ -147,6 +147,16 @@ static u_int32_t requested(private_ike_auth_t *this)
}
/**
+ * Implementation of transaction_t.set_config.
+ */
+static void set_config(private_ike_auth_t *this,
+ connection_t *connection, policy_t *policy)
+{
+ this->connection = connection;
+ this->policy = policy;
+}
+
+/**
* Implementation of transaction_t.set_nonces.
*/
static void set_nonces(private_ike_auth_t *this, chunk_t nonce_i, chunk_t nonce_r)
@@ -165,6 +175,23 @@ static void set_init_messages(private_ike_auth_t *this, chunk_t init_request, ch
}
/**
+ * destroy a list of traffic selectors
+ */
+static void destroy_ts_list(linked_list_t *list)
+{
+ if (list)
+ {
+ traffic_selector_t *ts;
+
+ while (list->remove_last(list, (void**)&ts) == SUCCESS)
+ {
+ ts->destroy(ts);
+ }
+ list->destroy(list);
+ }
+}
+
+/**
* Implementation of transaction_t.get_request.
*/
static status_t get_request(private_ike_auth_t *this, message_t **result)
@@ -181,10 +208,8 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
return SUCCESS;
}
- this->connection = this->ike_sa->get_connection(this->ike_sa);
- me = this->connection->get_my_host(this->connection);
- other = this->connection->get_other_host(this->connection);
- this->policy = this->ike_sa->get_policy(this->ike_sa);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
my_id = this->policy->get_my_id(this->policy);
other_id = this->policy->get_other_id(this->policy);
@@ -203,6 +228,7 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
{ /* build ID payload */
my_id_payload = id_payload_create_from_identification(TRUE, my_id);
request->add_payload(request, (payload_t*)my_id_payload);
+ this->ike_sa->set_my_id(this->ike_sa, my_id->clone(my_id));
}
{ /* TODO: build certreq payload */
@@ -239,9 +265,11 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
{ /* build auth payload */
authenticator_t *authenticator;
auth_payload_t *auth_payload;
+ auth_method_t auth_method;
status_t status;
-
- authenticator = authenticator_create(this->ike_sa);
+
+ auth_method = this->connection->get_auth_method(this->connection);
+ authenticator = authenticator_create(this->ike_sa, auth_method);
status = authenticator->compute_auth_data(authenticator, &auth_payload,
this->init_request, this->nonce_r, my_id_payload, TRUE);
authenticator->destroy(authenticator);
@@ -278,8 +306,9 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
linked_list_t *ts_list;
ts_payload_t *ts_payload;
- ts_list = this->policy->get_my_traffic_selectors(this->policy);
+ ts_list = this->policy->get_my_traffic_selectors(this->policy, me);
ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list);
+ destroy_ts_list(ts_list);
request->add_payload(request, (payload_t*)ts_payload);
}
@@ -288,8 +317,9 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
linked_list_t *ts_list;
ts_payload_t *ts_payload;
- ts_list = this->policy->get_other_traffic_selectors(this->policy);
+ ts_list = this->policy->get_other_traffic_selectors(this->policy, other);
ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list);
+ destroy_ts_list(ts_list);
request->add_payload(request, (payload_t*)ts_payload);
}
@@ -465,23 +495,6 @@ static status_t install_child_sa(private_ike_auth_t *this, bool initiator)
}
/**
- * destroy a list of traffic selectors
- */
-static void destroy_ts_list(linked_list_t *list)
-{
- if (list)
- {
- traffic_selector_t *ts;
-
- while (list->remove_last(list, (void**)&ts) == SUCCESS)
- {
- ts->destroy(ts);
- }
- list->destroy(list);
- }
-}
-
-/**
* Implementation of transaction_t.get_response.
*/
static status_t get_response(private_ike_auth_t *this, message_t *request,
@@ -508,9 +521,8 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
return SUCCESS;
}
- this->connection = this->ike_sa->get_connection(this->ike_sa);
- me = this->connection->get_my_host(this->connection);
- other = this->connection->get_other_host(this->connection);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
this->message_id = request->get_message_id(request);
/* set up response */
@@ -607,13 +619,32 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
{
my_id = identification_create_from_encoding(ID_ANY, CHUNK_INITIALIZER);
}
+ }
+
+ { /* get a policy and process traffic selectors */
+ linked_list_t *my_ts, *other_ts;
+
+ my_ts = tsr_request->get_traffic_selectors(tsr_request);
+ other_ts = tsi_request->get_traffic_selectors(tsi_request);
+
+ this->policy = charon->policies->get_policy(charon->policies,
+ my_id, other_id,
+ my_ts, other_ts,
+ me, other);
+ if (this->policy)
+ {
+ this->tsr = this->policy->select_my_traffic_selectors(this->policy, my_ts, me);
+ this->tsi = this->policy->select_other_traffic_selectors(this->policy, other_ts, other);
+ }
+ destroy_ts_list(my_ts);
+ destroy_ts_list(other_ts);
- /* get policy from store */
- this->policy = charon->policies->get_policy_by_ids(charon->policies, my_id, other_id);
+ /* TODO: We should check somehow if we have a policy, but with other
+ * traffic selectors. Then we would create a IKE_SA without a CHILD_SA. */
if (this->policy == NULL)
{
this->logger->log(this->logger, AUDIT,
- "we don't have a policy for IDs %s - %s, deleting IKE_SA",
+ "no acceptable policy for IDs %s - %s found, deleting IKE_SA",
my_id->get_string(my_id), other_id->get_string(other_id));
my_id->destroy(my_id);
other_id->destroy(other_id);
@@ -621,16 +652,12 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
return DESTROY_ME;
}
my_id->destroy(my_id);
- other_id->destroy(other_id);
/* get my id from policy, which must contain a fully qualified valid id */
my_id = this->policy->get_my_id(this->policy);
+ this->ike_sa->set_my_id(this->ike_sa, my_id->clone(my_id));
+ this->ike_sa->set_other_id(this->ike_sa, other_id);
- /* update others traffic selectors with actually used address */
- this->policy->update_my_ts(this->policy, me);
- this->policy->update_other_ts(this->policy, other);
-
- this->ike_sa->set_policy(this->ike_sa, this->policy);
idr_response = id_payload_create_from_identification(FALSE, my_id);
response->add_payload(response, (payload_t*)idr_response);
}
@@ -658,9 +685,11 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
{ /* process auth payload */
authenticator_t *authenticator;
auth_payload_t *auth_response;
+ auth_method_t auth_method;
status_t status;
-
- authenticator = authenticator_create(this->ike_sa);
+
+ auth_method = this->connection->get_auth_method(this->connection);
+ authenticator = authenticator_create(this->ike_sa, auth_method);
status = authenticator->verify_auth_data(authenticator, auth_request,
this->init_request,
this->nonce_r, idi_request,
@@ -688,18 +717,6 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
response->add_payload(response, (payload_t*)auth_response);
}
- { /* process traffic selectors for other */
- linked_list_t *ts_received = tsi_request->get_traffic_selectors(tsi_request);
- this->tsi = this->policy->select_other_traffic_selectors(this->policy, ts_received);
- destroy_ts_list(ts_received);
- }
-
- { /* process traffic selectors for us */
- linked_list_t *ts_received = ts_received = tsr_request->get_traffic_selectors(tsr_request);
- this->tsr = this->policy->select_my_traffic_selectors(this->policy, ts_received);
- destroy_ts_list(ts_received);
- }
-
{ /* process SA payload */
proposal_t *proposal;
linked_list_t *proposal_list;
@@ -793,8 +810,8 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
return DESTROY_ME;
}
- me = this->connection->get_my_host(this->connection);
- other = this->connection->get_other_host(this->connection);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
/* Iterate over all payloads to collect them */
payloads = response->get_payload_iterator(response);
@@ -872,8 +889,7 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
configured_other_id->get_string(configured_other_id));
return DESTROY_ME;
}
-
- this->policy->update_other_id(this->policy, other_id);
+ this->ike_sa->set_other_id(this->ike_sa, other_id);
}
if (cert_payload)
@@ -883,9 +899,11 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
{ /* authenticate peer */
authenticator_t *authenticator;
+ auth_method_t auth_method;
status_t status;
- authenticator = authenticator_create(this->ike_sa);
+ auth_method = this->connection->get_auth_method(this->connection);
+ authenticator = authenticator_create(this->ike_sa, auth_method);
status = authenticator->verify_auth_data(authenticator, auth_payload,
this->init_response,
this->nonce_i, idr_payload,
@@ -900,13 +918,13 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
{ /* process traffic selectors for us */
linked_list_t *ts_received = tsi_payload->get_traffic_selectors(tsi_payload);
- this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received);
+ this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received, me);
destroy_ts_list(ts_received);
}
{ /* process traffic selectors for other */
linked_list_t *ts_received = tsr_payload->get_traffic_selectors(tsr_payload);
- this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received);
+ this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received, other);
destroy_ts_list(ts_received);
}
@@ -952,18 +970,11 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
*/
static void destroy(private_ike_auth_t *this)
{
- if (this->message)
- {
- this->message->destroy(this->message);
- }
- if (this->proposal)
- {
- this->proposal->destroy(this->proposal);
- }
- if (this->child_sa)
- {
- this->child_sa->destroy(this->child_sa);
- }
+ DESTROY_IF(this->message);
+ DESTROY_IF(this->proposal);
+ DESTROY_IF(this->child_sa);
+ DESTROY_IF(this->policy);
+ DESTROY_IF(this->connection);
destroy_ts_list(this->tsi);
destroy_ts_list(this->tsr);
chunk_free(&this->nonce_i);
@@ -989,6 +1000,7 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa)
this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
/* public functions */
+ this->public.set_config = (void(*)(ike_auth_t*,connection_t*,policy_t*))set_config;
this->public.set_nonces = (void(*)(ike_auth_t*,chunk_t,chunk_t))set_nonces;
this->public.set_init_messages = (void(*)(ike_auth_t*,chunk_t,chunk_t))set_init_messages;
diff --git a/src/charon/sa/transactions/ike_auth.h b/src/charon/sa/transactions/ike_auth.h
index 5c2b14c79..89263d47c 100644
--- a/src/charon/sa/transactions/ike_auth.h
+++ b/src/charon/sa/transactions/ike_auth.h
@@ -50,6 +50,20 @@ struct ike_auth_t {
transaction_t transaction;
/**
+ * @brief Set the config used for the ike_auth exchange.
+ *
+ * The connection definition is used to complete IKE_SA setup, the
+ * policy defines the CHILD_SA which is created along with the ike_auth
+ * exchange.
+ *
+ * @param this calling object
+ * @param connection connection definition
+ * @param policy policy definition
+ */
+ void (*set_config) (ike_auth_t* this,
+ connection_t *connection, policy_t *policy);
+
+ /**
* @brief Set the nonces used in the previous ike_sa_init transaction.
*
* The nonces are used to create the authentication data.
diff --git a/src/charon/sa/transactions/ike_sa_init.c b/src/charon/sa/transactions/ike_sa_init.c
index d66ba8474..29cdcaf02 100644
--- a/src/charon/sa/transactions/ike_sa_init.c
+++ b/src/charon/sa/transactions/ike_sa_init.c
@@ -90,11 +90,16 @@ struct private_ike_sa_init_t {
chunk_t nonce_r;
/**
- * connection definition used
+ * connection definition used for initiation
*/
connection_t *connection;
/**
+ * policy definition forwarded to ike_auth transaction
+ */
+ policy_t *policy;
+
+ /**
* Negotiated proposal used for IKE_SA
*/
proposal_t *proposal;
@@ -150,8 +155,6 @@ struct private_ike_sa_init_t {
*/
static bool use_dh_group(private_ike_sa_init_t *this, diffie_hellman_group_t dh_group)
{
- this->connection = this->ike_sa->get_connection(this->ike_sa);
-
if (this->connection->check_dh_group(this->connection, dh_group))
{
this->diffie_hellman = diffie_hellman_create(dh_group);
@@ -164,6 +167,16 @@ static bool use_dh_group(private_ike_sa_init_t *this, diffie_hellman_group_t dh_
}
/**
+ * Implementation of ike_sa_init_t.set_config.
+ */
+static void set_config(private_ike_sa_init_t *this,
+ connection_t *connection, policy_t *policy)
+{
+ this->connection = connection;
+ this->policy = policy;
+}
+
+/**
* Implementation of transaction_t.get_message_id.
*/
static u_int32_t get_message_id(private_ike_sa_init_t *this)
@@ -264,7 +277,6 @@ static status_t get_request(private_ike_sa_init_t *this, message_t **result)
return SUCCESS;
}
- this->connection = this->ike_sa->get_connection(this->ike_sa);
me = this->connection->get_my_host(this->connection);
other = this->connection->get_other_host(this->connection);
@@ -398,6 +410,9 @@ static status_t process_notifys(private_ike_sa_init_t *this, notify_payload_t *n
return DESTROY_ME;
}
retry = ike_sa_init_create(this->ike_sa);
+ retry->set_config(retry, this->connection, this->policy);
+ this->connection = NULL;
+ this->policy = NULL;
retry->use_dh_group(retry, dh_group);
*this->next = (transaction_t*)retry;
return FAILED;
@@ -523,7 +538,8 @@ static status_t get_response(private_ike_sa_init_t *this,
me->get_string(me), other->get_string(other));
return DESTROY_ME;
}
- this->ike_sa->set_connection(this->ike_sa, this->connection);
+ this->ike_sa->set_name(this->ike_sa,
+ this->connection->get_name(this->connection));
/* Precompute NAT-D hashes for incoming NAT notify comparison */
ike_sa_id = request->get_ike_sa_id(request);
@@ -769,6 +785,9 @@ static status_t get_response(private_ike_sa_init_t *this,
/* create next transaction, for which we except a message */
ike_auth = ike_auth_create(this->ike_sa);
+ ike_auth->set_config(ike_auth, this->connection, this->policy);
+ this->connection = NULL;
+ this->policy = NULL;
ike_auth->set_nonces(ike_auth,
chunk_clone(this->nonce_i),
chunk_clone(this->nonce_r));
@@ -802,7 +821,6 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
sa_payload_t *sa_payload = NULL;
ke_payload_t *ke_payload = NULL;
nonce_payload_t *nonce_payload = NULL;
- policy_t *policy;
status_t status;
/* check message type */
@@ -816,7 +834,6 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
/* allow setting of next transaction in other functions */
this->next = next;
- this->connection = this->ike_sa->get_connection(this->ike_sa);
me = this->connection->get_my_host(this->connection);
other = this->connection->get_other_host(this->connection);
@@ -971,9 +988,6 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
other->set_port(other, IKEV2_NATT_PORT);
this->logger->log(this->logger, CONTROL|LEVEL1, "switching to port %d", IKEV2_NATT_PORT);
}
- policy = this->ike_sa->get_policy(this->ike_sa);
- policy->update_my_ts(policy, me);
- policy->update_other_ts(policy, other);
}
/* because we are original initiator we have to update the responder SPI to the new one */
@@ -1000,6 +1014,9 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
/* create next transaction, for which we except a message */
ike_auth = ike_auth_create(this->ike_sa);
+ ike_auth->set_config(ike_auth, this->connection, this->policy);
+ this->connection = NULL;
+ this->policy = NULL;
ike_auth->set_nonces(ike_auth,
chunk_clone(this->nonce_i),
chunk_clone(this->nonce_r));
@@ -1012,18 +1029,11 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
static void destroy(private_ike_sa_init_t *this)
{
- if (this->message)
- {
- this->message->destroy(this->message);
- }
- if (this->diffie_hellman)
- {
- this->diffie_hellman->destroy(this->diffie_hellman);
- }
- if (this->proposal)
- {
- this->proposal->destroy(this->proposal);
- }
+ DESTROY_IF(this->message);
+ DESTROY_IF(this->diffie_hellman);
+ DESTROY_IF(this->proposal);
+ DESTROY_IF(this->connection);
+ DESTROY_IF(this->policy);
chunk_free(&this->nonce_i);
chunk_free(&this->nonce_r);
this->randomizer->destroy(this->randomizer);
@@ -1049,6 +1059,7 @@ ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
/* public functions */
+ this->public.set_config = (void(*)(ike_sa_init_t*,connection_t*,policy_t*))set_config;
this->public.use_dh_group = (bool(*)(ike_sa_init_t*,diffie_hellman_group_t))use_dh_group;
/* private data */
@@ -1060,6 +1071,7 @@ ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
this->nonce_i = CHUNK_INITIALIZER;
this->nonce_r = CHUNK_INITIALIZER;
this->connection = NULL;
+ this->policy = NULL;
this->proposal = NULL;
this->randomizer = randomizer_create();
this->nat_hasher = hasher_create(HASH_SHA1);
@@ -1070,6 +1082,6 @@ ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
this->natd_src_matched = FALSE;
this->natd_dst_matched = FALSE;
this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
-
+
return &this->public;
}
diff --git a/src/charon/sa/transactions/ike_sa_init.h b/src/charon/sa/transactions/ike_sa_init.h
index b268fac11..3bc049db3 100644
--- a/src/charon/sa/transactions/ike_sa_init.h
+++ b/src/charon/sa/transactions/ike_sa_init.h
@@ -47,6 +47,19 @@ struct ike_sa_init_t {
transaction_t transaction;
/**
+ * @brief Set connection & policy to use for initiation.
+ *
+ * The policy is not used directly, but forwarded to the
+ * ike_auth transaction.
+ *
+ * @param this calling object
+ * @param connection connection to use for initiation
+ * @param policy policy used in ike_auth transaction
+ */
+ void (*set_config) (ike_sa_init_t* this,
+ connection_t *connection, policy_t *policy);
+
+ /**
* @brief Set the Diffie Hellman group to use for initiating.
*
* If a first exchange fails with a INVALID_KE_PAYLOAD, the second
diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c
index f4d7accfb..2242ea24a 100755
--- a/src/charon/threads/stroke_interface.c
+++ b/src/charon/threads/stroke_interface.c
@@ -260,12 +260,12 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
}
my_ts = traffic_selector_create_from_subnet(my_subnet,
- msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 32,
+ msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 0,
msg->add_conn.me.protocol, msg->add_conn.me.port);
my_subnet->destroy(my_subnet);
other_ts = traffic_selector_create_from_subnet(other_subnet,
- msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 32,
+ msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 0,
msg->add_conn.other.protocol, msg->add_conn.other.port);
other_subnet->destroy(other_subnet);
@@ -383,11 +383,11 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
policy = policy_create(msg->add_conn.name, my_id, other_id,
msg->add_conn.rekey.ipsec_lifetime,
msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
- msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100);
+ msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
+ msg->add_conn.me.updown);
policy->add_my_traffic_selector(policy, my_ts);
policy->add_other_traffic_selector(policy, other_ts);
policy->add_authorities(policy, my_ca, other_ca);
- policy->add_updown(policy, msg->add_conn.me.updown);
if (msg->add_conn.algorithms.esp)
{
@@ -479,40 +479,65 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
{
initiate_ike_sa_job_t *job;
connection_t *connection;
+ policy_t *policy;
linked_list_t *ike_sas;
ike_sa_id_t *ike_sa_id;
pop_string(msg, &(msg->initiate.name));
- this->logger->log(this->logger, CONTROL, "received stroke: initiate \"%s\"", msg->initiate.name);
- connection = charon->connections->get_connection_by_name(charon->connections, msg->initiate.name);
+ this->logger->log(this->logger, CONTROL,
+ "received stroke: initiate \"%s\"",
+ msg->initiate.name);
+
+ connection = charon->connections->get_connection_by_name(charon->connections,
+ msg->initiate.name);
if (connection == NULL)
{
- this->stroke_logger->log(this->stroke_logger, ERROR, "no connection named \"%s\"", msg->initiate.name);
+ this->stroke_logger->log(this->stroke_logger, ERROR,
+ "no connection named \"%s\"",
+ msg->initiate.name);
}
/* only initiate if it is an IKEv2 connection, ignore IKEv1 */
else if (connection->is_ikev2(connection))
{
- /* check for already set up IKE_SAs befor initiating */
- ike_sas = charon->ike_sa_manager->get_ike_sa_list_by_name(charon->ike_sa_manager, msg->initiate.name);
- if (ike_sas->get_count(ike_sas) == 0)
+
+ policy = charon->policies->get_policy_by_name(charon->policies,
+ msg->initiate.name);
+ if (policy == NULL)
{
- this->stroke_logger->log(this->stroke_logger, CONTROL,
- "initiating connection \"%s\" (see log)...", msg->initiate.name);
- job = initiate_ike_sa_job_create(connection);
- charon->job_queue->add(charon->job_queue, (job_t*)job);
+ this->stroke_logger->log(this->stroke_logger, ERROR,
+ "no policy named \"%s\"",
+ msg->initiate.name);
+ connection->destroy(connection);
+ return;
}
- else
+ /* check for already set up IKE_SAs befor initiating */
+ ike_sas = charon->ike_sa_manager->get_ike_sa_list_by_name(charon->ike_sa_manager,
+ msg->initiate.name);
+ if (ike_sas->get_count(ike_sas) > 0)
{
this->stroke_logger->log(this->stroke_logger, CONTROL,
- "connection \"%s\" already up", msg->initiate.name);
+ "connection \"%s\" already up",
+ msg->initiate.name);
+ /* TODO: setup CHILD_SA with policy */
connection->destroy(connection);
+ ike_sas->destroy(ike_sas);
+ return;
}
+ this->stroke_logger->log(this->stroke_logger, CONTROL,
+ "initiating connection \"%s\" (see log)...",
+ msg->initiate.name);
+ job = initiate_ike_sa_job_create(connection, policy);
+ charon->job_queue->add(charon->job_queue, (job_t*)job);
while (ike_sas->remove_last(ike_sas, (void**)&ike_sa_id) == SUCCESS)
{
ike_sa_id->destroy(ike_sa_id);
}
ike_sas->destroy(ike_sas);
}
+ else
+ {
+ connection->destroy(connection);
+ }
}
/**
diff --git a/src/libstrongswan/definitions.h b/src/libstrongswan/definitions.h
index c8839ef70..db920e3e6 100644
--- a/src/libstrongswan/definitions.h
+++ b/src/libstrongswan/definitions.h
@@ -90,6 +90,11 @@
#define min(x,y) ((x) < (y) ? (x):(y))
/**
+ * Call destructor of a object if object != NULL
+ */
+#define DESTROY_IF(obj) if (obj) obj->destroy(obj)
+
+/**
* Debug macro to follow control flow
*/
#define POS printf("%s, line %d\n", __FILE__, __LINE__)