Annotation of embedaddon/strongswan/src/libcharon/plugins/xauth_eap/xauth_eap.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_eap.h"
17:
18: #include <daemon.h>
19:
20: #include <library.h>
21: #include <credentials/sets/callback_cred.h>
22:
23: typedef struct private_xauth_eap_t private_xauth_eap_t;
24:
25: /**
26: * Private data of an xauth_eap_t object.
27: */
28: struct private_xauth_eap_t {
29:
30: /**
31: * Public interface.
32: */
33: xauth_eap_t public;
34:
35: /**
36: * ID of the server
37: */
38: identification_t *server;
39:
40: /**
41: * ID of the peer
42: */
43: identification_t *peer;
44:
45: /**
46: * Callback credential set
47: */
48: callback_cred_t *cred;
49:
50: /**
51: * XAuth password
52: */
53: chunk_t pass;
54: };
55:
56: /**
57: * Callback credential set function
58: */
59: static shared_key_t* shared_cb(private_xauth_eap_t *this, shared_key_type_t type,
60: identification_t *me, identification_t *other,
61: id_match_t *match_me, id_match_t *match_other)
62: {
63: shared_key_t *shared;
64:
65: if (!this->pass.len)
66: {
67: return NULL;
68: }
69: if (type != SHARED_EAP && type != SHARED_ANY)
70: {
71: return NULL;
72: }
73: if (me)
74: {
75: if (!this->peer->equals(this->peer, me))
76: {
77: return NULL;
78: }
79: if (match_me)
80: {
81: *match_me = ID_MATCH_PERFECT;
82: }
83: }
84: else if (match_me)
85: {
86: *match_me = ID_MATCH_ANY;
87: }
88: if (other)
89: {
90: if (!this->server->equals(this->server, other))
91: {
92: return NULL;
93: }
94: if (match_other)
95: {
96: *match_other = ID_MATCH_PERFECT;
97: }
98: }
99: else if (match_other)
100: {
101: *match_other = ID_MATCH_ANY;
102: }
103: shared = shared_key_create(SHARED_EAP, chunk_clone(this->pass));
104: this->pass = chunk_empty;
105: return shared;
106: }
107:
108: /**
109: * Do EAP exchanges to verify secret
110: */
111: static bool verify_eap(private_xauth_eap_t *this, eap_method_t *backend)
112: {
113: eap_payload_t *request, *response;
114: eap_method_t *frontend;
115: eap_type_t type;
116: uint32_t vendor;
117: status_t status;
118:
119: if (backend->initiate(backend, &request) != NEED_MORE)
120: {
121: return FALSE;
122: }
123: type = request->get_type(request, &vendor);
124: frontend = charon->eap->create_instance(charon->eap, type, vendor,
125: EAP_PEER, this->server, this->peer);
126: if (!frontend)
127: {
128: DBG1(DBG_IKE, "XAuth-EAP backend requested %N, but not supported",
129: eap_type_names, type);
130: request->destroy(request);
131: return FALSE;
132: }
133: while (TRUE)
134: {
135: /* credential set is active in frontend only, but not in backend */
136: lib->credmgr->add_local_set(lib->credmgr, &this->cred->set, TRUE);
137: status = frontend->process(frontend, request, &response);
138: lib->credmgr->remove_local_set(lib->credmgr, &this->cred->set);
139: request->destroy(request);
140: if (status != NEED_MORE)
141: { /* clients should never return SUCCESS */
142: frontend->destroy(frontend);
143: return FALSE;
144: }
145: status = backend->process(backend, response, &request);
146: response->destroy(response);
147: switch (status)
148: {
149: case SUCCESS:
150: frontend->destroy(frontend);
151: return TRUE;
152: case NEED_MORE:
153: break;
154: default:
155: frontend->destroy(frontend);
156: return FALSE;
157: }
158: }
159: }
160:
161: METHOD(xauth_method_t, initiate, status_t,
162: private_xauth_eap_t *this, cp_payload_t **out)
163: {
164: cp_payload_t *cp;
165:
166: cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
167: cp->add_attribute(cp, configuration_attribute_create_chunk(
168: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
169: cp->add_attribute(cp, configuration_attribute_create_chunk(
170: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
171: *out = cp;
172: return NEED_MORE;
173: }
174:
175: METHOD(xauth_method_t, process, status_t,
176: private_xauth_eap_t *this, cp_payload_t *in, cp_payload_t **out)
177: {
178: configuration_attribute_t *attr;
179: enumerator_t *enumerator;
180: identification_t *id;
181: chunk_t user = chunk_empty;
182: eap_method_t *backend;
183: eap_type_t type;
184: char *name;
185: bool ok;
186:
187: enumerator = in->create_attribute_enumerator(in);
188: while (enumerator->enumerate(enumerator, &attr))
189: {
190: switch (attr->get_type(attr))
191: {
192: case XAUTH_USER_NAME:
193: user = attr->get_chunk(attr);
194: break;
195: case XAUTH_USER_PASSWORD:
196: this->pass = attr->get_chunk(attr);
197: break;
198: default:
199: break;
200: }
201: }
202: enumerator->destroy(enumerator);
203:
204: if (!user.ptr || !this->pass.ptr)
205: {
206: DBG1(DBG_IKE, "peer did not respond to our XAuth request");
207: return FAILED;
208: }
209: if (user.len)
210: {
211: id = identification_create_from_data(user);
212: if (!id)
213: {
214: DBG1(DBG_IKE, "failed to parse provided XAuth username");
215: return FAILED;
216: }
217: this->peer->destroy(this->peer);
218: this->peer = id;
219: }
220: if (this->pass.len && this->pass.ptr[this->pass.len - 1] == 0)
221: { /* fix null-terminated passwords (Android etc.) */
222: this->pass.len -= 1;
223: }
224:
225: name = lib->settings->get_str(lib->settings,
226: "%s.plugins.xauth-eap.backend", "radius",
227: lib->ns);
228: type = eap_type_from_string(name);
229: if (!type)
230: {
231: DBG1(DBG_CFG, "Unknown XAuth-EAP method: %s", name);
232: return FAILED;
233: }
234: backend = charon->eap->create_instance(charon->eap, type, 0, EAP_SERVER,
235: this->server, this->peer);
236: if (!backend)
237: {
238: DBG1(DBG_CFG, "XAuth-EAP method backend not supported: %s", name);
239: return FAILED;
240: }
241: ok = verify_eap(this, backend);
242: backend->destroy(backend);
243: if (ok)
244: {
245: return SUCCESS;
246: }
247: return FAILED;
248: }
249:
250: METHOD(xauth_method_t, get_identity, identification_t*,
251: private_xauth_eap_t *this)
252: {
253: return this->peer;
254: }
255:
256: METHOD(xauth_method_t, destroy, void,
257: private_xauth_eap_t *this)
258: {
259: this->cred->destroy(this->cred);
260: this->server->destroy(this->server);
261: this->peer->destroy(this->peer);
262: free(this);
263: }
264:
265: /*
266: * Described in header.
267: */
268: xauth_eap_t *xauth_eap_create_server(identification_t *server,
269: identification_t *peer, char *profile)
270: {
271: private_xauth_eap_t *this;
272:
273: INIT(this,
274: .public = {
275: .xauth_method = {
276: .initiate = _initiate,
277: .process = _process,
278: .get_identity = _get_identity,
279: .destroy = _destroy,
280: },
281: },
282: .server = server->clone(server),
283: .peer = peer->clone(peer),
284: );
285:
286: this->cred = callback_cred_create_shared((void*)shared_cb, this);
287:
288: return &this->public;
289: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>