Skip to content

Commit

Permalink
Merge pull request #648 from Telecominfraproject/main
Browse files Browse the repository at this point in the history
merge for 3.0.2-RC2
  • Loading branch information
jaspreetsachdev committed Apr 5, 2024
2 parents f0035a9 + c227675 commit ca1eabf
Show file tree
Hide file tree
Showing 185 changed files with 71,322 additions and 12 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,350 @@
From 24763e3cd0a564eb71f3c501bbb4fbb0d7070762 Mon Sep 17 00:00:00 2001
From: Jouni Malinen <j@w1.fi>
Date: Fri, 15 Apr 2022 17:31:48 +0300
Subject: [PATCH] RADIUS: Attributes with Extended Types (RFC 6929)

Supported extended types for RADIUS attributes for the cases defined in
RFC 6929.

Signed-off-by: Jouni Malinen <j@w1.fi>
---
src/radius/radius.c | 195 ++++++++++++++++++++++++++++++++++++++------
src/radius/radius.h | 26 +++++-
2 files changed, 193 insertions(+), 28 deletions(-)

diff --git a/src/radius/radius.c b/src/radius/radius.c
index be16e27b9..a64228067 100644
--- a/src/radius/radius.c
+++ b/src/radius/radius.c
@@ -1,6 +1,6 @@
/*
* RADIUS message processing
- * Copyright (c) 2002-2009, 2011-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2009, 2011-2022, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -159,7 +159,8 @@ static const char *radius_code_string(u8 code)


struct radius_attr_type {
- u8 type;
+ u16 type; /* 0..255 for basic types;
+ * (241 << 8) | <ext-type> for extended types */
char *name;
enum {
RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP,
@@ -260,11 +261,31 @@ static const struct radius_attr_type radius_attrs[] =
RADIUS_ATTR_HEXDUMP },
{ RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, "WLAN-Group-Mgmt-Pairwise-Cipher",
RADIUS_ATTR_HEXDUMP },
+ { RADIUS_ATTR_EXT_TYPE_1, "Extended-Type-1", RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_EXT_TYPE_2, "Extended-Type-2", RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_EXT_TYPE_3, "Extended-Type-3", RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_EXT_TYPE_4, "Extended-Type-4", RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_LONG_EXT_TYPE_1, "Long-Extended-Type-1",
+ RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_LONG_EXT_TYPE_2, "Long-Extended-Type-2",
+ RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_1, "Extended-Vendor-Specific-1",
+ RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_2, "Extended-Vendor-Specific-2",
+ RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_3, "Extended-Vendor-Specific-3",
+ RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_4, "Extended-Vendor-Specific-4",
+ RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5, "Extended-Vendor-Specific-5",
+ RADIUS_ATTR_UNDIST },
+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_6, "Extended-Vendor-Specific-6",
+ RADIUS_ATTR_UNDIST },
};
#define RADIUS_ATTRS ARRAY_SIZE(radius_attrs)


-static const struct radius_attr_type *radius_get_attr_type(u8 type)
+static const struct radius_attr_type * radius_get_attr_type(u16 type)
{
size_t i;

@@ -277,23 +298,60 @@ static const struct radius_attr_type *radius_get_attr_type(u8 type)
}


