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

📄 radius.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 *	Check for socket errors.	 */	if (packet->data_len < 0) {		librad_log("Error receiving packet: %s", strerror(errno));		/* packet->data is NULL */		free(packet);		return NULL;	}	/*	 *	If the packet is too big, then rad_recvfrom did NOT	 *	allocate memory.  Instead, it just discarded the	 *	packet.	 */	if (packet->data_len > MAX_PACKET_LEN) {		librad_log("Discarding packet: Larger than RFC limitation of 4096 bytes.");		/* packet->data is NULL */		free(packet);		return NULL;	}	/*	 *	Read no data.  Continue.	 *	This check is AFTER the MAX_PACKET_LEN check above, because	 *	if the packet is larger than MAX_PACKET_LEN, we also have	 *	packet->data == NULL	 */	if ((packet->data_len == 0) || !packet->data) {		librad_log("Empty packet: Socket is not ready.");		free(packet);		return NULL;	}	/*	 *	See if it's a well-formed RADIUS packet.	 */	if (!rad_packet_ok(packet, flags)) {		rad_free(&packet);		return NULL;	}	/*	 *	Remember which socket we read the packet from.	 */	packet->sockfd = fd;	/*	 *	FIXME: Do even more filtering by only permitting	 *	certain IP's.  The problem is that we don't know	 *	how to do this properly for all possible clients...	 */	/*	 *	Explicitely set the VP list to empty.	 */	packet->vps = NULL;	if (librad_debug) {		char host_ipaddr[128];		if ((packet->code > 0) && (packet->code < MAX_PACKET_CODE)) {			DEBUG("rad_recv: %s packet from host %s port %d",			      packet_codes[packet->code],			      inet_ntop(packet->src_ipaddr.af,					&packet->src_ipaddr.ipaddr,					host_ipaddr, sizeof(host_ipaddr)),			      packet->src_port);		} else {			DEBUG("rad_recv: Packet from host %s port %d code=%d",			      inet_ntop(packet->src_ipaddr.af,					&packet->src_ipaddr.ipaddr,					host_ipaddr, sizeof(host_ipaddr)),			      packet->src_port,			      packet->code);		}		DEBUG(", id=%d, length=%d\n", packet->id, packet->data_len);	}	return packet;}/* *	Verify the signature of a packet. */int rad_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original,	       const char *secret){	uint8_t			*ptr;	int			length;	int			attrlen;	if (!packet || !packet->data) return -1;	/*	 *	Before we allocate memory for the attributes, do more	 *	sanity checking.	 */	ptr = packet->data + AUTH_HDR_LEN;	length = packet->data_len - AUTH_HDR_LEN;	while (length > 0) {		uint8_t	msg_auth_vector[AUTH_VECTOR_LEN];		uint8_t calc_auth_vector[AUTH_VECTOR_LEN];		attrlen = ptr[1];		switch (ptr[0]) {		default:	/* don't do anything. */			break;			/*			 *	Note that more than one Message-Authenticator			 *	attribute is invalid.			 */		case PW_MESSAGE_AUTHENTICATOR:			memcpy(msg_auth_vector, &ptr[2], sizeof(msg_auth_vector));			memset(&ptr[2], 0, AUTH_VECTOR_LEN);			switch (packet->code) {			default:				break;			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(packet->data + 4, 0, AUTH_VECTOR_LEN);				break;			case PW_AUTHENTICATION_ACK:			case PW_AUTHENTICATION_REJECT:			case PW_ACCESS_CHALLENGE:				if (!original) {					librad_log("ERROR: Cannot validate Message-Authenticator in response packet without a request packet.");					return -1;				}				memcpy(packet->data + 4, original->vector, AUTH_VECTOR_LEN);				break;			}			fr_hmac_md5(packet->data, packet->data_len,				    (const uint8_t *) secret, strlen(secret),				    calc_auth_vector);			if (memcmp(calc_auth_vector, msg_auth_vector,				   sizeof(calc_auth_vector)) != 0) {				char buffer[32];				librad_log("Received packet from %s with invalid Message-Authenticator!  (Shared secret is incorrect.)",					   inet_ntop(packet->src_ipaddr.af,						     &packet->src_ipaddr.ipaddr,						     buffer, sizeof(buffer)));				/* Silently drop packet, according to RFC 3579 */				return -1;			} /* else the message authenticator was good */			/*			 *	Reinitialize Authenticators.			 */			memcpy(&ptr[2], msg_auth_vector, AUTH_VECTOR_LEN);			memcpy(packet->data + 4, packet->vector, AUTH_VECTOR_LEN);			break;		} /* switch over the attributes */		ptr += attrlen;		length -= attrlen;	} /* loop over the packet, sanity checking the attributes */	/*	 *	It looks like a RADIUS packet, but we can't validate	 *	the signature.	 */	if ((packet->code == 0) || (packet->code >= MAX_PACKET_CODE)) {		char buffer[32];		librad_log("Received Unknown packet code %d "			   "from client %s port %d: Cannot validate signature.",			   packet->code,			   inet_ntop(packet->src_ipaddr.af,				     &packet->src_ipaddr.ipaddr,				     buffer, sizeof(buffer)),			   packet->src_port);		return -1;	}	/*	 *	Calculate and/or verify digest.	 */	switch(packet->code) {		int rcode;		char buffer[32];		case PW_AUTHENTICATION_REQUEST:		case PW_STATUS_SERVER:			/*			 *	The authentication vector is random			 *	nonsense, invented by the client.			 */			break;		case PW_COA_REQUEST:		case PW_DISCONNECT_REQUEST:		case PW_ACCOUNTING_REQUEST:			if (calc_acctdigest(packet, secret) > 1) {				librad_log("Received %s packet "					   "from %s with invalid signature!  (Shared secret is incorrect.)",					   packet_codes[packet->code],					   inet_ntop(packet->src_ipaddr.af,						     &packet->src_ipaddr.ipaddr,						     buffer, sizeof(buffer)));				return -1;			}			break;			/* Verify the reply digest */		case PW_AUTHENTICATION_ACK:		case PW_AUTHENTICATION_REJECT:		case PW_ACCESS_CHALLENGE:		case PW_ACCOUNTING_RESPONSE:		case PW_DISCONNECT_ACK:		case PW_DISCONNECT_NAK:		case PW_COA_ACK:		case PW_COA_NAK:			rcode = calc_replydigest(packet, original, secret);			if (rcode > 1) {				librad_log("Received %s packet "					   "from client %s port %d with invalid signature (err=%d)!  (Shared secret is incorrect.)",					   packet_codes[packet->code],					   inet_ntop(packet->src_ipaddr.af,						     &packet->src_ipaddr.ipaddr,						     buffer, sizeof(buffer)),					   packet->src_port,					   rcode);				return -1;			}			break;		default:			librad_log("Received Unknown packet code %d "				   "from client %s port %d: Cannot validate signature",				   packet->code,				   inet_ntop(packet->src_ipaddr.af,					     &packet->src_ipaddr.ipaddr,						     buffer, sizeof(buffer)),				   packet->src_port);			return -1;	}	return 0;}/* *	Parse a RADIUS attribute into a data structure. */VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,			const char *secret, int attribute, int length,			const uint8_t *data){	int offset = 0;	VALUE_PAIR *vp;	if ((vp = paircreate(attribute, PW_TYPE_OCTETS)) == NULL) {		return NULL;	}	/*	 *	If length is greater than 253, something is SERIOUSLY	 *	wrong.	 */	if (length > 253) length = 253;	/* paranoia (pair-anoia?) */	vp->length = length;	vp->operator = T_OP_EQ;	vp->next = NULL;	/*	 *	Handle tags.	 */	if (vp->flags.has_tag) {		if (TAG_VALID(data[0]) ||		    (vp->flags.encrypt == FLAG_ENCRYPT_TUNNEL_PASSWORD)) {			/*			 *	Tunnel passwords REQUIRE a tag, even			 *	if don't have a valid tag.			 */			vp->flags.tag = data[0];			if ((vp->type == PW_TYPE_STRING) ||			    (vp->type == PW_TYPE_OCTETS)) offset = 1;		}	}	/*	 *	Copy the data to be decrypted	 */	memcpy(&vp->vp_octets[0], data + offset, length - offset);	vp->length -= offset;	/*	 *	Decrypt the attribute.	 */	switch (vp->flags.encrypt) {		/*		 *  User-Password		 */	case FLAG_ENCRYPT_USER_PASSWORD:		if (original) {			rad_pwdecode((char *)vp->vp_strvalue,				     vp->length, secret,				     original->vector);		} else {			rad_pwdecode((char *)vp->vp_strvalue,				     vp->length, secret,				     packet->vector);		}		if (vp->attribute == PW_USER_PASSWORD) {			vp->length = strlen(vp->vp_strvalue);		}		break;		/*		 *	Tunnel-Password's may go ONLY		 *	in response packets.		 */	case FLAG_ENCRYPT_TUNNEL_PASSWORD:		if (!original) goto raw;		if (rad_tunnel_pwdecode(vp->vp_octets, &vp->length,					secret, original->vector) < 0) {			goto raw;		}		break;		/*		 *  Ascend-Send-Secret		 *  Ascend-Receive-Secret		 */	case FLAG_ENCRYPT_ASCEND_SECRET:		if (!original) {			goto raw;		} else {			uint8_t my_digest[AUTH_VECTOR_LEN];			make_secret(my_digest,				    original->vector,				    secret, data);			memcpy(vp->vp_strvalue, my_digest,			       AUTH_VECTOR_LEN );			vp->vp_strvalue[AUTH_VECTOR_LEN] = '\0';			vp->length = strlen(vp->vp_strvalue);		}		break;	default:		break;	} /* switch over encryption flags */	switch (vp->type) {	case PW_TYPE_STRING:	case PW_TYPE_OCTETS:	case PW_TYPE_ABINARY:		/* nothing more to do */		break;	case PW_TYPE_BYTE:		if (vp->length != 1) goto raw;		vp->vp_integer = vp->vp_octets[0];		break;	case PW_TYPE_SHORT:		if (vp->length != 2) goto raw;		vp->vp_integer = (vp->vp_octets[0] << 8) | vp->vp_octets[1];		break;	case PW_TYPE_INTEGER:		if (vp->length != 4) goto raw;		memcpy(&vp->vp_integer, vp->vp_octets, 4);		vp->vp_integer = ntohl(vp->vp_integer);		if (vp->flags.has_tag) vp->vp_integer &= 0x00ffffff;		/*		 *	Try to get named VALUEs		 */		{			DICT_VALUE *dval;			dval = dict_valbyattr(vp->attribute,					      vp->vp_integer);			if (dval) {				strlcpy(vp->vp_strvalue,					dval->name,					sizeof(vp->vp_strvalue));			}		}		break;	case PW_TYPE_DATE:		if (vp->length != 4) goto raw;		memcpy(&vp->vp_date, vp->vp_octets, 4);		vp->vp_date = ntohl(vp->vp_date);		break;	case PW_TYPE_IPADDR:		if (vp->length != 4) goto raw;		memcpy(&vp->vp_ipaddr, vp->vp_octets, 4);		break;		/*		 *	IPv6 interface ID is 8 octets long.		 */	case PW_TYPE_IFID:		if (vp->length != 8) goto raw;		/* vp->vp_ifid == vp->vp_octets */		break;		/*		 *	IPv6 addresses are 16 octets long		 */	case PW_TYPE_IPV6ADDR:		if (vp->length != 16) goto raw;		/* vp->vp_ipv6addr == vp->vp_octets */		break;		/*		 *	IPv6 prefixes are 2 to 18 octets long.		 *		 *	RFC 3162: The first octet is unused.		 *	The second is the length of the prefix		 *	the rest are the prefix data.		 *		 *	The prefix length can have value 0 to 128.		 */	case PW_TYPE_IPV6PREFIX:		if (vp->length < 2 || vp->length > 18) goto raw;		if (vp->vp_octets[1] > 128) goto raw;		/*		 *	FIXME: double-check that		 *	(vp->vp_octets[1] >> 3) matches vp->length + 2		 */		if (vp->length < 18) {			memset(vp->vp_octets + vp->length, 0,			       18 - vp->length);		}		break;	default:	raw:		vp->type = PW_TYPE_OCTETS;		vp->length = length;		memcpy(vp->vp_octets, data, length);		/*		 *	Ensure there's no encryption or tag stuff,		 *	we just pass the attribute as-is.		 */		memset(&vp->flags, 0, sizeof(vp->flags));	}	return vp;}/* *	Calculate/check digest, and decode radius attributes. *	Returns: *	-1 on decoding error *	0 on success */int rad_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original,	       const char *secret){	uint32_t		lvalue;	uint32_t		vendorcode;	VALUE_PAIR		**tail;	VALUE_PAIR		*pair;	uint8_t			*ptr;	int			packet_length;	int			attribute;	int			attrlen;	int			vendorlen;	radius_packet_t		*hdr;	int			vsa_tlen, vsa_llen;	DICT_VENDOR		*dv = NULL;	int			num_attributes = 0;	/*	 *	Extract attribute-value pairs	 */	hdr = (radius_packet_t *)packet->data;	ptr = hdr->data;	packet_length = packet->data_len - AUTH_HDR_LEN;	/*	 *	There may be VP's already in the packet.  Don't	 *	destroy them.	 */	for (tail = &packet->vps; *tail != NULL; tail = &((*tail)->next)) {		/* nothing */	}	vendorcode = 0;	vendorlen  = 0;	vsa_tlen = vsa_llen = 1;	/*	 *	We have to read at least two bytes.	 *	 *	rad_recv() above ensures that this is OK.	 */	while (packet_length > 0) {		attribute = -1;		attrlen = -1;		/*		 *	Normal attribute, handle it like normal.		 */		if (vendorcode == 0) {			/*			 *	No room to read attr/length,			 *	or bad attribute, or attribute is			 *	too short, or attribute is too long,			 *	stop processing the packet.			 */			if ((packet_length < 2) ||			    (ptr[0] == 0) ||  (ptr[1] < 2) ||			    (ptr[1] > packet_length)) break;			attribute = *ptr++;			attrlen   = *ptr++;			attrlen -= 2;			packet_length  -= 2;			if (attribute != PW_VENDOR_SPECIFIC) goto create_pair;			/*			 *	No vendor code, or ONLY vendor code.			 */			if (attrlen <= 4) goto create_pair;			vendorlen = 0;		}		/*		 *	Handle Vendor-Specific		 */		if (vendorlen == 0) {			uint8_t *subptr;			int sublen;			int myvendor;

⌨️ 快捷键说明

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