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

📄 radius.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	     const char *secret){	radius_packet_t	*hdr = (radius_packet_t *)packet->data;	/*	 *	It wasn't assigned an Id, this is bad!	 */	if (packet->id < 0) {		librad_log("ERROR: RADIUS packets must be assigned an Id.");		return -1;	}	if (!packet->data || (packet->data_len < AUTH_HDR_LEN) ||	    (packet->offset < 0)) {		librad_log("ERROR: You must call rad_encode() before rad_sign()");		return -1;	}	/*	 *	If there's a Message-Authenticator, update it	 *	now, BEFORE updating the authentication vector.	 */	if (packet->offset > 0) {		uint8_t calc_auth_vector[AUTH_VECTOR_LEN];		switch (packet->code) {		case PW_ACCOUNTING_REQUEST:		case PW_ACCOUNTING_RESPONSE:		case PW_DISCONNECT_REQUEST:		case PW_DISCONNECT_ACK:		case PW_DISCONNECT_NAK:		case PW_COA_REQUEST:		case PW_COA_ACK:		case PW_COA_NAK:			memset(hdr->vector, 0, AUTH_VECTOR_LEN);			break;		case PW_AUTHENTICATION_ACK:		case PW_AUTHENTICATION_REJECT:		case PW_ACCESS_CHALLENGE:			if (!original) {				librad_log("ERROR: Cannot sign response packet without a request packet.");				return -1;			}			memcpy(hdr->vector, original->vector,			       AUTH_VECTOR_LEN);			break;		default:	/* others have vector already set to zero */			break;		}		/*		 *	Set the authentication vector to zero,		 *	calculate the signature, and put it		 *	into the Message-Authenticator		 *	attribute.		 */		fr_hmac_md5(packet->data, packet->data_len,			    (const uint8_t *) secret, strlen(secret),			    calc_auth_vector);		memcpy(packet->data + packet->offset + 2,		       calc_auth_vector, AUTH_VECTOR_LEN);		/*		 *	Copy the original request vector back		 *	to the raw packet.		 */		memcpy(hdr->vector, packet->vector, AUTH_VECTOR_LEN);	}	/*	 *	Switch over the packet code, deciding how to	 *	sign the packet.	 */	switch (packet->code) {		/*		 *	Request packets are not signed, bur		 *	have a random authentication vector.		 */	case PW_AUTHENTICATION_REQUEST:	case PW_STATUS_SERVER:		break;		/*		 *	Reply packets are signed with the		 *	authentication vector of the request.		 */	default:		{			uint8_t digest[16];			FR_MD5_CTX	context;			fr_MD5Init(&context);			fr_MD5Update(&context, packet->data, packet->data_len);			fr_MD5Update(&context, (const uint8_t *) secret,				     strlen(secret));			fr_MD5Final(digest, &context);			memcpy(hdr->vector, digest, AUTH_VECTOR_LEN);			memcpy(packet->vector, digest, AUTH_VECTOR_LEN);			break;		}	}/* switch over packet codes */	return 0;}/* *	Reply to the request.  Also attach *	reply attribute value pairs and any user message provided. */int rad_send(RADIUS_PACKET *packet, const RADIUS_PACKET *original,	     const char *secret){	VALUE_PAIR		*reply;	const char		*what;	char			ip_buffer[128];	/*	 *	Maybe it's a fake packet.  Don't send it.	 */	if (!packet || (packet->sockfd < 0)) {		return 0;	}	if ((packet->code > 0) && (packet->code < MAX_PACKET_CODE)) {		what = packet_codes[packet->code];	} else {		what = "Reply";	}	/*	 *  First time through, allocate room for the packet	 */	if (!packet->data) {		/*		 *	Encode the packet.		 */		if (rad_encode(packet, original, secret) < 0) {			return -1;		}		/*		 *	Re-sign it, including updating the		 *	Message-Authenticator.		 */		if (rad_sign(packet, original, secret) < 0) {			return -1;		}		/*		 *	If packet->data points to data, then we print out		 *	the VP list again only for debugging.		 */	} else if (librad_debug) {	  	DEBUG("Sending %s of id %d to %s port %d\n", what, packet->id,		      inet_ntop(packet->dst_ipaddr.af,				&packet->dst_ipaddr.ipaddr,				ip_buffer, sizeof(ip_buffer)),		      packet->dst_port);		for (reply = packet->vps; reply; reply = reply->next) {			if ((VENDOR(reply->attribute) == 0) &&			    ((reply->attribute & 0xFFFF) > 0xff)) continue;			debug_pair(reply);		}	}	/*	 *	And send it on it's way.	 */	return rad_sendto(packet->sockfd, packet->data, packet->data_len, 0,			  &packet->src_ipaddr, packet->src_port,			  &packet->dst_ipaddr, packet->dst_port);}/* *	Validates the requesting client NAS.  Calculates the *	signature based on the clients private key. */static int calc_acctdigest(RADIUS_PACKET *packet, const char *secret){	uint8_t		digest[AUTH_VECTOR_LEN];	FR_MD5_CTX		context;	/*	 *	Zero out the auth_vector in the received packet.	 *	Then append the shared secret to the received packet,	 *	and calculate the MD5 sum. This must be the same	 *	as the original MD5 sum (packet->vector).	 */	memset(packet->data + 4, 0, AUTH_VECTOR_LEN);	/*	 *  MD5(packet + secret);	 */	fr_MD5Init(&context);	fr_MD5Update(&context, packet->data, packet->data_len);	fr_MD5Update(&context, (const uint8_t *) secret, strlen(secret));	fr_MD5Final(digest, &context);	/*	 *	Return 0 if OK, 2 if not OK.	 */	if (memcmp(digest, packet->vector, AUTH_VECTOR_LEN) != 0) return 2;	return 0;}/* *	Validates the requesting client NAS.  Calculates the *	signature based on the clients private key. */static int calc_replydigest(RADIUS_PACKET *packet, RADIUS_PACKET *original,			    const char *secret){	uint8_t		calc_digest[AUTH_VECTOR_LEN];	FR_MD5_CTX		context;	/*	 *	Very bad!	 */	if (original == NULL) {		return 3;	}	/*	 *  Copy the original vector in place.	 */	memcpy(packet->data + 4, original->vector, AUTH_VECTOR_LEN);	/*	 *  MD5(packet + secret);	 */	fr_MD5Init(&context);	fr_MD5Update(&context, packet->data, packet->data_len);	fr_MD5Update(&context, (const uint8_t *) secret, strlen(secret));	fr_MD5Final(calc_digest, &context);	/*	 *  Copy the packet's vector back to the packet.	 */	memcpy(packet->data + 4, packet->vector, AUTH_VECTOR_LEN);	/*	 *	Return 0 if OK, 2 if not OK.	 */	if (memcmp(packet->vector, calc_digest, AUTH_VECTOR_LEN) != 0) return 2;	return 0;}/* *	See if the data pointed to by PTR is a valid RADIUS packet. * *	packet is not 'const * const' because we may update data_len, *	if there's more data in the UDP packet than in the RADIUS packet. */int rad_packet_ok(RADIUS_PACKET *packet, int flags){	uint8_t			*attr;	int			totallen;	int			count;	radius_packet_t		*hdr;	char			host_ipaddr[128];	int			require_ma = 0;	int			seen_ma = 0;	int			num_attributes;	/*	 *	Check for packets smaller than the packet header.	 *	 *	RFC 2865, Section 3., subsection 'length' says:	 *	 *	"The minimum length is 20 ..."	 */	if (packet->data_len < AUTH_HDR_LEN) {		librad_log("WARNING: Malformed RADIUS packet from host %s: too short (received %d < minimum %d)",			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     host_ipaddr, sizeof(host_ipaddr)),			   packet->data_len, AUTH_HDR_LEN);		return 0;	}	/*	 *	RFC 2865, Section 3., subsection 'length' says:	 *	 *	" ... and maximum length is 4096."	 */	if (packet->data_len > MAX_PACKET_LEN) {		librad_log("WARNING: Malformed RADIUS packet from host %s: too long (received %d > maximum %d)",			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     host_ipaddr, sizeof(host_ipaddr)),			   packet->data_len, MAX_PACKET_LEN);		return 0;	}	/*	 *	Check for packets with mismatched size.	 *	i.e. We've received 128 bytes, and the packet header	 *	says it's 256 bytes long.	 */	totallen = (packet->data[2] << 8) | packet->data[3];	hdr = (radius_packet_t *)packet->data;	/*	 *	Code of 0 is not understood.	 *	Code of 16 or greate is not understood.	 */	if ((hdr->code == 0) ||	    (hdr->code >= MAX_PACKET_CODE)) {		librad_log("WARNING: Bad RADIUS packet from host %s: unknown packet code%d ",			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     host_ipaddr, sizeof(host_ipaddr)),			   hdr->code);		return 0;	}	/*	 *	Message-Authenticator is required in Status-Server	 *	packets, otherwise they can be trivially forged.	 */	if (hdr->code == PW_STATUS_SERVER) require_ma = 1;	/*	 *	It's also required if the caller asks for it.	 */	if (flags) require_ma = 1;	/*	 *	Repeat the length checks.  This time, instead of	 *	looking at the data we received, look at the value	 *	of the 'length' field inside of the packet.	 *	 *	Check for packets smaller than the packet header.	 *	 *	RFC 2865, Section 3., subsection 'length' says:	 *	 *	"The minimum length is 20 ..."	 */	if (totallen < AUTH_HDR_LEN) {		librad_log("WARNING: Malformed RADIUS packet from host %s: too short (length %d < minimum %d)",			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     host_ipaddr, sizeof(host_ipaddr)),			   totallen, AUTH_HDR_LEN);		return 0;	}	/*	 *	And again, for the value of the 'length' field.	 *	 *	RFC 2865, Section 3., subsection 'length' says:	 *	 *	" ... and maximum length is 4096."	 */	if (totallen > MAX_PACKET_LEN) {		librad_log("WARNING: Malformed RADIUS packet from host %s: too long (length %d > maximum %d)",			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     host_ipaddr, sizeof(host_ipaddr)),			   totallen, MAX_PACKET_LEN);		return 0;	}	/*	 *	RFC 2865, Section 3., subsection 'length' says:	 *	 *	"If the packet is shorter than the Length field	 *	indicates, it MUST be silently discarded."	 *	 *	i.e. No response to the NAS.	 */	if (packet->data_len < totallen) {		librad_log("WARNING: Malformed RADIUS packet from host %s: received %d octets, packet length says %d",			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     host_ipaddr, sizeof(host_ipaddr)),			   packet->data_len, totallen);		return 0;	}	/*	 *	RFC 2865, Section 3., subsection 'length' says:	 *	 *	"Octets outside the range of the Length field MUST be	 *	treated as padding and ignored on reception."	 */	if (packet->data_len > totallen) {		/*		 *	We're shortening the packet below, but just		 *	to be paranoid, zero out the extra data.		 */		memset(packet->data + totallen, 0, packet->data_len - totallen);		packet->data_len = totallen;	}	/*	 *	Walk through the packet's attributes, ensuring that	 *	they add up EXACTLY to the size of the packet.	 *	 *	If they don't, then the attributes either under-fill	 *	or over-fill the packet.  Any parsing of the packet	 *	is impossible, and will result in unknown side effects.	 *	 *	This would ONLY happen with buggy RADIUS implementations,	 *	or with an intentional attack.  Either way, we do NOT want	 *	to be vulnerable to this problem.	 */	attr = hdr->data;	count = totallen - AUTH_HDR_LEN;	num_attributes = 0;	while (count > 0) {		/*		 *	Attribute number zero is NOT defined.		 */		if (attr[0] == 0) {			librad_log("WARNING: Malformed RADIUS packet from host %s: Invalid attribute 0",				   inet_ntop(packet->src_ipaddr.af,					     &packet->src_ipaddr.ipaddr,					     host_ipaddr, sizeof(host_ipaddr)));			return 0;		}		/*		 *	Attributes are at LEAST as long as the ID & length		 *	fields.  Anything shorter is an invalid attribute.		 */       		if (attr[1] < 2) {			librad_log("WARNING: Malformed RADIUS packet from host %s: attribute %d too short",				   inet_ntop(packet->src_ipaddr.af,					     &packet->src_ipaddr.ipaddr,					     host_ipaddr, sizeof(host_ipaddr)),				   attr[0]);			return 0;		}		/*		 *	Sanity check the attributes for length.		 */		switch (attr[0]) {		default:	/* don't do anything by default */			break;			/*			 *	If there's an EAP-Message, we require			 *	a Message-Authenticator.			 */		case PW_EAP_MESSAGE:			require_ma = 1;			break;		case PW_MESSAGE_AUTHENTICATOR:			if (attr[1] != 2 + AUTH_VECTOR_LEN) {				librad_log("WARNING: Malformed RADIUS packet from host %s: Message-Authenticator has invalid length %d",					   inet_ntop(packet->src_ipaddr.af,						     &packet->src_ipaddr.ipaddr,						     host_ipaddr, sizeof(host_ipaddr)),					   attr[1] - 2);				return 0;			}			seen_ma = 1;			break;		}		/*		 *	FIXME: Look up the base 255 attributes in the		 *	dictionary, and switch over their type.  For		 *	integer/date/ip, the attribute length SHOULD		 *	be 6.		 */		count -= attr[1];	/* grab the attribute length */		attr += attr[1];		num_attributes++;	/* seen one more attribute */	}	/*	 *	If the attributes add up to a packet, it's allowed.	 *	 *	If not, we complain, and throw the packet away.	 */	if (count != 0) {		librad_log("WARNING: Malformed RADIUS packet from host %s: packet attributes do NOT exactly fill the packet",			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     host_ipaddr, sizeof(host_ipaddr)));		return 0;	}	/*	 *	If we're configured to look for a maximum number of	 *	attributes, and we've seen more than that maximum,	 *	then throw the packet away, as a possible DoS.	 */	if ((librad_max_attributes > 0) &&	    (num_attributes > librad_max_attributes)) {		librad_log("WARNING: Possible DoS attack from host %s: Too many attributes in request (received %d, max %d are allowed).",			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     host_ipaddr, sizeof(host_ipaddr)),			   num_attributes, librad_max_attributes);		return 0;	}	/*	 * 	http://www.freeradius.org/rfc/rfc2869.html#EAP-Message	 *	 *	A packet with an EAP-Message attribute MUST also have	 *	a Message-Authenticator attribute.	 *	 *	A Message-Authenticator all by itself is OK, though.	 *	 *	Similarly, Status-Server packets MUST contain	 *	Message-Authenticator attributes.	 */	if (require_ma && ! seen_ma) {		librad_log("WARNING: Insecure packet from host %s:  Packet does not contain required Message-Authenticator attribute",			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     host_ipaddr, sizeof(host_ipaddr)));		return 0;	}	/*	 *	Fill RADIUS header fields	 */	packet->code = hdr->code;	packet->id = hdr->id;	memcpy(packet->vector, hdr->vector, AUTH_VECTOR_LEN);	return 1;}/* *	Receive UDP client requests, and fill in *	the basics of a RADIUS_PACKET structure. */RADIUS_PACKET *rad_recv(int fd, int flags){	RADIUS_PACKET		*packet;	/*	 *	Allocate the new request data structure	 */	if ((packet = malloc(sizeof(*packet))) == NULL) {		librad_log("out of memory");		return NULL;	}	memset(packet, 0, sizeof(*packet));	packet->data_len = rad_recvfrom(fd, &packet->data, 0,					&packet->src_ipaddr, &packet->src_port,					&packet->dst_ipaddr, &packet->dst_port);

⌨️ 快捷键说明

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