Browse Source

Convert RADIUS message code to use wpabuf internally

Jouni Malinen 15 years ago
parent
commit
aa235d2ef7
4 changed files with 62 additions and 90 deletions
  1. 51 73
      src/radius/radius.c
  2. 1 11
      src/radius/radius.h
  3. 3 2
      src/radius/radius_client.c
  4. 7 4
      src/radius/radius_server.c

+ 51 - 73
src/radius/radius.c

@@ -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);

+ 1 - 11
src/radius/radius.h

@@ -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

+ 3 - 2
src/radius/radius_client.c

@@ -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);
 

+ 7 - 4
src/radius/radius_server.c

@@ -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]");