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

📄 radius.c

📁 802.1x 源码,基于linux平台开发
💻 C
📖 第 1 页 / 共 2 页
字号:
		{
			if (attr != 0)
			{
				DBGPRINT(RT_DEBUG_ERROR,"Multiple Message-Authenticator attributes in RADIUS message\n");
				return 1;
			}
			attr = msg->attrs[i];
		}
	}

	if (attr == NULL)
	{
		DBGPRINT(RT_DEBUG_ERROR,"No Message-Authenticator attribute found\n");
		return 1;
	}

	memcpy(orig, attr + 1, MD5_MAC_LEN);
	memset(attr + 1, 0, MD5_MAC_LEN);
	memcpy(orig_authenticator, msg->hdr->authenticator, sizeof(orig_authenticator));
	memcpy(msg->hdr->authenticator, sent_msg->hdr->authenticator, sizeof(msg->hdr->authenticator));
	hmac_md5(secret, secret_len, msg->buf, msg->buf_used, auth);
	memcpy(attr + 1, orig, MD5_MAC_LEN);
	memcpy(msg->hdr->authenticator, orig_authenticator, sizeof(orig_authenticator));

	if (memcmp(orig, auth, MD5_MAC_LEN) != 0)
	{
		DBGPRINT(RT_DEBUG_ERROR,"Invalid Message-Authenticator!\n");
		return 1;
	}

	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
	MD5Init(&context);
	MD5Update(&context, (u8 *) msg->hdr, 1 + 1 + 2);
	MD5Update(&context, sent_msg->hdr->authenticator, MD5_MAC_LEN);
	MD5Update(&context, (u8 *) (msg->hdr + 1), msg->buf_used - sizeof(*msg->hdr));
	MD5Update(&context, secret, secret_len);
	MD5Final(hash, &context);
	if (memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0)
	{
		DBGPRINT(RT_DEBUG_ERROR,"Response Authenticator invalid!\n");
		return 1;
	}
	return 0;

}

int Radius_msg_verify_acct(struct radius_msg *msg, u8 *secret,
			   size_t secret_len, struct radius_msg *sent_msg)
{
	MD5_CTX context;
	u8 hash[MD5_MAC_LEN];

	MD5Init(&context);
	MD5Update(&context, msg->buf, 4);
	MD5Update(&context, sent_msg->hdr->authenticator, MD5_MAC_LEN);
	if (msg->buf_used > sizeof(struct radius_hdr))
		MD5Update(&context, msg->buf + sizeof(struct radius_hdr), msg->buf_used - sizeof(struct radius_hdr));
	MD5Update(&context, secret, secret_len);
	MD5Final(hash, &context);
	if (memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0)
	{
		DBGPRINT(RT_DEBUG_ERROR,"Response Authenticator invalid!\n");
		return 1;
	}

	return 0;
}

int Radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src, u8 type)
{
	struct radius_attr_hdr *attr = NULL;
	int i;

	for (i = 0; i < src->attr_used; i++)
	{
		if (src->attrs[i]->type == type)
		{
			attr = src->attrs[i];
			break;
		}
	}

	if (attr == NULL)
		return 0;

	if (!Radius_msg_add_attr(dst, type, (u8 *) (attr + 1), attr->length - sizeof(*attr)))
		return -1;

	return 1;
}

/* Create Request Authenticator. The value should be unique over the lifetime
 * of the shared secret between authenticator and authentication server.
 * Use one-way MD5 hash calculated from current timestamp and some data given
 * by the caller. */
void Radius_msg_make_authenticator(struct radius_msg *msg, u8 *data, size_t len)
{
	struct timeval tv;
	MD5_CTX context;
	long int l;

	gettimeofday(&tv, NULL);
	l = random();
	MD5Init(&context);
	MD5Update(&context, (u8 *) &tv, sizeof(tv));
	MD5Update(&context, data, len);
	MD5Update(&context, (u8 *) &l, sizeof(l));
	MD5Final(msg->hdr->authenticator, &context);
}

/* Get Microsoft Vendor-specific RADIUS Attribute from a parsed RADIUS message.
 * Returns the Attribute payload and sets alen to indicate the length of the
 * payload if a vendor attribute with ms_type is found, otherwise returns NULL.
 * The returned payload is allocated with malloc() and caller must free it.
 */
static u8 *Radius_msg_get_ms_attr(struct radius_msg *msg, u8 ms_type, size_t *alen)
{
	char *data, *pos;
	int i;
	size_t len;

	if (msg == NULL)
		return NULL;

	for (i = 0; i < msg->attr_used; i++)
	{
		struct radius_attr_hdr *attr = msg->attrs[i];
		int left;
		u32 vendor_id;
		struct radius_attr_vendor_microsoft *ms;

		if (attr->type != RADIUS_ATTR_VENDOR_SPECIFIC)
			continue;

		left = attr->length - sizeof(*attr);
		if (left < 4)
			continue;

		pos = (char *) (attr + 1);

		memcpy(&vendor_id, pos, 4);
		pos += 4;
		left -= 4;

		if (ntohl(vendor_id) != RADIUS_VENDOR_ID_MICROSOFT)
			continue;

		while (left >= sizeof(*ms))
		{
			ms = (struct radius_attr_vendor_microsoft *) pos;
			if (ms->vendor_length > left)
			{
				left = 0;
				continue;
			}
			if (ms->vendor_type != ms_type)
			{
				pos += ms->vendor_length;
				left -= ms->vendor_length;
				continue;
			}

			len = ms->vendor_length - sizeof(*ms);
			data = (char *) malloc(len);
			if (data == NULL)
				return NULL;
			memcpy(data, pos + sizeof(*ms), len);
			if (alen)
				*alen = len;
			return data;
		}
	}

	return NULL;
}

