Esempio n. 1
0
struct radius_msg *radius_msg_new(u8 code, u8 identifier)
{
	struct radius_msg *msg;

	msg = os_malloc(sizeof(*msg));
	if (msg == NULL)
		return NULL;

	if (radius_msg_initialize(msg, RADIUS_DEFAULT_MSG_SIZE)) {
		os_free(msg);
		return NULL;
	}

	radius_msg_set_hdr(msg, code, identifier);

	return msg;
}
Esempio n. 2
0
/**
 * radius_msg_new - Create a new RADIUS message
 * @code: Code for RADIUS header
 * @identifier: Identifier for RADIUS header
 * Returns: Context for RADIUS message or %NULL on failure
 *
 * The caller is responsible for freeing the returned data with
 * radius_msg_free().
 */
struct radius_msg * radius_msg_new(u8 code, u8 identifier)
{
	struct radius_msg *msg;

	msg = os_zalloc(sizeof(*msg));
	if (msg == NULL)
		return NULL;

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

	return msg;
}
Esempio n. 3
0
struct radius_msg *radius_msg_parse(const u8 *data, size_t len)
{
	struct radius_msg *msg;
	struct radius_hdr *hdr;
	struct radius_attr_hdr *attr;
	size_t msg_len;
	unsigned char *pos, *end;

	if (data == NULL || len < sizeof(*hdr))
		return NULL;

	hdr = (struct radius_hdr *) data;

	msg_len = ntohs(hdr->length);
	if (msg_len < sizeof(*hdr) || msg_len > len) {
		printf("Invalid RADIUS message length\n");
		return NULL;
	}

	if (msg_len < len) {
		printf("Ignored %lu extra bytes after RADIUS message\n",
		       (unsigned long) len - msg_len);
	}

	msg = os_malloc(sizeof(*msg));
	if (msg == NULL)
		return NULL;

	if (radius_msg_initialize(msg, msg_len)) {
		os_free(msg);
		return NULL;
	}

	os_memcpy(msg->buf, data, msg_len);
	msg->buf_size = msg->buf_used = msg_len;

	/* parse attributes */
	pos = (unsigned char *) (msg->hdr + 1);
	end = msg->buf + msg->buf_used;
	while (pos < end) {
		if ((size_t) (end - pos) < sizeof(*attr))
			goto fail;

		attr = (struct radius_attr_hdr *) pos;

		if (pos + attr->length > end || attr->length < sizeof(*attr))
			goto fail;

		/* TODO: check that attr->length is suitable for attr->type */

		if (radius_msg_add_attr_to_array(msg, attr))
			goto fail;

		pos += attr->length;
	}

	return msg;

 fail:
	radius_msg_free(msg);
	os_free(msg);
	return NULL;
}
Esempio n. 4
0
/**
 * radius_msg_parse - Parse a RADIUS message
 * @data: RADIUS message to be parsed
 * @len: Length of data buffer in octets
 * Returns: Parsed RADIUS message or %NULL on failure
 *
 * This parses a RADIUS message and makes a copy of its data. The caller is
 * responsible for freeing the returned data with radius_msg_free().
 */
struct radius_msg * radius_msg_parse(const u8 *data, size_t len)
{
	struct radius_msg *msg;
	struct radius_hdr *hdr;
	struct radius_attr_hdr *attr;
	size_t msg_len;
	unsigned char *pos, *end;

	if (data == NULL || len < sizeof(*hdr))
		return NULL;

	hdr = (struct radius_hdr *) data;

	msg_len = ntohs(hdr->length);
	if (msg_len < sizeof(*hdr) || msg_len > len) {
		wpa_printf(MSG_INFO, "RADIUS: Invalid message length");
		return NULL;
	}

	if (msg_len < len) {
		wpa_printf(MSG_DEBUG, "RADIUS: Ignored %lu extra bytes after "
			   "RADIUS message", (unsigned long) len - msg_len);
	}

	msg = os_zalloc(sizeof(*msg));
	if (msg == NULL)
		return NULL;

	msg->buf = wpabuf_alloc_copy(data, msg_len);
	if (msg->buf == NULL || radius_msg_initialize(msg)) {
		radius_msg_free(msg);
		return NULL;
	}
	msg->hdr = wpabuf_mhead(msg->buf);

	/* parse attributes */
	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;

		attr = (struct radius_attr_hdr *) pos;

		if (pos + attr->length > end || attr->length < sizeof(*attr))
			goto fail;

