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

📄 radius.c

📁 linux 下的radius 最新版。linux 下的radius 最新版.linux 下的radius 最新版
💻 C
📖 第 1 页 / 共 4 页
字号:
				switch (vsa_llen) {				case 0:					attribute = (myvendor << 16) | myattr;					ptr += 4 + vsa_tlen;					attrlen -= (4 + vsa_tlen);					packet_length -= 4 + vsa_tlen;					goto create_pair;				case 1:					if (subptr[vsa_tlen] < (vsa_tlen + vsa_llen))						goto create_pair;					if (subptr[vsa_tlen] > sublen)						goto create_pair;					sublen -= subptr[vsa_tlen];					subptr += subptr[vsa_tlen];					break;				case 2:					if (subptr[vsa_tlen] != 0) goto create_pair;					if (subptr[vsa_tlen + 1] < (vsa_tlen + vsa_llen))						goto create_pair;					if (subptr[vsa_tlen + 1] > sublen)						goto create_pair;					sublen -= subptr[vsa_tlen + 1];					subptr += subptr[vsa_tlen + 1];					break;					/*					 *	Our dictionaries are					 *	broken.					 */				default:					goto create_pair;				}			} while (sublen > 0);			vendorcode = myvendor;			vendorlen = attrlen - 4;			packet_length -= 4;			ptr += 4;		}		/*		 *	attrlen is the length of this attribute.		 *	total_len is the length of the encompassing		 *	attribute.		 */		switch (vsa_tlen) {		case 1:			attribute = ptr[0];			break;					case 2:			attribute = (ptr[0] << 8) | ptr[1];			break;		default:	/* can't hit this. */			return -1;		}		attribute |= (vendorcode << 16);		ptr += vsa_tlen;		switch (vsa_llen) {		case 1:			attrlen = ptr[0] - (vsa_tlen + vsa_llen);			break;					case 2:			attrlen = ptr[1] - (vsa_tlen + vsa_llen);			break;		default:	/* can't hit this. */			return -1;		}		ptr += vsa_llen;		vendorlen -= vsa_tlen + vsa_llen + attrlen;		if (vendorlen == 0) vendorcode = 0;		packet_length -= (vsa_tlen + vsa_llen);		/*		 *	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:		pair = rad_attr2vp(packet, original, secret,				 attribute, attrlen, ptr);		if (!pair) {			pairfree(&packet->vps);			librad_log("out of memory");			return -1;		}		debug_pair(pair);		*tail = pair;		tail = &pair->next;		ptr += attrlen;		packet_length -= attrlen;	}	/*	 *	Merge information from the outside world into our	 *	random pool.	 */	lrad_rand_seed(packet->data, AUTH_HDR_LEN);	  	return 0;}/* *	Encode password. * *	We assume that the passwd buffer passed is big enough. *	RFC2138 says the password is max 128 chars, so the size *	of the passwd buffer must be at least 129 characters. *	Preferably it's just MAX_STRING_LEN. * *	int *pwlen is updated to the new length of the encrypted *	password - a multiple of 16 bytes. */int rad_pwencode(char *passwd, int *pwlen, const char *secret,		 const char *vector){	uint8_t	buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 1];	char	digest[AUTH_VECTOR_LEN];	int	i, n, secretlen;	int	len;	/*	 *	Pad password to multiple of AUTH_PASS_LEN bytes.	 */	len = *pwlen;	if (len > 128) len = 128;	*pwlen = len;	if (len % AUTH_PASS_LEN != 0) {		n = AUTH_PASS_LEN - (len % AUTH_PASS_LEN);		for (i = len; n > 0; n--, i++)			passwd[i] = 0;		len = *pwlen = i;	} else if (len == 0) {		memset(passwd, 0, AUTH_PASS_LEN);		*pwlen = len = AUTH_PASS_LEN;	}	/*	 *	Use the secret to setup the decryption digest	 */	secretlen = strlen(secret);	memcpy(buffer, secret, secretlen);	memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);	librad_md5_calc((u_char *)digest, buffer, secretlen + AUTH_VECTOR_LEN);	/*	 *	Now we can encode the password *in place*	 */	for (i = 0; i < AUTH_PASS_LEN; i++)		passwd[i] ^= digest[i];	if (len <= AUTH_PASS_LEN) return 0;	/*	 *	Length > AUTH_PASS_LEN, so we need to use the extended	 *	algorithm.	 */	for (n = 0; n < 128 && n <= (len - AUTH_PASS_LEN); n += AUTH_PASS_LEN) {		memcpy(buffer + secretlen, passwd + n, AUTH_PASS_LEN);		librad_md5_calc((u_char *)digest, buffer, secretlen + AUTH_PASS_LEN);		for (i = 0; i < AUTH_PASS_LEN; i++)			passwd[i + n + AUTH_PASS_LEN] ^= digest[i];	}	return 0;}/* *	Decode password. */int rad_pwdecode(char *passwd, int pwlen, const char *secret,		 const char *vector){	uint8_t	buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 1];	char	digest[AUTH_VECTOR_LEN];	char	r[AUTH_VECTOR_LEN];	char	*s;	int	i, n, secretlen;	int	rlen;	/*	 *	Use the secret to setup the decryption digest	 */	secretlen = strlen(secret);	memcpy(buffer, secret, secretlen);	memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);	librad_md5_calc((u_char *)digest, buffer, secretlen + AUTH_VECTOR_LEN);	/*	 *	Now we can decode the password *in place*	 */	memcpy(r, passwd, AUTH_PASS_LEN);	for (i = 0; i < AUTH_PASS_LEN && i < pwlen; i++)		passwd[i] ^= digest[i];	if (pwlen <= AUTH_PASS_LEN) {		passwd[pwlen+1] = 0;		return pwlen;	}	/*	 *	Length > AUTH_PASS_LEN, so we need to use the extended	 *	algorithm.	 */	rlen = ((pwlen - 1) / AUTH_PASS_LEN) * AUTH_PASS_LEN;	for (n = rlen; n > 0; n -= AUTH_PASS_LEN ) {		s = (n == AUTH_PASS_LEN) ? r : (passwd + n - AUTH_PASS_LEN);		memcpy(buffer + secretlen, s, AUTH_PASS_LEN);		librad_md5_calc((u_char *)digest, buffer, secretlen + AUTH_PASS_LEN);		for (i = 0; i < AUTH_PASS_LEN && (i + n) < pwlen; i++)			passwd[i + n] ^= digest[i];	}	passwd[pwlen] = 0;	return pwlen;}/* *	Encode Tunnel-Password attributes when sending them out on the wire. * *	int *pwlen is updated to the new length of the encrypted *	password - a multiple of 16 bytes. * *      This is per RFC-2868 which adds a two char SALT to the initial intermediate *      value MD5 hash. */int rad_tunnel_pwencode(char *passwd, int *pwlen, const char *secret,			const char *vector){	uint8_t	buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 3];	unsigned char	digest[AUTH_VECTOR_LEN];	char*   salt;	int	i, n, secretlen;	unsigned len, n2;	len = *pwlen;	if (len > 127) len = 127;	/*	 * Shift the password 3 positions right to place a salt and original	 * length, tag will be added automatically on packet send	 */	for (n=len ; n>=0 ; n--) passwd[n+3] = passwd[n];	salt = passwd;	passwd += 2;	/*	 * save original password length as first password character;	 */	*passwd = len;	len += 1;	/*	 *	Generate salt.  The RFC's say:	 *	 *	The high bit of salt[0] must be set, each salt in a	 *	packet should be unique, and they should be random	 *	 *	So, we set the high bit, add in a counter, and then	 *	add in some CSPRNG data.  should be OK..	 */	salt[0] = (0x80 | ( ((salt_offset++) & 0x0f) << 3) |		   (lrad_rand() & 0x07));	salt[1] = lrad_rand();	/*	 *	Padd password to multiple of AUTH_PASS_LEN bytes.	 */	n = len % AUTH_PASS_LEN;	if (n) {		n = AUTH_PASS_LEN - n;		for (; n > 0; n--, len++)			passwd[len] = 0;	}	/* set new password length */	*pwlen = len + 2;	/*	 *	Use the secret to setup the decryption digest	 */	secretlen = strlen(secret);	memcpy(buffer, secret, secretlen);	for (n2 = 0; n2 < len; n2+=AUTH_PASS_LEN) {		if (!n2) {			memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);			memcpy(buffer + secretlen + AUTH_VECTOR_LEN, salt, 2);			librad_md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN + 2);		} else {			memcpy(buffer + secretlen, passwd + n2 - AUTH_PASS_LEN, AUTH_PASS_LEN);			librad_md5_calc(digest, buffer, secretlen + AUTH_PASS_LEN);		}		for (i = 0; i < AUTH_PASS_LEN; i++) {			passwd[i + n2] ^= digest[i];		}	}	passwd[n2] = 0;	return 0;}/* *	Decode Tunnel-Password encrypted attributes. * *      Defined in RFC-2868, this uses a two char SALT along with the *      initial intermediate value, to differentiate it from the *      above. */int rad_tunnel_pwdecode(uint8_t *passwd, int *pwlen, const char *secret,			const char *vector){	uint8_t		buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 3];	uint8_t		digest[AUTH_VECTOR_LEN];	uint8_t		decrypted[MAX_STRING_LEN + 1];	int		secretlen;	unsigned	i, n, len;	len = *pwlen;	/*	 *	We need at least a salt.	 */	if (len < 2) {		librad_log("tunnel password is too short");		return -1;	}	/*	 *	There's a salt, but no password.  Or, there's a salt	 *	and a 'data_len' octet.  It's wrong, but at least we	 *	can figure out what it means: the password is empty.	 *	 *	Note that this means we ignore the 'data_len' field,	 *	if the attribute length tells us that there's no	 *	more data.  So the 'data_len' field may be wrong,	 *	but that's ok...	 */	if (len <= 3) {		passwd[0] = 0;		*pwlen = 0;		return 0;	}	len -= 2;		/* discount the salt */	/*	 *	Use the secret to setup the decryption digest	 */	secretlen = strlen(secret);	/*	 *	Set up the initial key:	 *	 *	 b(1) = MD5(secret + vector + salt)	 */	memcpy(buffer, secret, secretlen);	memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);	memcpy(buffer + secretlen + AUTH_VECTOR_LEN, passwd, 2);	librad_md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN + 2);	/*	 *	A quick check: decrypt the first octet of the password,	 *	which is the 'data_len' field.  Ensure it's sane.	 *	 *	'n' doesn't include the 'data_len' octet	 *	'len' does.	 */	n = passwd[2] ^ digest[0];	if (n >= len) {		librad_log("tunnel password is too long for the attribute");		return -1;	}	/*	 *	Loop over the data, decrypting it, and generating	 *	the key for the next round of decryption.	 */	for (n = 0; n < len; n += AUTH_PASS_LEN) {		for (i = 0; i < AUTH_PASS_LEN; i++) {			decrypted[n + i] = passwd[n + i + 2] ^ digest[i];			/*			 *	Encrypted password may not be aligned			 *	on 16 octets, so we catch that here...			 */			if ((n + i) == len) break;		}		/*		 *	Update the digest, based on		 *		 *	b(n) = MD5(secret + cleartext(n-1)		 *		 *	but only if there's more data...		 */		memcpy(buffer + secretlen, passwd + n + 2, AUTH_PASS_LEN);		librad_md5_calc(digest, buffer, secretlen + AUTH_PASS_LEN);	}	/*	 *	We've already validated the length of the decrypted	 *	password.  Copy it back to the caller.	 */	memcpy(passwd, decrypted + 1, decrypted[0]);	passwd[decrypted[0]] = 0;	*pwlen = decrypted[0];	return decrypted[0];}/* *	Encode a CHAP password * *	FIXME: might not work with Ascend because *	we use vp->length, and Ascend gear likes *	to send an extra '\0' in the string! */int rad_chap_encode(RADIUS_PACKET *packet, char *output, int id,		    VALUE_PAIR *password){	int		i;	char		*ptr;	char		string[MAX_STRING_LEN * 2 + 1];	VALUE_PAIR	*challenge;	/*	 *	Sanity check the input parameters	 */	if ((packet == NULL) || (password == NULL)) {		return -1;	}	/*	 *	Note that the password VP can be EITHER	 *	a User-Password attribute (from a check-item list),	 *	or a CHAP-Password attribute (the client asking	 *	the library to encode it).	 */	i = 0;	ptr = string;	*ptr++ = id;	i++;	memcpy(ptr, password->strvalue, password->length);	ptr += password->length;	i += password->length;	/*	 *	Use Chap-Challenge pair if present,	 *	Request-Authenticator otherwise.	 */	challenge = pairfind(packet->vps, PW_CHAP_CHALLENGE);	if (challenge) {		memcpy(ptr, challenge->strvalue, challenge->length);		i += challenge->length;	} else {		memcpy(ptr, packet->vector, AUTH_VECTOR_LEN);		i += AUTH_VECTOR_LEN;	}	*output = id;	librad_md5_calc((u_char *)output + 1, (u_char *)string, i);	return 0;}/* *	Seed the random number generator. * *	May be called any number of times. */void lrad_rand_seed(const void *data, size_t size){	uint32_t hash;	/*	 *	Ensure that the pool is initialized.	 */	if (lrad_rand_index < 0) {		int fd;				memset(&lrad_rand_pool, 0, sizeof(lrad_rand_pool));		fd = open("/dev/urandom", O_RDONLY);		if (fd >= 0) {			size_t total;			ssize_t this;			total = this = 0;			while (total < sizeof(lrad_rand_pool.randrsl)) {				this = read(fd, lrad_rand_pool.randrsl,					    sizeof(lrad_rand_pool.randrsl) - total);				if ((this < 0) && (errno != EINTR)) break;				if (this > 0) total += this; 			}			close(fd);		} else {			lrad_rand_pool.randrsl[0] = fd;			lrad_rand_pool.randrsl[1] = time(NULL);			lrad_rand_pool.randrsl[2] = errno;		}		lrad_randinit(&lrad_rand_pool, 1);		lrad_rand_index = 0;	}	if (!data) return;	/*	 *	Hash the user data	 */	hash = lrad_hash(data, size);		lrad_rand_pool.randrsl[lrad_rand_index & 0xff] ^= hash;	lrad_rand_index++;	lrad_rand_index &= 0xff;	/*	 *	Churn the pool every so often after seeding it.	 */	if (((int) (hash & 0xff)) == lrad_rand_index) {		lrad_isaac(&lrad_rand_pool);	}}/* *	Return a 32-bit random number. */uint32_t lrad_rand(void){	uint32_t num;	/*	 *	Ensure that the pool is initialized.	 */	if (lrad_rand_index < 0) {		lrad_rand_seed(NULL, 0);	}	/*	 *	We don't return data directly from the pool.	 *	Rather, we return a summary of the data.	 */	num = lrad_rand_pool.randrsl[lrad_rand_index & 0xff];	lrad_rand_index++;	lrad_rand_index &= 0xff;	/*	 *	Every so often, churn the pool.	 */	if (((int) (num & 0xff)) == lrad_rand_index) {		lrad_isaac(&lrad_rand_pool);	}	return num;}/* *	Allocate a new RADIUS_PACKET */RADIUS_PACKET *rad_alloc(int newvector){	RADIUS_PACKET	*rp;	if ((rp = malloc(sizeof(RADIUS_PACKET))) == NULL) {		librad_log("out of memory");		return NULL;	}	memset(rp, 0, sizeof(RADIUS_PACKET));	if (newvector) {		int i;		uint32_t hash, base;		/*		 *	Don't expose the actual contents of the random		 *	pool.		 */		base = lrad_rand();		for (i = 0; i < AUTH_VECTOR_LEN; i += sizeof(uint32_t)) {			hash = lrad_rand() ^ base;			memcpy(rp->vector + i, &hash, sizeof(hash));		}	}	lrad_rand();	return rp;}/* *	Free a RADIUS_PACKET */void rad_free(RADIUS_PACKET **radius_packet_ptr){	RADIUS_PACKET *radius_packet;	if (!radius_packet_ptr) return;	radius_packet = *radius_packet_ptr;	if (radius_packet->data) free(radius_packet->data);	if (radius_packet->vps) pairfree(&radius_packet->vps);	free(radius_packet);	*radius_packet_ptr = NULL;}

⌨️ 快捷键说明

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