static u8 * decrypt_ms_key(u8 *key, size_t len, struct radius_msg *sent_msg,
			   u8 *secret, size_t secret_len, size_t *reslen)
{
	u8 *pos, *plain, *ppos, *res;
	size_t left, plen;
	u8 hash[MD5_MAC_LEN];
	MD5_CTX context;
	int i, first = 1;

	/* key: 16-bit salt followed by encrypted key info */

	if (len < 2 + 16)
		return NULL;

	pos = key + 2;
	left = len - 2;
	if (left % 16)
	{
		DBGPRINT(RT_DEBUG_ERROR,"Invalid ms key len\n");
		return NULL;
	}

	plen = left;
	ppos = plain = malloc(plen);
	if (plain == NULL)
		return NULL;

	while (left > 0)
	{
		/* b(1) = MD5(Secret + Request-Authenticator + Salt)
		 * b(i) = MD5(Secret + c(i - 1)) for i > 1 */

		MD5Init(&context);
		MD5Update(&context, secret, secret_len);
		if (first)
		{
			MD5Update(&context, sent_msg->hdr->authenticator,
				  MD5_MAC_LEN);
			MD5Update(&context, key, 2); /* Salt */
			first = 0;
		} else
			MD5Update(&context, pos - MD5_MAC_LEN, MD5_MAC_LEN);
		MD5Final(hash, &context);

		for (i = 0; i < MD5_MAC_LEN; i++)
			*ppos++ = *pos++ ^ hash[i];
		left -= MD5_MAC_LEN;
	}

	if (plain[0] > plen - 1)
	{
		DBGPRINT(RT_DEBUG_ERROR,"Failed to decrypt MPPE key\n");
		free(plain);
		return NULL;
	}

	res = malloc(plain[0]);
	if (res == NULL)
	{
		free(plain);
		return NULL;
	}
	memcpy(res, plain + 1, plain[0]);
	if (reslen)
		*reslen = plain[0];
	free(plain);
	return res;
}

struct radius_ms_mppe_keys *
Radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
		       u8 *secret, size_t secret_len)
{
	u8 *key;
	size_t keylen;
	struct radius_ms_mppe_keys *keys;

	if (msg == NULL || sent_msg == NULL)
		return NULL;

	keys = (struct radius_ms_mppe_keys *) malloc(sizeof(*keys));
	if (keys == NULL)
		return NULL;

	memset(keys, 0, sizeof(*keys));

	key = Radius_msg_get_ms_attr(msg, RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY, &keylen);
	if (key)
	{
		keys->send = decrypt_ms_key(key, keylen, sent_msg, secret, secret_len, &keys->send_len);
		free(key);
	}
    DBGPRINT(RT_DEBUG_INFO," secret_len = %d, secret= %s\n",secret_len,secret);
	key = Radius_msg_get_ms_attr(msg, RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY, &keylen);
	if (key)
	{
		keys->recv = decrypt_ms_key(key, keylen, sent_msg, secret, secret_len, &keys->recv_len);
		free(key);
	}

	return keys;
}

/* Add User-Password attribute to a RADIUS message and encrypt it as specified
 * in RFC 2865, Chap. 5.2 */
struct radius_attr_hdr *
Radius_msg_add_attr_user_password(struct radius_msg *msg,
				  u8 *data, size_t data_len, u8 *secret, size_t secret_len)
{
	char buf[128];
	int padlen, i, pos;
	MD5_CTX context;
	size_t buf_len;
	char hash[16];

	if (data_len > 128)
		return NULL;

	memcpy(buf, data, data_len);
	buf_len = data_len;

	padlen = data_len % 16;
	if (padlen)
	{
		padlen = 16 - padlen;
		memset(buf + data_len, 0, padlen);
		buf_len += padlen;
	}

	MD5Init(&context);
	MD5Update(&context, secret, secret_len);
	MD5Update(&context, msg->hdr->authenticator, 16);
	MD5Final(hash, &context);

	for (i = 0; i < 16; i++)
		buf[i] ^= hash[i];
	pos = 16;

	while (pos < buf_len)
	{
		MD5Init(&context);
		MD5Update(&context, secret, secret_len);
		MD5Update(&context, &buf[pos - 16], 16);
		MD5Final(hash, &context);

		for (i = 0; i < 16; i++)
			buf[pos + i] ^= hash[i];

		pos += 16;
	}

	return Radius_msg_add_attr(msg, RADIUS_ATTR_USER_PASSWORD, buf, buf_len);
}

int Radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len)
{
	int i;
	struct radius_attr_hdr *attr = NULL;
	size_t dlen;

	for (i = 0; i < msg->attr_used; i++)
	{
		if (msg->attrs[i]->type == type)
		{
			attr = msg->attrs[i];
			break;
		}
	}

	if (!attr)
		return -1;

	dlen = attr->length - sizeof(*attr);
	if (buf)
		memcpy(buf, (attr + 1), dlen > len ? len : dlen);
	return dlen;
}

⌨️ 快捷键说明

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