diff options
author | Tobias Brunner <tobias@strongswan.org> | 2016-05-06 09:08:08 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2016-06-06 13:57:58 +0200 |
commit | 0a72d68ea824601358cd35dd4696a2a49dbdfdb4 (patch) | |
tree | abc63849ec86ab40811d541f4174af73aee914a2 /src/libcharon/control/controller.c | |
parent | 1b4e7fe1e83b685b79d87dba5df42b6a852845f1 (diff) | |
download | strongswan-0a72d68ea824601358cd35dd4696a2a49dbdfdb4.tar.bz2 strongswan-0a72d68ea824601358cd35dd4696a2a49dbdfdb4.tar.xz |
controller: Use separate callbacks to track termination and initiation of SAs
If a local authentication failure occurs in IKEv1 we delete the IKE_SA, which
we don't want the controller to detect as success.
Fixes #1449.
Diffstat (limited to 'src/libcharon/control/controller.c')
-rw-r--r-- | src/libcharon/control/controller.c | 66 |
1 files changed, 58 insertions, 8 deletions
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c index 3aed41418..93ff70bf3 100644 --- a/src/libcharon/control/controller.c +++ b/src/libcharon/control/controller.c @@ -272,6 +272,28 @@ METHOD(listener_t, ike_state_change, bool, } #endif /* ME */ case IKE_DESTROYING: + return listener_done(this); + default: + break; + } + } + return TRUE; +} + +METHOD(listener_t, ike_state_change_terminate, bool, + interface_listener_t *this, ike_sa_t *ike_sa, ike_sa_state_t state) +{ + ike_sa_t *target; + + this->lock->lock(this->lock); + target = this->ike_sa; + this->lock->unlock(this->lock); + + if (target == ike_sa) + { + switch (state) + { + case IKE_DESTROYING: if (ike_sa->get_state(ike_sa) == IKE_DELETING) { /* proper termination */ this->status = SUCCESS; @@ -304,10 +326,6 @@ METHOD(listener_t, child_state_change, bool, case CHILD_DESTROYING: switch (child_sa->get_state(child_sa)) { - case CHILD_DELETING: - /* proper delete */ - this->status = SUCCESS; - break; case CHILD_RETRYING: /* retrying with a different DH group; survive another * initiation round */ @@ -331,6 +349,38 @@ METHOD(listener_t, child_state_change, bool, return TRUE; } +METHOD(listener_t, child_state_change_terminate, bool, + interface_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + child_sa_state_t state) +{ + ike_sa_t *target; + + this->lock->lock(this->lock); + target = this->ike_sa; + this->lock->unlock(this->lock); + + if (target == ike_sa) + { + switch (state) + { + case CHILD_DESTROYING: + switch (child_sa->get_state(child_sa)) + { + case CHILD_DELETING: + /* proper delete */ + this->status = SUCCESS; + break; + default: + break; + } + return listener_done(this); + default: + break; + } + } + return TRUE; +} + METHOD(job_t, destroy_job, void, interface_job_t *this) { @@ -537,8 +587,8 @@ METHOD(controller_t, terminate_ike, status_t, INIT(job, .listener = { .public = { - .ike_state_change = _ike_state_change, - .child_state_change = _child_state_change, + .ike_state_change = _ike_state_change_terminate, + .child_state_change = _child_state_change_terminate, }, .logger = { .public = { @@ -639,8 +689,8 @@ METHOD(controller_t, terminate_child, status_t, INIT(job, .listener = { .public = { - .ike_state_change = _ike_state_change, - .child_state_change = _child_state_change, + .ike_state_change = _ike_state_change_terminate, + .child_state_change = _child_state_change_terminate, }, .logger = { .public = { |