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

📄 radius.c

📁 hostapd无线AP工具
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct radius_attr_hdr *attr = NULL;	int i;	for (i = 0; i < msg->attr_used; i++) {		if (msg->attrs[i]->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) {			if (attr != NULL) {				printf("Multiple Message-Authenticator "				       "attributes in RADIUS message\n");				return 1;			}			attr = msg->attrs[i];		}	}	if (attr == NULL) {		printf("No Message-Authenticator attribute found\n");		return 1;	}	memcpy(orig, attr + 1, MD5_MAC_LEN);	memset(attr + 1, 0, MD5_MAC_LEN);	if (req_auth) {		memcpy(orig_authenticator, msg->hdr->authenticator,		       sizeof(orig_authenticator));		memcpy(msg->hdr->authenticator, req_auth,		       sizeof(msg->hdr->authenticator));	}	hmac_md5(secret, secret_len, msg->buf, msg->buf_used, auth);	memcpy(attr + 1, orig, MD5_MAC_LEN);	if (req_auth) {		memcpy(msg->hdr->authenticator, orig_authenticator,		       sizeof(orig_authenticator));	}	if (memcmp(orig, auth, MD5_MAC_LEN) != 0) {		printf("Invalid Message-Authenticator!\n");		return 1;	}	return 0;}int radius_msg_verify(struct radius_msg *msg, u8 *secret, size_t secret_len,		      struct radius_msg *sent_msg){	MD5_CTX context;	u8 hash[MD5_MAC_LEN];	if (sent_msg == NULL) {		printf("No matching Access-Request message found\n");		return 1;	}	if (radius_msg_verify_msg_auth(msg, secret, secret_len,				       sent_msg->hdr->authenticator)) {		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) {		printf("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) {		printf("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 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 subtype is found, otherwise returns NULL. * The returned payload is allocated with malloc() and caller must free it. */static u8 *radius_msg_get_vendor_attr(struct radius_msg *msg, u32 vendor,				      u8 subtype, size_t *alen){	u8 *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 *vhdr;		if (attr->type != RADIUS_ATTR_VENDOR_SPECIFIC)			continue;		left = attr->length - sizeof(*attr);		if (left < 4)			continue;		pos = (u8 *) (attr + 1);		memcpy(&vendor_id, pos, 4);		pos += 4;		left -= 4;		if (ntohl(vendor_id) != vendor)			continue;		while (left >= sizeof(*vhdr)) {			vhdr = (struct radius_attr_vendor *) pos;			if (vhdr->vendor_length > left ||			    vhdr->vendor_length < sizeof(*vhdr)) {				left = 0;				break;			}			if (vhdr->vendor_type != subtype) {				pos += vhdr->vendor_length;				left -= vhdr->vendor_length;				continue;			}			len = vhdr->vendor_length - sizeof(*vhdr);			data = malloc(len);			if (data == NULL)				return NULL;			memcpy(data, pos + sizeof(*vhdr), len);			if (alen)				*alen = len;			return data;		}	}	return NULL;}static u8 * decrypt_ms_key(const u8 *key, size_t len,			   const u8 *req_authenticator,			   const u8 *secret, size_t secret_len, size_t *reslen){	u8 *plain, *ppos, *res;	const u8 *pos;	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) {		printf("Invalid ms key len %lu\n", (unsigned long) left);		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, req_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) {		printf("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;}static void encrypt_ms_key(const u8 *key, size_t key_len, u16 salt,			   const u8 *req_authenticator,			   const u8 *secret, size_t secret_len,			   u8 *ebuf, size_t *elen){	int i, len, first = 1;	u8 hash[MD5_MAC_LEN], saltbuf[2], *pos;	MD5_CTX context;	saltbuf[0] = salt >> 8;	saltbuf[1] = salt;	len = 1 + key_len;	if (len & 0x0f) {		len = (len & 0xf0) + 16;	}	memset(ebuf, 0, len);	ebuf[0] = key_len;	memcpy(ebuf + 1, key, key_len);	*elen = len;	pos = ebuf;	while (len > 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, req_authenticator, MD5_MAC_LEN);			MD5Update(&context, saltbuf, sizeof(saltbuf));			first = 0;		} else {			MD5Update(&context, pos - MD5_MAC_LEN, MD5_MAC_LEN);		}		MD5Final(hash, &context);		for (i = 0; i < MD5_MAC_LEN; i++)			*pos++ ^= hash[i];		len -= MD5_MAC_LEN;	}}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_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT,					 RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY,					 &keylen);	if (key) {		keys->send = decrypt_ms_key(key, keylen,					    sent_msg->hdr->authenticator,					    secret, secret_len,					    &keys->send_len);		free(key);	}	key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT,					 RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY,					 &keylen);	if (key) {		keys->recv = decrypt_ms_key(key, keylen,					    sent_msg->hdr->authenticator,					    secret, secret_len,					    &keys->recv_len);		free(key);	}	return keys;}struct radius_ms_mppe_keys *radius_msg_get_cisco_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_vendor_attr(msg, RADIUS_VENDOR_ID_CISCO,					 RADIUS_CISCO_AV_PAIR, &keylen);	if (key && keylen == 51 && memcmp(key, "leap:session-key=", 17) == 0) {		keys->recv = decrypt_ms_key(key + 17, keylen - 17,					    sent_msg->hdr->authenticator,					    secret, secret_len,					    &keys->recv_len);		free(key);	}	return keys;}int radius_msg_add_mppe_keys(struct radius_msg *msg,			     const u8 *req_authenticator,			     const u8 *secret, size_t secret_len,			     const u8 *send_key, size_t send_key_len,			     const u8 *recv_key, size_t recv_key_len){	struct radius_attr_hdr *attr;	u32 vendor_id = htonl(RADIUS_VENDOR_ID_MICROSOFT);	u8 *buf;	struct radius_attr_vendor *vhdr;	u8 *pos;	size_t elen;	int hlen;	u16 salt;	hlen = sizeof(vendor_id) + sizeof(*vhdr) + 2;	/* MS-MPPE-Send-Key */	buf = malloc(hlen + send_key_len + 16);	if (buf == NULL) {		return 0;	}	pos = buf;	memcpy(pos, &vendor_id, sizeof(vendor_id));	pos += sizeof(vendor_id);	vhdr = (struct radius_attr_vendor *) pos;	vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY;	pos = (u8 *) (vhdr + 1);	salt = random() | 0x8000;	*pos++ = salt >> 8;	*pos++ = salt;	encrypt_ms_key(send_key, send_key_len, salt, req_authenticator, secret,		       secret_len, pos, &elen);	vhdr->vendor_length = hlen + elen - sizeof(vendor_id);	attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,				   buf, hlen + elen);	free(buf);	if (attr == NULL) {		return 0;	}	/* MS-MPPE-Recv-Key */	buf = malloc(hlen + send_key_len + 16);	if (buf == NULL) {		return 0;	}	pos = buf;	memcpy(pos, &vendor_id, sizeof(vendor_id));	pos += sizeof(vendor_id);	vhdr = (struct radius_attr_vendor *) pos;	vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY;	pos = (u8 *) (vhdr + 1);	salt ^= 1;	*pos++ = salt >> 8;	*pos++ = salt;	encrypt_ms_key(recv_key, recv_key_len, salt, req_authenticator, secret,		       secret_len, pos, &elen);	vhdr->vendor_length = hlen + elen - sizeof(vendor_id);	attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,				   buf, hlen + elen);	free(buf);	if (attr == NULL) {		return 0;	}	return 1;}/* 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){	u8 buf[128];	int padlen, i, pos;	MD5_CTX context;	size_t buf_len;	u8 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;}int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf,			    size_t *len, const u8 *start){	int i;	struct radius_attr_hdr *attr = NULL;	for (i = 0; i < msg->attr_used; i++) {		if (msg->attrs[i]->type == type &&		    (start == NULL || (u8 *) msg->attrs[i] > start)) {			attr = msg->attrs[i];			break;		}	}	if (!attr)		return -1;	*buf = (u8 *) (attr + 1);	*len = attr->length - sizeof(*attr);	return 0;}int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len){	int i, count;	for (count = 0, i = 0; i < msg->attr_used; i++) {		if (msg->attrs[i]->type == type &&		    msg->attrs[i]->length >=		    sizeof(struct radius_attr_hdr) + min_len)			count++;	}	return count;}

⌨️ 快捷键说明

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