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

📄 eap.c

📁 RADIUS 服务器介绍 RADIUS服务器支持标准的RADIUS协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * eap.c    rfc2284 & rfc2869 implementation * * Version:     $Id: eap.c,v 1.22 2003/07/07 15:20:42 aland 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,2001  The FreeRADIUS server project * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com> *//* *  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 *eap_types[] = {  "",     "identity",  "notification",  "nak",			/* NAK */  "md5",  "otp",  "gtc",  "7",  "8",  "9",  "10",  "11",  "12",  "tls",			/* 13 */  "14",  "15",  "16",  "leap",			/* 17 */  "18",  "19",  "20",  "ttls",			/* 21 */  "22",  "23",  "24",  "peap"			/* 25 */};/* * Load all the required eap authentication types. * Get all the supported EAP-types from config file.  */int eaptype_load(EAP_TYPES **type_list, const char *type_name,		 CONF_SECTION *cs){	EAP_TYPES **last, *node;	lt_dlhandle handle;	char auth_type_name[NAME_LEN];	int i;	snprintf(auth_type_name, sizeof(auth_type_name), "rlm_eap_%s", type_name);	last = type_list;	/* Go to the end of the EAP-Type list, if it is not already loaded */	for (node = *type_list; node != NULL; node = node->next) {		if (strcmp(node->typename, auth_type_name) == 0)			return 0;		last = &node->next;	}	/* Link the loaded EAP-Type */	handle = lt_dlopenext(auth_type_name);	if (handle == NULL) {		radlog(L_ERR, "rlm_eap: Failed to link EAP-Type/%s: %s", 				type_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;	}	/* fill in the structure */	node->next = NULL;	node->handle = handle;	node->cs = cs;	node->typeid = 0;	memset(node->typename, 0, NAME_LEN);	node->type_stuff = NULL;	strNcpy(node->typename, type_name, sizeof(node->typename));	for (i = PW_EAP_MAX_TYPES; i > 0; i--) {		if (!strcmp(type_name, eap_types[i])) {			node->typeid = i;			break;		}	}	if (node->typeid == 0) {		radlog(L_ERR, "rlm_eap: Invalid type name %s cannot be linked", type_name);		free(node);		return -1;	}		node->type = (EAP_TYPE *)lt_dlsym(node->handle, auth_type_name);	if (!node->type) {		radlog(L_ERR, "rlm_eap: Failed linking to %s structure in %s: %s",				auth_type_name, type_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_stuff)) < 0)) {		radlog(L_ERR, "rlm_eap: Failed to initialize the type %s", type_name);		lt_dlclose(node->handle);		free(node);		return -1;	}	DEBUG("rlm_eap: Loaded and initialized the type %s", type_name);	*last = node;	return 0;}/* * Get the handle for the requested authentication type,  * if supported. */EAP_TYPES *eaptype_byid(EAP_TYPES **list, int type){	EAP_TYPES *node;	for(node = *list; node != NULL; node = node->next) {		if (node->typeid == type)			return node;	}	return NULL;}EAP_TYPES *eaptype_byname(EAP_TYPES **list, const char *name){	EAP_TYPES *node;	for(node = *list; node != NULL; node = node->next) {		if (strcmp(node->typename, name) == 0)			return node;	}	return NULL;}/* * Call the appropriate handle with the right eap_type. */int eaptype_call(int eap_type, operation_t action, 	EAP_TYPES *type_list, EAP_HANDLER *handler){	EAP_TYPES *atype;	atype = eaptype_byid(&type_list, eap_type);	if (!atype) {		radlog(L_ERR, "rlm_eap: Unsupported EAP_TYPE %d",			handler->eap_ds->response->type.type);		return 0;	}	DEBUG2("  rlm_eap: processing type %s", atype->typename);	switch (action) {	case INITIATE:		if (!atype->type->initiate(atype->type_stuff, handler))			return 0;		break;	case AUTHENTICATE:		/*		 * when it returns, eap_ds->reply is expected to have complete info		 */		if (!atype->type->authenticate(atype->type_stuff, handler))			return 0;		break;	default:		/* Should never enter here */		radlog(L_DBG, "rlm_eap: Invalid operation  on eap_type");		break;	}	return 1;}/* * Based on TYPE, call the appropriate EAP-type handler * Default to the configured EAP-Type  * for all Unsupported EAP-Types  */int eaptype_select(EAP_TYPES *type_list, EAP_HANDLER *handler, char *conftype){	int type = 0, i;	eaptype_t *eaptype;	for (i = PW_EAP_MAX_TYPES; i > 0; i--) {		if (strcmp(conftype, eap_types[i]) == 0) {			type = i;			break;		}	}	if (type == 0) {		radlog(L_ERR, "rlm_eap: Configured  EAP_TYPE is not supported");	}	eaptype = &handler->eap_ds->response->type;	switch(eaptype->type) {	case PW_EAP_IDENTITY:		DEBUG2("  rlm_eap: EAP Identity");		if (eaptype_call(type, INITIATE, type_list, handler) == 0)			return EAP_INVALID;			break;	case PW_EAP_NAK:		DEBUG2("  rlm_eap: EAP NAK");		/*		 * It is invalid to request identity, notification & nak in nak		 */		if ((eaptype->data != NULL) &&			(eaptype->data[0] < PW_EAP_MD5)) {			return EAP_INVALID;		}		/*		 *	The one byte of NAK data is the preferred EAP type		 *	of the client.		 */		switch (eaptype->data[0]) {		case PW_EAP_MD5:		case PW_EAP_TLS:		case PW_EAP_LEAP:			/*			 * eap-type specified in typdata is supported			 */			if (eaptype_call(eaptype->data[0],				INITIATE, type_list, handler) == 0)				return EAP_INVALID;			break;		default :			DEBUG2("  rlm_eap: Unknown EAP type %d, reverting to default_eap_type",			       eaptype->data[0]);			/*			 * Unsupported type, default to configured one.			 * or rather reject it			 */			/* handler->eap_ds->request->code = PW_EAP_FAILURE; */			if (eaptype_call(type, INITIATE, type_list, handler) == 0)				return EAP_INVALID;			break;		}		break;		case PW_EAP_MD5:		case PW_EAP_OTP:		case PW_EAP_GTC:		case PW_EAP_TLS:		case PW_EAP_LEAP:		default:			DEBUG2("  rlm_eap: EAP_TYPE - %s",				eap_types[eaptype->type]);			if (eaptype_call(eaptype->type, AUTHENTICATE,				type_list, handler) == 0) {				return EAP_INVALID;		}		break;	}	return EAP_OK;}/* * Handles multiple EAP-Message attrs * ie concatenates all to get the complete EAP packet * * NOTE: Sometimes Framed-MTU might contain the length of EAP-Message, *      refer fragmentation in rfc2869. */eap_packet_t *eap_attribute(VALUE_PAIR *vps){	VALUE_PAIR *first, *vp;	eap_packet_t *eap_packet;	unsigned char *ptr;	uint16_t len;	int total_len;	/*	 *	Get only EAP-Message attribute list	 */	first = pairfind(vps, PW_EAP_MESSAGE);	if (first == NULL) {		radlog(L_ERR, "rlm_eap: EAP-Message not found");		return NULL;	}	/*	 *	Sanity check the length before doing anything.	 */	if (first->length < 4) {		radlog(L_ERR, "rlm_eap: EAP packet is too short.");		return NULL;	}	/*	 *	Get the Actual length from the EAP packet	 *	First EAP-Message contains the EAP packet header	 */	memcpy(&len, first->strvalue + 2, sizeof(len));	len = ntohs(len);	/*	 *	Take out even more weird things.	 */	if (len < 4) {		radlog(L_ERR, "rlm_eap: EAP packet has invalid length.");		return NULL;	}	/*	 *	Sanity check the length, BEFORE malloc'ing memory.	 */	total_len = 0;	for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE)) {		total_len += vp->length;				if (total_len > len) {			radlog(L_ERR, "rlm_eap: Malformed EAP packet.  Length in packet header does not match actual length");			return NULL;		}	}	/*	 *	If the length is SMALLER, die, too.	 */	if (total_len < len) {		radlog(L_ERR, "rlm_eap: Malformed EAP packet.  Length in packet header does not match actual length");		return NULL;	}	/*	 *	Now that we know the lengths are OK, allocate memory.	 */	eap_packet = (eap_packet_t *) malloc(len);	if (eap_packet == NULL) {		radlog(L_ERR, "rlm_eap: out of memory");		return NULL;	}	/*	 *	Copy the data from EAP-Message's over to out EAP packet.	 */	ptr = (unsigned char *)eap_packet;	/* RADIUS ensures order of attrs, so just concatenate all */	for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE)) {		memcpy(ptr, vp->strvalue, vp->length);		ptr += vp->length;	}	return eap_packet;}/* * EAP packet format to be sent over the wire * ie code+id+length+data where data = null/type+typedata * based on code. */int eap_wireformat(EAP_PACKET *reply){	eap_packet_t	*hdr;	uint16_t total_length = 0;	if (reply == NULL) return EAP_INVALID;	total_length = EAP_HEADER_LEN;	if (reply->code < 3) {		total_length += 1/*EAPtype*/;		if (reply->type.data && reply->type.length > 0) {			total_length += reply->type.length;		}	}	reply->packet = (unsigned char *)malloc(total_length);	hdr = (eap_packet_t *)reply->packet;	if (!hdr) {		radlog(L_ERR, "rlm_eap: out of memory");		return EAP_INVALID;	}	hdr->code = (reply->code & 0xFF);	hdr->id = (reply->id & 0xFF);	total_length = htons(total_length);	memcpy(hdr->length, &total_length, sizeof(uint16_t));	if (reply->code < 3) {		hdr->data[0] = (reply->type.type & 0xFF);		/*		 * Here since we cannot know the typedata format and length		 * Type_data is expected to be wired by each EAP-Type		 * Zero length/No typedata is supported as long as type is defined		 */		if (reply->type.data && reply->type.length > 0) {			memcpy(&hdr->data[1], reply->type.data, reply->type.length);			free(reply->type.data);			reply->type.data = reply->packet + EAP_HEADER_LEN + 1/*EAPtype*/;		}	}	return EAP_VALID;}/* * 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(REQUEST *request, EAP_DS *eap_ds){	uint16_t eap_len, len;	VALUE_PAIR *eap_msg;	EAP_PACKET *rq;	VALUE_PAIR *vp;	eap_packet_t *eap_packet;	unsigned char 	*ptr;	EAP_PACKET *reply = eap_ds->request;	/*	 * 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.	 */	eap_msg = pairfind(request->packet->vps, PW_EAP_MESSAGE);	rq = (EAP_PACKET *)eap_msg->strvalue;	/*	 *	The ID for the EAP packet to the NAS wasn't set.	 *	Do so now.	 */	if (!eap_ds->set_request_id) {		reply->id = rq->id;				switch (reply->code) {		case PW_EAP_SUCCESS:		case PW_EAP_FAILURE:	    		break;					default:	    		++reply->id;		}	} else {		DEBUG2("  rlm_eap: Underlying EAP-Type set EAP ID to %d",		       reply->id);	}	if (eap_wireformat(reply) == EAP_INVALID) {		return EAP_INVALID;	}

⌨️ 快捷键说明

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