d9f3fe8de75d3b43708cb6f6cc00b33cf23f8e70
[strongswan.git] / src / libcharon / sa / ikev2 / tasks / ike_reauth.c
1 /*
2 * Copyright (C) 2006-2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "ike_reauth.h"
17
18 #include <daemon.h>
19 #include <sa/ikev2/tasks/ike_delete.h>
20
21
22 typedef struct private_ike_reauth_t private_ike_reauth_t;
23
24 /**
25 * Private members of a ike_reauth_t task.
26 */
27 struct private_ike_reauth_t {
28
29 /**
30 * Public methods and task_t interface.
31 */
32 ike_reauth_t public;
33
34 /**
35 * Assigned IKE_SA.
36 */
37 ike_sa_t *ike_sa;
38
39 /**
40 * reused ike_delete task
41 */
42 ike_delete_t *ike_delete;
43 };
44
45 METHOD(task_t, build_i, status_t,
46 private_ike_reauth_t *this, message_t *message)
47 {
48 return this->ike_delete->task.build(&this->ike_delete->task, message);
49 }
50
51 METHOD(task_t, process_i, status_t,
52 private_ike_reauth_t *this, message_t *message)
53 {
54 ike_sa_t *new;
55 host_t *host;
56 enumerator_t *enumerator;
57 ike_version_t version;
58 child_sa_t *child_sa;
59 peer_cfg_t *peer_cfg;
60
61 /* process delete response first */
62 this->ike_delete->task.process(&this->ike_delete->task, message);
63
64 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
65
66 /* reauthenticate only if we have children */
67 if (this->ike_sa->get_child_count(this->ike_sa) == 0
68 #ifdef ME
69 /* we allow peers to reauth mediation connections (without children) */
70 && !peer_cfg->is_mediation(peer_cfg)
71 #endif /* ME */
72 )
73 {
74 DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA to recreate");
75 return FAILED;
76 }
77
78 version = this->ike_sa->get_version(this->ike_sa);
79 new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, version,
80 TRUE);
81
82 new->set_peer_cfg(new, peer_cfg);
83 host = this->ike_sa->get_other_host(this->ike_sa);
84 new->set_other_host(new, host->clone(host));
85 host = this->ike_sa->get_my_host(this->ike_sa);
86 new->set_my_host(new, host->clone(host));
87 /* if we already have a virtual IP, we reuse it */
88 host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
89 if (host)
90 {
91 new->set_virtual_ip(new, TRUE, host);
92 }
93
94 #ifdef ME
95 /* we initiate the new IKE_SA of the mediation connection without CHILD_SA */
96 if (peer_cfg->is_mediation(peer_cfg))
97 {
98 if (new->initiate(new, NULL, 0, NULL, NULL) == DESTROY_ME)
99 {
100 charon->ike_sa_manager->checkin_and_destroy(
101 charon->ike_sa_manager, new);
102 /* set threads active IKE_SA after checkin */
103 charon->bus->set_sa(charon->bus, this->ike_sa);
104 DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
105 return FAILED;
106 }
107 }
108 #endif /* ME */
109
110 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
111 while (enumerator->enumerate(enumerator, (void**)&child_sa))
112 {
113 switch (child_sa->get_state(child_sa))
114 {
115 case CHILD_ROUTED:
116 {
117 /* move routed child directly */
118 this->ike_sa->remove_child_sa(this->ike_sa, enumerator);
119 new->add_child_sa(new, child_sa);
120 break;
121 }
122 default:
123 {
124 /* initiate/queue all child SAs */
125 child_cfg_t *child_cfg = child_sa->get_config(child_sa);
126 child_cfg->get_ref(child_cfg);
127 if (new->initiate(new, child_cfg, 0, NULL, NULL) == DESTROY_ME)
128 {
129 enumerator->destroy(enumerator);
130 charon->ike_sa_manager->checkin_and_destroy(
131 charon->ike_sa_manager, new);
132 /* set threads active IKE_SA after checkin */
133 charon->bus->set_sa(charon->bus, this->ike_sa);
134 DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
135 return FAILED;
136 }
137 break;
138 }
139 }
140 }
141 enumerator->destroy(enumerator);
142 charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
143 /* set threads active IKE_SA after checkin */
144 charon->bus->set_sa(charon->bus, this->ike_sa);
145
146 /* we always destroy the obsolete IKE_SA */
147 return DESTROY_ME;
148 }
149
150 METHOD(task_t, get_type, task_type_t,
151 private_ike_reauth_t *this)
152 {
153 return TASK_IKE_REAUTH;
154 }
155
156 METHOD(task_t, migrate, void,
157 private_ike_reauth_t *this, ike_sa_t *ike_sa)
158 {
159 this->ike_delete->task.migrate(&this->ike_delete->task, ike_sa);
160 this->ike_sa = ike_sa;
161 }
162
163 METHOD(task_t, destroy, void,
164 private_ike_reauth_t *this)
165 {
166 this->ike_delete->task.destroy(&this->ike_delete->task);
167 free(this);
168 }
169
170 /*
171 * Described in header.
172 */
173 ike_reauth_t *ike_reauth_create(ike_sa_t *ike_sa)
174 {
175 private_ike_reauth_t *this;
176
177 INIT(this,
178 .public = {
179 .task = {
180 .get_type = _get_type,
181 .migrate = _migrate,
182 .build = _build_i,
183 .process = _process_i,
184 .destroy = _destroy,
185 },
186 },
187 .ike_sa = ike_sa,
188 .ike_delete = ike_delete_create(ike_sa, TRUE),
189 );
190
191 return &this->public;
192 }