📄 eap.c
字号:
/* * eap.c rfc2284 & rfc2869 implementation * * Version: $Id: eap.c,v 1.52.4.1 2006/02/06 16:23:49 nbk Exp $ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright 2000-2003 The FreeRADIUS server project * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com> * Copyright 2003 Alan DeKok <aland@freeradius.org> *//* * EAP PACKET FORMAT * --- ------ ------ * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Code | Identifier | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Data ... * +-+-+-+-+ * * * EAP Request and Response Packet Format * --- ------- --- -------- ------ ------ * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Code | Identifier | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Type-Data ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- * * * EAP Success and Failure Packet Format * --- ------- --- ------- ------ ------ * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Code | Identifier | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */#include "rlm_eap.h"static const char rcsid[] = "$Id: eap.c,v 1.52.4.1 2006/02/06 16:23:49 nbk Exp $";static const char *eap_codes[] = { "", /* 0 is invalid */ "request", "response", "success", "failure"};/* * Load all the required eap authentication types. * Get all the supported EAP-types from config file. */int eaptype_load(EAP_TYPES **type, int eap_type, CONF_SECTION *cs){ char buffer[64]; char namebuf[64]; const char *eaptype_name; lt_dlhandle handle; EAP_TYPES *node; eaptype_name = eaptype_type2name(eap_type, namebuf, sizeof(namebuf)); snprintf(buffer, sizeof(buffer), "rlm_eap_%s", eaptype_name); /* Link the loaded EAP-Type */ handle = lt_dlopenext(buffer); if (handle == NULL) { radlog(L_ERR, "rlm_eap: Failed to link EAP-Type/%s: %s", eaptype_name, lt_dlerror()); return -1; } /* Make room for the EAP-Type */ node = (EAP_TYPES *)malloc(sizeof(EAP_TYPES)); if (node == NULL) { radlog(L_ERR, "rlm_eap: out of memory"); return -1; } memset(node, 0, sizeof(*node)); /* fill in the structure */ node->handle = handle; node->cs = cs; /* * In general, this is a terrible idea. It works here * solely because the eap_type2name function returns a * 'static const char *' pointer sometimes, and we can * ONLY link to module which are named in that static * array. */ node->typename = eaptype_name; node->type_data = NULL; node->type = (EAP_TYPE *)lt_dlsym(node->handle, buffer); if (!node->type) { radlog(L_ERR, "rlm_eap: Failed linking to %s structure in %s: %s", buffer, eaptype_name, lt_dlerror()); lt_dlclose(node->handle); /* ignore any errors */ free(node); return -1; } if ((node->type->attach) && ((node->type->attach)(node->cs, &(node->type_data)) < 0)) { radlog(L_ERR, "rlm_eap: Failed to initialize type %s", eaptype_name); lt_dlclose(node->handle); free(node); return -1; } DEBUG("rlm_eap: Loaded and initialized type %s", eaptype_name); *type = node; return 0;}/* * Call the appropriate handle with the right eap_type. */static int eaptype_call(EAP_TYPES *atype, EAP_HANDLER *handler){ int rcode = 1; DEBUG2(" rlm_eap: processing type %s", atype->typename); rad_assert(atype != NULL); switch (handler->stage) { case INITIATE: if (!atype->type->initiate(atype->type_data, handler)) rcode = 0; break; case AUTHORIZE: /* * The called function updates the EAP reply packet. */ if (!atype->type->authorize || !atype->type->authorize(atype->type_data, handler)) rcode = 0; break; case AUTHENTICATE: /* * The called function updates the EAP reply packet. */ if (!atype->type->authenticate || !atype->type->authenticate(atype->type_data, handler)) rcode = 0; break; default: /* Should never enter here */ radlog(L_DBG, "rlm_eap: Invalid operation on eap_type"); rcode = 0; break; } return rcode;}/* * Based on TYPE, call the appropriate EAP-type handler * Default to the configured EAP-Type * for all Unsupported EAP-Types */int eaptype_select(rlm_eap_t *inst, EAP_HANDLER *handler){ unsigned int default_eap_type = inst->default_eap_type; eaptype_t *eaptype; VALUE_PAIR *vp; char namebuf[64]; const char *eaptype_name; eaptype = &handler->eap_ds->response->type; /* * Don't trust anyone. */ if ((eaptype->type == 0) || (eaptype->type > PW_EAP_MAX_TYPES)) { DEBUG2(" rlm_eap: Asked to select bad type"); return EAP_INVALID; } /* * Figure out what to do. */ switch(eaptype->type) { case PW_EAP_IDENTITY: DEBUG2(" rlm_eap: EAP Identity"); /* * Allow per-user configuration of EAP types. */ vp = pairfind(handler->request->config_items, PW_EAP_TYPE); if (vp) default_eap_type = vp->lvalue; do_initiate: /* * Ensure it's valid. */ if ((default_eap_type < PW_EAP_MD5) || (default_eap_type > PW_EAP_MAX_TYPES) || (inst->types[default_eap_type] == NULL)) { DEBUG2(" rlm_eap: No such EAP type %s", eaptype_type2name(default_eap_type, namebuf, sizeof(namebuf))); return EAP_INVALID; } handler->stage = INITIATE; handler->eap_type = default_eap_type; /* * Wild & crazy stuff! For TTLS & PEAP, we * initiate a TLS session, and then pass that * session data to TTLS or PEAP for the * authenticate stage. * * Handler->eap_type holds the TRUE type. */ if ((default_eap_type == PW_EAP_TTLS) || (default_eap_type == PW_EAP_PEAP)) { default_eap_type = PW_EAP_TLS; } /* * We don't do TLS inside of TLS, as it's a bad * idea... */ if (((handler->request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) && (default_eap_type == PW_EAP_TLS)) { DEBUG2(" rlm_eap: Unable to tunnel TLS inside of TLS"); return EAP_INVALID; } if (eaptype_call(inst->types[default_eap_type], handler) == 0) { DEBUG2(" rlm_eap: Default EAP type %s failed in initiate", eaptype_type2name(default_eap_type, namebuf, sizeof(namebuf))); return EAP_INVALID; } break; case PW_EAP_NAK: /* * The NAK data is the preferred EAP type(s) of * the client. * * RFC 3748 says to list one or more proposed * alternative types, one per octet, or to use * 0 for no alternative. */ DEBUG2(" rlm_eap: EAP NAK"); /* * Delete old data, if necessary. */ if (handler->opaque && handler->free_opaque) { handler->free_opaque(handler->opaque); handler->free_opaque = NULL; handler->opaque = NULL; } /* * It is invalid to request identity, * notification & nak in nak */ if (eaptype->data == NULL) { DEBUG2(" rlm_eap: Empty NAK packet, cannot decide what EAP type the client wants."); return EAP_INVALID; } /* * FIXME: Pick one type out of the one they asked * for, as they may have asked for many. */ if ((eaptype->data[0] < PW_EAP_MD5) || (eaptype->data[0] > PW_EAP_MAX_TYPES)) { DEBUG2(" rlm_eap: NAK asked for bad type %d", eaptype->data[0]); return EAP_INVALID; } default_eap_type = eaptype->data[0]; eaptype_name = eaptype_type2name(default_eap_type, namebuf, sizeof(namebuf)); DEBUG2(" rlm_eap: EAP-NAK asked for EAP-Type/%s", eaptype_name); /* * Prevent a firestorm if the client is confused. */ if (handler->eap_type == default_eap_type) { DEBUG2(" rlm_eap: ERROR! Our request for %s was NAK'd with a request for %s, what is the client thinking?", eaptype_name, eaptype_name); return EAP_INVALID; } /* * Enforce per-user configuration of EAP types. */ vp = pairfind(handler->request->config_items, PW_EAP_TYPE); if (vp && (vp->lvalue != default_eap_type)) { char mynamebuf[64]; DEBUG2(" rlm_eap: Client wants %s, while we require %s, rejecting the user.", eaptype_name, eaptype_type2name(vp->lvalue, mynamebuf, sizeof(mynamebuf))); return EAP_INVALID; } goto do_initiate; break; /* * Key off of the configured sub-modules. */ default: eaptype_name = eaptype_type2name(eaptype->type, namebuf, sizeof(namebuf)); DEBUG2(" rlm_eap: EAP/%s", eaptype_name); /* * We haven't configured it, it doesn't exit. */ if (!inst->types[eaptype->type]) { DEBUG2(" rlm_eap: EAP type %d is unsupported", eaptype->type); return EAP_INVALID; } rad_assert(handler->stage == AUTHENTICATE); handler->eap_type = eaptype->type; if (eaptype_call(inst->types[eaptype->type], handler) == 0) { DEBUG2(" rlm_eap: Handler failed in EAP/%s", eaptype_name); return EAP_INVALID; } break; } return EAP_OK;}/* * EAP packet format to be sent over the wire *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -