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

📄 ttls.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * rlm_eap_ttls.c  contains the interfaces that are called from eap * * Version:     $Id: ttls.c,v 1.45 2008/03/07 09:53:26 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * *   Copyright 2003 Alan DeKok <aland@freeradius.org> *   Copyright 2006 The FreeRADIUS server project */#include <freeradius-devel/ident.h>RCSID("$Id: ttls.c,v 1.45 2008/03/07 09:53:26 aland Exp $")#include "eap_ttls.h"/* *    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 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |                           AVP Code                            | *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |V M r r r r r r|                  AVP Length                   | *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |                        Vendor-ID (opt)                        | *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |    Data ... *   +-+-+-+-+-+-+-+-+ *//* *	Verify that the diameter packet is valid. */static int diameter_verify(const uint8_t *data, unsigned int data_len){	uint32_t attr;	uint32_t length;	unsigned int offset;	unsigned int data_left = data_len;	while (data_left > 0) {		if (data_len < 12) {			DEBUG2("  rlm_eap_ttls:  Diameter attribute is too small to contain a Diameter header");			return 0;		}		rad_assert(data_left <= data_len);		memcpy(&attr, data, sizeof(attr));		data += 4;		attr = ntohl(attr);		if (attr > 255) {			DEBUG2("  rlm_eap_ttls:  Non-RADIUS attribute in tunneled authentication is not supported");			return 0;		}		memcpy(&length, data , sizeof(length));		data += 4;		length = ntohl(length);		/*		 *	A "vendor" flag, with a vendor ID of zero,		 *	is equivalent to no vendor.  This is stupid.		 */		offset = 8;		if ((length & (1 << 31)) != 0) {			int attribute;			uint32_t vendor;			DICT_ATTR *da;			memcpy(&vendor, data, sizeof(vendor));			vendor = ntohl(vendor);			if (vendor > 65535) {				DEBUG2("  rlm_eap_ttls: Vendor codes larger than 65535 are not supported");				return 0;			}			attribute = (vendor << 16) | attr;			da = dict_attrbyvalue(attribute);			/*			 *	SHOULD check ((length & (1 << 30)) != 0)			 *	for the mandatory bit.			 */			if (!da) {				DEBUG2("  rlm_eap_ttls: Fatal! Vendor %u, Attribute %u was not found in our dictionary. ",				       vendor, attr);				return 0;			}			data += 4; /* skip the vendor field */			offset += 4; /* offset to value field */		}		/*		 *	Ignore the M bit.  We support all RADIUS attributes...		 */		/*		 *	Get the length.  If it's too big, die.		 */		length &= 0x00ffffff;		/*		 *	Too short or too long is bad.		 */		if (length < offset) {			DEBUG2("  rlm_eap_ttls: Tunneled attribute %d is too short (%d)to contain anything useful.", attr, length);			return 0;		}		/*		 *	EAP Messages cane be longer than MAX_STRING_LEN.		 *	Other attributes cannot be.		 */		if ((attr != PW_EAP_MESSAGE) &&		    (length > (MAX_STRING_LEN + 8))) {			DEBUG2("  rlm_eap_ttls: Tunneled attribute %d is too long (%d) to pack into a RADIUS attribute.", attr, length);			return 0;		}		if (length > data_left) {			DEBUG2("  rlm_eap_ttls: Tunneled attribute %d is longer than room left in the packet (%d > %d).", attr, length, data_left);			return 0;		}		/*		 *	Check for broken implementations, which don't		 *	pad the AVP to a 4-octet boundary.		 */		if (data_left == length) break;		/*		 *	The length does NOT include the padding, so		 *	we've got to account for it here by rounding up		 *	to the nearest 4-byte boundary.		 */		length += 0x03;		length &= ~0x03;		/*		 *	If the rest of the diameter packet is larger than		 *	this attribute, continue.		 *		 *	Otherwise, if the attribute over-flows the end		 *	of the packet, die.		 */		if (data_left < length) {			DEBUG2("  rlm_eap_ttls: ERROR! Diameter attribute overflows packet!");			return 0;		}		/*		 *	Check again for equality, now that we're padded		 *	length to a multiple of 4 octets.		 */		if (data_left == length) break;		/*		 *	data_left > length, continue.		 */		data_left -= length;		data += length - offset;	}	/*	 *	We got this far.  It looks OK.	 */	return 1;}/* *	Convert diameter attributes to our VALUE_PAIR's */static VALUE_PAIR *diameter2vp(SSL *ssl,			       const uint8_t *data, size_t data_len){	uint32_t	attr;	uint32_t	length;	size_t		offset;	size_t		size;	size_t		data_left = data_len;	VALUE_PAIR	*first = NULL;	VALUE_PAIR	**last = &first;	VALUE_PAIR	*vp;	while (data_left > 0) {		rad_assert(data_left <= data_len);		memcpy(&attr, data, sizeof(attr));		data += 4;		attr = ntohl(attr);		memcpy(&length, data, sizeof(length));		data += 4;		length = ntohl(length);		/*		 *	A "vendor" flag, with a vendor ID of zero,		 *	is equivalent to no vendor.  This is stupid.		 */		offset = 8;		if ((length & (1 << 31)) != 0) {			uint32_t vendor;			memcpy(&vendor, data, sizeof(vendor));			vendor = ntohl(vendor);			if (attr > 65535) {				DEBUG2("  rlm_eap_ttls: Cannot handle vendor attributes greater than 65535");				pairfree(&first);				return NULL;			}			if (vendor > 32767) {				DEBUG2("  rlm_eap_ttls: Cannot handle vendor Id greater than 32767");				pairfree(&first);				return NULL;			}			attr |= (vendor << 16);			data += 4; /* skip the vendor field, it's zero */			offset += 4; /* offset to value field */		}		/*		 *	Vendor attributes can be larger than 255.		 *	Normal attributes cannot be.		 */		if ((attr > 255) && (VENDOR(attr) == 0)) {			DEBUG2("  rlm_eap_ttls: Cannot handle Diameter attributes");			pairfree(&first);			return NULL;		}		/*		 *	FIXME: Handle the M bit.  For now, we assume that		 *	some other module takes care of any attribute		 *	with the M bit set.		 */				/*		 *	Get the length.		 */		length &= 0x00ffffff;		/*		 *	Get the size of the value portion of the		 *	attribute.		 */		size = length - offset;		/*		 *	Create it.		 */		vp = paircreate(attr, PW_TYPE_OCTETS);		if (!vp) {			DEBUG2("  rlm_eap_ttls: Failure in creating VP");			pairfree(&first);			return NULL;		}		/*		 *	If it's a type from our dictionary, then		 *	we need to put the data in a relevant place.		 */		switch (vp->type) {		case PW_TYPE_INTEGER:		case PW_TYPE_DATE:			if (size != vp->length) {				DEBUG2("  rlm_eap_ttls: Invalid length attribute %d",				       attr);				pairfree(&first);				pairfree(&vp);				return NULL;			}			memcpy(&vp->vp_integer, data, vp->length);			/*			 *	Stored in host byte order: change it.			 */			vp->vp_integer = ntohl(vp->vp_integer);			break;		case PW_TYPE_IPADDR:			if (size != vp->length) {				DEBUG2("  rlm_eap_ttls: Invalid length attribute %d",				       attr);				pairfree(&first);				pairfree(&vp);				return NULL;			}		  memcpy(&vp->vp_ipaddr, data, vp->length);		  /*		   *	Stored in network byte order: don't change it.		   */		  break;		  /*		   *	String, octet, etc.  Copy the data from the		   *	value field over verbatim.		   *		   *	FIXME: Ipv6 attributes ?		   *		   */		case PW_TYPE_OCTETS:			if (attr == PW_EAP_MESSAGE) {				const uint8_t *eap_message = data;				/*				 *	vp exists the first time around.				 */				while (1) {					vp->length = size;					if (vp->length > 253) vp->length = 253;					memcpy(vp->vp_octets, eap_message,					       vp->length);					size -= vp->length;					eap_message += vp->length;					*last = vp;					last = &(vp->next);					if (size == 0) break;					vp = paircreate(attr, PW_TYPE_OCTETS);					if (!vp) {						DEBUG2("  rlm_eap_ttls: Failure in creating VP");						pairfree(&first);						return NULL;					}				}				goto next_attr;			} /* else it's another kind of attribute */			/* FALL-THROUGH */		default:			vp->length = size;			memcpy(vp->vp_strvalue, data, vp->length);			break;		}		/*		 *	User-Password is NUL padded to a multiple		 *	of 16 bytes.  Let's chop it to something		 *	more reasonable.		 *		 *	NOTE: This means that the User-Password		 *	attribute CANNOT EVER have embedded zeros in it!		 */		switch (vp->attribute) {		case PW_USER_PASSWORD:			/*			 *	If the password is exactly 16 octets,			 *	it won't be zero-terminated.			 */			vp->vp_strvalue[vp->length] = '\0';			vp->length = strlen(vp->vp_strvalue);			break;			/*			 *	Ensure that the client is using the			 *	correct challenge.  This weirdness is			 *	to protect against against replay			 *	attacks, where anyone observing the			 *	CHAP exchange could pose as that user,			 *	by simply choosing to use the same			 *	challenge.			 *			 *	By using a challenge based on			 *	information from the current session,			 *	we can guarantee that the client is			 *	not *choosing* a challenge.			 *			 *	We're a little forgiving in that we			 *	have loose checks on the length, and			 *	we do NOT check the Id (first octet of			 *	the response to the challenge)			 *			 *	But if the client gets the challenge correct,			 *	we're not too worried about the Id.			 */		case PW_CHAP_CHALLENGE:		case PW_MSCHAP_CHALLENGE:			if ((vp->length < 8) ||			    (vp->length > 16)) {				DEBUG2("  TTLS: Tunneled challenge has invalid length");				pairfree(&first);				pairfree(&vp);				return NULL;			} else {				uint8_t	challenge[16];				eapttls_gen_challenge(ssl, challenge,						      sizeof(challenge));				if (memcmp(challenge, vp->vp_octets,					   vp->length) != 0) {					DEBUG2("  TTLS: Tunneled challenge is incorrect");					pairfree(&first);					pairfree(&vp);					return NULL;				}			}			break;		default:			break;		} /* switch over checking/re-writing of attributes. */		/*		 *	Update the list.		 */		*last = vp;		last = &(vp->next);	next_attr:		/*		 *	Catch non-aligned attributes.		 */		if (data_left == length) break;		/*

⌨️ 快捷键说明

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