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

📄 radius.c

📁 IEEE 802.11a/b/g 服务器端AP
💻 C
📖 第 1 页 / 共 2 页
字号:
	os_memcpy(attr + 1, orig, MD5_MAC_LEN);	if (req_auth) {		os_memcpy(msg->hdr->authenticator, orig_authenticator,			  sizeof(orig_authenticator));	}	if (os_memcmp(orig, auth, MD5_MAC_LEN) != 0) {		printf("Invalid Message-Authenticator!\n");		return 1;	}	return 0;}int radius_msg_verify(struct radius_msg *msg, const u8 *secret,		      size_t secret_len, struct radius_msg *sent_msg, int auth){	const u8 *addr[4];	size_t len[4];	u8 hash[MD5_MAC_LEN];	if (sent_msg == NULL) {		printf("No matching Access-Request message found\n");		return 1;	}	if (auth &&	    radius_msg_verify_msg_auth(msg, secret, secret_len,				       sent_msg->hdr->authenticator)) {		return 1;	}	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */	addr[0] = (u8 *) msg->hdr;	len[0] = 1 + 1 + 2;	addr[1] = sent_msg->hdr->authenticator;	len[1] = MD5_MAC_LEN;	addr[2] = (u8 *) (msg->hdr + 1);	len[2] = msg->buf_used - sizeof(*msg->hdr);	addr[3] = secret;	len[3] = secret_len;	md5_vector(4, addr, len, hash);	if (os_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;	size_t i;	int count = 0;	for (i = 0; i < src->attr_used; i++) {		attr = radius_get_attr_hdr(src, i);		if (attr->type == type) {			if (!radius_msg_add_attr(dst, type, (u8 *) (attr + 1),						 attr->length - sizeof(*attr)))				return -1;			count++;		}	}	return count;}/* 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,				   const u8 *data, size_t len){	struct os_time tv;	long int l;	const u8 *addr[3];	size_t elen[3];	os_get_time(&tv);	l = os_random();	addr[0] = (u8 *) &tv;	elen[0] = sizeof(tv);	addr[1] = data;	elen[1] = len;	addr[2] = (u8 *) &l;	elen[2] = sizeof(l);	md5_vector(3, addr, elen, msg->hdr->authenticator);}/* 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 os_malloc() and caller must free it * by calling os_free(). */static u8 *radius_msg_get_vendor_attr(struct radius_msg *msg, u32 vendor,				      u8 subtype, size_t *alen){	u8 *data, *pos;	size_t i, len;	if (msg == NULL)		return NULL;	for (i = 0; i < msg->attr_used; i++) {		struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i);		size_t 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);		os_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 = os_malloc(len);			if (data == NULL)				return NULL;			os_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];	int i, first = 1;	const u8 *addr[3];	size_t elen[3];	/* 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 = os_malloc(plen);	if (plain == NULL)		return NULL;	plain[0] = 0;	while (left > 0) {		/* b(1) = MD5(Secret + Request-Authenticator + Salt)		 * b(i) = MD5(Secret + c(i - 1)) for i > 1 */		addr[0] = secret;		elen[0] = secret_len;		if (first) {			addr[1] = req_authenticator;			elen[1] = MD5_MAC_LEN;			addr[2] = key;			elen[2] = 2; /* Salt */		} else {			addr[1] = pos - MD5_MAC_LEN;			elen[1] = MD5_MAC_LEN;		}		md5_vector(first ? 3 : 2, addr, elen, hash);		first = 0;		for (i = 0; i < MD5_MAC_LEN; i++)			*ppos++ = *pos++ ^ hash[i];		left -= MD5_MAC_LEN;	}	if (plain[0] == 0 || plain[0] > plen - 1) {		printf("Failed to decrypt MPPE key\n");		os_free(plain);		return NULL;	}	res = os_malloc(plain[0]);	if (res == NULL) {		os_free(plain);		return NULL;	}	os_memcpy(res, plain + 1, plain[0]);	if (reslen)		*reslen = plain[0];	os_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;	const u8 *addr[3];	size_t _len[3];	WPA_PUT_BE16(saltbuf, salt);	len = 1 + key_len;	if (len & 0x0f) {		len = (len & 0xf0) + 16;	}	os_memset(ebuf, 0, len);	ebuf[0] = key_len;	os_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 */		addr[0] = secret;		_len[0] = secret_len;		if (first) {			addr[1] = req_authenticator;			_len[1] = MD5_MAC_LEN;			addr[2] = saltbuf;			_len[2] = sizeof(saltbuf);		} else {			addr[1] = pos - MD5_MAC_LEN;			_len[1] = MD5_MAC_LEN;		}		md5_vector(first ? 3 : 2, addr, _len, hash);		first = 0;		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 = os_zalloc(sizeof(*keys));	if (keys == NULL)		return NULL;	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);		os_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);		os_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 = os_zalloc(sizeof(*keys));	if (keys == NULL)		return NULL;	key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_CISCO,					 RADIUS_CISCO_AV_PAIR, &keylen);	if (key && keylen == 51 &&	    os_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);	}	os_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 = os_malloc(hlen + send_key_len + 16);	if (buf == NULL) {		return 0;	}	pos = buf;	os_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 = os_random() | 0x8000;	WPA_PUT_BE16(pos, salt);	pos += 2;	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);	os_free(buf);	if (attr == NULL) {		return 0;	}	/* MS-MPPE-Recv-Key */	buf = os_malloc(hlen + send_key_len + 16);	if (buf == NULL) {		return 0;	}	pos = buf;	os_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;	WPA_PUT_BE16(pos, salt);	pos += 2;	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);	os_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;	size_t buf_len, pos;	const u8 *addr[2];	size_t len[2];	u8 hash[16];	if (data_len > 128)		return NULL;	os_memcpy(buf, data, data_len);	buf_len = data_len;	padlen = data_len % 16;	if (padlen) {		padlen = 16 - padlen;		os_memset(buf + data_len, 0, padlen);		buf_len += padlen;	}	addr[0] = secret;	len[0] = secret_len;	addr[1] = msg->hdr->authenticator;	len[1] = 16;	md5_vector(2, addr, len, hash);	for (i = 0; i < 16; i++)		buf[i] ^= hash[i];	pos = 16;	while (pos < buf_len) {		addr[0] = secret;		len[0] = secret_len;		addr[1] = &buf[pos - 16];		len[1] = 16;		md5_vector(2, addr, len, hash);		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){	struct radius_attr_hdr *attr = NULL, *tmp;	size_t i, dlen;	for (i = 0; i < msg->attr_used; i++) {		tmp = radius_get_attr_hdr(msg, i);		if (tmp->type == type) {			attr = tmp;			break;		}	}	if (!attr)		return -1;	dlen = attr->length - sizeof(*attr);	if (buf)		os_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){	size_t i;	struct radius_attr_hdr *attr = NULL, *tmp;	for (i = 0; i < msg->attr_used; i++) {		tmp = radius_get_attr_hdr(msg, i);		if (tmp->type == type &&		    (start == NULL || (u8 *) tmp > start)) {			attr = tmp;			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){	size_t i;	int count;	for (count = 0, i = 0; i < msg->attr_used; i++) {		struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i);		if (attr->type == type &&		    attr->length >= sizeof(struct radius_attr_hdr) + min_len)			count++;	}	return count;}struct radius_tunnel_attrs {	int tag_used;	int type; /* Tunnel-Type */	int medium_type; /* Tunnel-Medium-Type */	int vlanid;};/** * radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information * @msg: RADIUS message * Returns: VLAN ID for the first tunnel configuration of -1 if none is found */int radius_msg_get_vlanid(struct radius_msg *msg){	struct radius_tunnel_attrs tunnel[RADIUS_TUNNEL_TAGS], *tun;	size_t i;	struct radius_attr_hdr *attr = NULL;	const u8 *data;	char buf[10];	size_t dlen;	os_memset(&tunnel, 0, sizeof(tunnel));	for (i = 0; i < msg->attr_used; i++) {		attr = radius_get_attr_hdr(msg, i);		data = (const u8 *) (attr + 1);		dlen = attr->length - sizeof(*attr);		if (attr->length < 3)			continue;		if (data[0] >= RADIUS_TUNNEL_TAGS)			tun = &tunnel[0];		else			tun = &tunnel[data[0]];		switch (attr->type) {		case RADIUS_ATTR_TUNNEL_TYPE:			if (attr->length != 6)				break;			tun->tag_used++;			tun->type = WPA_GET_BE24(data + 1);			break;		case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE:			if (attr->length != 6)				break;			tun->tag_used++;			tun->medium_type = WPA_GET_BE24(data + 1);			break;		case RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID:			if (data[0] < RADIUS_TUNNEL_TAGS) {				data++;				dlen--;			}			if (dlen >= sizeof(buf))				break;			os_memcpy(buf, data, dlen);			buf[dlen] = '\0';			tun->tag_used++;			tun->vlanid = atoi(buf);			break;		}	}	for (i = 0; i < RADIUS_TUNNEL_TAGS; i++) {		tun = &tunnel[i];		if (tun->tag_used &&		    tun->type == RADIUS_TUNNEL_TYPE_VLAN &&		    tun->medium_type == RADIUS_TUNNEL_MEDIUM_TYPE_802 &&		    tun->vlanid > 0)			return tun->vlanid;	}	return -1;}

⌨️ 快捷键说明

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