view extensions/radius_gw/rgw_msg.c @ 365:0146c60af026

Moved to the hostap implementation of RADIUS processing (copied radius.* and md5.* files)
author Sebastien Decugis <sdecugis@nict.go.jp>
date Fri, 22 May 2009 18:11:49 +0900
parents 9d330bd07134
children e25e6117e6a1
line wrap: on
line source

/*********************************************************************************************************
* Software License Agreement (BSD License)                                                               *
* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
*													 *
* Copyright (c) 2008, WIDE Project and NICT								 *
* All rights reserved.											 *
* 													 *
* Redistribution and use of this software in source and binary forms, with or without modification, are  *
* permitted provided that the following conditions are met:						 *
* 													 *
* * Redistributions of source code must retain the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer.										 *
*    													 *
* * Redistributions in binary form must reproduce the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer in the documentation and/or other						 *
*   materials provided with the distribution.								 *
* 													 *
* * Neither the name of the WIDE Project or NICT nor the 						 *
*   names of its contributors may be used to endorse or 						 *
*   promote products derived from this software without 						 *
*   specific prior written permission of WIDE Project and 						 *
*   NICT.												 *
* 													 *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
*********************************************************************************************************/

/* This file contains all support functions to parse, create, and manipulate RADIUS messages. Other 
modules do not need to "know" the actual representation of RADIUS messages on the network. They only 
receive the logical view as exposed in the radius_gw.h file. */

#include "radius_gw.h"

/* Two functions for dumping */
#include "rgw_msg_codes.c"
#include "rgw_msg_attrtype.c"

/* Destroy a message */
void rgw_msg_free(struct rgw_radius_msg_meta ** msg)
{
	if (!msg || !*msg)
		return;
	
	radius_msg_free(&(*msg)->radius);
	free(*msg);
	*msg = NULL;
}

/* This function is derived from radius_msg_parse, but creates a rgw_radius_msg_meta structure instead */
int rgw_msg_parse(unsigned char * buf, size_t len, struct rgw_radius_msg_meta ** msg)
{
	struct radius_hdr *hdr;
	struct radius_attr_hdr *attr;
	size_t msg_len;
	unsigned char *pos, *end;
	
	TRACE_ENTRY("%p %g %p", buf, len, msg);
	
	CHECK_PARAMS( buf && len && msg );
	
	*msg = NULL;
	
	if (len < sizeof(struct radius_hdr)) {
		TRACE_DEBUG(INFO, "Buffer too short to contain a RADIUS message: %g", len);
		return EINVAL;
	}
	
	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: %g (buf: %g)", msg_len, len);
		return EINVAL;
	}

	if (msg_len < len) {
		TRACE_DEBUG(INFO, "Received data after RADIUS message, ignoring %g bytes.", len - msg_len);
	}

	/* Create the structure to store the parsing information */
	CHECK_MALLOC( *msg = malloc(sizeof(struct rgw_radius_msg_meta)) );
	memset(*msg, 0, sizeof(struct rgw_radius_msg_meta));
	
	if (radius_msg_initialize(&(*msg)->radius, msg_len)) {
		TRACE_DEBUG(INFO, "Error in radius_msg_initialize");
		free(*msg);
		return ENOMEM; /* the most likely error... */
	}

	memcpy((*msg)->radius.buf, buf, msg_len);
	(*msg)->radius.buf_size = (*msg)->radius.buf_used = msg_len;

	/* parse attributes */
	pos = (unsigned char *) ((*msg)->radius.hdr + 1);
	end = (*msg)->radius.buf + (*msg)->radius.buf_used;
	while (pos < end) {
		if ((size_t) (end - pos) < sizeof(*attr)) {
			TRACE_DEBUG(INFO, "Invalid RADIUS message size (rem: %d)", (end - pos));
			rgw_msg_free(msg);
			return EINVAL;
		}

		attr = (struct radius_attr_hdr *) pos;

		if (pos + attr->length > end || attr->length < sizeof(*attr)) {
			TRACE_DEBUG(INFO, "Invalid RADIUS message or attribute size (attr: %hhd, rem: %d)", attr->length, (end - pos));
			rgw_msg_free(msg);
			return EINVAL;
		}

		if (radius_msg_add_attr_to_array(&(*msg)->radius, attr)) {
			TRACE_DEBUG(INFO, "Error in radius_msg_add_attr_to_array");
			rgw_msg_free(msg);
			return ENOMEM;
		}

		pos += attr->length;
	}

	return 0;
}

/* Check if the message has a valid authenticator, and update the meta-data accordingly */
int rgw_msg_auth_check(struct rgw_radius_msg_meta * msg, struct rgw_client * cli, uint8_t * req_auth)
{
	unsigned char * key;
	size_t keylen;
	
	TRACE_ENTRY("%p %p %p", msg, cli, req_auth);
	
	CHECK_PARAMS(msg && cli);
	
	CHECK_FCT(rgw_clients_getkey(cli, &key, &keylen));
	
	msg->valid_mac = ! radius_msg_verify_msg_auth( &msg->radius, key, keylen, req_auth );
	
	return 0;
}


"Welcome to our mercurial repository"