]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libcharon/plugins/eap_gtc/eap_gtc.c
libcharon: Use lib->ns instead of charon->name
[people/ms/strongswan.git] / src / libcharon / plugins / eap_gtc / eap_gtc.c
CommitLineData
1caa265c 1/*
27128c1e
MW
2 * Copyright (C) 2007-2012 Martin Willi
3 * Copyright (C) 2012 revosec AG
1caa265c
MW
4 * 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.
1caa265c 15 */
7daf5226 16
1caa265c
MW
17#include "eap_gtc.h"
18
19#include <daemon.h>
20#include <library.h>
1caa265c 21
1995f79f 22#define GTC_REQUEST_MSG "password"
1caa265c
MW
23
24typedef struct private_eap_gtc_t private_eap_gtc_t;
25
26/**
27 * Private data of an eap_gtc_t object.
28 */
29struct private_eap_gtc_t {
7daf5226 30
1caa265c
MW
31 /**
32 * Public authenticator_t interface.
33 */
34 eap_gtc_t public;
7daf5226 35
1caa265c
MW
36 /**
37 * ID of the server
38 */
39 identification_t *server;
7daf5226 40
1caa265c
MW
41 /**
42 * ID of the peer
43 */
44 identification_t *peer;
7daf5226 45
1caa265c
MW
46 /**
47 * EAP message identififier
48 */
49 u_int8_t identifier;
50};
51
52typedef struct eap_gtc_header_t eap_gtc_header_t;
53
54/**
55 * packed eap GTC header struct
56 */
57struct eap_gtc_header_t {
58 /** EAP code (REQUEST/RESPONSE) */
59 u_int8_t code;
60 /** unique message identifier */
61 u_int8_t identifier;
62 /** length of whole message */
63 u_int16_t length;
64 /** EAP type */
65 u_int8_t type;
66 /** type data */
67 u_int8_t data[];
68} __attribute__((__packed__));
69
e053961d
AS
70METHOD(eap_method_t, initiate_peer, status_t,
71 private_eap_gtc_t *this, eap_payload_t **out)
1caa265c
MW
72{
73 /* peer never initiates */
74 return FAILED;
75}
76
e053961d
AS
77METHOD(eap_method_t, initiate_server, status_t,
78 private_eap_gtc_t *this, eap_payload_t **out)
1caa265c
MW
79{
80 eap_gtc_header_t *req;
81 size_t len;
7daf5226 82
1caa265c
MW
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);
7daf5226 90
1caa265c
MW
91 *out = eap_payload_create_data(chunk_create((void*)req,
92 sizeof(eap_gtc_header_t) + len));
93 return NEED_MORE;
94}
95
e053961d
AS
96METHOD(eap_method_t, process_peer, status_t,
97 private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
1caa265c
MW
98{
99 eap_gtc_header_t *res;
100 shared_key_t *shared;
101 chunk_t key;
102 size_t len;
103
2ccc02a4
MW
104 shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP,
105 this->peer, this->server);
1caa265c
MW
106 if (shared == NULL)
107 {
d24a74c5 108 DBG1(DBG_IKE, "no EAP key found for '%Y' - '%Y'",
1995f79f 109 this->peer, this->server);
1caa265c
MW
110 return FAILED;
111 }
112 key = shared->get_key(shared);
113 len = key.len;
7daf5226 114
b848f037 115 /* TODO: According to the draft we should "SASLprep" password, RFC4013. */
1caa265c 116
07313dbe 117 this->identifier = in->get_identifier(in);
1caa265c
MW
118 res = alloca(sizeof(eap_gtc_header_t) + len);
119 res->length = htons(sizeof(eap_gtc_header_t) + len);
120 res->code = EAP_RESPONSE;
07313dbe 121 res->identifier = this->identifier;
1caa265c
MW
122 res->type = EAP_GTC;
123 memcpy(res->data, key.ptr, len);
7daf5226 124
1caa265c 125 shared->destroy(shared);
7daf5226 126
1caa265c
MW
127 *out = eap_payload_create_data(chunk_create((void*)res,
128 sizeof(eap_gtc_header_t) + len));
129 return NEED_MORE;
130}
131
e053961d
AS
132METHOD(eap_method_t, process_server, status_t,
133 private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
1caa265c 134{
27128c1e
MW
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)
1caa265c
MW
144 {
145 DBG1(DBG_IKE, "received invalid EAP-GTC message");
146 return FAILED;
147 }
7daf5226 148
27128c1e
MW
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,
d223fe80 152 "%s.plugins.eap-gtc.backend", "pam", lib->ns);
27128c1e
MW
153 xauth = charon->xauth->create_instance(charon->xauth, backend, XAUTH_SERVER,
154 this->server, this->peer);
155 if (!xauth)
1995f79f 156 {
27128c1e
MW
157 DBG1(DBG_IKE, "creating EAP-GTC XAuth backend '%s' failed", backend);
158 return FAILED;
1995f79f 159 }
27128c1e 160 if (xauth->initiate(xauth, &co) == NEED_MORE)
1caa265c 161 {
27128c1e
MW
162 /* assume that "out" contains username/password attributes */
163 co->destroy(co);
164 ci = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
165 ci->add_attribute(ci, configuration_attribute_create_chunk(
166 CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, user));
167 ci->add_attribute(ci, configuration_attribute_create_chunk(
168 CONFIGURATION_ATTRIBUTE_V1, 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);
1caa265c 183 }
27128c1e
MW
184 xauth->destroy(xauth);
185 return status;
1caa265c
MW
186}
187
e053961d
AS
188METHOD(eap_method_t, get_type, eap_type_t,
189 private_eap_gtc_t *this, u_int32_t *vendor)
1caa265c
MW
190{
191 *vendor = 0;
192 return EAP_GTC;
193}
194
e053961d
AS
195METHOD(eap_method_t, get_msk, status_t,
196 private_eap_gtc_t *this, chunk_t *msk)
1caa265c
MW
197{
198 return FAILED;
199}
200
05aa206d
AS
201METHOD(eap_method_t, get_identifier, u_int8_t,
202 private_eap_gtc_t *this)
203{
204 return this->identifier;
205}
206
207METHOD(eap_method_t, set_identifier, void,
208 private_eap_gtc_t *this, u_int8_t identifier)
209{
210 this->identifier = identifier;
211}
212
e053961d
AS
213METHOD(eap_method_t, is_mutual, bool,
214 private_eap_gtc_t *this)
1caa265c
MW
215{
216 return FALSE;
217}
218
e053961d
AS
219METHOD(eap_method_t, destroy, void,
220 private_eap_gtc_t *this)
1caa265c 221{
82290106
MW
222 this->peer->destroy(this->peer);
223 this->server->destroy(this->server);
1caa265c
MW
224 free(this);
225}
226
227/**
228 * Generic constructor
229 */
230static private_eap_gtc_t *eap_gtc_create_generic(identification_t *server,
231 identification_t *peer)
232{
e053961d
AS
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,
05aa206d
AS
241 .get_identifier = _get_identifier,
242 .set_identifier = _set_identifier,
e053961d
AS
243 .destroy = _destroy,
244 },
245 },
246 .peer = peer->clone(peer),
247 .server = server->clone(server),
248 );
7daf5226 249
1caa265c
MW
250 return this;
251}
252
253/*
254 * see header
255 */
256eap_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);
7daf5226 259
e053961d
AS
260 this->public.eap_method_interface.initiate = _initiate_server;
261 this->public.eap_method_interface.process = _process_server;
1caa265c 262
82290106
MW
263 /* generate a non-zero identifier */
264 do {
265 this->identifier = random();
266 } while (!this->identifier);
267
1caa265c
MW
268 return &this->public;
269}
270
271/*
272 * see header
273 */
274eap_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);
7daf5226 277
e053961d
AS
278 this->public.eap_method_interface.initiate = _initiate_peer;
279 this->public.eap_method_interface.process = _process_peer;
1caa265c
MW
280
281 return &this->public;
282}