aboutsummaryrefslogtreecommitdiffstats
path: root/Source/charon/sa
diff options
context:
space:
mode:
Diffstat (limited to 'Source/charon/sa')
-rw-r--r--Source/charon/sa/authenticator.c3
-rw-r--r--Source/charon/sa/ike_sa.c28
-rw-r--r--Source/charon/sa/ike_sa.h16
-rw-r--r--Source/charon/sa/ike_sa_manager.c99
-rw-r--r--Source/charon/sa/ike_sa_manager.h33
5 files changed, 169 insertions, 10 deletions
diff --git a/Source/charon/sa/authenticator.c b/Source/charon/sa/authenticator.c
index 20667f736..9c2a05cb3 100644
--- a/Source/charon/sa/authenticator.c
+++ b/Source/charon/sa/authenticator.c
@@ -353,7 +353,8 @@ static status_t compute_auth_data (private_authenticator_t *this,
allocator_free_chunk(&octets);
if (status != SUCCESS)
{
- return status;
+ private_key->destroy(private_key);
+ return status;
}
*auth_payload = auth_payload_create();
diff --git a/Source/charon/sa/ike_sa.c b/Source/charon/sa/ike_sa.c
index cbdd22a84..89f3fff29 100644
--- a/Source/charon/sa/ike_sa.c
+++ b/Source/charon/sa/ike_sa.c
@@ -288,7 +288,7 @@ static status_t initiate_connection(private_ike_sa_t *this, connection_t *connec
initiator_init_t *current_state;
/* Work is done in state object of type INITIATOR_INIT. All other states are not
- * initial states and so don't have a initialize_connection function */
+ * initial states and so don't have a initiate_connection function */
if (this->current_state->get_state(this->current_state) != INITIATOR_INIT)
{
@@ -350,7 +350,7 @@ static void send_delete_ike_sa_request (private_ike_sa_t *this)
}
/**
- * Implementation of protected_ike_sa_t.get_id.
+ * Implementation of ike_sa_t.get_id.
*/
static ike_sa_id_t* get_id(private_ike_sa_t *this)
{
@@ -358,6 +358,22 @@ static ike_sa_id_t* get_id(private_ike_sa_t *this)
}
/**
+ * Implementation of ike_sa_t.get_my_host.
+ */
+static host_t* get_my_host(private_ike_sa_t *this)
+{
+ return this->connection->get_my_host(this->connection);;
+}
+
+/**
+ * Implementation of ike_sa_t.get_other_host.
+ */
+static host_t* get_other_host(private_ike_sa_t *this)
+{
+ return this->connection->get_other_host(this->connection);;
+}
+
+/**
* Implementation of private_ike_sa_t.resend_last_reply.
*/
static status_t resend_last_reply(private_ike_sa_t *this)
@@ -998,6 +1014,12 @@ static void destroy (private_ike_sa_t *this)
}
if (this->connection)
{
+ host_t *me, *other;
+ me = this->connection->get_my_host(this->connection);
+ other = this->connection->get_other_host(this->connection);
+
+ this->logger->log(this->logger, AUDIT, "IKE_SA deleted between %s - %s",
+ me->get_address(me), other->get_address(other));
this->connection->destroy(this->connection);
}
if (this->policy)
@@ -1030,6 +1052,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->protected.public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
this->protected.public.initiate_connection = (status_t(*)(ike_sa_t*,connection_t*)) initiate_connection;
this->protected.public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
+ this->protected.public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host;
+ this->protected.public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host;
this->protected.public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request;
this->protected.public.get_state = (ike_sa_state_t (*) (ike_sa_t *this)) get_state;
this->protected.public.send_delete_ike_sa_request = (void (*)(ike_sa_t*)) send_delete_ike_sa_request;
diff --git a/Source/charon/sa/ike_sa.h b/Source/charon/sa/ike_sa.h
index 0a2661541..16c0111f6 100644
--- a/Source/charon/sa/ike_sa.h
+++ b/Source/charon/sa/ike_sa.h
@@ -120,6 +120,22 @@ struct ike_sa_t {
* @return ike_sa's ike_sa_id_t
*/
ike_sa_id_t* (*get_id) (ike_sa_t *this);
+
+ /**
+ * @brief Get local peer address of the IKE_SA.
+ *
+ * @param this calling object
+ * @return local host_t
+ */
+ host_t* (*get_my_host) (ike_sa_t *this);
+
+ /**
+ * @brief Get remote peer address of the IKE_SA.
+ *
+ * @param this calling object
+ * @return remote host_t
+ */
+ host_t* (*get_other_host) (ike_sa_t *this);
/**
* @brief Get the state of type of associated state object.
diff --git a/Source/charon/sa/ike_sa_manager.c b/Source/charon/sa/ike_sa_manager.c
index ebb306a49..2838d2b8a 100644
--- a/Source/charon/sa/ike_sa_manager.c
+++ b/Source/charon/sa/ike_sa_manager.c
@@ -490,6 +490,91 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
}
/**
+ * Implementation of of ike_sa_manager.checkout_by_hosts.
+ */
+static status_t checkout_by_hosts(private_ike_sa_manager_t *this, host_t *me, host_t *other, ike_sa_t **ike_sa)
+{
+ iterator_t *iterator;
+ ike_sa_id_t *ike_sa_id = NULL;
+
+ pthread_mutex_lock(&(this->mutex));
+
+ iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
+ while (iterator->has_next(iterator))
+ {
+ ike_sa_entry_t *current;
+ host_t *sa_me, *sa_other;
+
+ iterator->current(iterator, (void**)&current);
+ sa_me = current->ike_sa->get_my_host(current->ike_sa);
+ sa_other = current->ike_sa->get_other_host(current->ike_sa);
+
+ /* one end may be default/any, but not both */
+ if (me->is_default_route(me))
+ {
+ if (other->is_default_route(other))
+ {
+ break;
+ }
+ if (other->equals(other, sa_other))
+ {
+ /* other matches */
+ ike_sa_id = current->ike_sa_id;
+ }
+ }
+ else if (other->is_default_route(other))
+ {
+ if (me->equals(me, sa_me))
+ {
+ /* ME matches */
+ ike_sa_id = current->ike_sa_id;
+ }
+ }
+ else
+ {
+ if (me->equals(me, sa_me) && other->equals(other, sa_other))
+ {
+ /* both matches */
+ ike_sa_id = current->ike_sa_id;
+ }
+ }
+ }
+ iterator->destroy(iterator);
+ pthread_mutex_unlock(&(this->mutex));
+
+ if (ike_sa_id)
+ {
+ /* checkout is done in the checkout function, since its rather complex */
+ return checkout(this, ike_sa_id, ike_sa);
+ }
+ return NOT_FOUND;
+}
+
+/**
+ * Implementation of ike_sa_manager_t.get_ike_sa_list.
+ */
+linked_list_t *get_ike_sa_list(private_ike_sa_manager_t* this)
+{
+ linked_list_t *list;
+ iterator_t *iterator;
+
+ 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))
+ {
+ ike_sa_entry_t *entry;
+ iterator->current(iterator, (void**)&entry);
+ list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id));
+ }
+ iterator->destroy(iterator);
+
+ pthread_mutex_unlock(&(this->mutex));
+ return list;
+}
+
+/**
* Implementation of ike_sa_manager_t.checkin.
*/
static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
@@ -518,7 +603,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
else
{
this->logger->log(this->logger,ERROR,"Fatal Error: Tried to checkin nonexisting IKE_SA");
- /* this SA is no more, this RELEVEL3Y should not happen */
+ /* this SA is no more, this REALLY should not happen */
retval = NOT_FOUND;
}
pthread_mutex_unlock(&(this->mutex));
@@ -679,11 +764,13 @@ ike_sa_manager_t *ike_sa_manager_create()
/* assign public functions */
this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
- this->public.create_and_checkout = (void(*)(ike_sa_manager_t*, ike_sa_t **sa))create_and_checkout;
- this->public.checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t *sa_id, ike_sa_t **sa))checkout;
- this->public.checkin = (status_t(*)(ike_sa_manager_t*, ike_sa_t *sa))checkin;
- this->public.delete = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t *sa_id))delete;
- this->public.checkin_and_delete = (status_t(*)(ike_sa_manager_t*, ike_sa_t *ike_sa))checkin_and_delete;
+ this->public.create_and_checkout = (void(*)(ike_sa_manager_t*,ike_sa_t**))create_and_checkout;
+ this->public.checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t*,ike_sa_t**))checkout;
+ this->public.checkout_by_hosts = (status_t(*)(ike_sa_manager_t*,host_t*,host_t*,ike_sa_t**))checkout_by_hosts;
+ this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list;
+ this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
+ this->public.delete = (status_t(*)(ike_sa_manager_t*,ike_sa_id_t*))delete;
+ this->public.checkin_and_delete = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_delete;
/* initialize private functions */
this->get_next_spi = get_next_spi;
diff --git a/Source/charon/sa/ike_sa_manager.h b/Source/charon/sa/ike_sa_manager.h
index 5ba9e87d5..a00f37e4f 100644
--- a/Source/charon/sa/ike_sa_manager.h
+++ b/Source/charon/sa/ike_sa_manager.h
@@ -78,7 +78,37 @@ struct ike_sa_manager_t {
* @param ike_sa[out] checked out SA
*/
void (*create_and_checkout) (ike_sa_manager_t* ike_sa_manager,ike_sa_t **ike_sa);
-
+
+ /**
+ * @brief Check out an IKE_SA, defined be the two peers.
+ *
+ * Checking out an IKE_SA by their peer addresses may be necessary
+ * for kernel traps, status querying and so on... one of the hosts
+ * may be 0.0.0.0 (defaultroute/any), but not both.
+ *
+ * @param ike_sa_manager the manager object
+ * @param me host on local side
+ * @param other host on remote side
+ * @param ike_sa[out] checked out SA
+ * @return
+ * - NOT_FOUND, if no such SA found
+ * - SUCCESS, if SA found and ike_sa set appropriatly
+ */
+ status_t (*checkout_by_hosts) (ike_sa_manager_t* ike_sa_manager, host_t *me, host_t *other, ike_sa_t **ike_sa);
+
+ /**
+ * @brief Get a list of all IKE_SA SAs currently set up.
+ *
+ * The resulting list with all IDs must be destroyd by
+ * the caller. There is no guarantee an ike_sa with the
+ * corrensponding ID really exists, since it may be deleted
+ * in the meantime by another thread.
+ *
+ * @param ike_sa_manager the manager object
+ * @return a list with ike_sa_id_t s
+ */
+ linked_list_t *(*get_ike_sa_list) (ike_sa_manager_t* ike_sa_manager);
+
/**
* @brief Checkin the SA after usage.
*
@@ -93,6 +123,7 @@ struct ike_sa_manager_t {
* - NOT_FOUND when not found (shouldn't happen!)
*/
status_t (*checkin) (ike_sa_manager_t* ike_sa_manager, ike_sa_t *ike_sa);
+
/**
* @brief Delete a SA, which was not checked out.
*