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

📄 radius.c

📁 radius服务器
💻 C
📖 第 1 页 / 共 4 页
字号:
	    (seen_eap != (PW_EAP_MESSAGE | PW_MESSAGE_AUTHENTICATOR))) {		librad_log("WARNING: Insecure packet from host %s:  Received EAP-Message with no Message-Authenticator.",			   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;}/* *	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			length;	int			attribute;	int			attrlen;	int			vendorlen;	radius_packet_t		*hdr;	hdr = (radius_packet_t *)packet->data;	/*	 *	Before we allocate memory for the attributes, do more	 *	sanity checking.	 */	ptr = hdr->data;	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_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));				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 */	/*	 *	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_ACCOUNTING_RESPONSE:			rcode = calc_replydigest(packet, original, secret);			if (rcode > 1) {				char buffer[32];				librad_log("Received %s packet "					   "from %s:%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;	}	/*	 *	Extract attribute-value pairs	 */	ptr = hdr->data;	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;	while (length > 0) {		if (vendorlen > 0) {			attribute = *ptr++ | (vendorcode << 16);			attrlen   = *ptr++;		} else {			attribute = *ptr++;			attrlen   = *ptr++;		}		attrlen -= 2;		length  -= 2;		/*		 *	This could be a Vendor-Specific attribute.		 */		if ((vendorlen <= 0) &&		    (attribute == PW_VENDOR_SPECIFIC)) {			int	sublen;			uint8_t	*subptr;			/*			 *	attrlen was checked to be >= 6, in rad_recv			 */			memcpy(&lvalue, ptr, 4);			vendorcode = ntohl(lvalue);			/*			 *	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 (vendorcode > 65535) goto create_pair;			/*			 *	vendorcode was checked to be non-zero			 *	above, in rad_recv.			 */			/*			 *	First, check to see if the			 *	sub-attributes fill the VSA, as			 *	defined by the RFC.  If not, then it			 *	may be a USR-style VSA, or it may be a			 *	vendor who packs all of the			 *	information into one nonsense			 *	attribute			 */			subptr = ptr + 4;			sublen = attrlen - 4;			while (sublen > 0) {				if (subptr[1] < 2) { /* too short */					break;				}				if (subptr[1] > sublen) { /* too long */					break;				}				sublen -= subptr[1]; /* just right */				subptr += subptr[1];			}			/*			 *	If the attribute is RFC compatible,			 *	then allow it as an RFC style VSA.			 */			if (sublen == 0) {				ptr += 4;				vendorlen = attrlen - 4;				attribute = *ptr++ | (vendorcode << 16);				attrlen   = *ptr++;				attrlen -= 2;				length -= 6;				/*				 *	USR-style attributes are 4 octets,				 *	with the upper 2 octets being zero.				 *				 *	The upper octets may not be zero,				 *	but that then means we won't be				 *	able to pack the vendor & attribute				 *	into a 32-bit number, so we can't				 *	handle it.				 *				 *				 *	FIXME: Update the dictionaries so				 *	that we key off of per-attribute				 *	flags "4-octet", instead of hard				 *	coding USR here.  This will also				 *	let us send packets with other				 *	vendors having 4-octet attributes.				 */			} else if ((vendorcode == VENDORPEC_USR) &&				   ((ptr[4] == 0) && (ptr[5] == 0)) &&				   (attrlen >= 8)) {				DICT_ATTR *da;				da = dict_attrbyvalue((vendorcode << 16) |						      (ptr[6] << 8) |						      ptr[7]);				/*				 *	See if it's in the dictionary.				 *	If so, it's a valid USR style				 *	attribute.  If not, it's not...				 *				 *	Don't touch 'attribute' until				 *	we know what to do!				 */				if (da != NULL) {					attribute = ((vendorcode << 16) |						     (ptr[6] << 8) |						     ptr[7]);					ptr += 8;					attrlen -= 8;					length -= 8;				} /* else it's not in the dictionary */			} /* else it was a stupid vendor format */		} /* else it wasn't a VSA */		/*		 *	Create the attribute, setting the default type		 *	to 'octects'.  If the type in the dictionary		 *	is different, then the dictionary type will		 *	over-ride this one.		 */	create_pair:		if ((pair = paircreate(attribute, PW_TYPE_OCTETS)) == NULL) {			pairfree(&packet->vps);			librad_log("out of memory");			return -1;		}		pair->length = attrlen;		pair->operator = T_OP_EQ;		pair->next = NULL;		switch (pair->type) {			/*			 *	The attribute may be zero length,			 *	or it may have a tag, and then no data...			 */		case PW_TYPE_STRING:			if (pair->flags.has_tag) {				int offset = 0;				/*				 *	If there's sufficient room for				 *	a tag, and the tag looks valid,				 *	then use it.				 */				if ((pair->length > 0) &&				    TAG_VALID_ZERO(*ptr)) {					pair->flags.tag = *ptr;					pair->length--;					offset = 1;					/*					 *	If the leading tag					 *	isn't valid, then it's					 *	ignored for the tunnel					 *	password attribute.					 */				} else if (pair->flags.encrypt == FLAG_ENCRYPT_TUNNEL_PASSWORD) {					/*					 * from RFC2868 - 3.5.  Tunnel-Password					 * If the value of the Tag field is greater than					 * 0x00 and less than or equal to 0x1F, it SHOULD					 * be interpreted as indicating which tunnel					 * (of several alternatives) this attribute pertains;					 * otherwise, the Tag field SHOULD be ignored.					 */					pair->flags.tag = 0x00;					if (pair->length > 0) pair->length--;					offset = 1;				} else {				       pair->flags.tag = 0x00;				}				/*				 *	pair->length MAY be zero here.				 */				memcpy(pair->strvalue, ptr + offset,				       pair->length);			} else {			  /*			   *	Ascend binary attributes never have a			   *	tag, and neither do the 'octets' type.			   */			case PW_TYPE_ABINARY:			case PW_TYPE_OCTETS:				/* attrlen always < MAX_STRING_LEN */				memcpy(pair->strvalue, ptr, attrlen);			        pair->flags.tag = 0;			}			/*			 *	Decrypt passwords here.			 */			switch (pair->flags.encrypt) {			default:				break;				/*				 *  User-Password				 */			case FLAG_ENCRYPT_USER_PASSWORD:				if (original) {					rad_pwdecode((char *)pair->strvalue,						     pair->length, secret,						     (char *)original->vector);				} else {					rad_pwdecode((char *)pair->strvalue,						     pair->length, secret,						     (char *)packet->vector);				}				if (pair->attribute == PW_USER_PASSWORD) {					pair->length = strlen(pair->strvalue);				}				break;				/*				 *	Tunnel-Password's may go ONLY				 *	in response packets.				 */			case FLAG_ENCRYPT_TUNNEL_PASSWORD:				if (!original) {					librad_log("ERROR: Tunnel-Password attribute in request: Cannot decrypt it.");					free(pair);					return -1;				}				if (rad_tunnel_pwdecode(pair->strvalue,							&pair->length,							secret,							(char *)original->vector) < 0) {					free(pair);					return -1;				}				break;				/*				 *  Ascend-Send-Secret				 *  Ascend-Receive-Secret				 */			case FLAG_ENCRYPT_ASCEND_SECRET:				if (!original) {					librad_log("ERROR: Ascend-Send-Secret attribute in request: Cannot decrypt it.");					free(pair);					return -1;				} else {					uint8_t my_digest[AUTH_VECTOR_LEN];					make_secret(my_digest,						    original->vector,						    secret, ptr);					memcpy(pair->strvalue, my_digest,					       AUTH_VECTOR_LEN );					pair->strvalue[AUTH_VECTOR_LEN] = '\0';					pair->length = strlen(pair->strvalue);				}				break;			} /* switch over encryption flags */			break;	/* from octets/string/abinary */		case PW_TYPE_INTEGER:		case PW_TYPE_DATE:		case PW_TYPE_IPADDR:			/*			 *	Check for RFC compliance.  If the			 *	attribute isn't compliant, turn it			 *	into a string of raw octets.			 *			 *	Also set the lvalue to something			 *	which should never match anything.			 */			if (attrlen != 4) {				pair->type = PW_TYPE_OCTETS;				memcpy(pair->strvalue, ptr, attrlen);				pair->lvalue = 0xbad1bad1;				break;			}      			memcpy(&lvalue, ptr, 4);			if (pair->type != PW_TYPE_IPADDR) {				pair->lvalue = ntohl(lvalue);			} else {				 /*				  *  It's an IP address, keep it in network				  *  byte order, and put the ASCII IP				  *  address or host name into the string				  *  value.				  */				pair->lvalue = lvalue;				ip_ntoa(pair->strvalue, pair->lvalue);			}			/*			 *	Tagged attributes of type integer have			 *	special treatment.			 */			if (pair->flags.has_tag &&			    pair->type == PW_TYPE_INTEGER) {			        pair->flags.tag = (pair->lvalue >> 24) & 0xff;				pair->lvalue &= 0x00ffffff;			}			/*			 *	Try to get the name for integer			 *	attributes.			 */			if (pair->type == PW_TYPE_INTEGER) {				DICT_VALUE *dval;				dval = dict_valbyattr(pair->attribute,						      pair->lvalue);				if (dval) {					strNcpy(pair->strvalue,						dval->name,						sizeof(pair->strvalue));				}			}			break;			/*			 *	IPv6 interface ID is 8 octets long.			 */		case PW_TYPE_IFID:			if (attrlen != 8)				pair->type = PW_TYPE_OCTETS;			memcpy(pair->strvalue, ptr, attrlen);			break;			/*			 *	IPv6 addresses are 16 octets long			 */		case PW_TYPE_IPV6ADDR:			if (attrlen != 16)				pair->type = PW_TYPE_OCTETS;			memcpy(pair->strvalue, ptr, attrlen);			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 (attrlen < 2 || attrlen > 18)				pair->type = PW_TYPE_OCTETS;			if (attrlen >= 2) {				if (ptr[1] > 128) {					pair->type = PW_TYPE_OCTETS;				}				/*				 *	FIXME: double-check that				 *	(ptr[1] >> 3) matches attrlen + 2

⌨️ 快捷键说明

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