+static bool radius_is_long_ext_type(u8 type)
+{
+ return type == RADIUS_ATTR_LONG_EXT_TYPE_1 ||
+ type == RADIUS_ATTR_LONG_EXT_TYPE_2;
+}
+
+
+static bool radius_is_ext_type(u8 type)
+{
+ return type >= RADIUS_ATTR_EXT_TYPE_1 &&
+ type <= RADIUS_ATTR_LONG_EXT_TYPE_2;
+}
+
+
static void radius_msg_dump_attr(struct radius_attr_hdr *hdr)
{
+ struct radius_attr_hdr_ext *ext = NULL;
const struct radius_attr_type *attr;
int len;
unsigned char *pos;
char buf[1000];

- attr = radius_get_attr_type(hdr->type);
+ if (hdr->length < sizeof(struct radius_attr_hdr))
+ return;

- wpa_printf(MSG_INFO, " Attribute %d (%s) length=%d",
- hdr->type, attr ? attr->name : "?Unknown?", hdr->length);
+ if (radius_is_ext_type(hdr->type)) {
+ if (hdr->length < 4) {
+ wpa_printf(MSG_INFO,
+ " Invalid attribute %d (too short for extended type)",
+ hdr->type);
+ return;
+ }

- if (attr == NULL || hdr->length < sizeof(struct radius_attr_hdr))
- return;
+ ext = (struct radius_attr_hdr_ext *) hdr;
+ }
+
+ if (ext) {
+ attr = radius_get_attr_type((ext->type << 8) | ext->ext_type);
+ wpa_printf(MSG_INFO, " Attribute %d.%d (%s) length=%d",
+ ext->type, ext->ext_type,
+ attr ? attr->name : "?Unknown?", ext->length);
+ pos = (unsigned char *) (ext + 1);
+ len = ext->length - sizeof(struct radius_attr_hdr_ext);
+ } else {
+ attr = radius_get_attr_type(hdr->type);
+ wpa_printf(MSG_INFO, " Attribute %d (%s) length=%d",
+ hdr->type, attr ? attr->name : "?Unknown?",
+ hdr->length);
+ pos = (unsigned char *) (hdr + 1);
+ len = hdr->length - sizeof(struct radius_attr_hdr);
+ }

- len = hdr->length - sizeof(struct radius_attr_hdr);
- pos = (unsigned char *) (hdr + 1);
+ if (!attr)
+ return;

switch (attr->data_type) {
case RADIUS_ATTR_TEXT:
@@ -627,22 +685,54 @@ static int radius_msg_add_attr_to_array(struct radius_msg *msg,
}


-struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
- const u8 *data, size_t data_len)
+struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u16 type,
+ const u8 *data, size_t data_len)
{
- size_t buf_needed;
- struct radius_attr_hdr *attr;
+ size_t buf_needed, max_len;
+ struct radius_attr_hdr *attr = NULL;
+ struct radius_attr_hdr_ext *ext;
+ u8 ext_type = 0;

if (TEST_FAIL())
return NULL;

- if (data_len > RADIUS_MAX_ATTR_LEN) {
- wpa_printf(MSG_ERROR, "radius_msg_add_attr: too long attribute (%lu bytes)",
- (unsigned long) data_len);
- return NULL;
+ if (type > 255) {
+ if (!radius_is_ext_type(type >> 8)) {
+ wpa_printf(MSG_ERROR,
+ "%s: Undefined extended type %d.%d",
+ __func__, type >> 8, type & 0xff);
+ return NULL;
+ }
+ ext_type = type & 0xff;
+ type >>= 8;
+ } else if (radius_is_ext_type(type)) {
+ wpa_printf(MSG_ERROR, "%s: Unexpected extended type use for %d",
+ __func__, type);
}

- buf_needed = sizeof(*attr) + data_len;
+ if (radius_is_long_ext_type(type)) {
+ size_t hdr_len = sizeof(struct radius_attr_hdr_ext) + 1;
+ size_t plen = 255 - hdr_len;
+ size_t num;
+
+ max_len = 4096;
+ num = (data_len + plen - 1) / plen;
+ if (num == 0)
+ num = 1;
+ buf_needed = num * hdr_len + data_len;
+ } else if (radius_is_ext_type(type)) {
+ max_len = RADIUS_MAX_EXT_ATTR_LEN;
+ buf_needed = sizeof(struct radius_attr_hdr_ext) + data_len;
+ } else {
+ max_len = RADIUS_MAX_ATTR_LEN;
+ buf_needed = sizeof(*attr) + data_len;
+ }
+ if (data_len > max_len) {
+ wpa_printf(MSG_ERROR,
+ "%s: too long attribute (%zu > %zu bytes)",
+ __func__, data_len, max_len);
+ return NULL;
+ }

if (wpabuf_tailroom(msg->buf) < buf_needed) {
/* allocate more space for message buffer */
@@ -651,13 +741,44 @@ struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
msg->hdr = wpabuf_mhead(msg->buf);
}

- attr = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr));
- attr->type = type;
- attr->length = sizeof(*attr) + data_len;
- wpabuf_put_data(msg->buf, data, data_len);
-
- if (radius_msg_add_attr_to_array(msg, attr))
- return NULL;
+ if (radius_is_long_ext_type(type)) {
+ size_t plen = 255 - sizeof(struct radius_attr_hdr_ext) - 1;
+ size_t alen;
+
+ do {
+ alen = data_len > plen ? plen : data_len;
+ ext = wpabuf_put(msg->buf,
+ sizeof(struct radius_attr_hdr_ext));
+ if (!attr)
+ attr = (struct radius_attr_hdr *) ext;
+ ext->type = type;
+ ext->length = sizeof(*ext) + 1 + alen;
+ ext->ext_type = ext_type;
+ wpabuf_put_u8(msg->buf, data_len > alen ? 0x80 : 0);
+ wpabuf_put_data(msg->buf, data, data_len);
+ data += alen;
+ data_len -= alen;
+ if (radius_msg_add_attr_to_array(
+ msg, (struct radius_attr_hdr *) ext))
+ return NULL;
+ } while (data_len > 0);
+ } else if (radius_is_ext_type(type)) {
+ ext = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr_ext));
+ attr = (struct radius_attr_hdr *) ext;
+ ext->type = type;
+ ext->length = sizeof(*ext) + data_len;
+ ext->ext_type = ext_type;
+ wpabuf_put_data(msg->buf, data, data_len);
+ if (radius_msg_add_attr_to_array(msg, attr))
+ return NULL;
+ } else {
+ attr = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr));
+ attr->type = type;
+ attr->length = sizeof(*attr) + data_len;
+ wpabuf_put_data(msg->buf, data, data_len);
+ if (radius_msg_add_attr_to_array(msg, attr))
+ return NULL;
+ }

