Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_gtc/eap_gtc.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2007-2012 Martin Willi
3: * Copyright (C) 2012 revosec AG
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include "eap_gtc.h"
18:
19: #include <daemon.h>
20: #include <library.h>
21:
22: #define GTC_REQUEST_MSG "password"
23:
24: typedef struct private_eap_gtc_t private_eap_gtc_t;
25:
26: /**
27: * Private data of an eap_gtc_t object.
28: */
29: struct private_eap_gtc_t {
30:
31: /**
32: * Public authenticator_t interface.
33: */
34: eap_gtc_t public;
35:
36: /**
37: * ID of the server
38: */
39: identification_t *server;
40:
41: /**
42: * ID of the peer
43: */
44: identification_t *peer;
45:
46: /**
47: * EAP message identifier
48: */
49: uint8_t identifier;
50: };
51:
52: typedef struct eap_gtc_header_t eap_gtc_header_t;
53:
54: /**
55: * packed eap GTC header struct
56: */
57: struct eap_gtc_header_t {
58: /** EAP code (REQUEST/RESPONSE) */
59: uint8_t code;
60: /** unique message identifier */
61: uint8_t identifier;
62: /** length of whole message */
63: uint16_t length;
64: /** EAP type */
65: uint8_t type;
66: /** type data */
67: uint8_t data[];
68: } __attribute__((__packed__));
69:
70: METHOD(eap_method_t, initiate_peer, status_t,
71: private_eap_gtc_t *this, eap_payload_t **out)
72: {
73: /* peer never initiates */
74: return FAILED;
75: }
76:
77: METHOD(eap_method_t, initiate_server, status_t,
78: private_eap_gtc_t *this, eap_payload_t **out)
79: {
80: eap_gtc_header_t *req;
81: size_t len;
82:
83: len = strlen(GTC_REQUEST_MSG);
84: req = alloca(sizeof(eap_gtc_header_t) + len);
85: req->length = htons(sizeof(eap_gtc_header_t) + len);
86: req->code = EAP_REQUEST;
87: req->identifier = this->identifier;
88: req->type = EAP_GTC;
89: memcpy(req->data, GTC_REQUEST_MSG, len);
90:
91: *out = eap_payload_create_data(chunk_create((void*)req,
92: sizeof(eap_gtc_header_t) + len));
93: return NEED_MORE;
94: }
95:
96: METHOD(eap_method_t, process_peer, status_t,
97: private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
98: {
99: eap_gtc_header_t *res;
100: shared_key_t *shared;
101: chunk_t key;
102: size_t len;
103:
104: shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP,
105: this->peer, this->server);
106: if (shared == NULL)
107: {
108: DBG1(DBG_IKE, "no EAP key found for '%Y' - '%Y'",
109: this->peer, this->server);
110: return FAILED;
111: }
112: key = shared->get_key(shared);
113: len = key.len;
114:
115: /* TODO: According to the draft we should "SASLprep" password, RFC4013. */
116:
117: this->identifier = in->get_identifier(in);
118: res = alloca(sizeof(eap_gtc_header_t) + len);
119: res->length = htons(sizeof(eap_gtc_header_t) + len);
120: res->code = EAP_RESPONSE;
121: res->identifier = this->identifier;
122: res->type = EAP_GTC;
123: memcpy(res->data, key.ptr, len);
124:
125: shared->destroy(shared);
126:
127: *out = eap_payload_create_data(chunk_create((void*)res,
128: sizeof(eap_gtc_header_t) + len));
129: return NEED_MORE;
130: }
131:
132: METHOD(eap_method_t, process_server, status_t,
133: private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
134: {
135: status_t status = FAILED;
136: chunk_t user, pass;
137: xauth_method_t *xauth;
138: cp_payload_t *ci, *co;
139: char *backend;
140:
141: user = this->peer->get_encoding(this->peer);
142: pass = chunk_skip(in->get_data(in), 5);
143: if (this->identifier != in->get_identifier(in) || !pass.len)
144: {
145: DBG1(DBG_IKE, "received invalid EAP-GTC message");
146: return FAILED;
147: }
148:
149: /* get XAuth backend to use for credential verification. Default to PAM
150: * to support legacy EAP-GTC configurations */
151: backend = lib->settings->get_str(lib->settings,
152: "%s.plugins.eap-gtc.backend", "pam", lib->ns);
153: xauth = charon->xauth->create_instance(charon->xauth, backend, XAUTH_SERVER,
154: this->server, this->peer);
155: if (!xauth)
156: {
157: DBG1(DBG_IKE, "creating EAP-GTC XAuth backend '%s' failed", backend);
158: return FAILED;
159: }
160: if (xauth->initiate(xauth, &co) == NEED_MORE)
161: {
162: /* assume that "out" contains username/password attributes */
163: co->destroy(co);
164: ci = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
165: ci->add_attribute(ci, configuration_attribute_create_chunk(
166: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, user));
167: ci->add_attribute(ci, configuration_attribute_create_chunk(
168: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, pass));
169: switch (xauth->process(xauth, ci, &co))
170: {
171: case SUCCESS:
172: status = SUCCESS;
173: break;
174: case NEED_MORE:
175: /* TODO: multiple exchanges currently not supported */
176: co->destroy(co);
177: break;
178: case FAILED:
179: default:
180: break;
181: }
182: ci->destroy(ci);
183: }
184: xauth->destroy(xauth);
185: return status;
186: }
187:
188: METHOD(eap_method_t, get_type, eap_type_t,
189: private_eap_gtc_t *this, uint32_t *vendor)
190: {
191: *vendor = 0;
192: return EAP_GTC;
193: }
194:
195: METHOD(eap_method_t, get_msk, status_t,
196: private_eap_gtc_t *this, chunk_t *msk)
197: {
198: return FAILED;
199: }
200:
201: METHOD(eap_method_t, get_identifier, uint8_t,
202: private_eap_gtc_t *this)
203: {
204: return this->identifier;
205: }
206:
207: METHOD(eap_method_t, set_identifier, void,
208: private_eap_gtc_t *this, uint8_t identifier)
209: {
210: this->identifier = identifier;
211: }
212:
213: METHOD(eap_method_t, is_mutual, bool,
214: private_eap_gtc_t *this)
215: {
216: return FALSE;
217: }
218:
219: METHOD(eap_method_t, destroy, void,
220: private_eap_gtc_t *this)
221: {
222: this->peer->destroy(this->peer);
223: this->server->destroy(this->server);
224: free(this);
225: }
226:
227: /**
228: * Generic constructor
229: */
230: static private_eap_gtc_t *eap_gtc_create_generic(identification_t *server,
231: identification_t *peer)
232: {
233: private_eap_gtc_t *this;
234:
235: INIT(this,
236: .public = {
237: .eap_method_interface = {
238: .get_type = _get_type,
239: .is_mutual = _is_mutual,
240: .get_msk = _get_msk,
241: .get_identifier = _get_identifier,
242: .set_identifier = _set_identifier,
243: .destroy = _destroy,
244: },
245: },
246: .peer = peer->clone(peer),
247: .server = server->clone(server),
248: );
249:
250: return this;
251: }
252:
253: /*
254: * see header
255: */
256: eap_gtc_t *eap_gtc_create_server(identification_t *server, identification_t *peer)
257: {
258: private_eap_gtc_t *this = eap_gtc_create_generic(server, peer);
259:
260: this->public.eap_method_interface.initiate = _initiate_server;
261: this->public.eap_method_interface.process = _process_server;
262:
263: /* generate a non-zero identifier */
264: do {
265: this->identifier = random();
266: } while (!this->identifier);
267:
268: return &this->public;
269: }
270:
271: /*
272: * see header
273: */
274: eap_gtc_t *eap_gtc_create_peer(identification_t *server, identification_t *peer)
275: {
276: private_eap_gtc_t *this = eap_gtc_create_generic(server, peer);
277:
278: this->public.eap_method_interface.initiate = _initiate_peer;
279: this->public.eap_method_interface.process = _process_peer;
280:
281: return &this->public;
282: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>