diff options
Diffstat (limited to 'Source/charon/sa')
-rw-r--r-- | Source/charon/sa/authenticator.c | 3 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.c | 28 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.h | 16 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa_manager.c | 99 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa_manager.h | 33 |
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**)¤t); + 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. * |