return attr;
}
@@ -1285,6 +1406,28 @@ int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data,
}


+int radius_msg_add_ext_vs(struct radius_msg *msg, u16 type, u32 vendor_id,
+ u8 vendor_type, const u8 *data, size_t len)
+{
+ struct radius_attr_hdr *attr;
+ u8 *buf, *pos;
+ size_t alen;
+
+ alen = 4 + 1 + len;
+ buf = os_malloc(alen);
+ if (!buf)
+ return 0;
+ pos = buf;
+ WPA_PUT_BE32(pos, vendor_id);
+ pos += 4;
+ *pos++ = vendor_type;
+ os_memcpy(pos, data, len);
+ attr = radius_msg_add_attr(msg, type, buf, alen);
+ os_free(buf);
+ return attr != NULL;
+}
+
+
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 fb8148180..490c8d1f6 100644
--- a/src/radius/radius.h
+++ b/src/radius/radius.h
@@ -1,6 +1,6 @@
/*
* RADIUS message processing
- * Copyright (c) 2002-2009, 2012, 2014-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2009, 2012, 2014-2022, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -46,7 +46,15 @@ struct radius_attr_hdr {
/* followed by length-2 octets of attribute value */
} STRUCT_PACKED;

+struct radius_attr_hdr_ext {
+ u8 type;
+ u8 length; /* including this header */
+ u8 ext_type;
+ /* followed by length-3 octets of attribute value */
+} STRUCT_PACKED;
+
#define RADIUS_MAX_ATTR_LEN (255 - sizeof(struct radius_attr_hdr))
+#define RADIUS_MAX_EXT_ATTR_LEN (255 - sizeof(struct radius_attr_hdr_ext))

enum { RADIUS_ATTR_USER_NAME = 1,
RADIUS_ATTR_USER_PASSWORD = 2,
@@ -113,6 +121,18 @@ 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_EXT_TYPE_1 = 241,
+ RADIUS_ATTR_EXT_TYPE_2 = 242,
+ RADIUS_ATTR_EXT_TYPE_3 = 243,
+ RADIUS_ATTR_EXT_TYPE_4 = 244,
+ RADIUS_ATTR_LONG_EXT_TYPE_1 = 245,
+ RADIUS_ATTR_LONG_EXT_TYPE_2 = 246,
+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_1 = (241 << 8) | 26,
+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_2 = (242 << 8) | 26,
+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_3 = (243 << 8) | 26,
+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_4 = (244 << 8) | 26,
+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5 = (245 << 8) | 26,
+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_6 = (246 << 8) | 26,
};


@@ -257,7 +277,7 @@ int radius_msg_verify_acct_req(struct radius_msg *msg, const u8 *secret,
int radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret,
size_t secret_len,
int require_message_authenticator);
-struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u8 type,
+struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u16 type,
const u8 *data, size_t data_len);
struct radius_msg * radius_msg_parse(const u8 *data, size_t len);
int radius_msg_add_eap(struct radius_msg *msg, const u8 *data,
@@ -284,6 +304,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_ext_vs(struct radius_msg *msg, u16 type, u32 vendor_id,
+ u8 vendor_type, const u8 *data, size_t len);
int radius_user_password_hide(struct radius_msg *msg,
const u8 *data, size_t data_len,
const u8 *secret, size_t secret_len,
--
2.25.1

Loading

0 comments on commit ca1eabf

Please sign in to comment.