From: Martin Willi Date: Wed, 4 Jan 2012 16:51:22 +0000 (+0100) Subject: Try to detect reauthentication as responder and adopt children to new SA X-Git-Tag: 5.0.0~338^2~9^2~91 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b147679a2c1b3c232a13f8f58418b4976571b8da;p=thirdparty%2Fstrongswan.git Try to detect reauthentication as responder and adopt children to new SA --- diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 8db43f1883..979b725c32 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -114,7 +114,8 @@ sa/ikev1/tasks/isakmp_delete.c sa/ikev1/tasks/isakmp_delete.h \ sa/ikev1/tasks/xauth.c sa/ikev1/tasks/xauth.h \ sa/ikev1/tasks/quick_mode.c sa/ikev1/tasks/quick_mode.h \ sa/ikev1/tasks/quick_delete.c sa/ikev1/tasks/quick_delete.h \ -sa/ikev1/tasks/mode_config.c sa/ikev1/tasks/mode_config.h +sa/ikev1/tasks/mode_config.c sa/ikev1/tasks/mode_config.h \ +processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h endif diff --git a/src/libcharon/processing/jobs/adopt_children_job.c b/src/libcharon/processing/jobs/adopt_children_job.c new file mode 100644 index 0000000000..6f7e119da8 --- /dev/null +++ b/src/libcharon/processing/jobs/adopt_children_job.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "adopt_children_job.h" + +#include +#include + +typedef struct private_adopt_children_job_t private_adopt_children_job_t; + +/** + * Private data of an adopt_children_job_t object. + */ +struct private_adopt_children_job_t { + + /** + * Public adopt_children_job_t interface. + */ + adopt_children_job_t public; + + /** + * IKE_SA id to adopt children from + */ + ike_sa_id_t *id; +}; + +METHOD(job_t, destroy, void, + private_adopt_children_job_t *this) +{ + this->id->destroy(this->id); + free(this); +} + +METHOD(job_t, execute, void, + private_adopt_children_job_t *this) +{ + identification_t *my_id, *other_id, *xauth; + host_t *me, *other; + peer_cfg_t *cfg; + linked_list_t *children; + enumerator_t *enumerator, *childenum; + ike_sa_id_t *id; + ike_sa_t *ike_sa; + child_sa_t *child_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->id); + if (ike_sa) + { + /* get what we need from new SA */ + me = ike_sa->get_my_host(ike_sa); + me = me->clone(me); + other = ike_sa->get_other_host(ike_sa); + other = other->clone(other); + my_id = ike_sa->get_my_id(ike_sa); + my_id = my_id->clone(my_id); + other_id = ike_sa->get_other_id(ike_sa); + other_id = other_id->clone(other_id); + xauth = ike_sa->get_other_eap_id(ike_sa); + xauth = xauth->clone(xauth); + cfg = ike_sa->get_peer_cfg(ike_sa); + cfg->get_ref(cfg); + + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + + /* find old SA to adopt children from */ + children = linked_list_create(); + enumerator = charon->ike_sa_manager->create_id_enumerator( + charon->ike_sa_manager, my_id, other_id, + other->get_family(other)); + while (enumerator->enumerate(enumerator, &id)) + { + if (id->equals(id, this->id)) + { /* not from self */ + continue; + } + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id); + if (ike_sa) + { + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && + me->equals(me, ike_sa->get_my_host(ike_sa)) && + other->equals(other, ike_sa->get_other_host(ike_sa)) && + xauth->equals(xauth, ike_sa->get_other_eap_id(ike_sa)) && + cfg->equals(cfg, ike_sa->get_peer_cfg(ike_sa))) + { + childenum = ike_sa->create_child_sa_enumerator(ike_sa); + while (childenum->enumerate(childenum, &child_sa)) + { + ike_sa->remove_child_sa(ike_sa, childenum); + children->insert_last(children, child_sa); + } + childenum->destroy(childenum); + DBG1(DBG_IKE, "detected reauth of existing IKE_SA, " + "adopting %d children", children->get_count(children)); + ike_sa->set_state(ike_sa, IKE_DELETING); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, ike_sa); + } + else + { + charon->ike_sa_manager->checkin( + charon->ike_sa_manager, ike_sa); + } + if (children->get_count(children)) + { + break; + } + } + } + enumerator->destroy(enumerator); + + me->destroy(me); + other->destroy(other); + my_id->destroy(my_id); + other_id->destroy(other_id); + xauth->destroy(xauth); + cfg->destroy(cfg); + + if (children->get_count(children)) + { + /* adopt children by new SA */ + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->id); + if (ike_sa) + { + while (children->remove_last(children, + (void**)&child_sa) == SUCCESS) + { + ike_sa->add_child_sa(ike_sa, child_sa); + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + } + children->destroy_offset(children, offsetof(child_sa_t, destroy)); + } + destroy(this); +} + +METHOD(job_t, get_priority, job_priority_t, + private_adopt_children_job_t *this) +{ + return JOB_PRIO_HIGH; +} + +/** + * See header + */ +adopt_children_job_t *adopt_children_job_create(ike_sa_id_t *id) +{ + private_adopt_children_job_t *this; + + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .get_priority = _get_priority, + .destroy = _destroy, + }, + }, + .id = id->clone(id), + ); + + return &this->public; +} diff --git a/src/libcharon/processing/jobs/adopt_children_job.h b/src/libcharon/processing/jobs/adopt_children_job.h new file mode 100644 index 0000000000..073504abd1 --- /dev/null +++ b/src/libcharon/processing/jobs/adopt_children_job.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup adopt_children_job adopt_children_job + * @{ @ingroup cjobs + */ + +#ifndef ADOPT_CHILDREN_JOB_H_ +#define ADOPT_CHILDREN_JOB_H_ + +#include +#include +#include + +typedef struct adopt_children_job_t adopt_children_job_t; + +/** + * Job adopting children after IKEv1 reauthentication from old SA. + */ +struct adopt_children_job_t { + + /** + * Implements job_t. + */ + job_t job_interface; +}; + +/** + * Create a adopt_children_job instance. + * + * @param id ike_sa_id_t of old ISAKMP SA to adopt children from + * @return job + */ +adopt_children_job_t *adopt_children_job_create(ike_sa_id_t *id); + +#endif /** ADOPT_CHILDREN_JOB_H_ @}*/ diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c index 75f167b1d0..3c0a2520e7 100644 --- a/src/libcharon/sa/ikev1/tasks/main_mode.c +++ b/src/libcharon/sa/ikev1/tasks/main_mode.c @@ -32,6 +32,7 @@ #include #include #include +#include typedef struct private_main_mode_t private_main_mode_t; @@ -966,6 +967,9 @@ METHOD(task_t, build_r, status_t, return FAILED; default: establish(this); + lib->processor->queue_job(lib->processor, (job_t*) + adopt_children_job_create( + this->ike_sa->get_id(this->ike_sa))); return SUCCESS; } } diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c index 8d8744b3d2..e836bed16c 100755 --- a/src/libcharon/sa/ikev1/tasks/xauth.c +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -18,6 +18,7 @@ #include #include #include +#include typedef struct private_xauth_t private_xauth_t; @@ -212,6 +213,8 @@ METHOD(task_t, build_r_ack, status_t, if (this->status == XAUTH_OK) { establish(this); + lib->processor->queue_job(lib->processor, (job_t*) + adopt_children_job_create(this->ike_sa->get_id(this->ike_sa))); return SUCCESS; } return FAILED;