summaryrefslogtreecommitdiffstats
path: root/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c')
-rw-r--r--src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c b/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c
new file mode 100644
index 0000000..031eba2
--- /dev/null
+++ b/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c
@@ -0,0 +1,250 @@
+/*
+ * rlm_eap_gtc.c Handles that are called from eap
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2003,2006 The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "eap.h"
+
+#include <freeradius-devel/rad_assert.h>
+
+/*
+ * EAP-GTC is just ASCII data carried inside of the EAP session.
+ * The length of the data is indicated by the encapsulating EAP
+ * protocol.
+ */
+typedef struct rlm_eap_gtc_t {
+ char const *challenge;
+ char const *auth_type_name;
+ int auth_type;
+} rlm_eap_gtc_t;
+
+static CONF_PARSER module_config[] = {
+ { "challenge", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_gtc_t, challenge), "Password: " },
+ { "auth_type", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_gtc_t, auth_type_name), "PAP" },
+ CONF_PARSER_TERMINATOR
+};
+
+
+
+/*
+ * Attach the module.
+ */
+static int mod_instantiate(CONF_SECTION *cs, void **instance)
+{
+ rlm_eap_gtc_t *inst;
+ DICT_VALUE *dval;
+
+ *instance = inst = talloc_zero(cs, rlm_eap_gtc_t);
+ if (!inst) return -1;
+
+ /*
+ * Parse the configuration attributes.
+ */
+ if (cf_section_parse(cs, inst, module_config) < 0) {
+ return -1;
+ }
+
+ if (inst->auth_type_name && *inst->auth_type_name) {
+ dval = dict_valbyname(PW_AUTH_TYPE, 0, inst->auth_type_name);
+ if (!dval) {
+ ERROR("rlm_eap_gtc: Unknown Auth-Type %s",
+ inst->auth_type_name);
+ return -1;
+ }
+
+ inst->auth_type = dval->value;
+ } else {
+ inst->auth_type = PW_AUTH_TYPE_LOCAL;
+ }
+ return 0;
+}
+
+/*
+ * Initiate the EAP-GTC session by sending a challenge to the peer.
+ */
+static int mod_session_init(void *instance, eap_handler_t *handler)
+{
+ char challenge_str[1024];
+ int length;
+ EAP_DS *eap_ds = handler->eap_ds;
+ rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) instance;
+
+ if (radius_xlat(challenge_str, sizeof(challenge_str), handler->request, inst->challenge, NULL, NULL) < 0) {
+ return 0;
+ }
+
+ length = strlen(challenge_str);
+
+ /*
+ * We're sending a request...
+ */
+ eap_ds->request->code = PW_EAP_REQUEST;
+
+ eap_ds->request->type.data = talloc_array(eap_ds->request,
+ uint8_t, length);
+ if (!eap_ds->request->type.data) {
+ return 0;
+ }
+
+ memcpy(eap_ds->request->type.data, challenge_str, length);
+ eap_ds->request->type.length = length;
+
+ /*
+ * We don't need to authorize the user at this point.
+ *
+ * We also don't need to keep the challenge, as it's
+ * stored in 'handler->eap_ds', which will be given back
+ * to us...
+ */
+ handler->stage = PROCESS;
+
+ return 1;
+}
+
+
+/*
+ * Authenticate a previously sent challenge.
+ */
+static int CC_HINT(nonnull) mod_process(void *instance, eap_handler_t *handler)
+{
+ VALUE_PAIR *vp;
+ EAP_DS *eap_ds = handler->eap_ds;
+ rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) instance;
+ REQUEST *request = handler->request;
+
+ /*
+ * Get the Cleartext-Password for this user.
+ */
+ rad_assert(handler->stage == PROCESS);
+
+ /*
+ * Sanity check the response. We need at least one byte
+ * of data.
+ */
+ if (eap_ds->response->length <= 4) {
+ ERROR("rlm_eap_gtc: corrupted data");
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+#if 0
+ if ((rad_debug_lvl > 2) && fr_log_fp) {
+ int i;
+
+ for (i = 0; i < eap_ds->response->length - 4; i++) {
+ if ((i & 0x0f) == 0) fprintf(fr_log_fp, "%d: ", i);
+
+ fprintf(fr_log_fp, "%02x ", eap_ds->response->type.data[i]);
+
+ if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
+ }
+ }
+#endif
+
+ /*
+ * Handle passwords here.
+ */
+ if (inst->auth_type == PW_AUTH_TYPE_LOCAL) {
+ /*
+ * For now, do cleartext password authentication.
+ */
+ vp = fr_pair_find_by_num(request->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY);
+ if (!vp) {
+ REDEBUG2("Cleartext-Password is required for authentication");
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+ if (eap_ds->response->type.length != vp->vp_length) {
+ REDEBUG2("Passwords are of different length. %u %u", (unsigned) eap_ds->response->type.length, (unsigned) vp->vp_length);
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+ if (memcmp(eap_ds->response->type.data,
+ vp->vp_strvalue, vp->vp_length) != 0) {
+ REDEBUG2("Passwords are different");
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+ /*
+ * EAP packets can be ~64k long maximum, and
+ * we don't like that.
+ */
+ } else if (eap_ds->response->type.length <= 128) {
+ int rcode;
+
+ /*
+ * If there was a User-Password in the request,
+ * why the heck are they using EAP-GTC?
+ */
+ fr_pair_delete_by_num(&request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);
+
+ vp = pair_make_request("User-Password", NULL, T_OP_EQ);
+ if (!vp) {
+ return 0;
+ }
+
+ fr_pair_value_bstrncpy(vp, eap_ds->response->type.data, eap_ds->response->type.length);
+
+ /*
+ * Add the password to the request, and allow
+ * another module to do the work of authenticating it.
+ */
+ request->password = vp;
+
+ /*
+ * This is a wild & crazy hack.
+ */
+ rcode = process_authenticate(inst->auth_type, request);
+ if (rcode != RLM_MODULE_OK) {
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+ }
+
+ } else {
+ ERROR("rlm_eap_gtc: Response is too large to understand");
+ eap_ds->request->code = PW_EAP_FAILURE;
+ return 0;
+
+ }
+
+ eap_ds->request->code = PW_EAP_SUCCESS;
+
+ return 1;
+}
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ */
+extern rlm_eap_module_t rlm_eap_gtc;
+rlm_eap_module_t rlm_eap_gtc = {
+ .name = "eap_gtc",
+ .instantiate = mod_instantiate, /* Create new submodule instance */
+ .session_init = mod_session_init, /* Initialise a new EAP session */
+ .process = mod_process /* Process next round of EAP method */
+};