[PATCHv3 2/3] radius: add extended attributes support

michael-dev at fami-braun.de michael-dev at fami-braun.de
Sat May 1 01:46:43 BST 2021


From: Michael Braun <michael-dev at fami-braun.de>

Signed-off-by: Michael Braun <michael-dev at fami-braun.de>

--
v3: fix missing evs header len on fragment len calculation
---
 src/radius/radius.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
 src/radius/radius.h |  9 +++++
 2 files changed, 102 insertions(+)

diff --git a/src/radius/radius.c b/src/radius/radius.c
index fe4d23a5d..60fd44bbf 100644
--- a/src/radius/radius.c
+++ b/src/radius/radius.c
@@ -14,6 +14,9 @@
 #include "crypto/crypto.h"
 #include "radius.h"
 
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
 
 /**
  * struct radius_msg - RADIUS message structure for new and parsed messages
@@ -1295,6 +1298,96 @@ int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data,
 }
 
 
+// RFC 6929
+size_t _radius_msg_add_extended_vsa(struct radius_msg *msg, u8 type, u8 *evs,
+				    size_t evslen, const u8 *data, size_t len,
+				    size_t offset)
+{
+	const u8 *bufptr[2];
+	size_t buflen[2];
+	u8 hdr[2];
+	size_t hdrlen, hlen;
+	size_t fraglen;
+	struct radius_attr_hdr *attr;
+	size_t numbuf;
+	size_t remaining = len - offset;
+
+	// independently defined as 26 by RFC 6929
+	hdr[0] = RADIUS_ATTR_VENDOR_SPECIFIC;
+	hdrlen = 1;
+
+	switch (type) {
+		case RADIUS_ATTR_EXTENDED_1:
+		case RADIUS_ATTR_EXTENDED_2:
+		case RADIUS_ATTR_EXTENDED_3:
+		case RADIUS_ATTR_EXTENDED_4:
+			hlen = evslen + hdrlen;
+			if (hlen + remaining > RADIUS_MAX_ATTR_LEN) {
+				wpa_printf(MSG_ERROR,
+					   "WARNING: attr data too exceeds maximum size of extended attribute");
+				return 0;
+			}
+			fraglen = remaining;
+			break;
+		case RADIUS_ATTR_EXTENDED_5:
+		case RADIUS_ATTR_EXTENDED_6:
+			hdr[1] = 0;
+			hdrlen++;
+
+			hlen = evslen + hdrlen;
+
+			fraglen = MIN(remaining, RADIUS_MAX_ATTR_LEN - hlen);
+			if (fraglen < remaining)
+				hdr[1] |= RADIUS_LONGEXT_FLAG_MORE;
+			break;
+		default:
+			wpa_printf(MSG_ERROR,
+				   "WARNING: Invalid attr type %d used with %s",
+				   type, __FUNCTION__);
+			return 0;
+	}
+
+	bufptr[0] = hdr;
+	buflen[0] = hdrlen;
+	numbuf = 1;
+	if (evslen) {
+		bufptr[1] = evs;
+		buflen[1] = evslen;
+		numbuf = 2;
+	}
+
+	attr = radius_msg_add_attr_frag(msg, type, numbuf, bufptr, buflen,
+					data + offset, fraglen);
+	if (attr == NULL)
+		return 0;
+
+	offset += fraglen;
+
+	return offset;
+}
+
+int radius_msg_add_extended_vsa(struct radius_msg *msg, u8 type, u8 subtype,
+				const u8 *data, size_t len, u32 vendor)
+{
+	size_t offset = 0;
+	u8 evs[5];
+	size_t evslen = sizeof(evs);
+
+	WPA_PUT_BE32(evs, vendor);
+	evs[4] = subtype;
+
+	do {
+		offset = _radius_msg_add_extended_vsa(msg, type, evs, evslen,
+						      data, len, offset);
+		if (!offset)
+			return 0;
+
+		evslen = 0; // evs only added on first fragment
+	} while (offset < len);
+
+	return 1;
+}
+
 int radius_user_password_hide(struct radius_msg *msg,
 			      const u8 *data, size_t data_len,
 			      const u8 *secret, size_t secret_len,
diff --git a/src/radius/radius.h b/src/radius/radius.h
index 3dc73bdc5..0f2420567 100644
--- a/src/radius/radius.h
+++ b/src/radius/radius.h
@@ -113,6 +113,12 @@ enum { RADIUS_ATTR_USER_NAME = 1,
        RADIUS_ATTR_WLAN_GROUP_CIPHER = 187,
        RADIUS_ATTR_WLAN_AKM_SUITE = 188,
        RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER = 189,
+       RADIUS_ATTR_EXTENDED_1 = 241,
+       RADIUS_ATTR_EXTENDED_2 = 242,
+       RADIUS_ATTR_EXTENDED_3 = 243,
+       RADIUS_ATTR_EXTENDED_4 = 244,
+       RADIUS_ATTR_EXTENDED_5 = 245, // long extended
+       RADIUS_ATTR_EXTENDED_6 = 246, // long extended
 };
 
 
@@ -172,6 +178,7 @@ enum { RADIUS_ATTR_USER_NAME = 1,
 #define RADIUS_TUNNEL_MEDIUM_TYPE_IPV6 2
 #define RADIUS_TUNNEL_MEDIUM_TYPE_802 6
 
+#define RADIUS_LONGEXT_FLAG_MORE 0x80
 
 struct radius_attr_vendor {
 	u8 vendor_type;
@@ -290,6 +297,8 @@ int radius_msg_add_mppe_keys(struct radius_msg *msg,
 			     const u8 *recv_key, size_t recv_key_len);
 int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data,
 		       size_t len);
+int radius_msg_add_extended_vsa(struct radius_msg *msg, u8 type, u8 subtype,
+				const u8 *data, size_t len, u32 vendor);
 int radius_user_password_hide(struct radius_msg *msg,
 			      const u8 *data, size_t data_len,
 			      const u8 *secret, size_t secret_len,
-- 
2.20.1




More information about the Hostap mailing list