Convert RADIUS message code to use wpabuf internally

This commit is contained in:
Jouni Malinen 2009-12-19 17:12:07 +02:00
parent 9e7245bdb4
commit aa235d2ef7
4 changed files with 62 additions and 90 deletions

View file

@ -15,6 +15,7 @@
#include "utils/includes.h"
#include "utils/common.h"
#include "utils/wpabuf.h"
#include "crypto/md5.h"
#include "crypto/crypto.h"
#include "radius.h"
@ -23,7 +24,8 @@
static struct radius_attr_hdr *
radius_get_attr_hdr(struct radius_msg *msg, int idx)
{
return (struct radius_attr_hdr *) (msg->buf + msg->attr_pos[idx]);
return (struct radius_attr_hdr *)
(wpabuf_mhead_u8(msg->buf) + msg->attr_pos[idx]);
}
@ -34,27 +36,12 @@ static void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier)
}
static int radius_msg_initialize(struct radius_msg *msg, size_t init_len)
static int radius_msg_initialize(struct radius_msg *msg)
{
if (init_len < sizeof(struct radius_hdr))
return -1;
msg->buf = os_zalloc(init_len);
if (msg->buf == NULL)
return -1;
msg->buf_size = init_len;
msg->hdr = (struct radius_hdr *) msg->buf;
msg->buf_used = sizeof(*msg->hdr);
msg->attr_pos =
os_zalloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attr_pos));
if (msg->attr_pos == NULL) {
os_free(msg->buf);
msg->buf = NULL;
msg->hdr = NULL;
if (msg->attr_pos == NULL)
return -1;
}
msg->attr_size = RADIUS_DEFAULT_ATTR_COUNT;
msg->attr_used = 0;
@ -80,10 +67,12 @@ struct radius_msg * radius_msg_new(u8 code, u8 identifier)
if (msg == NULL)
return NULL;
if (radius_msg_initialize(msg, RADIUS_DEFAULT_MSG_SIZE)) {
os_free(msg);
msg->buf = wpabuf_alloc(RADIUS_DEFAULT_MSG_SIZE);
if (msg->buf == NULL || radius_msg_initialize(msg)) {
radius_msg_free(msg);
return NULL;
}
msg->hdr = wpabuf_put(msg->buf, sizeof(struct radius_hdr));
radius_msg_set_hdr(msg, code, identifier);
@ -100,7 +89,7 @@ void radius_msg_free(struct radius_msg *msg)
if (msg == NULL)
return;
os_free(msg->buf);
wpabuf_free(msg->buf);
os_free(msg->attr_pos);
os_free(msg);
}
@ -315,19 +304,19 @@ int radius_msg_finish(struct radius_msg *msg, const u8 *secret,
RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
auth, MD5_MAC_LEN);
if (attr == NULL) {
printf("WARNING: Could not add "
"Message-Authenticator\n");
wpa_printf(MSG_WARNING, "RADIUS: Could not add "
"Message-Authenticator");
return -1;
}
msg->hdr->length = htons(msg->buf_used);
hmac_md5(secret, secret_len, msg->buf, msg->buf_used,
(u8 *) (attr + 1));
msg->hdr->length = htons(wpabuf_len(msg->buf));
hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), (u8 *) (attr + 1));
} else
msg->hdr->length = htons(msg->buf_used);
msg->hdr->length = htons(wpabuf_len(msg->buf));
if (msg->buf_used > 0xffff) {
printf("WARNING: too long RADIUS message (%lu)\n",
(unsigned long) msg->buf_used);
if (wpabuf_len(msg->buf) > 0xffff) {
wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)",
(unsigned long) wpabuf_len(msg->buf));
return -1;
}
return 0;
@ -349,26 +338,26 @@ int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
printf("WARNING: Could not add Message-Authenticator\n");
return -1;
}
msg->hdr->length = htons(msg->buf_used);
msg->hdr->length = htons(wpabuf_len(msg->buf));
os_memcpy(msg->hdr->authenticator, req_authenticator,
sizeof(msg->hdr->authenticator));
hmac_md5(secret, secret_len, msg->buf, msg->buf_used,
(u8 *) (attr + 1));
hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), (u8 *) (attr + 1));
/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
addr[0] = (u8 *) msg->hdr;
len[0] = 1 + 1 + 2;
addr[1] = req_authenticator;
len[1] = MD5_MAC_LEN;
addr[2] = (u8 *) (msg->hdr + 1);
len[2] = msg->buf_used - sizeof(*msg->hdr);
addr[2] = wpabuf_head_u8(msg->buf) + sizeof(struct radius_hdr);
len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr);
addr[3] = secret;
len[3] = secret_len;
md5_vector(4, addr, len, msg->hdr->authenticator);
if (msg->buf_used > 0xffff) {
printf("WARNING: too long RADIUS message (%lu)\n",
(unsigned long) msg->buf_used);
if (wpabuf_len(msg->buf) > 0xffff) {
wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)",
(unsigned long) wpabuf_len(msg->buf));
return -1;
}
return 0;
@ -381,17 +370,17 @@ void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret,
const u8 *addr[2];
size_t len[2];
msg->hdr->length = htons(msg->buf_used);
msg->hdr->length = htons(wpabuf_len(msg->buf));
os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN);
addr[0] = msg->buf;
len[0] = msg->buf_used;
addr[0] = wpabuf_head(msg->buf);
len[0] = wpabuf_len(msg->buf);
addr[1] = secret;
len[1] = secret_len;
md5_vector(2, addr, len, msg->hdr->authenticator);
if (msg->buf_used > 0xffff) {
printf("WARNING: too long RADIUS messages (%lu)\n",
(unsigned long) msg->buf_used);
if (wpabuf_len(msg->buf) > 0xffff) {
wpa_printf(MSG_WARNING, "RADIUS: Too long messages (%lu)",
(unsigned long) wpabuf_len(msg->buf));
}
}
@ -412,7 +401,8 @@ static int radius_msg_add_attr_to_array(struct radius_msg *msg,
msg->attr_size = nlen;
}
msg->attr_pos[msg->attr_used++] = (unsigned char *) attr - msg->buf;
msg->attr_pos[msg->attr_used++] =
(unsigned char *) attr - wpabuf_head_u8(msg->buf);
return 0;
}
@ -430,31 +420,19 @@ struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
return NULL;
}
buf_needed = msg->buf_used + sizeof(*attr) + data_len;
buf_needed = sizeof(*attr) + data_len;
if (msg->buf_size < buf_needed) {
if (wpabuf_tailroom(msg->buf) < buf_needed) {
/* allocate more space for message buffer */
unsigned char *nbuf;
size_t nlen = msg->buf_size;
while (nlen < buf_needed)
nlen *= 2;
nbuf = os_realloc(msg->buf, nlen);
if (nbuf == NULL)
if (wpabuf_resize(&msg->buf, buf_needed) < 0)
return NULL;
msg->buf = nbuf;
msg->hdr = (struct radius_hdr *) msg->buf;
os_memset(msg->buf + msg->buf_size, 0, nlen - msg->buf_size);
msg->buf_size = nlen;
msg->hdr = wpabuf_mhead(msg->buf);
}
attr = (struct radius_attr_hdr *) (msg->buf + msg->buf_used);
attr = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr));
attr->type = type;
attr->length = sizeof(*attr) + data_len;
if (data_len > 0)
os_memcpy(attr + 1, data, data_len);
msg->buf_used += sizeof(*attr) + data_len;
wpabuf_put_data(msg->buf, data, data_len);
if (radius_msg_add_attr_to_array(msg, attr))
return NULL;
@ -500,17 +478,16 @@ struct radius_msg * radius_msg_parse(const u8 *data, size_t len)
if (msg == NULL)
return NULL;
if (radius_msg_initialize(msg, msg_len)) {
os_free(msg);
msg->buf = wpabuf_alloc_copy(data, msg_len);
if (msg->buf == NULL || radius_msg_initialize(msg)) {
radius_msg_free(msg);
return NULL;
}
os_memcpy(msg->buf, data, msg_len);
msg->buf_size = msg->buf_used = msg_len;
msg->hdr = wpabuf_mhead(msg->buf);
/* parse attributes */
pos = (unsigned char *) (msg->hdr + 1);
end = msg->buf + msg->buf_used;
pos = wpabuf_mhead_u8(msg->buf) + sizeof(struct radius_hdr);
end = wpabuf_mhead_u8(msg->buf) + wpabuf_len(msg->buf);
while (pos < end) {
if ((size_t) (end - pos) < sizeof(*attr))
goto fail;
@ -633,7 +610,8 @@ int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret,
os_memcpy(msg->hdr->authenticator, req_auth,
sizeof(msg->hdr->authenticator));
}
hmac_md5(secret, secret_len, msg->buf, msg->buf_used, auth);
hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), auth);
os_memcpy(attr + 1, orig, MD5_MAC_LEN);
if (req_auth) {
os_memcpy(msg->hdr->authenticator, orig_authenticator,
@ -672,8 +650,8 @@ int radius_msg_verify(struct radius_msg *msg, const u8 *secret,
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[2] = wpabuf_head_u8(msg->buf) + sizeof(struct radius_hdr);
len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr);
addr[3] = secret;
len[3] = secret_len;
md5_vector(4, addr, len, hash);

View file

@ -180,17 +180,7 @@ struct radius_msg {
/**
* buf - Allocated buffer for RADIUS message
*/
unsigned char *buf;
/**
* buf_size - Total size of the allocated buf in octets
*/
size_t buf_size;
/**
* buf_used - bytes used in buf
*/
size_t buf_used;
struct wpabuf *buf;
/**
* hdr - Pointer to the RADIUS header in buf

View file

@ -357,7 +357,8 @@ static int radius_client_retransmit(struct radius_client_data *radius,
entry->msg->hdr->identifier);
os_get_time(&entry->last_attempt);
if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
if (send(s, wpabuf_head(entry->msg->buf), wpabuf_len(entry->msg->buf),
0) < 0)
radius_client_handle_send_error(radius, s, entry->msg_type);
entry->next_try = now + entry->next_wait;
@ -673,7 +674,7 @@ int radius_client_send(struct radius_client_data *radius,
if (conf->msg_dumps)
radius_msg_dump(msg);
res = send(s, msg->buf, msg->buf_used, 0);
res = send(s, wpabuf_head(msg->buf), wpabuf_len(msg->buf), 0);
if (res < 0)
radius_client_handle_send_error(radius, s, msg_type);

View file

@ -637,7 +637,8 @@ static int radius_server_reject(struct radius_server_data *data,
data->counters.access_rejects++;
client->counters.access_rejects++;
if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0,
if (sendto(data->auth_sock, wpabuf_head(msg->buf),
wpabuf_len(msg->buf), 0,
(struct sockaddr *) from, sizeof(*from)) < 0) {
perror("sendto[RADIUS SRV]");
ret = -1;
@ -705,8 +706,9 @@ static int radius_server_request(struct radius_server_data *data,
client->counters.dup_access_requests++;
if (sess->last_reply) {
res = sendto(data->auth_sock, sess->last_reply->buf,
sess->last_reply->buf_used, 0,
res = sendto(data->auth_sock,
wpabuf_head(sess->last_reply->buf),
wpabuf_len(sess->last_reply->buf), 0,
(struct sockaddr *) from, fromlen);
if (res < 0) {
perror("sendto[RADIUS SRV]");
@ -796,7 +798,8 @@ static int radius_server_request(struct radius_server_data *data,
client->counters.access_challenges++;
break;
}
res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0,
res = sendto(data->auth_sock, wpabuf_head(reply->buf),
wpabuf_len(reply->buf), 0,
(struct sockaddr *) from, fromlen);
if (res < 0) {
perror("sendto[RADIUS SRV]");