2
* rlm_eap_gtc.c Handles that are called from eap
4
* Version: $Id: rlm_eap_gtc.c,v 1.3 2004/02/26 19:04:30 aland Exp $
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
* Copyright 2003 The FreeRADIUS server project
30
#include <rad_assert.h>
33
* EAP-GTC is just ASCII data carried inside of the EAP session.
34
* The length of the data is indicated by the encapsulating EAP
37
typedef struct rlm_eap_gtc_t {
38
const char *challenge;
39
const char *auth_type_name;
43
static CONF_PARSER module_config[] = {
44
{ "challenge", PW_TYPE_STRING_PTR,
45
offsetof(rlm_eap_gtc_t, challenge), NULL, "Password: " },
47
{ "auth_type", PW_TYPE_STRING_PTR,
48
offsetof(rlm_eap_gtc_t, auth_type_name), NULL, "PAP" },
50
{ NULL, -1, 0, NULL, NULL } /* end the list */
57
static int gtc_detach(void *arg)
59
rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) arg;
61
if (inst->challenge) free(inst->challenge);
62
if (inst->auth_type_name) free(inst->auth_type_name);
72
static int gtc_attach(CONF_SECTION *cs, void **instance)
77
inst = malloc(sizeof(*inst));
79
radlog(L_ERR, "rlm_eap_gtc: out of memory");
82
memset(inst, 0, sizeof(*inst));
85
* Parse the configuration attributes.
87
if (cf_section_parse(cs, inst, module_config) < 0) {
92
dval = dict_valbyname(PW_AUTH_TYPE, inst->auth_type_name);
94
radlog(L_ERR, "rlm_eap_gtc: Unknown Auth-Type %s",
95
inst->auth_type_name);
100
inst->auth_type = dval->value;
108
* Initiate the EAP-GTC session by sending a challenge to the peer.
110
static int gtc_initiate(void *type_data, EAP_HANDLER *handler)
113
EAP_DS *eap_ds = handler->eap_ds;
114
rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) type_data;
117
* FIXME: call radius_xlat on the challenge
119
length = strlen(inst->challenge);
122
* We're sending a request...
124
eap_ds->request->code = PW_EAP_REQUEST;
126
eap_ds->request->type.data = malloc(length);
127
if (eap_ds->request->type.data == NULL) {
128
radlog(L_ERR, "rlm_eap_gtc: out of memory");
132
memcpy(eap_ds->request->type.data, inst->challenge, length);
133
eap_ds->request->type.length = length;
136
* We don't need to authorize the user at this point.
138
* We also don't need to keep the challenge, as it's
139
* stored in 'handler->eap_ds', which will be given back
142
handler->stage = AUTHENTICATE;
149
* Authenticate a previously sent challenge.
151
static int gtc_authenticate(void *type_data, EAP_HANDLER *handler)
154
EAP_DS *eap_ds = handler->eap_ds;
155
rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) type_data;
158
* Get the User-Password for this user.
160
rad_assert(handler->request != NULL);
161
rad_assert(handler->stage == AUTHENTICATE);
164
* Sanity check the response. We need at least one byte
167
if (eap_ds->response->length <= 4) {
168
radlog(L_ERR, "rlm_eap_gtc: corrupted data");
169
eap_ds->request->code = PW_EAP_FAILURE;
174
if (debug_flag > 2) {
177
for (i = 0; i < eap_ds->response->length - 4; i++) {
178
if ((i & 0x0f) == 0) printf("%d: ", i);
180
printf("%02x ", eap_ds->response->type.data[i]);
182
if ((i & 0x0f) == 0x0f) printf("\n");
188
* Handle passwords here.
190
if (inst->auth_type == PW_AUTHTYPE_LOCAL) {
192
* For now, do clear-text password authentication.
194
vp = pairfind(handler->request->config_items, PW_PASSWORD);
196
DEBUG2(" rlm_eap_gtc: ERROR: Clear-test User-Password is required for authentication.");
197
eap_ds->request->code = PW_EAP_FAILURE;
201
if (eap_ds->response->type.length != vp->length) {
202
DEBUG2(" rlm_eap_gtc: ERROR: Passwords are of different length. %d %d", eap_ds->response->type.length, vp->length);
203
eap_ds->request->code = PW_EAP_FAILURE;
207
if (memcmp(eap_ds->response->type.data,
208
vp->strvalue, vp->length) != 0) {
209
DEBUG2(" rlm_eap_gtc: ERROR: Passwords are different");
210
eap_ds->request->code = PW_EAP_FAILURE;
215
* EAP packets can be ~64k long maximum, and
216
* we don't like that.
218
} else if (eap_ds->response->type.length <= 128) {
222
* If there was a User-Password in the request,
223
* why the heck are they using EAP-GTC?
225
rad_assert(handler->request->password == NULL);
227
vp = pairmake("User-Password", "", T_OP_EQ);
229
radlog(L_ERR, "rlm_eap_gtc: out of memory");
232
vp->length = eap_ds->response->type.length;
233
memcpy(vp->strvalue, eap_ds->response->type.data, vp->length);
234
vp->strvalue[vp->length] = 0;
237
* Add the password to the request, and allow
238
* another module to do the work of authenticating it.
240
pairadd(&handler->request->packet->vps, vp);
241
handler->request->password = vp;
244
* This is a wild & crazy hack.
246
rcode = module_authenticate(inst->auth_type, handler->request);
247
if (rcode != RLM_MODULE_OK) {
248
eap_ds->request->code = PW_EAP_FAILURE;
253
radlog(L_ERR, "rlm_eap_gtc: Response is too large to understand");
254
eap_ds->request->code = PW_EAP_FAILURE;
259
DEBUG2(" rlm_eap_gtc: Everything is OK.");
261
eap_ds->request->code = PW_EAP_SUCCESS;
267
* The module name should be the only globally exported symbol.
268
* That is, everything else should be 'static'.
270
EAP_TYPE rlm_eap_gtc = {
272
gtc_attach, /* attach */
273
gtc_initiate, /* Start the initial request */
274
NULL, /* authorization */
275
gtc_authenticate, /* authentication */
276
gtc_detach /* detach */