657d1c8a0a1cfd13072219e95b84699bf577e813
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / xauth.c
1 /*
2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
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 "xauth.h"
17
18 #include <daemon.h>
19 #include <hydra.h>
20 #include <encoding/payloads/cp_payload.h>
21 #include <processing/jobs/adopt_children_job.h>
22
23 typedef struct private_xauth_t private_xauth_t;
24
25 /**
26 * Status types exchanged
27 */
28 typedef enum {
29 XAUTH_FAILED = 0,
30 XAUTH_OK = 1,
31 } xauth_status_t;
32
33 /**
34 * Private members of a xauth_t task.
35 */
36 struct private_xauth_t {
37
38 /**
39 * Public methods and task_t interface.
40 */
41 xauth_t public;
42
43 /**
44 * Assigned IKE_SA.
45 */
46 ike_sa_t *ike_sa;
47
48 /**
49 * Are we the XAUTH initiator?
50 */
51 bool initiator;
52
53 /**
54 * XAuth backend to use
55 */
56 xauth_method_t *xauth;
57
58 /**
59 * XAuth username
60 */
61 identification_t *user;
62
63 /**
64 * Generated configuration payload
65 */
66 cp_payload_t *cp;
67
68 /**
69 * received identifier
70 */
71 u_int16_t identifier;
72
73 /**
74 * status of Xauth exchange
75 */
76 xauth_status_t status;
77 };
78
79 /**
80 * Load XAuth backend
81 */
82 static xauth_method_t *load_method(private_xauth_t* this)
83 {
84 identification_t *server, *peer;
85 enumerator_t *enumerator;
86 xauth_method_t *xauth;
87 xauth_role_t role;
88 peer_cfg_t *peer_cfg;
89 auth_cfg_t *auth;
90 char *name;
91
92 if (this->initiator)
93 {
94 server = this->ike_sa->get_my_id(this->ike_sa);
95 peer = this->ike_sa->get_other_id(this->ike_sa);
96 role = XAUTH_SERVER;
97 }
98 else
99 {
100 peer = this->ike_sa->get_my_id(this->ike_sa);
101 server = this->ike_sa->get_other_id(this->ike_sa);
102 role = XAUTH_PEER;
103 }
104 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
105 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, !this->initiator);
106 if (!enumerator->enumerate(enumerator, &auth) ||
107 (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH)
108 {
109 if (!enumerator->enumerate(enumerator, &auth) ||
110 (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH)
111 {
112 DBG1(DBG_CFG, "no XAuth authentication round found");
113 enumerator->destroy(enumerator);
114 return NULL;
115 }
116 }
117 name = auth->get(auth, AUTH_RULE_XAUTH_BACKEND);
118 this->user = auth->get(auth, AUTH_RULE_XAUTH_IDENTITY);
119 if (!this->initiator && this->user)
120 { /* use XAUTH username, if configured */
121 peer = this->user;
122 }
123 enumerator->destroy(enumerator);
124 xauth = charon->xauth->create_instance(charon->xauth, name, role,
125 server, peer);
126 if (!xauth)
127 {
128 if (name)
129 {
130 DBG1(DBG_CFG, "no XAuth method found named '%s'", name);
131 }
132 else
133 {
134 DBG1(DBG_CFG, "no XAuth method found");
135 }
136 }
137 return xauth;
138 }
139
140 /**
141 * Check if XAuth connection is allowed to succeed
142 */
143 static bool allowed(private_xauth_t *this)
144 {
145 if (!charon->bus->authorize(charon->bus, FALSE))
146 {
147 DBG1(DBG_IKE, "XAuth authorization hook forbids IKE_SA, cancelling");
148 return FALSE;
149 }
150 if (!charon->bus->authorize(charon->bus, TRUE))
151 {
152 DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
153 return FALSE;
154 }
155 return TRUE;
156 }
157
158 /**
159 * Set IKE_SA to established state
160 */
161 static bool establish(private_xauth_t *this)
162 {
163 DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
164 this->ike_sa->get_name(this->ike_sa),
165 this->ike_sa->get_unique_id(this->ike_sa),
166 this->ike_sa->get_my_host(this->ike_sa),
167 this->ike_sa->get_my_id(this->ike_sa),
168 this->ike_sa->get_other_host(this->ike_sa),
169 this->ike_sa->get_other_id(this->ike_sa));
170
171 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
172 charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
173
174 return TRUE;
175 }
176
177 /**
178 * Create auth config after successful authentication
179 */
180 static void add_auth_cfg(private_xauth_t *this, identification_t *id, bool local)
181 {
182 auth_cfg_t *auth;
183
184 auth = auth_cfg_create();
185 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
186 auth->add(auth, AUTH_RULE_XAUTH_IDENTITY, id->clone(id));
187
188 this->ike_sa->add_auth_cfg(this->ike_sa, local, auth);
189 }
190
191 METHOD(task_t, build_i_status, status_t,
192 private_xauth_t *this, message_t *message)
193 {
194 cp_payload_t *cp;
195
196 cp = cp_payload_create_type(CONFIGURATION_V1, CFG_SET);
197 cp->add_attribute(cp,
198 configuration_attribute_create_value(XAUTH_STATUS, this->status));
199
200 message->add_payload(message, (payload_t *)cp);
201
202 return NEED_MORE;
203 }
204
205 METHOD(task_t, build_i, status_t,
206 private_xauth_t *this, message_t *message)
207 {
208 if (!this->xauth)
209 {
210 cp_payload_t *cp;
211
212 this->xauth = load_method(this);
213 if (!this->xauth)
214 {
215 return FAILED;
216 }
217 if (this->xauth->initiate(this->xauth, &cp) != NEED_MORE)
218 {
219 return FAILED;
220 }
221 message->add_payload(message, (payload_t *)cp);
222 return NEED_MORE;
223 }
224
225 if (this->cp)
226 { /* send previously generated payload */
227 message->add_payload(message, (payload_t *)this->cp);
228 this->cp = NULL;
229 return NEED_MORE;
230 }
231 return FAILED;
232 }
233
234 METHOD(task_t, build_r_ack, status_t,
235 private_xauth_t *this, message_t *message)
236 {
237 cp_payload_t *cp;
238
239 cp = cp_payload_create_type(CONFIGURATION_V1, CFG_ACK);
240 cp->set_identifier(cp, this->identifier);
241 cp->add_attribute(cp,
242 configuration_attribute_create_chunk(
243 CONFIGURATION_ATTRIBUTE_V1, XAUTH_STATUS, chunk_empty));
244
245 message->add_payload(message, (payload_t *)cp);
246
247 if (this->status == XAUTH_OK && allowed(this) && establish(this))
248 {
249 return SUCCESS;
250 }
251 return FAILED;
252 }
253
254 METHOD(task_t, process_r, status_t,
255 private_xauth_t *this, message_t *message)
256 {
257 cp_payload_t *cp;
258
259 if (!this->xauth)
260 {
261 this->xauth = load_method(this);
262 if (!this->xauth)
263 { /* send empty reply */
264 return NEED_MORE;
265 }
266 }
267 cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1);
268 if (!cp)
269 {
270 DBG1(DBG_IKE, "configuration payload missing in XAuth request");
271 return FAILED;
272 }
273 if (cp->get_type(cp) == CFG_REQUEST)
274 {
275 switch (this->xauth->process(this->xauth, cp, &this->cp))
276 {
277 case NEED_MORE:
278 return NEED_MORE;
279 case SUCCESS:
280 case FAILED:
281 default:
282 break;
283 }
284 this->cp = NULL;
285 return NEED_MORE;
286 }
287 if (cp->get_type(cp) == CFG_SET)
288 {
289 configuration_attribute_t *attribute;
290 enumerator_t *enumerator;
291
292 enumerator = cp->create_attribute_enumerator(cp);
293 while (enumerator->enumerate(enumerator, &attribute))
294 {
295 if (attribute->get_type(attribute) == XAUTH_STATUS)
296 {
297 this->status = attribute->get_value(attribute);
298 }
299 }
300 enumerator->destroy(enumerator);
301 if (this->status == XAUTH_OK)
302 {
303 DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) successful",
304 this->xauth->get_identity(this->xauth));
305 add_auth_cfg(this, this->xauth->get_identity(this->xauth), TRUE);
306 }
307 else
308 {
309 DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) failed",
310 this->xauth->get_identity(this->xauth));
311 }
312 }
313 this->identifier = cp->get_identifier(cp);
314 this->public.task.build = _build_r_ack;
315 return NEED_MORE;
316 }
317
318 METHOD(task_t, build_r, status_t,
319 private_xauth_t *this, message_t *message)
320 {
321 if (!this->cp)
322 { /* send empty reply if building data failed */
323 this->cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
324 }
325 message->add_payload(message, (payload_t *)this->cp);
326 this->cp = NULL;
327 return NEED_MORE;
328 }
329
330 METHOD(task_t, process_i_status, status_t,
331 private_xauth_t *this, message_t *message)
332 {
333 cp_payload_t *cp;
334
335 cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1);
336 if (!cp || cp->get_type(cp) != CFG_ACK)
337 {
338 DBG1(DBG_IKE, "received invalid XAUTH status response");
339 return FAILED;
340 }
341 if (this->status != XAUTH_OK)
342 {
343 DBG1(DBG_IKE, "destroying IKE_SA after failed XAuth authentication");
344 return FAILED;
345 }
346 if (!establish(this))
347 {
348 return FAILED;
349 }
350 this->ike_sa->set_condition(this->ike_sa, COND_XAUTH_AUTHENTICATED, TRUE);
351 lib->processor->queue_job(lib->processor, (job_t*)
352 adopt_children_job_create(this->ike_sa->get_id(this->ike_sa)));
353 return SUCCESS;
354 }
355
356 METHOD(task_t, process_i, status_t,
357 private_xauth_t *this, message_t *message)
358 {
359 identification_t *id;
360 cp_payload_t *cp;
361
362 cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1);
363 if (!cp)
364 {
365 DBG1(DBG_IKE, "configuration payload missing in XAuth response");
366 return FAILED;
367 }
368 switch (this->xauth->process(this->xauth, cp, &this->cp))
369 {
370 case NEED_MORE:
371 return NEED_MORE;
372 case SUCCESS:
373 id = this->xauth->get_identity(this->xauth);
374 if (this->user && !id->matches(id, this->user))
375 {
376 DBG1(DBG_IKE, "XAuth username '%Y' does not match to "
377 "configured username '%Y'", id, this->user);
378 break;
379 }
380 DBG1(DBG_IKE, "XAuth authentication of '%Y' successful", id);
381 add_auth_cfg(this, id, FALSE);
382 if (allowed(this))
383 {
384 this->status = XAUTH_OK;
385 }
386 break;
387 case FAILED:
388 DBG1(DBG_IKE, "XAuth authentication of '%Y' failed",
389 this->xauth->get_identity(this->xauth));
390 break;
391 default:
392 return FAILED;
393 }
394 this->public.task.build = _build_i_status;
395 this->public.task.process = _process_i_status;
396 return NEED_MORE;
397 }
398
399 METHOD(task_t, get_type, task_type_t,
400 private_xauth_t *this)
401 {
402 return TASK_XAUTH;
403 }
404
405 METHOD(task_t, migrate, void,
406 private_xauth_t *this, ike_sa_t *ike_sa)
407 {
408 DESTROY_IF(this->xauth);
409 DESTROY_IF(this->cp);
410
411 this->ike_sa = ike_sa;
412 this->xauth = NULL;
413 this->cp = NULL;
414 this->user = NULL;
415 this->status = XAUTH_FAILED;
416
417 if (this->initiator)
418 {
419 this->public.task.build = _build_i;
420 this->public.task.process = _process_i;
421 }
422 else
423 {
424 this->public.task.build = _build_r;
425 this->public.task.process = _process_r;
426 }
427 }
428
429 METHOD(task_t, destroy, void,
430 private_xauth_t *this)
431 {
432 DESTROY_IF(this->xauth);
433 DESTROY_IF(this->cp);
434 free(this);
435 }
436
437 /*
438 * Described in header.
439 */
440 xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator)
441 {
442 private_xauth_t *this;
443
444 INIT(this,
445 .public = {
446 .task = {
447 .get_type = _get_type,
448 .migrate = _migrate,
449 .destroy = _destroy,
450 },
451 },
452 .initiator = initiator,
453 .ike_sa = ike_sa,
454 .status = XAUTH_FAILED,
455 );
456
457 if (initiator)
458 {
459 this->public.task.build = _build_i;
460 this->public.task.process = _process_i;
461 }
462 else
463 {
464 this->public.task.build = _build_r;
465 this->public.task.process = _process_r;
466 }
467 return &this->public;
468 }