⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eap.c

📁 freeradius-server-2.1.3.tar.gz安装源文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * eap.c    rfc2284 & rfc2869 implementation * * 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 2000-2003,2006  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 <freeradius-devel/ident.h>RCSID("$Id$")#include "rlm_eap.h"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;	}	cf_log_module(cs, "Linked to sub-module %s", buffer);	cf_log_module(cs, "Instantiating eap-%s", eaptype_name);	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;	}	*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;	REQUEST *request = handler->request;	const char *module = request->module;	RDEBUG2("processing type %s", atype->typename);	request->module = 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 */		RDEBUG("Internal sanity check failed on eap_type");		rcode = 0;		break;	}	request->module = module;	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){	size_t		i;	unsigned int	default_eap_type = inst->default_eap_type;	eaptype_t	*eaptype;	VALUE_PAIR	*vp;	char		namebuf[64];	const char	*eaptype_name;	REQUEST		*request = handler->request;	eaptype = &handler->eap_ds->response->type;	/*	 *	Don't trust anyone.	 */	if ((eaptype->type == 0) ||	    (eaptype->type > PW_EAP_MAX_TYPES)) {		RDEBUG2("Asked to select bad type");		return EAP_INVALID;	}	/*	 *	Multiple levels of nesting are invalid.	 */	if (handler->request->parent && handler->request->parent->parent) {		RDEBUG2("Multiple levels of TLS nesting is invalid.");		return EAP_INVALID;	}	/*	 *	Figure out what to do.	 */	switch(eaptype->type) {	case PW_EAP_IDENTITY:		RDEBUG2("EAP Identity");		/*		 *	Allow per-user configuration of EAP types.		 */		vp = pairfind(handler->request->config_items,			      PW_EAP_TYPE);		if (vp) default_eap_type = vp->vp_integer;	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)) {			RDEBUG2("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;		}		if ((default_eap_type == PW_EAP_TNC) &&		    !handler->request->parent) {			RDEBUG2("ERROR: EAP-TNC must be run inside of a TLS method.");			return EAP_INVALID;		}		if (eaptype_call(inst->types[default_eap_type],				 handler) == 0) {			RDEBUG2("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.		 */		RDEBUG2("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;		}		if (eaptype->data == NULL) {			RDEBUG2("Empty NAK packet, cannot decide what EAP type the client wants.");			return EAP_INVALID;		}		/*		 *	Pick one type out of the one they asked for,		 *	as they may have asked for many.		 */		default_eap_type = 0;		vp = pairfind(handler->request->config_items,			      PW_EAP_TYPE);		for (i = 0; i < eaptype->length; i++) {			/*			 *	It is invalid to request identity,			 *	notification & nak in nak.			 *			 *	Type 0 is valid, and means there are no			 *	common choices.			 */			if (eaptype->data[i] < PW_EAP_MD5) {				RDEBUG2("NAK asked for bad type %d",				       eaptype->data[i]);				return EAP_INVALID;			}			if ((eaptype->data[i] > PW_EAP_MAX_TYPES) ||			    !inst->types[eaptype->data[i]]) {				RDEBUG2("NAK asked for unsupported type %d",				       eaptype->data[i]);				continue;			}			eaptype_name = eaptype_type2name(eaptype->data[i],							 namebuf,							 sizeof(namebuf));						/*			 *	Prevent a firestorm if the client is confused.			 */			if (handler->eap_type == eaptype->data[i]) {				RDEBUG2("ERROR! Our request for %s was NAK'd with a request for %s.  Skipping the requested type.",				       eaptype_name, eaptype_name);				continue;			}			/*			 *	Enforce per-user configuration of EAP			 *	types.			 */			if (vp && (vp->vp_integer != eaptype->data[i])) {				char	mynamebuf[64];				RDEBUG2("Client wants %s, while we require %s.  Skipping the requested type.",				       eaptype_name,				       eaptype_type2name(vp->vp_integer,							 mynamebuf,							 sizeof(mynamebuf)));				continue;			}			default_eap_type = eaptype->data[i];			break;		}		/*		 *	We probably want to return 'fail' here...		 */		if (!default_eap_type) {			RDEBUG2("No common EAP types found.");			return EAP_INVALID;		}		eaptype_name = eaptype_type2name(default_eap_type,						 namebuf, sizeof(namebuf));		RDEBUG2("EAP-NAK asked for EAP-Type/%s",		       eaptype_name);		goto do_initiate;		break;		/*		 *	Key off of the configured sub-modules.		 */		default:			eaptype_name = eaptype_type2name(eaptype->type,							 namebuf,							 sizeof(namebuf));			RDEBUG2("EAP/%s", eaptype_name);			/*			 *	We haven't configured it, it doesn't exit.			 */			if (!inst->types[eaptype->type]) {				RDEBUG2("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) {				RDEBUG2("Handler failed in EAP/%s",				       eaptype_name);				return EAP_INVALID;			}		break;	}	return EAP_OK;}/* *	compose EAP reply packet in EAP-Message attr of RADIUS.  If *	EAP exceeds 253, frame it in multiple EAP-Message attrs. * *	Set the RADIUS reply codes based on EAP request codes.  Append *	any additonal VPs to RADIUS reply */int eap_compose(EAP_HANDLER *handler){	VALUE_PAIR *vp;	eap_packet_t *eap_packet;	REQUEST *request = handler->request;	EAP_DS *eap_ds = handler->eap_ds;	EAP_PACKET *reply = eap_ds->request;	int rcode;	/*	 *	The Id for the EAP packet to the NAS wasn't set.	 *	Do so now.	 *	 *	LEAP requires the Id to be incremented on EAP-Success	 *	in Stage 4, so that we can carry on the conversation	 *	where the client asks us to authenticate ourselves	 *	in stage 5.	 */	if (!eap_ds->set_request_id) {		/*		 *	Id serves to suppport request/response		 *	retransmission in the EAP layer and as such		 *	must be different for 'adjacent' packets		 *	except in case of success/failure-replies.		 *		 *	RFC2716 (EAP-TLS) requires this to be		 *	incremented, RFC2284 only makes the above-		 *	mentioned restriction.		 */		reply->id = handler->eap_ds->response->id;		switch (reply->code) {			/*			 *	The Id is a simple "ack" for success			 *	and failure.			 *			 *	RFC 3748 section 4.2 says			 *			 *	... The Identifier field MUST match			 *	the Identifier field of the Response			 *	packet that it is sent in response			 *	to.			 */		case PW_EAP_SUCCESS:		case PW_EAP_FAILURE:	    		break;			/*			 *	We've sent a response to their			 *	request, the Id is incremented.			 */		default:	    		++reply->id;		}	} else {		RDEBUG2("Underlying EAP-Type set EAP ID to %d",		       reply->id);	}	/*	 *	For Request & Response packets, set the EAP sub-type,	 *	if the EAP sub-module didn't already set it.	 *	 *	This allows the TLS module to be "morphic", and means	 *	that the TTLS and PEAP modules can call it to do most	 *	of their dirty work.	 */	if (((eap_ds->request->code == PW_EAP_REQUEST) ||	     (eap_ds->request->code == PW_EAP_RESPONSE)) &&	    (eap_ds->request->type.type == 0)) {		rad_assert(handler->eap_type >= PW_EAP_MD5);		rad_assert(handler->eap_type <= PW_EAP_MAX_TYPES);		eap_ds->request->type.type = handler->eap_type;	}	/*	 *	FIXME: We malloc memory for the eap packet, and then	 *	immediately copy that data into VALUE_PAIRs.  This	 *	could be done more efficiently...	 */	if (eap_wireformat(reply) == EAP_INVALID) {		return RLM_MODULE_INVALID;	}	eap_packet = (eap_packet_t *)reply->packet;	vp = eap_packet2vp(eap_packet);	if (!vp) return RLM_MODULE_INVALID;	pairadd(&(request->reply->vps), vp);	/*	 *	EAP-Message is always associated with	 *	Message-Authenticator but not vice-versa.	 *	 *	Don't add a Message-Authenticator if it's already	 *	there.	 */	vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR);	if (!vp) {		vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);		memset(vp->vp_octets, 0, AUTH_VECTOR_LEN);		vp->length = AUTH_VECTOR_LEN;		pairadd(&(request->reply->vps), vp);	}	/* Set request reply code, but only if it's not already set. */	rcode = RLM_MODULE_OK;	if (!request->reply->code) switch(reply->code) {	case PW_EAP_RESPONSE:		request->reply->code = PW_AUTHENTICATION_ACK;		rcode = RLM_MODULE_HANDLED; /* leap weirdness */		break;	case PW_EAP_SUCCESS:		request->reply->code = PW_AUTHENTICATION_ACK;		rcode = RLM_MODULE_OK;		break;	case PW_EAP_FAILURE:		request->reply->code = PW_AUTHENTICATION_REJECT;		rcode = RLM_MODULE_REJECT;		break;	case PW_EAP_REQUEST:		request->reply->code = PW_ACCESS_CHALLENGE;		rcode = RLM_MODULE_HANDLED;		break;	default:		/*		 *	When we're pulling MS-CHAPv2 out of EAP-MS-CHAPv2,		 *	we do so WITHOUT setting a reply code, as the		 *	request is being proxied.		 */		if (request->options & RAD_REQUEST_OPTION_PROXY_EAP) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -