Convert RADIUS message code to use wpabuf internally
authorJouni Malinen <j@w1.fi>
Sat, 19 Dec 2009 15:12:07 +0000 (17:12 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 19 Dec 2009 15:12:07 +0000 (17:12 +0200)
src/radius/radius.c
src/radius/radius.h
src/radius/radius_client.c
src/radius/radius_server.c

index a00cee5..656431a 100644 (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);
index 6050b54..c4c80be 100644 (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
index 0ace8d1..f48df52 100644 (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);
 
index 54bfdac..05b4a29 100644 (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]");