RADIUS: Allow Message-Authenticator attribute as the first attribute

If a Message-Authenticator attribute was already added to a RADIUS
message, use that attribute instead of adding a new one when finishing
message building. This allows the Message-Authenticator attribute to be
placed as the first attribute in the message.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2024-03-16 11:11:44 +02:00
parent 566dc139a0
commit adac846bd0
2 changed files with 54 additions and 32 deletions

View file

@ -423,25 +423,54 @@ void radius_msg_dump(struct radius_msg *msg)
}
u8 * radius_msg_add_msg_auth(struct radius_msg *msg)
{
u8 auth[MD5_MAC_LEN];
struct radius_attr_hdr *attr;
os_memset(auth, 0, MD5_MAC_LEN);
attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
auth, MD5_MAC_LEN);
if (!attr) {
wpa_printf(MSG_ERROR,
"WARNING: Could not add Message-Authenticator");
return NULL;
}
return (u8 *) (attr + 1);
}
static u8 * radius_msg_auth_pos(struct radius_msg *msg)
{
u8 *pos;
size_t alen;
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
&pos, &alen, NULL) == 0 &&
alen == MD5_MAC_LEN) {
/* Use already added Message-Authenticator attribute */
return pos;
}
/* Add a Message-Authenticator attribute */
return radius_msg_add_msg_auth(msg);
}
int radius_msg_finish(struct radius_msg *msg, const u8 *secret,
size_t secret_len)
{
if (secret) {
u8 auth[MD5_MAC_LEN];
struct radius_attr_hdr *attr;
u8 *pos;
os_memset(auth, 0, MD5_MAC_LEN);
attr = radius_msg_add_attr(msg,
RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
auth, MD5_MAC_LEN);
if (attr == NULL) {
wpa_printf(MSG_WARNING, "RADIUS: Could not add "
"Message-Authenticator");
pos = radius_msg_auth_pos(msg);
if (!pos)
return -1;
}
msg->hdr->length = host_to_be16(wpabuf_len(msg->buf));
hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), (u8 *) (attr + 1));
if (hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), pos) < 0)
return -1;
} else
msg->hdr->length = host_to_be16(wpabuf_len(msg->buf));
@ -457,23 +486,19 @@ int radius_msg_finish(struct radius_msg *msg, const u8 *secret,
int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
size_t secret_len, const u8 *req_authenticator)
{
u8 auth[MD5_MAC_LEN];
struct radius_attr_hdr *attr;
const u8 *addr[4];
size_t len[4];
u8 *pos;
os_memset(auth, 0, MD5_MAC_LEN);
attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
auth, MD5_MAC_LEN);
if (attr == NULL) {
wpa_printf(MSG_ERROR, "WARNING: Could not add Message-Authenticator");
pos = radius_msg_auth_pos(msg);
if (!pos)
return -1;
}
msg->hdr->length = host_to_be16(wpabuf_len(msg->buf));
os_memcpy(msg->hdr->authenticator, req_authenticator,
sizeof(msg->hdr->authenticator));
hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), (u8 *) (attr + 1));
if (hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), pos) < 0)
return -1;
/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
addr[0] = (u8 *) msg->hdr;
@ -501,21 +526,17 @@ int radius_msg_finish_das_resp(struct radius_msg *msg, const u8 *secret,
{
const u8 *addr[2];
size_t len[2];
u8 auth[MD5_MAC_LEN];
struct radius_attr_hdr *attr;
u8 *pos;
os_memset(auth, 0, MD5_MAC_LEN);
attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
auth, MD5_MAC_LEN);
if (attr == NULL) {
wpa_printf(MSG_WARNING, "Could not add Message-Authenticator");
pos = radius_msg_auth_pos(msg);
if (!pos)
return -1;
}
msg->hdr->length = host_to_be16(wpabuf_len(msg->buf));
os_memcpy(msg->hdr->authenticator, req_hdr->authenticator, 16);
hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), (u8 *) (attr + 1));
if (hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), pos) < 0)
return -1;
/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
addr[0] = wpabuf_head_u8(msg->buf);

View file

@ -268,6 +268,7 @@ struct wpabuf * radius_msg_get_buf(struct radius_msg *msg);
struct radius_msg * radius_msg_new(u8 code, u8 identifier);
void radius_msg_free(struct radius_msg *msg);
void radius_msg_dump(struct radius_msg *msg);
u8 * radius_msg_add_msg_auth(struct radius_msg *msg);
int radius_msg_finish(struct radius_msg *msg, const u8 *secret,
size_t secret_len);
int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,