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

📄 radius.c

📁 linux 下的radius 最新版。linux 下的radius 最新版.linux 下的radius 最新版
💻 C
📖 第 1 页 / 共 4 页
字号:
		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",					   ip_ntoa(host_ipaddr, packet->src_ipaddr),					   attr[1] - 2);				free(packet);				return NULL;			}			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",			   ip_ntoa(host_ipaddr, packet->src_ipaddr));		free(packet);		return NULL;	}	/*	 *	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).",			   ip_ntoa(host_ipaddr, packet->src_ipaddr),			   num_attributes, librad_max_attributes);		free(packet);		return NULL;	}	/*	 * 	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",			   ip_ntoa(host_ipaddr, packet->src_ipaddr));		free(packet);		return NULL;	}	if (librad_debug) {		if ((hdr->code > 0) && (hdr->code < 52)) {			printf("rad_recv: %s packet from host %s:%d",			       packet_codes[hdr->code],			       ip_ntoa(host_ipaddr, packet->src_ipaddr), packet->src_port);		} else {			printf("rad_recv: Packet from host %s:%d code=%d",			       ip_ntoa(host_ipaddr, packet->src_ipaddr), packet->src_port,			       hdr->code);		}		printf(", id=%d, length=%d\n", hdr->id, totallen);	}	/*	 *	Fill RADIUS header fields	 */	packet->code = hdr->code;	packet->id = hdr->id;	memcpy(packet->vector, hdr->vector, AUTH_VECTOR_LEN);	/*	 *  Now that we've sanity checked the packet, we can allocate	 *  memory for it, and copy the data from the local area to	 *  the packet buffer.	 */	if ((packet->data = malloc(packet->data_len)) == NULL) {	  free(packet);	  librad_log("out of memory");	  return NULL;	}	memcpy(packet->data, data, 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;			}			lrad_hmac_md5(packet->data, packet->data_len,				      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.)",					   ip_ntoa(buffer, packet->src_ipaddr));				/* Silently drop packet, according to RFC 3579 */				return -2;			} /* 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 */	/*	 *	Calculate and/or verify digest.	 */	switch(packet->code) {		int rcode;		case PW_AUTHENTICATION_REQUEST:		case PW_STATUS_SERVER:		case PW_DISCONNECT_REQUEST:			/*			 *	The authentication vector is random			 *	nonsense, invented by the client.			 */			break;		case PW_ACCOUNTING_REQUEST:			if (calc_acctdigest(packet, secret) > 1) {				char buffer[32];				librad_log("Received Accounting-Request packet "					   "from %s with invalid signature!  (Shared secret is incorrect.)",					   ip_ntoa(buffer, packet->src_ipaddr));				return -1;			}			break;			/* Verify the reply digest */		case PW_AUTHENTICATION_ACK:		case PW_AUTHENTICATION_REJECT:		case PW_ACCESS_CHALLENGE:		case PW_ACCOUNTING_RESPONSE:			rcode = calc_replydigest(packet, original, secret);			if (rcode > 1) {				char buffer[32];				librad_log("Received %s packet "					   "from client %s port %d with invalid signature (err=%d)!  (Shared secret is incorrect.)",					   packet_codes[packet->code],					   ip_ntoa(buffer, packet->src_ipaddr),					   packet->src_port,					   rcode);				return -1;			}		  break;	}	return 0;}/* *	Parse a RADIUS attribute into a data structure. */static 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->strvalue[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->strvalue,				     vp->length, secret,				     original->vector);		} else {			rad_pwdecode((char *)vp->strvalue,				     vp->length, secret,				     packet->vector);		}		if (vp->attribute == PW_USER_PASSWORD) {			vp->length = strlen(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->strvalue, &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->strvalue, my_digest,			       AUTH_VECTOR_LEN );			vp->strvalue[AUTH_VECTOR_LEN] = '\0';			vp->length = strlen(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_INTEGER:		if (vp->length != 4) goto raw;		memcpy(&vp->lvalue, vp->strvalue, 4);		vp->lvalue = ntohl(vp->lvalue);		if (vp->flags.has_tag) vp->lvalue &= 0x00ffffff;		/*		 *	Try to get named VALUEs		 */		{			DICT_VALUE *dval;			dval = dict_valbyattr(vp->attribute,					      vp->lvalue);			if (dval) {				strNcpy(vp->strvalue,					dval->name,					sizeof(vp->strvalue));			}		}		break;	case PW_TYPE_DATE:		if (vp->length != 4) goto raw;		memcpy(&vp->lvalue, vp->strvalue, 4);		vp->lvalue = ntohl(vp->lvalue);		break;		/*		 *	IPv4 address. Keep it in network byte order in		 *	vp->lvalue and put ASCII IP address in standard		 *	dot notation into vp->strvalue.		 */	case PW_TYPE_IPADDR:		if (vp->length != 4) goto raw;		memcpy(&vp->lvalue, vp->strvalue, 4);		ip_ntoa(vp->strvalue, vp->lvalue);		break;		/*		 *	IPv6 interface ID is 8 octets long.		 */	case PW_TYPE_IFID:		if (vp->length != 8) goto raw;		/* vp->vp_ifid == vp->strvalue */		break;				/*		 *	IPv6 addresses are 16 octets long		 */	case PW_TYPE_IPV6ADDR:		if (vp->length != 16) goto raw;		/* vp->vp_ipv6addr == vp->strvalue */		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->strvalue[1] > 128) goto raw;		/*		 *	FIXME: double-check that		 *	(vp->strvalue[1] >> 3) matches vp->length + 2		 */		if (vp->length < 18) {			memset(vp->strvalue + vp->length, 0,			       18 - vp->length);		}		break;	default:	raw:		vp->type = PW_TYPE_OCTETS;		vp->length = length;		memcpy(vp->strvalue, 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. */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;	/*	 *	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;						/*			 *	attrlen was checked above.			 */			memcpy(&lvalue, ptr, 4);			myvendor = ntohl(lvalue);			/*			 *	Zero isn't allowed.			 */			if (myvendor == 0) goto create_pair;						/*			 *	This is an implementation issue.			 *	We currently pack vendor into the upper			 *	16 bits of a 32-bit attribute number,			 *	so we can't handle vendor numbers larger			 *	than 16 bits.			 */			if (myvendor > 65535) goto create_pair;						vsa_tlen = vsa_llen = 1;			dv = dict_vendorbyvalue(myvendor);			if (dv) {				vsa_tlen = dv->type;				vsa_llen = dv->length;			}						/*			 *	Sweep through the list of VSA's,			 *	seeing if they exactly fill the			 *	outer Vendor-Specific attribute.			 *			 *	If not, create a raw Vendor-Specific.			 */			subptr = ptr + 4;			sublen = attrlen - 4;			/*			 *	See if we can parse it.			 */			do {				int myattr = 0;				/*				 *	Don't have a type, it's bad.				 */				if (sublen < vsa_tlen) goto create_pair;								/*				 *	Ensure that the attribute number				 *	is OK.				 */				switch (vsa_tlen) {				case 1:					myattr = subptr[0];					break;									case 2:					myattr = (subptr[0] << 8) | subptr[1];					break;									case 4:					if ((subptr[0] != 0) ||					    (subptr[1] != 0)) goto create_pair;										myattr = (subptr[2] << 8) | subptr[3];					break;										/*					 *	Our dictionary is broken.					 */				default:					goto create_pair;				}								/*				 *	Not enough room for one more				 *	attribute.  Die!				 */				if (sublen < vsa_tlen + vsa_llen) goto create_pair;

⌨️ 快捷键说明

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