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

📄 radius.c

📁 radius服务器
💻 C
📖 第 1 页 / 共 4 页
字号:
				 */			}			memcpy(pair->strvalue, ptr, attrlen);			break;		default:			DEBUG("    %s (Unknown Type %d)\n",			      pair->name, pair->type);			free(pair);			pair = NULL;			break;		}		if (pair) {			debug_pair(pair);			*tail = pair;			tail = &pair->next;		}		ptr += attrlen;		length -= attrlen;		if (vendorlen > 0) vendorlen -= (attrlen + 2);	}	/*	 *	Merge information from the outside world into our	 *	random pool	 */	for (length = 0; length < AUTH_VECTOR_LEN; length++) {		lrad_rand_pool.randmem[length] += packet->vector[length];	}	lrad_rand_pool.randmem[lrad_rand_pool.randmem[0] & 0xff] += packet->id;	lrad_rand_pool.randmem[lrad_rand_pool.randmem[1] & 0xff] += packet->data_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. */#define AUTH_PASS_LEN (16)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;}static unsigned int salt_offset = 0;/* *	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;}/* *	Create a random vector of AUTH_VECTOR_LEN bytes. */static void random_vector(uint8_t *vector){	int i;	if (!lrad_pool_initialized) {		memset(&lrad_rand_pool, 0, sizeof(lrad_rand_pool));		/*		 *	Initialize the state to something, using		 *	numbers which aren't random, but which also		 *	aren't static.		 */		lrad_rand_pool.randrsl[0] = (uint32_t) &lrad_pool_initialized;		lrad_rand_pool.randrsl[1] = (uint32_t) &i;		lrad_rand_pool.randrsl[2] = (uint32_t) vector;		lrad_randinit(&lrad_rand_pool, 1);	}	lrad_isaac(&lrad_rand_pool);	/*	 *	Copy the random data over.	 */	for (i = 0; i < AUTH_VECTOR_LEN; i++) {		*(vector++) = lrad_rand_pool.randrsl[i] & 0xff;	}}/* *	Return a 32-bit random number. */uint32_t lrad_rand(void){	uint32_t answer;	static int rand_index = 0;	/*	 *	Ensure that the pool is initialized.	 */	if (!lrad_pool_initialized) {		uint8_t vector[AUTH_VECTOR_LEN];		random_vector(vector);	}	/*	 *	Grab an entry from the pool.	 */	answer = lrad_rand_pool.randrsl[rand_index];	/*	 *	Go to the next entry (wrapping around to zero).	 */	rand_index++;	rand_index &= 0xff;	/*	 *	Every 256 numbers, churn the pool again.	 */	if (rand_index == 0) {		lrad_isaac(&lrad_rand_pool);	}	return answer;}/* *	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)		random_vector(rp->vector);	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;}/************************************************************************* * *      Function: make_secret * *      Purpose: Build an encrypted secret value to return in a reply *               packet.  The secret is hidden by xoring with a MD5 digest *               created from the shared secret and the authentication *               vector.  We put them into MD5 in the reverse order from *               that used when encrypting passwords to RADIUS. * *************************************************************************/static void make_secret(unsigned char *digest, uint8_t *vector,			const char *secret, char *value){        u_char  buffer[256 + AUTH_VECTOR_LEN];        int             secretLen = strlen(secret);        int             i;        memcpy(buffer, vector, AUTH_VECTOR_LEN );        memcpy(buffer + AUTH_VECTOR_LEN, secret, secretLen );        librad_md5_calc(digest, buffer, AUTH_VECTOR_LEN + secretLen );        memset(buffer, 0, sizeof(buffer));        for ( i = 0; i < AUTH_VECTOR_LEN; i++ ) {		digest[i] ^= value[i];        }}

⌨️ 快捷键说明

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