diff options
-rw-r--r-- | src/libcharon/control/controller.c | 11 | ||||
-rw-r--r-- | src/libcharon/plugins/android/android_service.c | 11 | ||||
-rw-r--r-- | src/libcharon/plugins/maemo/maemo_service.c | 10 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_service.c | 8 | ||||
-rw-r--r-- | src/libcharon/sa/ike_sa.c | 26 | ||||
-rw-r--r-- | src/libcharon/sa/ike_sa_manager.c | 37 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_reauth.c | 10 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_rekey.c | 16 | ||||
-rw-r--r-- | src/libcharon/sa/trap_manager.c | 29 |
9 files changed, 111 insertions, 47 deletions
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c index 0f247962b..4aded8f9d 100644 --- a/src/libcharon/control/controller.c +++ b/src/libcharon/control/controller.c @@ -217,6 +217,17 @@ METHOD(job_t, initiate_execute, void, ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, peer_cfg); + if (!ike_sa) + { + listener->child_cfg->destroy(listener->child_cfg); + peer_cfg->destroy(peer_cfg); + /* trigger down event to release listener */ + listener->ike_sa = charon->ike_sa_manager->checkout_new( + charon->ike_sa_manager, IKE_ANY, TRUE); + DESTROY_IF(listener->ike_sa); + listener->status = FAILED; + return; + } listener->ike_sa = ike_sa; if (ike_sa->get_peer_cfg(ike_sa) == NULL) diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c index 96603ab29..8aba925a2 100644 --- a/src/libcharon/plugins/android/android_service.c +++ b/src/libcharon/plugins/android/android_service.c @@ -300,12 +300,17 @@ static job_requeue_t initiate(private_android_service_t *this) 0, "255.255.255.255", 65535); child_cfg->add_traffic_selector(child_cfg, FALSE, ts); peer_cfg->add_child_cfg(peer_cfg, child_cfg); - /* get an additional reference because initiate consumes one */ - child_cfg->get_ref(child_cfg); /* get us an IKE_SA */ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, peer_cfg); + if (!ike_sa) + { + peer_cfg->destroy(peer_cfg); + send_status(this, VPN_ERROR_CONNECTION_FAILED); + return JOB_REQUEUE_NONE; + } + if (!ike_sa->get_peer_cfg(ike_sa)) { ike_sa->set_peer_cfg(ike_sa, peer_cfg); @@ -318,6 +323,8 @@ static job_requeue_t initiate(private_android_service_t *this) /* confirm that we received the request */ send_status(this, i); + /* get an additional reference because initiate consumes one */ + child_cfg->get_ref(child_cfg); if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS) { DBG1(DBG_CFG, "failed to initiate tunnel"); diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c index 58361a408..69eac084c 100644 --- a/src/libcharon/plugins/maemo/maemo_service.c +++ b/src/libcharon/plugins/maemo/maemo_service.c @@ -355,12 +355,16 @@ static gboolean initiate_connection(private_maemo_service_t *this, 0, "255.255.255.255", 65535); child_cfg->add_traffic_selector(child_cfg, FALSE, ts); peer_cfg->add_child_cfg(peer_cfg, child_cfg); - /* get an additional reference because initiate consumes one */ - child_cfg->get_ref(child_cfg); /* get us an IKE_SA */ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, peer_cfg); + if (!ike_sa) + { + peer_cfg->destroy(peer_cfg); + this->status = VPN_STATUS_CONNECTION_FAILED; + return FALSE; + } if (!ike_sa->get_peer_cfg(ike_sa)) { ike_sa->set_peer_cfg(ike_sa, peer_cfg); @@ -374,6 +378,8 @@ static gboolean initiate_connection(private_maemo_service_t *this, this->public.listener.ike_state_change = _ike_state_change; charon->bus->add_listener(charon->bus, &this->public.listener); + /* get an additional reference because initiate consumes one */ + child_cfg->get_ref(child_cfg); if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS) { DBG1(DBG_CFG, "failed to initiate tunnel"); diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c index 8135476fd..788291531 100644 --- a/src/libcharon/plugins/nm/nm_service.c +++ b/src/libcharon/plugins/nm/nm_service.c @@ -533,6 +533,13 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, */ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, peer_cfg); + if (!ike_sa) + { + peer_cfg->destroy(peer_cfg); + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, + "IKE version not supported."); + return FALSE; + } if (!ike_sa->get_peer_cfg(ike_sa)) { ike_sa->set_peer_cfg(ike_sa, peer_cfg); @@ -550,6 +557,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, /** * Initiate */ + child_cfg->get_ref(child_cfg); if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS) { charon->bus->remove_listener(charon->bus, &priv->listener); diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 78ffbe5b9..442eb7208 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -1412,6 +1412,10 @@ METHOD(ike_sa_t, reestablish, status_t, new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, this->version, TRUE); + if (!new) + { + return FAILED; + } new->set_peer_cfg(new, this->peer_cfg); host = this->other_host; new->set_other_host(new, host->clone(host)); @@ -1802,7 +1806,7 @@ METHOD(ike_sa_t, destroy, void, charon->bus->set_sa(charon->bus, &this->public); set_state(this, IKE_DESTROYING); - this->task_manager->destroy(this->task_manager); + DESTROY_IF(this->task_manager); /* remove attributes first, as we pass the IKE_SA to the handler */ while (this->attributes->remove_last(this->attributes, @@ -1820,7 +1824,7 @@ METHOD(ike_sa_t, destroy, void, /* unset SA after here to avoid usage by the listeners */ charon->bus->set_sa(charon->bus, NULL); - this->keymat->destroy(this->keymat); + DESTROY_IF(this->keymat); if (this->my_virtual_ip) { @@ -1881,6 +1885,15 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, private_ike_sa_t *this; static u_int32_t unique_id = 0; + if (version == IKE_ANY) + { /* prefer IKEv2 if protocol not specified */ +#ifdef USE_IKEV2 + version = IKEV2; +#else + version = IKEV1; +#endif + } + INIT(this, .public = { .get_version = _get_version, @@ -1991,8 +2004,11 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, this->task_manager = task_manager_create(&this->public); this->my_host->set_port(this->my_host, IKEV2_UDP_PORT); - /* TODO-IKEv1: check if keymat and task manager created successfully. - * Return NULL otherwise? */ - + if (!this->task_manager || !this->keymat) + { + DBG1(DBG_IKE, "IKE version %d not supported", this->version); + destroy(this); + return NULL; + } return &this->public; } diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index 776b2b7ae..d992ce1dc 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -955,9 +955,11 @@ METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*, ike_sa = ike_sa_create(ike_sa_id, initiator, version); ike_sa_id->destroy(ike_sa_id); - DBG2(DBG_MGR, "created IKE_SA %s[%u]", ike_sa->get_name(ike_sa), - ike_sa->get_unique_id(ike_sa)); - + if (ike_sa) + { + DBG2(DBG_MGR, "created IKE_SA %s[%u]", ike_sa->get_name(ike_sa), + ike_sa->get_unique_id(ike_sa)); + } return ike_sa; } @@ -1033,23 +1035,26 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, { /* no IKE_SA found, create a new one */ id->set_responder_spi(id, get_spi(this)); - entry = entry_create(); - /* a new SA checked out by message is a responder SA */ - entry->ike_sa = ike_sa_create(id, FALSE, ike_version); - entry->ike_sa_id = id->clone(id); + ike_sa = ike_sa_create(id, FALSE, ike_version); + if (ike_sa) + { + entry = entry_create(); + /* a new SA checked out by message is a responder SA */ + entry->ike_sa = ike_sa; + entry->ike_sa_id = id->clone(id); - segment = put_entry(this, entry); - entry->checked_out = TRUE; - unlock_single_segment(this, segment); + segment = put_entry(this, entry); + entry->checked_out = TRUE; + unlock_single_segment(this, segment); - entry->message_id = message->get_message_id(message); - entry->init_hash = hash; - ike_sa = entry->ike_sa; + entry->message_id = message->get_message_id(message); + entry->init_hash = hash; - DBG2(DBG_MGR, "created IKE_SA %s[%u]", - ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); + DBG2(DBG_MGR, "created IKE_SA %s[%u]", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); + } } - else + if (ike_sa == NULL) { chunk_free(&hash); DBG1(DBG_MGR, "ignoring message, no such IKE_SA"); diff --git a/src/libcharon/sa/ikev2/tasks/ike_reauth.c b/src/libcharon/sa/ikev2/tasks/ike_reauth.c index d9f3fe8de..8371b8b6a 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_reauth.c +++ b/src/libcharon/sa/ikev2/tasks/ike_reauth.c @@ -54,7 +54,6 @@ METHOD(task_t, process_i, status_t, ike_sa_t *new; host_t *host; enumerator_t *enumerator; - ike_version_t version; child_sa_t *child_sa; peer_cfg_t *peer_cfg; @@ -75,9 +74,12 @@ METHOD(task_t, process_i, status_t, return FAILED; } - version = this->ike_sa->get_version(this->ike_sa); - new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, version, - TRUE); + new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, + this->ike_sa->get_version(this->ike_sa), TRUE); + if (!new) + { /* shouldn't happen */ + return FAILED; + } new->set_peer_cfg(new, peer_cfg); host = this->ike_sa->get_other_host(this->ike_sa); diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c index 2cfcdc1fc..c3c6cf00e 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c @@ -123,16 +123,20 @@ METHOD(task_t, process_i_delete, status_t, METHOD(task_t, build_i, status_t, private_ike_rekey_t *this, message_t *message) { + ike_version_t version; peer_cfg_t *peer_cfg; host_t *other_host; /* create new SA only on first try */ if (this->new_sa == NULL) { - ike_version_t version = this->ike_sa->get_version(this->ike_sa); + version = this->ike_sa->get_version(this->ike_sa); this->new_sa = charon->ike_sa_manager->checkout_new( charon->ike_sa_manager, version, TRUE); - + if (!this->new_sa) + { /* shouldn't happen */ + return FAILED; + } peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); other_host = this->ike_sa->get_other_host(this->ike_sa); this->new_sa->set_peer_cfg(this->new_sa, peer_cfg); @@ -149,7 +153,6 @@ METHOD(task_t, process_r, status_t, private_ike_rekey_t *this, message_t *message) { enumerator_t *enumerator; - ike_version_t version; peer_cfg_t *peer_cfg; child_sa_t *child_sa; @@ -177,9 +180,12 @@ METHOD(task_t, process_r, status_t, } enumerator->destroy(enumerator); - version = this->ike_sa->get_version(this->ike_sa); this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, - version, FALSE); + this->ike_sa->get_version(this->ike_sa), FALSE); + if (!this->new_sa) + { /* shouldn't happen */ + return FAILED; + } peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); this->new_sa->set_peer_cfg(this->new_sa, peer_cfg); diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c index bf9f8432c..3f434dae1 100644 --- a/src/libcharon/sa/trap_manager.c +++ b/src/libcharon/sa/trap_manager.c @@ -274,21 +274,24 @@ METHOD(trap_manager_t, acquire, void, peer = found->peer_cfg; ike_sa = charon->ike_sa_manager->checkout_by_config( charon->ike_sa_manager, peer); - if (ike_sa->get_peer_cfg(ike_sa) == NULL) + if (ike_sa) { - ike_sa->set_peer_cfg(ike_sa, peer); - } - child->get_ref(child); - reqid = found->child_sa->get_reqid(found->child_sa); - if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME) - { - found->pending = ike_sa; - charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - } - else - { - charon->ike_sa_manager->checkin_and_destroy( + if (ike_sa->get_peer_cfg(ike_sa) == NULL) + { + ike_sa->set_peer_cfg(ike_sa, peer); + } + child->get_ref(child); + reqid = found->child_sa->get_reqid(found->child_sa); + if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME) + { + found->pending = ike_sa; + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + else + { + charon->ike_sa_manager->checkin_and_destroy( charon->ike_sa_manager, ike_sa); + } } } this->lock->unlock(this->lock); |