		/* TODO: check that attr->length is suitable for attr->type */

		if (radius_msg_add_attr_to_array(msg, attr))
			goto fail;

		pos += attr->length;
	}

	return msg;

 fail:
	radius_msg_free(msg);
	return NULL;
}
Esempio n. 5
0
/* Modified version of radius_msg_parse */
int rgw_msg_parse(unsigned char * buf, size_t len, struct rgw_radius_msg_meta ** msg)
{
	struct rgw_radius_msg_meta * temp_msg = NULL;
	struct radius_hdr *hdr;
	struct radius_attr_hdr *attr;
	size_t msg_len;
	unsigned char *pos, *end;
	int ret = 0;
	
	TRACE_ENTRY("%p %zd %p", buf, len, msg);
	
	CHECK_PARAMS( buf && len >= sizeof(*hdr) && msg );
	
	*msg = NULL;
	
	/* Parse the RADIUS message */
	hdr = (struct radius_hdr *) buf;
	msg_len = ntohs(hdr->length);
	if (msg_len < sizeof(*hdr) || msg_len > len) {
		TRACE_DEBUG(INFO, "Invalid RADIUS message length");
		return EINVAL;
	}

	if (msg_len < len) {
		TRACE_DEBUG(INFO, "Ignored %lu extra bytes after RADIUS message",
		       (unsigned long) len - msg_len);
	}

	CHECK_MALLOC( temp_msg = malloc(sizeof(struct rgw_radius_msg_meta)) );
	memset(temp_msg, 0, sizeof(struct rgw_radius_msg_meta));
	
	if (radius_msg_initialize(&temp_msg->radius, msg_len)) {
		TRACE_DEBUG(INFO, "Error in radius_msg_initialize, returning ENOMEM.");
		free(temp_msg);
		return ENOMEM;
	}
	
	/* Store the received data in the alloc'd buffer */
	memcpy(temp_msg->radius.buf, buf, msg_len);
	temp_msg->radius.buf_size = temp_msg->radius.buf_used = msg_len;
	
	/* parse attributes */
	pos = (unsigned char *) (temp_msg->radius.hdr + 1);
	end = temp_msg->radius.buf + temp_msg->radius.buf_used;
	
	while (pos < end) {
		if ((size_t) (end - pos) < sizeof(*attr)) {
			TRACE_DEBUG(INFO, "Trucated attribute found in RADIUS buffer, EINVAL.");
			ret = EINVAL;
			break;
		}
			
		attr = (struct radius_attr_hdr *) pos;
	
		if (pos + attr->length > end || attr->length < sizeof(*attr)) {
			TRACE_DEBUG(INFO, "Trucated attribute found in RADIUS buffer, EINVAL.");
			ret = EINVAL;
			break;
		}

		if (radius_msg_add_attr_to_array(&temp_msg->radius, attr)) {
			TRACE_DEBUG(INFO, "Error in radius_msg_add_attr_to_array, ENOMEM");
			ret = ENOMEM;
			break;
		}
		
		if (attr->type == RADIUS_ATTR_PROXY_STATE)
			temp_msg->ps_nb += 1;

		pos += attr->length;
	}
	
	if (ret != 0) {
		radius_msg_free(&temp_msg->radius);
		free(temp_msg);
		return ret;
	}
	
	/* Now move all the proxy-state attributes at the end of the attr_pos array */
	if (temp_msg->ps_nb) {
		size_t *temp_ps = NULL;
		int n, new_n = 0, p = 0;
		
		CHECK_MALLOC( temp_ps = calloc(temp_msg->ps_nb, sizeof(size_t)) );
		
		/* Move all the Proxy-State attributes into the temp_ps array */
		for (n=0; n < temp_msg->radius.attr_used; n++) {
			struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(temp_msg->radius.buf + temp_msg->radius.attr_pos[n]);
			
			if (attr->type == RADIUS_ATTR_PROXY_STATE) {
				temp_ps[p++] = temp_msg->radius.attr_pos[n];
			} else {
				temp_msg->radius.attr_pos[new_n++] = temp_msg->radius.attr_pos[n];
			}
		}
		temp_msg->radius.attr_used = new_n; /* hide the proxy-state to other modules */
		temp_msg->ps_first = new_n;
		
		/* And back into the array */
		memcpy(temp_msg->radius.attr_pos + new_n, temp_ps, p * sizeof(size_t));
		free(temp_ps);
	}
	
	*msg = temp_msg;
	return 0;
}