2 * rlm_eap_gtc.c Handles that are called from eap
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2003,2006 The FreeRADIUS server project
23 #include <freeradius-devel/ident.h>
26 #include <freeradius-devel/autoconf.h>
33 #include <freeradius-devel/rad_assert.h>
36 * EAP-GTC is just ASCII data carried inside of the EAP session.
37 * The length of the data is indicated by the encapsulating EAP
40 typedef struct rlm_eap_gtc_t {
41 const char *challenge;
42 const char *auth_type_name;
46 static CONF_PARSER module_config[] = {
47 { "challenge", PW_TYPE_STRING_PTR,
48 offsetof(rlm_eap_gtc_t, challenge), NULL, "Password: " },
50 { "auth_type", PW_TYPE_STRING_PTR,
51 offsetof(rlm_eap_gtc_t, auth_type_name), NULL, "PAP" },
53 { NULL, -1, 0, NULL, NULL } /* end the list */
60 static int gtc_detach(void *arg)
62 rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) arg;
73 static int gtc_attach(CONF_SECTION *cs, void **instance)
78 inst = malloc(sizeof(*inst));
80 radlog(L_ERR, "rlm_eap_gtc: out of memory");
83 memset(inst, 0, sizeof(*inst));
86 * Parse the configuration attributes.
88 if (cf_section_parse(cs, inst, module_config) < 0) {
93 dval = dict_valbyname(PW_AUTH_TYPE, 0, inst->auth_type_name);
95 radlog(L_ERR, "rlm_eap_gtc: Unknown Auth-Type %s",
96 inst->auth_type_name);
101 inst->auth_type = dval->value;
109 * Initiate the EAP-GTC session by sending a challenge to the peer.
111 static int gtc_initiate(void *type_data, EAP_HANDLER *handler)
114 EAP_DS *eap_ds = handler->eap_ds;
115 rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) type_data;
118 * FIXME: call radius_xlat on the challenge
120 length = strlen(inst->challenge);
123 * We're sending a request...
125 eap_ds->request->code = PW_EAP_REQUEST;
127 eap_ds->request->type.data = malloc(length);
128 if (eap_ds->request->type.data == NULL) {
129 radlog(L_ERR, "rlm_eap_gtc: out of memory");
133 memcpy(eap_ds->request->type.data, inst->challenge, length);
134 eap_ds->request->type.length = length;
137 * We don't need to authorize the user at this point.
139 * We also don't need to keep the challenge, as it's
140 * stored in 'handler->eap_ds', which will be given back
143 handler->stage = AUTHENTICATE;
150 * Authenticate a previously sent challenge.
152 static int gtc_authenticate(void *type_data, EAP_HANDLER *handler)
155 EAP_DS *eap_ds = handler->eap_ds;
156 rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) type_data;
159 * Get the Cleartext-Password for this user.
161 rad_assert(handler->request != NULL);
162 rad_assert(handler->stage == AUTHENTICATE);
165 * Sanity check the response. We need at least one byte
168 if (eap_ds->response->length <= 4) {
169 radlog(L_ERR, "rlm_eap_gtc: corrupted data");
170 eap_ds->request->code = PW_EAP_FAILURE;
175 if ((debug_flag > 2) && fr_log_fp) {
178 for (i = 0; i < eap_ds->response->length - 4; i++) {
179 if ((i & 0x0f) == 0) fprintf(fr_log_fp, "%d: ", i);
181 fprintf(fr_log_fp, "%02x ", eap_ds->response->type.data[i]);
183 if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
189 * Handle passwords here.
191 if (inst->auth_type == PW_AUTHTYPE_LOCAL) {
193 * For now, do clear-text password authentication.
195 vp = pairfind(handler->request->config_items, PW_CLEARTEXT_PASSWORD, 0);
197 DEBUG2(" rlm_eap_gtc: ERROR: Cleartext-Password is required for authentication.");
198 eap_ds->request->code = PW_EAP_FAILURE;
202 if (eap_ds->response->type.length != vp->length) {
203 DEBUG2(" rlm_eap_gtc: ERROR: Passwords are of different length. %d %d", (int) eap_ds->response->type.length, (int) vp->length);
204 eap_ds->request->code = PW_EAP_FAILURE;
208 if (memcmp(eap_ds->response->type.data,
209 vp->vp_strvalue, vp->length) != 0) {
210 DEBUG2(" rlm_eap_gtc: ERROR: Passwords are different");
211 eap_ds->request->code = PW_EAP_FAILURE;
216 * EAP packets can be ~64k long maximum, and
217 * we don't like that.
219 } else if (eap_ds->response->type.length <= 128) {
223 * If there was a User-Password in the request,
224 * why the heck are they using EAP-GTC?
226 pairdelete(&handler->request->packet->vps, PW_USER_PASSWORD, 0);
228 vp = pairmake("User-Password", "", T_OP_EQ);
230 radlog(L_ERR, "rlm_eap_gtc: out of memory");
233 vp->length = eap_ds->response->type.length;
234 memcpy(vp->vp_strvalue, eap_ds->response->type.data, vp->length);
235 vp->vp_strvalue[vp->length] = 0;
238 * Add the password to the request, and allow
239 * another module to do the work of authenticating it.
241 pairadd(&handler->request->packet->vps, vp);
242 handler->request->password = vp;
245 * This is a wild & crazy hack.
247 rcode = module_authenticate(inst->auth_type, handler->request);
248 if (rcode != RLM_MODULE_OK) {
249 eap_ds->request->code = PW_EAP_FAILURE;
254 radlog(L_ERR, "rlm_eap_gtc: Response is too large to understand");
255 eap_ds->request->code = PW_EAP_FAILURE;
260 DEBUG2(" rlm_eap_gtc: Everything is OK.");
262 eap_ds->request->code = PW_EAP_SUCCESS;
268 * The module name should be the only globally exported symbol.
269 * That is, everything else should be 'static'.
271 EAP_TYPE rlm_eap_gtc = {
273 gtc_attach, /* attach */
274 gtc_initiate, /* Start the initial request */
275 NULL, /* authorization */
276 gtc_authenticate, /* authentication */
277 gtc_detach /* detach */