Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/xauth.c, revision 1.1.1.1
1.1 misho 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 <encoding/payloads/cp_payload.h>
20: #include <processing/jobs/adopt_children_job.h>
21: #include <sa/ikev1/tasks/mode_config.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: uint16_t identifier;
72:
73: /**
74: * status of Xauth exchange
75: */
76: xauth_status_t status;
77:
78: /**
79: * Queue a Mode Config Push mode after completing XAuth?
80: */
81: bool mode_config_push;
82: };
83:
84: /**
85: * Load XAuth backend
86: */
87: static xauth_method_t *load_method(private_xauth_t* this)
88: {
89: identification_t *server, *peer;
90: enumerator_t *enumerator;
91: xauth_method_t *xauth;
92: xauth_role_t role;
93: peer_cfg_t *peer_cfg;
94: auth_cfg_t *auth;
95: char *name;
96:
97: if (this->initiator)
98: {
99: server = this->ike_sa->get_my_id(this->ike_sa);
100: peer = this->ike_sa->get_other_id(this->ike_sa);
101: role = XAUTH_SERVER;
102: }
103: else
104: {
105: peer = this->ike_sa->get_my_id(this->ike_sa);
106: server = this->ike_sa->get_other_id(this->ike_sa);
107: role = XAUTH_PEER;
108: }
109: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
110: enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, !this->initiator);
111: if (!enumerator->enumerate(enumerator, &auth) ||
112: (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH)
113: {
114: if (!enumerator->enumerate(enumerator, &auth) ||
115: (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH)
116: {
117: DBG1(DBG_CFG, "no XAuth authentication round found");
118: enumerator->destroy(enumerator);
119: return NULL;
120: }
121: }
122: name = auth->get(auth, AUTH_RULE_XAUTH_BACKEND);
123: this->user = auth->get(auth, AUTH_RULE_XAUTH_IDENTITY);
124: enumerator->destroy(enumerator);
125: if (!this->initiator && this->user)
126: { /* use XAUTH username, if configured */
127: peer = this->user;
128: }
129: xauth = charon->xauth->create_instance(charon->xauth, name, role,
130: server, peer);
131: if (!xauth)
132: {
133: if (name)
134: {
135: DBG1(DBG_CFG, "no XAuth method found for '%s'", name);
136: }
137: else
138: {
139: DBG1(DBG_CFG, "no XAuth method found");
140: }
141: }
142: return xauth;
143: }
144:
145: /**
146: * Check if XAuth connection is allowed to succeed
147: */
148: static bool allowed(private_xauth_t *this)
149: {
150: if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
151: this->ike_sa, FALSE))
152: {
153: DBG1(DBG_IKE, "cancelling XAuth due to uniqueness policy");
154: return FALSE;
155: }
156: if (!charon->bus->authorize(charon->bus, FALSE))
157: {
158: DBG1(DBG_IKE, "XAuth authorization hook forbids IKE_SA, cancelling");
159: return FALSE;
160: }
161: if (!charon->bus->authorize(charon->bus, TRUE))
162: {
163: DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
164: return FALSE;
165: }
166: return TRUE;
167: }
168:
169: /**
170: * Set IKE_SA to established state
171: */
172: static bool establish(private_xauth_t *this)
173: {
174: DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
175: this->ike_sa->get_name(this->ike_sa),
176: this->ike_sa->get_unique_id(this->ike_sa),
177: this->ike_sa->get_my_host(this->ike_sa),
178: this->ike_sa->get_my_id(this->ike_sa),
179: this->ike_sa->get_other_host(this->ike_sa),
180: this->ike_sa->get_other_id(this->ike_sa));
181:
182: this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
183: charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
184:
185: return TRUE;
186: }
187:
188: /**
189: * Check if we are compliant to a given peer config
190: */
191: static bool is_compliant(private_xauth_t *this, peer_cfg_t *peer_cfg, bool log)
192: {
193: bool complies = TRUE;
194: enumerator_t *e1, *e2;
195: auth_cfg_t *c1, *c2;
196:
197: e1 = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
198: e2 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
199: while (e1->enumerate(e1, &c1))
200: {
201: if (!e2->enumerate(e2, &c2) || !c2->complies(c2, c1, log))
202: {
203: complies = FALSE;
204: break;
205: }
206: }
207: e1->destroy(e1);
208: e2->destroy(e2);
209:
210: return complies;
211: }
212:
213: /**
214: * Check if we are compliant to current config, switch to another if not
215: */
216: static bool select_compliant_config(private_xauth_t *this)
217: {
218: peer_cfg_t *peer_cfg = NULL, *old, *current;
219: identification_t *my_id, *other_id;
220: host_t *my_host, *other_host;
221: enumerator_t *enumerator;
222: bool aggressive;
223:
224: old = this->ike_sa->get_peer_cfg(this->ike_sa);
225: if (is_compliant(this, old, TRUE))
226: { /* current config is fine */
227: return TRUE;
228: }
229: DBG1(DBG_CFG, "selected peer config '%s' unacceptable",
230: old->get_name(old));
231: aggressive = old->use_aggressive(old);
232:
233: my_host = this->ike_sa->get_my_host(this->ike_sa);
234: other_host = this->ike_sa->get_other_host(this->ike_sa);
235: my_id = this->ike_sa->get_my_id(this->ike_sa);
236: other_id = this->ike_sa->get_other_id(this->ike_sa);
237: enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
238: my_host, other_host, my_id, other_id, IKEV1);
239: while (enumerator->enumerate(enumerator, ¤t))
240: {
241: if (!current->equals(current, old) &&
242: current->use_aggressive(current) == aggressive &&
243: is_compliant(this, current, FALSE))
244: {
245: peer_cfg = current;
246: break;
247: }
248: }
249: if (peer_cfg)
250: {
251: DBG1(DBG_CFG, "switching to peer config '%s'",
252: peer_cfg->get_name(peer_cfg));
253: this->ike_sa->set_peer_cfg(this->ike_sa, peer_cfg);
254: }
255: else
256: {
257: DBG1(DBG_CFG, "no alternative config found");
258: }
259: enumerator->destroy(enumerator);
260:
261: return peer_cfg != NULL;
262: }
263:
264: /**
265: * Create auth config after successful authentication
266: */
267: static bool add_auth_cfg(private_xauth_t *this, identification_t *id, bool local)
268: {
269: auth_cfg_t *auth;
270:
271: auth = auth_cfg_create();
272: auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
273: if (id)
274: {
275: auth->add(auth, AUTH_RULE_XAUTH_IDENTITY, id->clone(id));
276: }
277: auth->merge(auth, this->ike_sa->get_auth_cfg(this->ike_sa, local), FALSE);
278: this->ike_sa->add_auth_cfg(this->ike_sa, local, auth);
279:
280: return select_compliant_config(this);
281: }
282:
283: METHOD(task_t, build_i_status, status_t,
284: private_xauth_t *this, message_t *message)
285: {
286: cp_payload_t *cp;
287:
288: cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_SET);
289: cp->add_attribute(cp,
290: configuration_attribute_create_value(XAUTH_STATUS, this->status));
291:
292: message->add_payload(message, (payload_t *)cp);
293:
294: return NEED_MORE;
295: }
296:
297: METHOD(task_t, process_i_status, status_t,
298: private_xauth_t *this, message_t *message)
299: {
300: cp_payload_t *cp;
301: adopt_children_job_t *job;
302:
303: cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
304: if (!cp || cp->get_type(cp) != CFG_ACK)
305: {
306: DBG1(DBG_IKE, "received invalid XAUTH status response");
307: return FAILED;
308: }
309: if (this->status != XAUTH_OK)
310: {
311: DBG1(DBG_IKE, "destroying IKE_SA after failed XAuth authentication");
312: return FAILED;
313: }
314: if (!establish(this))
315: {
316: return FAILED;
317: }
318: this->ike_sa->set_condition(this->ike_sa, COND_XAUTH_AUTHENTICATED, TRUE);
319: job = adopt_children_job_create(this->ike_sa->get_id(this->ike_sa));
320: if (this->mode_config_push)
321: {
322: job->queue_task(job,
323: (task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
324: }
325: lib->processor->queue_job(lib->processor, (job_t*)job);
326: return SUCCESS;
327: }
328:
329: METHOD(task_t, build_i, status_t,
330: private_xauth_t *this, message_t *message)
331: {
332: if (!this->xauth)
333: {
334: cp_payload_t *cp = NULL;
335:
336: this->xauth = load_method(this);
337: if (!this->xauth)
338: {
339: return FAILED;
340: }
341: switch (this->xauth->initiate(this->xauth, &cp))
342: {
343: case NEED_MORE:
344: break;
345: case SUCCESS:
346: DESTROY_IF(cp);
347: if (add_auth_cfg(this, NULL, FALSE) && allowed(this))
348: {
349: this->status = XAUTH_OK;
350: }
351: this->public.task.process = _process_i_status;
352: return build_i_status(this, message);
353: default:
354: return FAILED;
355: }
356: message->add_payload(message, (payload_t *)cp);
357: return NEED_MORE;
358: }
359:
360: if (this->cp)
361: { /* send previously generated payload */
362: message->add_payload(message, (payload_t *)this->cp);
363: this->cp = NULL;
364: return NEED_MORE;
365: }
366: return FAILED;
367: }
368:
369: METHOD(task_t, build_r_ack, status_t,
370: private_xauth_t *this, message_t *message)
371: {
372: cp_payload_t *cp;
373:
374: cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_ACK);
375: cp->set_identifier(cp, this->identifier);
376: cp->add_attribute(cp,
377: configuration_attribute_create_chunk(
378: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_STATUS, chunk_empty));
379:
380: message->add_payload(message, (payload_t *)cp);
381:
382: if (this->status == XAUTH_OK && allowed(this) && establish(this))
383: {
384: return SUCCESS;
385: }
386: return FAILED;
387: }
388:
389: METHOD(task_t, process_r, status_t,
390: private_xauth_t *this, message_t *message)
391: {
392: cp_payload_t *cp;
393:
394: if (!this->xauth)
395: {
396: this->xauth = load_method(this);
397: if (!this->xauth)
398: { /* send empty reply */
399: return NEED_MORE;
400: }
401: }
402: cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
403: if (!cp)
404: {
405: DBG1(DBG_IKE, "configuration payload missing in XAuth request");
406: return FAILED;
407: }
408: if (cp->get_type(cp) == CFG_REQUEST)
409: {
410: switch (this->xauth->process(this->xauth, cp, &this->cp))
411: {
412: case NEED_MORE:
413: return NEED_MORE;
414: case SUCCESS:
415: case FAILED:
416: default:
417: break;
418: }
419: this->cp = NULL;
420: return NEED_MORE;
421: }
422: if (cp->get_type(cp) == CFG_SET)
423: {
424: configuration_attribute_t *attribute;
425: enumerator_t *enumerator;
426:
427: enumerator = cp->create_attribute_enumerator(cp);
428: while (enumerator->enumerate(enumerator, &attribute))
429: {
430: if (attribute->get_type(attribute) == XAUTH_STATUS)
431: {
432: this->status = attribute->get_value(attribute);
433: }
434: }
435: enumerator->destroy(enumerator);
436: if (this->status == XAUTH_OK &&
437: add_auth_cfg(this, this->xauth->get_identity(this->xauth), TRUE))
438: {
439: DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) successful",
440: this->xauth->get_identity(this->xauth));
441: }
442: else
443: {
444: DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) failed",
445: this->xauth->get_identity(this->xauth));
446: }
447: }
448: this->identifier = cp->get_identifier(cp);
449: this->public.task.build = _build_r_ack;
450: return NEED_MORE;
451: }
452:
453: METHOD(task_t, build_r, status_t,
454: private_xauth_t *this, message_t *message)
455: {
456: if (!this->cp)
457: { /* send empty reply if building data failed */
458: this->cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
459: }
460: message->add_payload(message, (payload_t *)this->cp);
461: this->cp = NULL;
462: return NEED_MORE;
463: }
464:
465: METHOD(task_t, process_i, status_t,
466: private_xauth_t *this, message_t *message)
467: {
468: identification_t *id;
469: cp_payload_t *cp;
470:
471: cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
472: if (!cp)
473: {
474: DBG1(DBG_IKE, "configuration payload missing in XAuth response");
475: return FAILED;
476: }
477: switch (this->xauth->process(this->xauth, cp, &this->cp))
478: {
479: case NEED_MORE:
480: return NEED_MORE;
481: case SUCCESS:
482: id = this->xauth->get_identity(this->xauth);
483: DBG1(DBG_IKE, "XAuth authentication of '%Y' successful", id);
484: if (add_auth_cfg(this, id, FALSE) && allowed(this))
485: {
486: this->status = XAUTH_OK;
487: }
488: break;
489: case FAILED:
490: DBG1(DBG_IKE, "XAuth authentication of '%Y' failed",
491: this->xauth->get_identity(this->xauth));
492: break;
493: default:
494: return FAILED;
495: }
496: this->public.task.build = _build_i_status;
497: this->public.task.process = _process_i_status;
498: return NEED_MORE;
499: }
500:
501: METHOD(task_t, get_type, task_type_t,
502: private_xauth_t *this)
503: {
504: return TASK_XAUTH;
505: }
506:
507: METHOD(task_t, migrate, void,
508: private_xauth_t *this, ike_sa_t *ike_sa)
509: {
510: DESTROY_IF(this->xauth);
511: DESTROY_IF(this->cp);
512:
513: this->ike_sa = ike_sa;
514: this->xauth = NULL;
515: this->cp = NULL;
516: this->user = NULL;
517: this->status = XAUTH_FAILED;
518:
519: if (this->initiator)
520: {
521: this->public.task.build = _build_i;
522: this->public.task.process = _process_i;
523: }
524: else
525: {
526: this->public.task.build = _build_r;
527: this->public.task.process = _process_r;
528: }
529: }
530:
531: METHOD(xauth_t, queue_mode_config_push, void,
532: private_xauth_t *this)
533: {
534: this->mode_config_push = TRUE;
535: }
536:
537: METHOD(task_t, destroy, void,
538: private_xauth_t *this)
539: {
540: DESTROY_IF(this->xauth);
541: DESTROY_IF(this->cp);
542: free(this);
543: }
544:
545: /*
546: * Described in header.
547: */
548: xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator)
549: {
550: private_xauth_t *this;
551:
552: INIT(this,
553: .public = {
554: .task = {
555: .get_type = _get_type,
556: .migrate = _migrate,
557: .destroy = _destroy,
558: },
559: .queue_mode_config_push = _queue_mode_config_push,
560: },
561: .initiator = initiator,
562: .ike_sa = ike_sa,
563: .status = XAUTH_FAILED,
564: );
565:
566: if (initiator)
567: {
568: this->public.task.build = _build_i;
569: this->public.task.process = _process_i;
570: }
571: else
572: {
573: this->public.task.build = _build_r;
574: this->public.task.process = _process_r;
575: }
576: return &this->public;
577: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>