diff options
Diffstat (limited to 'src/charon/sa/ike_sa.c')
-rw-r--r-- | src/charon/sa/ike_sa.c | 713 |
1 files changed, 328 insertions, 385 deletions
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 68aba3064..8b4b53e10 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -26,6 +26,7 @@ #include <string.h> #include <printf.h> #include <sys/stat.h> +#include <errno.h> #include "ike_sa.h" @@ -56,13 +57,11 @@ #include <sa/tasks/child_create.h> #include <sa/tasks/child_delete.h> #include <sa/tasks/child_rekey.h> -#include <queues/jobs/retransmit_job.h> -#include <queues/jobs/delete_ike_sa_job.h> -#include <queues/jobs/send_dpd_job.h> -#include <queues/jobs/send_keepalive_job.h> -#include <queues/jobs/rekey_ike_sa_job.h> -#include <queues/jobs/route_job.h> -#include <queues/jobs/initiate_job.h> +#include <processing/jobs/retransmit_job.h> +#include <processing/jobs/delete_ike_sa_job.h> +#include <processing/jobs/send_dpd_job.h> +#include <processing/jobs/send_keepalive_job.h> +#include <processing/jobs/rekey_ike_sa_job.h> #ifndef RESOLV_CONF @@ -105,14 +104,14 @@ struct private_ike_sa_t { ike_sa_state_t state; /** - * connection used to establish this IKE_SA. + * IKE configuration used to set up this IKE_SA */ - connection_t *connection; + ike_cfg_t *ike_cfg; /** * Peer and authentication information to establish IKE_SA. */ - policy_t *policy; + peer_cfg_t *peer_cfg; /** * Juggles tasks to process messages @@ -140,6 +139,11 @@ struct private_ike_sa_t { identification_t *other_id; /** + * CA that issued the certificate of other + */ + ca_info_t *other_ca; + + /** * Linked List containing the child sa's of the current IKE_SA. */ linked_list_t *child_sas; @@ -175,14 +179,14 @@ struct private_ike_sa_t { prf_t *child_prf; /** - * PRF to build outging authentication data + * Key to build outging authentication data (SKp) */ - prf_t *auth_build; + chunk_t skp_build; /** - * PRF to verify incoming authentication data + * Key to verify incoming authentication data (SKp) */ - prf_t *auth_verify; + chunk_t skp_verify; /** * NAT status of local host. @@ -273,79 +277,126 @@ static u_int32_t get_unique_id(private_ike_sa_t *this) */ static char *get_name(private_ike_sa_t *this) { - if (this->connection) + if (this->peer_cfg) { - return this->connection->get_name(this->connection); + return this->peer_cfg->get_name(this->peer_cfg); } return "(unnamed)"; } + /** - * Implementation of ike_sa_t.get_connection + * Implementation of ike_sa_t.get_stats. */ -static connection_t* get_connection(private_ike_sa_t *this) +static void get_stats(private_ike_sa_t *this, u_int32_t *next_rekeying) { - return this->connection; + if (next_rekeying) + { + *next_rekeying = this->time.rekey; + } } /** - * Implementation of ike_sa_t.set_connection + * Implementation of ike_sa_t.get_my_host. */ -static void set_connection(private_ike_sa_t *this, connection_t *connection) +static host_t *get_my_host(private_ike_sa_t *this) { - this->connection = connection; - connection->get_ref(connection); + return this->my_host; } /** - * Implementation of ike_sa_t.get_policy + * Implementation of ike_sa_t.set_my_host. */ -static policy_t *get_policy(private_ike_sa_t *this) +static void set_my_host(private_ike_sa_t *this, host_t *me) { - return this->policy; + DESTROY_IF(this->my_host); + this->my_host = me; } /** - * Implementation of ike_sa_t.set_policy + * Implementation of ike_sa_t.get_other_host. */ -static void set_policy(private_ike_sa_t *this, policy_t *policy) +static host_t *get_other_host(private_ike_sa_t *this) { - policy->get_ref(policy); - this->policy = policy; + return this->other_host; } /** - * Implementation of ike_sa_t.get_my_host. + * Implementation of ike_sa_t.set_other_host. */ -static host_t *get_my_host(private_ike_sa_t *this) +static void set_other_host(private_ike_sa_t *this, host_t *other) { - return this->my_host; + DESTROY_IF(this->other_host); + this->other_host = other; } /** - * Implementation of ike_sa_t.set_my_host. + * Implementation of ike_sa_t.get_peer_cfg */ -static void set_my_host(private_ike_sa_t *this, host_t *me) +static peer_cfg_t* get_peer_cfg(private_ike_sa_t *this) { - DESTROY_IF(this->my_host); - this->my_host = me; + return this->peer_cfg; } /** - * Implementation of ike_sa_t.get_other_host. + * Implementation of ike_sa_t.set_peer_cfg */ -static host_t *get_other_host(private_ike_sa_t *this) +static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg) { - return this->other_host; + peer_cfg->get_ref(peer_cfg); + this->peer_cfg = peer_cfg; + + if (this->ike_cfg == NULL) + { + this->ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); + this->ike_cfg->get_ref(this->ike_cfg); + } + + /* apply values, so we are ready to initate/acquire */ + if (this->my_host->is_anyaddr(this->my_host)) + { + host_t *me = this->ike_cfg->get_my_host(this->ike_cfg); + + set_my_host(this, me->clone(me)); + } + if (this->other_host->is_anyaddr(this->other_host)) + { + host_t *other = this->ike_cfg->get_other_host(this->ike_cfg); + + set_other_host(this, other->clone(other)); + } + /* apply IDs if they are not already set */ + if (this->my_id->contains_wildcards(this->my_id)) + { + identification_t *my_id = this->peer_cfg->get_my_id(this->peer_cfg); + + DESTROY_IF(this->my_id); + this->my_id = my_id->clone(my_id); + } + if (this->other_id->contains_wildcards(this->other_id)) + { + identification_t *other_id = this->peer_cfg->get_other_id(this->peer_cfg); + + DESTROY_IF(this->other_id); + this->other_id = other_id->clone(other_id); + } } /** - * Implementation of ike_sa_t.set_other_host. + * Implementation of ike_sa_t.get_ike_cfg */ -static void set_other_host(private_ike_sa_t *this, host_t *other) +static ike_cfg_t *get_ike_cfg(private_ike_sa_t *this) { - DESTROY_IF(this->other_host); - this->other_host = other; + return this->ike_cfg; +} + +/** + * Implementation of ike_sa_t.set_ike_cfg + */ +static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg) +{ + ike_cfg->get_ref(ike_cfg); + this->ike_cfg = ike_cfg; } /** @@ -356,7 +407,7 @@ static status_t send_dpd(private_ike_sa_t *this) send_dpd_job_t *job; time_t diff, delay; - delay = this->connection->get_dpd_delay(this->connection); + delay = this->peer_cfg->get_dpd_delay(this->peer_cfg); if (delay == 0) { @@ -402,15 +453,14 @@ static status_t send_dpd(private_ike_sa_t *this) static void send_keepalive(private_ike_sa_t *this) { send_keepalive_job_t *job; - time_t last_out, now, diff, interval; + time_t last_out, now, diff; last_out = get_use_time(this, FALSE); now = time(NULL); diff = now - last_out; - interval = charon->configuration->get_keepalive_interval(charon->configuration); - if (diff >= interval) + if (diff >= KEEPALIVE_INTERVAL) { packet_t *packet; chunk_t data; @@ -428,7 +478,7 @@ static void send_keepalive(private_ike_sa_t *this) } job = send_keepalive_job_create(this->ike_sa_id); charon->event_queue->add_relative(charon->event_queue, (job_t*)job, - (interval - diff) * 1000); + (KEEPALIVE_INTERVAL - diff) * 1000); } /** @@ -464,9 +514,9 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state) send_dpd(this); /* schedule rekeying/reauthentication */ - soft = this->connection->get_soft_lifetime(this->connection); - hard = this->connection->get_hard_lifetime(this->connection); - reauth = this->connection->get_reauth(this->connection); + soft = this->peer_cfg->get_lifetime(this->peer_cfg, TRUE); + hard = this->peer_cfg->get_lifetime(this->peer_cfg, FALSE); + reauth = this->peer_cfg->use_reauth(this->peer_cfg); DBG1(DBG_IKE, "scheduling %s in %ds, maximum lifetime %ds", reauth ? "reauthentication": "rekeying", soft, hard); @@ -492,9 +542,8 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state) { /* delete may fail if a packet gets lost, so set a timeout */ job_t *job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE); - charon->event_queue->add_relative(charon->event_queue, job, - charon->configuration->get_half_open_ike_sa_timeout( - charon->configuration)); + charon->event_queue->add_relative(charon->event_queue, job, + HALF_OPEN_IKE_SA_TIMEOUT); break; } default: @@ -521,7 +570,7 @@ static void reset(private_ike_sa_t *this) } /** - * Update connection host, as addresses may change (NAT) + * Update hosts, as addresses may change (NAT) */ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other) { @@ -696,16 +745,16 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) me = message->get_destination(message); other = message->get_source(message); - /* if this IKE_SA is virgin, we check for a connection */ - if (this->connection == NULL) + /* if this IKE_SA is virgin, we check for a config */ + if (this->ike_cfg == NULL) { job_t *job; - this->connection = charon->connections->get_connection_by_hosts( - charon->connections, me, other); - if (this->connection == NULL) + this->ike_cfg = charon->backends->get_ike_cfg(charon->backends, + me, other); + if (this->ike_cfg == NULL) { - /* no connection found for these hosts, destroy */ - DBG1(DBG_IKE, "no connection found for %H...%H, sending %N", + /* no config found for these hosts, destroy */ + DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N", me, other, notify_type_names, NO_PROPOSAL_CHOSEN); send_notify_response(this, message, NO_PROPOSAL_CHOSEN); return DESTROY_ME; @@ -713,11 +762,10 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) /* add a timeout if peer does not establish it completely */ job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, FALSE); charon->event_queue->add_relative(charon->event_queue, job, - charon->configuration->get_half_open_ike_sa_timeout( - charon->configuration)); + HALF_OPEN_IKE_SA_TIMEOUT); } - - /* check if message is trustworthy, and update connection information */ + + /* check if message is trustworthy, and update host information */ if (this->state == IKE_CREATED || message->get_exchange_type(message) != IKE_SA_INIT) { @@ -729,46 +777,14 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) } /** - * apply the connection/policy information to this IKE_SA - */ -static void apply_config(private_ike_sa_t *this, - connection_t *connection, policy_t *policy) -{ - host_t *me, *other; - identification_t *my_id, *other_id; - - if (this->connection == NULL && this->policy == NULL) - { - this->connection = connection; - connection->get_ref(connection); - this->policy = policy; - policy->get_ref(policy); - - me = connection->get_my_host(connection); - other = connection->get_other_host(connection); - my_id = policy->get_my_id(policy); - other_id = policy->get_other_id(policy); - set_my_host(this, me->clone(me)); - set_other_host(this, other->clone(other)); - DESTROY_IF(this->my_id); - DESTROY_IF(this->other_id); - this->my_id = my_id->clone(my_id); - this->other_id = other_id->clone(other_id); - } -} - -/** * Implementation of ike_sa_t.initiate. */ -static status_t initiate(private_ike_sa_t *this, - connection_t *connection, policy_t *policy) +static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg) { task_t *task; if (this->state == IKE_CREATED) { - /* if we aren't established/establishing, do so */ - apply_config(this, connection, policy); if (this->other_host->is_anyaddr(this->other_host)) { @@ -785,11 +801,12 @@ static status_t initiate(private_ike_sa_t *this, this->task_manager->queue_task(this->task_manager, task); task = (task_t*)ike_auth_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); - task = (task_t*)ike_config_create(&this->public, policy); + task = (task_t*)ike_config_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); } - task = (task_t*)child_create_create(&this->public, policy); + task = (task_t*)child_create_create(&this->public, child_cfg); + child_cfg->destroy(child_cfg); this->task_manager->queue_task(this->task_manager, task); return this->task_manager->initiate(this->task_manager); @@ -800,7 +817,7 @@ static status_t initiate(private_ike_sa_t *this, */ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid) { - policy_t *policy; + child_cfg_t *child_cfg; iterator_t *iterator; child_sa_t *current, *child_sa = NULL; task_t *task; @@ -833,7 +850,6 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid) return FAILED; } - policy = child_sa->get_policy(child_sa); if (this->state == IKE_CREATED) { @@ -845,11 +861,12 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid) this->task_manager->queue_task(this->task_manager, task); task = (task_t*)ike_auth_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); - task = (task_t*)ike_config_create(&this->public, policy); + task = (task_t*)ike_config_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); } - child_create = child_create_create(&this->public, policy); + child_cfg = child_sa->get_config(child_sa); + child_create = child_create_create(&this->public, child_cfg); child_create->use_reqid(child_create, reqid); this->task_manager->queue_task(this->task_manager, (task_t*)child_create); @@ -857,40 +874,11 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid) } /** - * compare two lists of traffic selectors for equality - */ -static bool ts_list_equals(linked_list_t *l1, linked_list_t *l2) -{ - bool equals = TRUE; - iterator_t *i1, *i2; - traffic_selector_t *t1, *t2; - - if (l1->get_count(l1) != l2->get_count(l2)) - { - return FALSE; - } - - i1 = l1->create_iterator(l1, TRUE); - i2 = l2->create_iterator(l2, TRUE); - while (i1->iterate(i1, (void**)&t1) && i2->iterate(i2, (void**)&t2)) - { - if (!t1->equals(t1, t2)) - { - equals = FALSE; - break; - } - } - i1->destroy(i1); - i2->destroy(i2); - return equals; -} - -/** * Implementation of ike_sa_t.route. */ -static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t *policy) +static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg) { - child_sa_t *child_sa = NULL; + child_sa_t *child_sa; iterator_t *iterator; linked_list_t *my_ts, *other_ts; status_t status; @@ -901,27 +889,12 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t iterator = this->child_sas->create_iterator(this->child_sas, TRUE); while (iterator->iterate(iterator, (void**)&child_sa)) { - if (child_sa->get_state(child_sa) == CHILD_ROUTED) + if (child_sa->get_state(child_sa) == CHILD_ROUTED && + streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg))) { - linked_list_t *my_ts_conf, *other_ts_conf; - - my_ts = child_sa->get_my_traffic_selectors(child_sa); - other_ts = child_sa->get_other_traffic_selectors(child_sa); - - my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host); - other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host); - - if (ts_list_equals(my_ts, my_ts_conf) && - ts_list_equals(other_ts, other_ts_conf)) - { - iterator->destroy(iterator); - my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy)); - other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy)); - SIG(CHILD_ROUTE_FAILED, "CHILD_SA with such a policy already routed"); - return FAILED; - } - my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy)); - other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy)); + iterator->destroy(iterator); + SIG(CHILD_ROUTE_FAILED, "CHILD_SA with such a config already routed"); + return FAILED; } } iterator->destroy(iterator); @@ -934,9 +907,6 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t "unable to route CHILD_SA, as its IKE_SA gets deleted"); return FAILED; case IKE_CREATED: - /* apply connection information, we need it to acquire */ - apply_config(this, connection, policy); - break; case IKE_CONNECTING: case IKE_ESTABLISHED: default: @@ -944,29 +914,37 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t } /* install kernel policies */ - child_sa = child_sa_create(this->my_host, this->other_host, - this->my_id, this->other_id, policy, FALSE, 0); + child_sa = child_sa_create(this->my_host, this->other_host, this->my_id, + this->other_id, child_cfg, FALSE, 0); - my_ts = policy->get_my_traffic_selectors(policy, this->my_host); - other_ts = policy->get_other_traffic_selectors(policy, this->other_host); + my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, + this->my_host); + other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, + this->other_host); status = child_sa->add_policies(child_sa, my_ts, other_ts, - policy->get_mode(policy)); + child_cfg->get_mode(child_cfg)); my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); - this->child_sas->insert_last(this->child_sas, child_sa); - SIG(CHILD_ROUTE_SUCCESS, "CHILD_SA routed"); + if (status == SUCCESS) + { + this->child_sas->insert_last(this->child_sas, child_sa); + SIG(CHILD_ROUTE_SUCCESS, "CHILD_SA routed"); + } + else + { + SIG(CHILD_ROUTE_FAILED, "routing CHILD_SA failed"); + } return status; } /** * Implementation of ike_sa_t.unroute. */ -static status_t unroute(private_ike_sa_t *this, policy_t *policy) +static status_t unroute(private_ike_sa_t *this, u_int32_t reqid) { iterator_t *iterator; - child_sa_t *child_sa = NULL; + child_sa_t *child_sa; bool found = FALSE; - linked_list_t *my_ts, *other_ts, *my_ts_conf, *other_ts_conf; SIG(CHILD_UNROUTE_START, "unrouting CHILD_SA"); @@ -974,27 +952,14 @@ static status_t unroute(private_ike_sa_t *this, policy_t *policy) iterator = this->child_sas->create_iterator(this->child_sas, TRUE); while (iterator->iterate(iterator, (void**)&child_sa)) { - if (child_sa->get_state(child_sa) == CHILD_ROUTED) + if (child_sa->get_state(child_sa) == CHILD_ROUTED && + child_sa->get_reqid(child_sa) == reqid) { - my_ts = child_sa->get_my_traffic_selectors(child_sa); - other_ts = child_sa->get_other_traffic_selectors(child_sa); - - my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host); - other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host); - - if (ts_list_equals(my_ts, my_ts_conf) && - ts_list_equals(other_ts, other_ts_conf)) - { - iterator->remove(iterator); - SIG(CHILD_UNROUTE_SUCCESS, "CHILD_SA unrouted"); - child_sa->destroy(child_sa); - my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy)); - other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy)); - found = TRUE; - break; - } - my_ts_conf->destroy_offset(my_ts_conf, offsetof(traffic_selector_t, destroy)); - other_ts_conf->destroy_offset(other_ts_conf, offsetof(traffic_selector_t, destroy)); + iterator->remove(iterator); + SIG(CHILD_UNROUTE_SUCCESS, "CHILD_SA unrouted"); + child_sa->destroy(child_sa); + found = TRUE; + break; } } iterator->destroy(iterator); @@ -1021,7 +986,7 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) this->time.outbound = time(NULL); if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS) { - policy_t *policy; + child_cfg_t *child_cfg; child_sa_t* child_sa; linked_list_t *to_route, *to_restart; iterator_t *iterator; @@ -1032,7 +997,7 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) case IKE_CONNECTING: { /* retry IKE_SA_INIT if we have multiple keyingtries */ - u_int32_t tries = this->connection->get_keyingtries(this->connection); + u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg); this->keyingtry++; if (tries == 0 || tries > this->keyingtry) { @@ -1060,23 +1025,23 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) iterator = this->child_sas->create_iterator(this->child_sas, TRUE); while (iterator->iterate(iterator, (void**)&child_sa)) { - policy = child_sa->get_policy(child_sa); + child_cfg = child_sa->get_config(child_sa); if (child_sa->get_state(child_sa) == CHILD_ROUTED) { /* reroute routed CHILD_SAs */ - to_route->insert_last(to_route, policy); + to_route->insert_last(to_route, child_cfg); } else { /* use DPD action for established CHILD_SAs */ - switch (policy->get_dpd_action(policy)) + switch (this->peer_cfg->get_dpd_action(this->peer_cfg)) { case DPD_ROUTE: - to_route->insert_last(to_route, policy); + to_route->insert_last(to_route, child_cfg); break; case DPD_RESTART: - to_restart->insert_last(to_restart, policy); + to_restart->insert_last(to_restart, child_cfg); break; default: break; @@ -1094,15 +1059,15 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) new = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new( charon->ike_sa_manager, TRUE); - apply_config(new, this->connection, this->policy); - /* use actual used host, not the wildcarded one in connection */ + set_peer_cfg(new, this->peer_cfg); + /* use actual used host, not the wildcarded one in config */ new->other_host->destroy(new->other_host); new->other_host = this->other_host->clone(this->other_host); /* install routes */ - while (to_route->remove_last(to_route, (void**)&policy) == SUCCESS) + while (to_route->remove_last(to_route, (void**)&child_cfg) == SUCCESS) { - route(new, new->connection, policy); + route(new, child_cfg); } /* restart children */ @@ -1114,14 +1079,14 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) new->task_manager->queue_task(new->task_manager, task); task = (task_t*)ike_cert_create(&new->public, TRUE); new->task_manager->queue_task(new->task_manager, task); - task = (task_t*)ike_config_create(&new->public, new->policy); + task = (task_t*)ike_config_create(&new->public, TRUE); new->task_manager->queue_task(new->task_manager, task); task = (task_t*)ike_auth_create(&new->public, TRUE); new->task_manager->queue_task(new->task_manager, task); - while (to_restart->remove_last(to_restart, (void**)&policy) == SUCCESS) + while (to_restart->remove_last(to_restart, (void**)&child_cfg) == SUCCESS) { - task = (task_t*)child_create_create(&new->public, policy); + task = (task_t*)child_create_create(&new->public, child_cfg); new->task_manager->queue_task(new->task_manager, task); } new->task_manager->initiate(new->task_manager); @@ -1152,19 +1117,19 @@ static prf_t *get_child_prf(private_ike_sa_t *this) } /** - * Implementation of ike_sa_t.get_auth_bild + * Implementation of ike_sa_t.get_skp_bild */ -static prf_t *get_auth_build(private_ike_sa_t *this) +static chunk_t get_skp_build(private_ike_sa_t *this) { - return this->auth_build; + return this->skp_build; } /** - * Implementation of ike_sa_t.get_auth_verify + * Implementation of ike_sa_t.get_skp_verify */ -static prf_t *get_auth_verify(private_ike_sa_t *this) +static chunk_t get_skp_verify(private_ike_sa_t *this) { - return this->auth_verify; + return this->skp_verify; } /** @@ -1210,6 +1175,71 @@ static void set_other_id(private_ike_sa_t *this, identification_t *other) } /** + * Implementation of ike_sa_t.get_other_ca. + */ +static ca_info_t* get_other_ca(private_ike_sa_t *this) +{ + return this->other_ca; +} + +/** + * Implementation of ike_sa_t.set_other_ca. + */ +static void set_other_ca(private_ike_sa_t *this, ca_info_t *other_ca) +{ + this->other_ca = other_ca; +} + +/** + * Implementation of ike_sa_t.set_virtual_ip + */ +static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip) +{ + if (local) + { + DBG1(DBG_IKE, "installing new virtual IP %H", ip); + if (this->my_virtual_ip) + { + DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip); + charon->kernel_interface->del_ip(charon->kernel_interface, + this->my_virtual_ip, + this->my_host); + this->my_virtual_ip->destroy(this->my_virtual_ip); + } + if (charon->kernel_interface->add_ip(charon->kernel_interface, ip, + this->my_host) == SUCCESS) + { + this->my_virtual_ip = ip->clone(ip); + } + else + { + DBG1(DBG_IKE, "installing virtual IP %H failed", ip); + this->my_virtual_ip = NULL; + } + } + else + { + DESTROY_IF(this->other_virtual_ip); + this->other_virtual_ip = ip->clone(ip); + } +} + +/** + * Implementation of ike_sa_t.get_virtual_ip + */ +static host_t* get_virtual_ip(private_ike_sa_t *this, bool local) +{ + if (local) + { + return this->my_virtual_ip; + } + else + { + return this->other_virtual_ip; + } +} + +/** * Implementation of ike_sa_t.derive_keys. */ static status_t derive_keys(private_ike_sa_t *this, @@ -1223,7 +1253,6 @@ static status_t derive_keys(private_ike_sa_t *this, size_t key_size; crypter_t *crypter_i, *crypter_r; signer_t *signer_i, *signer_r; - prf_t *prf_i, *prf_r; u_int8_t spi_i_buf[sizeof(u_int64_t)], spi_r_buf[sizeof(u_int64_t)]; chunk_t spi_i = chunk_from_buf(spi_i_buf); chunk_t spi_r = chunk_from_buf(spi_r_buf); @@ -1364,31 +1393,27 @@ static status_t derive_keys(private_ike_sa_t *this, this->crypter_out = crypter_r; } - /* SK_pi/SK_pr used for authentication => prf_auth_i, prf_auth_r */ - proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo); - prf_i = prf_create(algo->algorithm); - prf_r = prf_create(algo->algorithm); - - key_size = prf_i->get_key_size(prf_i); + /* SK_pi/SK_pr used for authentication => stored for later */ + key_size = this->prf->get_key_size(this->prf); prf_plus->allocate_bytes(prf_plus, key_size, &key); DBG4(DBG_IKE, "Sk_pi secret %B", &key); - prf_i->set_key(prf_i, key); - chunk_free(&key); - + if (initiator) + { + this->skp_build = key; + } + else + { + this->skp_verify = key; + } prf_plus->allocate_bytes(prf_plus, key_size, &key); DBG4(DBG_IKE, "Sk_pr secret %B", &key); - prf_r->set_key(prf_r, key); - chunk_free(&key); - if (initiator) { - this->auth_verify = prf_r; - this->auth_build = prf_i; + this->skp_verify = key; } else { - this->auth_verify = prf_i; - this->auth_build = prf_r; + this->skp_build = key; } /* all done, prf_plus not needed anymore */ @@ -1507,8 +1532,6 @@ static status_t delete_(private_ike_sa_t *this) switch (this->state) { case IKE_ESTABLISHED: - DBG1(DBG_IKE, "deleting IKE_SA"); - /* do not log when rekeyed */ case IKE_REKEYING: ike_delete = ike_delete_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, &ike_delete->task); @@ -1542,16 +1565,21 @@ static void reestablish(private_ike_sa_t *this) private_ike_sa_t *other; iterator_t *iterator; child_sa_t *child_sa; - policy_t *policy; + child_cfg_t *child_cfg; task_t *task; job_t *job; other = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new( charon->ike_sa_manager, TRUE); - apply_config(other, this->connection, this->policy); + set_peer_cfg(other, this->peer_cfg); other->other_host->destroy(other->other_host); other->other_host = this->other_host->clone(this->other_host); + if (this->my_virtual_ip) + { + /* if we already have a virtual IP, we reuse it */ + set_virtual_ip(other, TRUE, this->my_virtual_ip); + } if (this->state == IKE_ESTABLISHED) { @@ -1561,7 +1589,7 @@ static void reestablish(private_ike_sa_t *this) other->task_manager->queue_task(other->task_manager, task); task = (task_t*)ike_cert_create(&other->public, TRUE); other->task_manager->queue_task(other->task_manager, task); - task = (task_t*)ike_config_create(&other->public, other->policy); + task = (task_t*)ike_config_create(&other->public, TRUE); other->task_manager->queue_task(other->task_manager, task); task = (task_t*)ike_auth_create(&other->public, TRUE); other->task_manager->queue_task(other->task_manager, task); @@ -1583,8 +1611,8 @@ static void reestablish(private_ike_sa_t *this) } default: { - policy = child_sa->get_policy(child_sa); - task = (task_t*)child_create_create(&other->public, policy); + child_cfg = child_sa->get_config(child_sa); + task = (task_t*)child_create_create(&other->public, child_cfg); other->task_manager->queue_task(other->task_manager, task); break; } @@ -1678,55 +1706,6 @@ static void enable_natt(private_ike_sa_t *this, bool local) } /** - * Implementation of ike_sa_t.set_virtual_ip - */ -static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip) -{ - if (local) - { - DBG1(DBG_IKE, "installing new virtual IP %H", ip); - if (this->my_virtual_ip) - { - DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip); - charon->kernel_interface->del_ip(charon->kernel_interface, - this->my_virtual_ip, - this->my_host); - this->my_virtual_ip->destroy(this->my_virtual_ip); - } - if (charon->kernel_interface->add_ip(charon->kernel_interface, ip, - this->my_host) == SUCCESS) - { - this->my_virtual_ip = ip->clone(ip); - } - else - { - DBG1(DBG_IKE, "installing virtual IP %H failed", ip); - this->my_virtual_ip = NULL; - } - } - else - { - DESTROY_IF(this->other_virtual_ip); - this->other_virtual_ip = ip->clone(ip); - } -} - -/** - * Implementation of ike_sa_t.get_virtual_ip - */ -static host_t* get_virtual_ip(private_ike_sa_t *this, bool local) -{ - if (local) - { - return this->my_virtual_ip; - } - else - { - return this->other_virtual_ip; - } -} - -/** * Implementation of ike_sa_t.remove_dns_server */ static void remove_dns_servers(private_ike_sa_t *this) @@ -1747,7 +1726,8 @@ static void remove_dns_servers(private_ike_sa_t *this) file = fopen(RESOLV_CONF, "r"); if (file == NULL || stat(RESOLV_CONF, &stats) != 0) { - DBG1(DBG_IKE, "unable to open DNS configuration file %s: %m", RESOLV_CONF); + DBG1(DBG_IKE, "unable to open DNS configuration file %s: %s", + RESOLV_CONF, strerror(errno)); return; } @@ -1755,7 +1735,7 @@ static void remove_dns_servers(private_ike_sa_t *this) if (fread(contents.ptr, 1, contents.len, file) != contents.len) { - DBG1(DBG_IKE, "unable to read DNS configuration file: %m"); + DBG1(DBG_IKE, "unable to read DNS configuration file: %s", strerror(errno)); fclose(file); return; } @@ -1764,7 +1744,8 @@ static void remove_dns_servers(private_ike_sa_t *this) file = fopen(RESOLV_CONF, "w"); if (file == NULL) { - DBG1(DBG_IKE, "unable to open DNS configuration file %s: %m", RESOLV_CONF); + DBG1(DBG_IKE, "unable to open DNS configuration file %s: %s", + RESOLV_CONF, strerror(errno)); return; } @@ -1820,7 +1801,8 @@ static void add_dns_server(private_ike_sa_t *this, host_t *dns) file = fopen(RESOLV_CONF, "a+"); if (file == NULL || stat(RESOLV_CONF, &stats) != 0) { - DBG1(DBG_IKE, "unable to open DNS configuration file %s: %m", RESOLV_CONF); + DBG1(DBG_IKE, "unable to open DNS configuration file %s: %s", + RESOLV_CONF, strerror(errno)); return; } @@ -1828,7 +1810,7 @@ static void add_dns_server(private_ike_sa_t *this, host_t *dns) if (fread(contents.ptr, 1, contents.len, file) != contents.len) { - DBG1(DBG_IKE, "unable to read DNS configuration file: %m"); + DBG1(DBG_IKE, "unable to read DNS configuration file: %s", strerror(errno)); fclose(file); return; } @@ -1837,14 +1819,15 @@ static void add_dns_server(private_ike_sa_t *this, host_t *dns) file = fopen(RESOLV_CONF, "w"); if (file == NULL) { - DBG1(DBG_IKE, "unable to open DNS configuration file %s: %m", RESOLV_CONF); + DBG1(DBG_IKE, "unable to open DNS configuration file %s: %s", + RESOLV_CONF, strerror(errno)); return; } if (fprintf(file, "nameserver %H # added by strongSwan, assigned by %D\n", dns, this->other_id) < 0) { - DBG1(DBG_IKE, "unable to write DNS configuration: %m"); + DBG1(DBG_IKE, "unable to write DNS configuration: %s", strerror(errno)); } else { @@ -1856,50 +1839,6 @@ static void add_dns_server(private_ike_sa_t *this, host_t *dns) } /** - * output handler in printf() - */ -static int print(FILE *stream, const struct printf_info *info, - const void *const *args) -{ - int written = 0; - bool reauth = FALSE; - private_ike_sa_t *this = *((private_ike_sa_t**)(args[0])); - - if (this->connection) - { - reauth = this->connection->get_reauth(this->connection); - } - - if (this == NULL) - { - return fprintf(stream, "(null)"); - } - - written = fprintf(stream, "%12s[%d]: %N, %H[%D]...%H[%D]", get_name(this), - this->unique_id, ike_sa_state_names, this->state, - this->my_host, this->my_id, this->other_host, - this->other_id); - written += fprintf(stream, "\n%12s[%d]: IKE SPIs: %J, %s in %ds", - get_name(this), this->unique_id, this->ike_sa_id, - this->connection && reauth? "reauthentication":"rekeying", - this->time.rekey - time(NULL)); - - if (info->alt) - { - - } - return written; -} - -/** - * register printf() handlers - */ -static void __attribute__ ((constructor))print_register() -{ - register_printf_function(PRINTF_IKE_SA, print, arginfo_ptr); -} - -/** * Implementation of ike_sa_t.destroy. */ static void destroy(private_ike_sa_t *this) @@ -1912,8 +1851,8 @@ static void destroy(private_ike_sa_t *this) DESTROY_IF(this->signer_out); DESTROY_IF(this->prf); DESTROY_IF(this->child_prf); - DESTROY_IF(this->auth_verify); - DESTROY_IF(this->auth_build); + chunk_free(&this->skp_verify); + chunk_free(&this->skp_build); if (this->my_virtual_ip) { @@ -1931,8 +1870,8 @@ static void destroy(private_ike_sa_t *this) DESTROY_IF(this->my_id); DESTROY_IF(this->other_id); - DESTROY_IF(this->connection); - DESTROY_IF(this->policy); + DESTROY_IF(this->ike_cfg); + DESTROY_IF(this->peer_cfg); this->ike_sa_id->destroy(this->ike_sa_id); this->task_manager->destroy(this->task_manager); @@ -1948,54 +1887,57 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) static u_int32_t unique_id = 0; /* 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.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message; - this->public.initiate = (status_t(*)(ike_sa_t*,connection_t*,policy_t*)) initiate; - this->public.route = (status_t(*)(ike_sa_t*,connection_t*,policy_t*)) route; - this->public.unroute = (status_t(*)(ike_sa_t*,policy_t*)) unroute; - this->public.acquire = (status_t(*)(ike_sa_t*,u_int32_t)) acquire; - this->public.get_connection = (connection_t*(*)(ike_sa_t*))get_connection; - this->public.set_connection = (void(*)(ike_sa_t*,connection_t*))set_connection; - this->public.get_policy = (policy_t*(*)(ike_sa_t*))get_policy; - this->public.set_policy = (void(*)(ike_sa_t*,policy_t*))set_policy; - 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.set_my_host = (void(*)(ike_sa_t*,host_t*)) set_my_host; - this->public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host; - this->public.set_other_host = (void(*)(ike_sa_t*,host_t*)) set_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.retransmit = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit; - this->public.delete = (status_t(*)(ike_sa_t*))delete_; - this->public.destroy = (void(*)(ike_sa_t*))destroy; + 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_stats = (void (*)(ike_sa_t*,u_int32_t*))get_stats; + this->public.get_name = (char* (*)(ike_sa_t*))get_name; + this->public.process_message = (status_t (*)(ike_sa_t*, message_t*)) process_message; + this->public.initiate = (status_t (*)(ike_sa_t*,child_cfg_t*)) initiate; + this->public.route = (status_t (*)(ike_sa_t*,child_cfg_t*)) route; + this->public.unroute = (status_t (*)(ike_sa_t*,u_int32_t)) unroute; + this->public.acquire = (status_t (*)(ike_sa_t*,u_int32_t)) acquire; + this->public.get_ike_cfg = (ike_cfg_t* (*)(ike_sa_t*))get_ike_cfg; + this->public.set_ike_cfg = (void (*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg; + this->public.get_peer_cfg = (peer_cfg_t* (*)(ike_sa_t*))get_peer_cfg; + this->public.set_peer_cfg = (void (*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg; + 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.set_my_host = (void (*)(ike_sa_t*,host_t*)) set_my_host; + this->public.get_other_host = (host_t* (*)(ike_sa_t*)) get_other_host; + this->public.set_other_host = (void (*)(ike_sa_t*,host_t*)) set_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_other_ca = (ca_info_t* (*)(ike_sa_t*)) get_other_ca; + this->public.set_other_ca = (void (*)(ike_sa_t*,ca_info_t*)) set_other_ca; + this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit; + this->public.delete = (status_t (*)(ike_sa_t*))delete_; + this->public.destroy = (void (*)(ike_sa_t*))destroy; this->public.send_dpd = (status_t (*)(ike_sa_t*)) send_dpd; this->public.send_keepalive = (void (*)(ike_sa_t*)) send_keepalive; - this->public.get_prf = (prf_t *(*) (ike_sa_t *)) get_prf; - this->public.get_child_prf = (prf_t *(*) (ike_sa_t *)) get_child_prf; - this->public.get_auth_verify = (prf_t *(*) (ike_sa_t *)) get_auth_verify; - this->public.get_auth_build = (prf_t *(*) (ike_sa_t *)) get_auth_build; - this->public.derive_keys = (status_t (*) (ike_sa_t *,proposal_t*,chunk_t,chunk_t,chunk_t,bool,prf_t*,prf_t*)) derive_keys; - this->public.add_child_sa = (void (*) (ike_sa_t*,child_sa_t*)) add_child_sa; + this->public.get_prf = (prf_t* (*)(ike_sa_t*)) get_prf; + this->public.get_child_prf = (prf_t* (*)(ike_sa_t *)) get_child_prf; + this->public.get_skp_verify = (chunk_t (*)(ike_sa_t *)) get_skp_verify; + this->public.get_skp_build = (chunk_t (*)(ike_sa_t *)) get_skp_build; + this->public.derive_keys = (status_t (*)(ike_sa_t *,proposal_t*,chunk_t,chunk_t,chunk_t,bool,prf_t*,prf_t*)) derive_keys; + 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; this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator; - this->public.rekey_child_sa = (status_t(*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa; - this->public.delete_child_sa = (status_t(*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa; + this->public.rekey_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa; + this->public.delete_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa; this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa; - this->public.enable_natt = (void(*)(ike_sa_t*, bool)) enable_natt; - this->public.is_natt_enabled = (bool(*)(ike_sa_t*)) is_natt_enabled; - this->public.rekey = (status_t(*)(ike_sa_t*))rekey; - this->public.reestablish = (void(*)(ike_sa_t*))reestablish; - this->public.inherit = (status_t(*)(ike_sa_t*,ike_sa_t*))inherit; - this->public.generate_message = (status_t(*)(ike_sa_t*,message_t*,packet_t**))generate_message; - this->public.reset = (void(*)(ike_sa_t*))reset; - this->public.get_unique_id = (u_int32_t(*)(ike_sa_t*))get_unique_id; - this->public.set_virtual_ip = (void(*)(ike_sa_t*,bool,host_t*))set_virtual_ip; - this->public.get_virtual_ip = (host_t*(*)(ike_sa_t*,bool))get_virtual_ip; - this->public.add_dns_server = (void(*)(ike_sa_t*,host_t*))add_dns_server; + this->public.enable_natt = (void (*)(ike_sa_t*, bool)) enable_natt; + this->public.is_natt_enabled = (bool (*)(ike_sa_t*)) is_natt_enabled; + this->public.rekey = (status_t (*)(ike_sa_t*))rekey; + this->public.reestablish = (void (*)(ike_sa_t*))reestablish; + this->public.inherit = (status_t (*)(ike_sa_t*,ike_sa_t*))inherit; + this->public.generate_message = (status_t (*)(ike_sa_t*,message_t*,packet_t**))generate_message; + this->public.reset = (void (*)(ike_sa_t*))reset; + this->public.get_unique_id = (u_int32_t (*)(ike_sa_t*))get_unique_id; + this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip; + this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip; + this->public.add_dns_server = (void (*)(ike_sa_t*,host_t*))add_dns_server; /* initialize private fields */ this->ike_sa_id = ike_sa_id->clone(ike_sa_id); @@ -2004,13 +1946,14 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->other_host = host_create_any(AF_INET); this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty); this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty); + this->other_ca = NULL; this->crypter_in = NULL; this->crypter_out = NULL; this->signer_in = NULL; this->signer_out = NULL; this->prf = NULL; - this->auth_verify = NULL; - this->auth_build = NULL; + this->skp_verify = chunk_empty; + this->skp_build = chunk_empty; this->child_prf = NULL; this->nat_here = FALSE; this->nat_there = FALSE; @@ -2019,8 +1962,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->time.established = 0; this->time.rekey = 0; this->time.delete = 0; - this->connection = NULL; - this->policy = NULL; + this->ike_cfg = NULL; + this->peer_cfg = NULL; this->task_manager = task_manager_create(&this->public); this->unique_id = ++unique_id; this->my_virtual_ip = NULL; |