⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radclient.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * radclient.c	General radius packet debug tool. * * Version:	$Id: radclient.c,v 1.120 2008/04/03 13:43:12 aland Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2000,2006  The FreeRADIUS server project * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl> * Copyright 2000  Alan DeKok <aland@ox.org> */#include <freeradius-devel/ident.h>RCSID("$Id: radclient.c,v 1.120 2008/04/03 13:43:12 aland Exp $")#include <freeradius-devel/libradius.h>#include <freeradius-devel/conf.h>#include <freeradius-devel/radpaths.h>#include <ctype.h>#ifdef HAVE_GETOPT_H#	include <getopt.h>#endif#include <assert.h>static int retries = 10;static float timeout = 3;static const char *secret = NULL;static int do_output = 1;static int totalapp = 0;static int totaldeny = 0;static int totallost = 0;static int server_port = 0;static int packet_code = 0;static fr_ipaddr_t server_ipaddr;static int resend_count = 1;static int done = 1;static int print_filename = 0;static fr_ipaddr_t client_ipaddr;static int client_port = 0;static int sockfd;static int last_used_id = -1;static rbtree_t *filename_tree = NULL;static fr_packet_list_t *pl = NULL;static int sleep_time = -1;typedef struct radclient_t {	struct		radclient_t *prev;	struct		radclient_t *next;	const char	*filename;	int		packet_number; /* in the file */	char		password[256];	time_t		timestamp;	RADIUS_PACKET	*request;	RADIUS_PACKET	*reply;	int		resend;	int		tries;	int		done;} radclient_t;static radclient_t *radclient_head = NULL;static radclient_t *radclient_tail = NULL;static void NEVER_RETURNS usage(void){	fprintf(stderr, "Usage: radclient [options] server[:port] <command> [<secret>]\n");	fprintf(stderr, "  <command>    One of auth, acct, status, coa, or disconnect.\n");	fprintf(stderr, "  -c count    Send each packet 'count' times.\n");	fprintf(stderr, "  -d raddb    Set dictionary directory.\n");	fprintf(stderr, "  -f file     Read packets from file, not stdin.\n");	fprintf(stderr, "  -i id       Set request id to 'id'.  Values may be 0..255\n");	fprintf(stderr, "  -n num      Send N requests/s\n");	fprintf(stderr, "  -p num      Send 'num' packets from a file in parallel.\n");	fprintf(stderr, "  -q          Do not print anything out.\n");	fprintf(stderr, "  -r retries  If timeout, retry sending the packet 'retries' times.\n");	fprintf(stderr, "  -s          Print out summary information of auth results.\n");	fprintf(stderr, "  -S file     read secret from file, not command line.\n");	fprintf(stderr, "  -t timeout  Wait 'timeout' seconds before retrying (may be a floating point number).\n");	fprintf(stderr, "  -v          Show program version information.\n");	fprintf(stderr, "  -x          Debugging mode.\n");	fprintf(stderr, "  -4          Use IPv4 address of server\n");	fprintf(stderr, "  -6          Use IPv6 address of server.\n");	exit(1);}/* *	Free a radclient struct, which may (or may not) *	already be in the list. */static void radclient_free(radclient_t *radclient){	radclient_t *prev, *next;	if (radclient->request) rad_free(&radclient->request);	if (radclient->reply) rad_free(&radclient->reply);	prev = radclient->prev;	next = radclient->next;	if (prev) {		assert(radclient_head != radclient);		prev->next = next;	} else if (radclient_head) {		assert(radclient_head == radclient);		radclient_head = next;	}	if (next) {		assert(radclient_tail != radclient);		next->prev = prev;	} else if (radclient_tail) {		assert(radclient_tail == radclient);		radclient_tail = prev;	}	free(radclient);}/* *	Initialize a radclient data structure */static radclient_t *radclient_init(const char *filename){	FILE *fp;	VALUE_PAIR *vp;	radclient_t *start, *radclient, *prev = NULL;	int filedone = 0;	int packet_number = 1;	start = NULL;	assert(filename != NULL);	/*	 *	Determine where to read the VP's from.	 */	if (strcmp(filename, "-") != 0) {		fp = fopen(filename, "r");		if (!fp) {			fprintf(stderr, "radclient: Error opening %s: %s\n",				filename, strerror(errno));			return NULL;		}	} else {		fp = stdin;	}	/*	 *	Loop until the file is done.	 */	do {		/*		 *	Allocate it.		 */		radclient = malloc(sizeof(*radclient));		if (!radclient) {			perror("radclient: X");			if (fp != stdin) fclose(fp);			return NULL; /* memory leak "start" */		}		memset(radclient, 0, sizeof(*radclient));		radclient->request = rad_alloc(1);		if (!radclient->request) {			librad_perror("radclient: Y");			radclient_free(radclient);			if (fp != stdin) fclose(fp);			return NULL; /* memory leak "start" */		}		radclient->filename = filename;		radclient->request->id = -1; /* allocate when sending */		radclient->packet_number = packet_number++;		/*		 *	Read the VP's.		 */		radclient->request->vps = readvp2(fp, &filedone, "radclient:");		if (!radclient->request->vps) {			radclient_free(radclient);			if (fp != stdin) fclose(fp);			return start; /* done: return the list */		}		/*		 *	Keep a copy of the the User-Password attribute.		 */		if ((vp = pairfind(radclient->request->vps, PW_USER_PASSWORD)) != NULL) {			strlcpy(radclient->password, vp->vp_strvalue,				sizeof(radclient->password));			/*			 *	Otherwise keep a copy of the CHAP-Password attribute.			 */		} else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {			strlcpy(radclient->password, vp->vp_strvalue,				sizeof(radclient->password));		} else {			radclient->password[0] = '\0';		}		/*		 *  Fix up Digest-Attributes issues		 */		for (vp = radclient->request->vps; vp != NULL; vp = vp->next) {			switch (vp->attribute) {			default:				break;				/*				 *	Allow it to set the packet type in				 *	the attributes read from the file.				 */			case PW_PACKET_TYPE:				radclient->request->code = vp->vp_integer;				break;			case PW_PACKET_DST_PORT:				radclient->request->dst_port = (vp->vp_integer & 0xffff);				break;			case PW_PACKET_DST_IP_ADDRESS:				radclient->request->dst_ipaddr.af = AF_INET;				radclient->request->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;				break;			case PW_PACKET_DST_IPV6_ADDRESS:				radclient->request->dst_ipaddr.af = AF_INET6;				radclient->request->dst_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;				break;			case PW_PACKET_SRC_PORT:				radclient->request->src_port = (vp->vp_integer & 0xffff);				break;			case PW_PACKET_SRC_IP_ADDRESS:				radclient->request->src_ipaddr.af = AF_INET;				radclient->request->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;				break;			case PW_PACKET_SRC_IPV6_ADDRESS:				radclient->request->src_ipaddr.af = AF_INET6;				radclient->request->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;				break;			case PW_DIGEST_REALM:			case PW_DIGEST_NONCE:			case PW_DIGEST_METHOD:			case PW_DIGEST_URI:			case PW_DIGEST_QOP:			case PW_DIGEST_ALGORITHM:			case PW_DIGEST_BODY_DIGEST:			case PW_DIGEST_CNONCE:			case PW_DIGEST_NONCE_COUNT:			case PW_DIGEST_USER_NAME:				/* overlapping! */				memmove(&vp->vp_octets[2], &vp->vp_octets[0],					vp->length);				vp->vp_octets[0] = vp->attribute - PW_DIGEST_REALM + 1;				vp->length += 2;				vp->vp_octets[1] = vp->length;				vp->attribute = PW_DIGEST_ATTRIBUTES;				break;			}		} /* loop over the VP's we read in */		if (!start) {			start = radclient;			prev = start;		} else {			prev->next = radclient;			radclient->prev = prev;			prev = radclient;		}	} while (!filedone); /* loop until the file is done. */	if (fp != stdin) fclose(fp);	/*	 *	And we're done.	 */	return start;}/* *	Sanity check each argument. */static int radclient_sane(radclient_t *radclient){	if (radclient->request->dst_port == 0) {		radclient->request->dst_port = server_port;	}	if (radclient->request->dst_ipaddr.af == AF_UNSPEC) {		if (server_ipaddr.af == AF_UNSPEC) {			fprintf(stderr, "radclient: No server was given, but request %d in file %s did not contain Packet-Dst-IP-Address\n",				radclient->packet_number, radclient->filename);			return -1;		}		radclient->request->dst_ipaddr = server_ipaddr;	}	if (radclient->request->code == 0) {		if (packet_code == -1) {			fprintf(stderr, "radclient: Request was \"auto\", but request %d in file %s did not contain Packet-Type\n",				radclient->packet_number, radclient->filename);			return -1;		}		radclient->request->code = packet_code;	}	radclient->request->sockfd = -1;	return 0;}/* *	For request handline. */static int filename_cmp(const void *one, const void *two){	return strcmp((const char *) one, (const char *) two);}static int filename_walk(void *context, void *data){	const char	*filename = data;	radclient_t	*radclient;	context = context;	/* -Wunused */	/*	 *	Initialize the request we're about	 *	to send.	 */	radclient = radclient_init(filename);	if (!radclient) {		exit(1);	}	if (!radclient_head) {		assert(radclient_tail == NULL);		radclient_head = radclient;	} else {		assert(radclient_tail->next == NULL);		radclient_tail->next = radclient;		radclient->prev = radclient_tail;	}	/*	 *	We may have had a list of "radclient" structures	 *	returned to us.	 */	while (radclient->next) radclient = radclient->next;	radclient_tail = radclient;	return 0;}/* *	Deallocate packet ID, etc. */static void deallocate_id(radclient_t *radclient){	if (!radclient || !radclient->request ||	    (radclient->request->id < 0)) {		return;	}	/*	 *	One more unused RADIUS ID.	 */	fr_packet_list_id_free(pl, radclient->request);	radclient->request->id = -1;	/*	 *	If we've already sent a packet, free up the old one,	 *	and ensure that the next packet has a unique	 *	authentication vector.	 */	if (radclient->request->data) {		free(radclient->request->data);		radclient->request->data = NULL;	}	if (radclient->reply) rad_free(&radclient->reply);}static void print_hex(RADIUS_PACKET *packet){	int i;	if (!packet->data) return;	printf("  Code:\t\t%u\n", packet->data[0]);	printf("  Id:\t\t%u\n", packet->data[1]);	printf("  Length:\t%u\n", ((packet->data[2] << 8) |				   (packet->data[3])));	printf("  Vector:\t");	for (i = 4; i < 20; i++) {		printf("%02x", packet->data[i]);	}	printf("\n");	if (packet->data_len > 20) {		int total;		const uint8_t *ptr;		printf("  Data:");		total = packet->data_len - 20;		ptr = packet->data + 20;		while (total > 0) {			int attrlen;			printf("\t\t");			if (total < 2) { /* too short */				printf("%02x\n", *ptr);				break;			}			if (ptr[1] > total) { /* too long */				for (i = 0; i < total; i++) {					printf("%02x ", ptr[i]);				}				break;			}			printf("%02x  %02x  ", ptr[0], ptr[1]);			attrlen = ptr[1] - 2;			ptr += 2;			total -= 2;			for (i = 0; i < attrlen; i++) {				if ((i > 0) && ((i & 0x0f) == 0x00))					printf("\t\t\t");				printf("%02x ", ptr[i]);				if ((i & 0x0f) == 0x0f) printf("\n");			}			if ((attrlen & 0x0f) != 0x00) printf("\n");			ptr += attrlen;			total -= attrlen;		}	}	fflush(stdout);}/* *	Send one packet. */static int send_one_packet(radclient_t *radclient){	assert(radclient->done == 0);	/*	 *	Remember when we have to wake up, to re-send the	 *	request, of we didn't receive a response.	 */	if ((sleep_time == -1) ||	    (sleep_time > (int) timeout)) {		sleep_time = (int) timeout;	}	/*	 *	Haven't sent the packet yet.  Initialize it.	 */	if (radclient->request->id == -1) {		int i, rcode;		assert(radclient->reply == NULL);		/*		 *	Didn't find a free packet ID, we're not done,		 *	we don't sleep, and we stop trying to process		 *	this packet.		 */	retry:		rcode = fr_packet_list_id_alloc(pl, radclient->request);		if (rcode < 0) {			int mysockfd;			mysockfd = fr_socket(&client_ipaddr, 0);			if (!mysockfd) {				fprintf(stderr, "radclient: Can't open new socket\n");				exit(1);			}			if (!fr_packet_list_socket_add(pl, mysockfd)) {				fprintf(stderr, "radclient: Can't add new socket\n");				exit(1);			}			goto retry;		}		if (rcode == 0) {			done = 0;			sleep_time = 0;			return 0;		}		assert(radclient->request->id != -1);		assert(radclient->request->data == NULL);		for (i = 0; i < 4; i++) {			*((uint32_t *) radclient->request->vector) = fr_rand();		}		/*		 *	Update the password, so it can be encrypted with the		 *	new authentication vector.		 */		if (radclient->password[0] != '\0') {			VALUE_PAIR *vp;			if ((vp = pairfind(radclient->request->vps, PW_USER_PASSWORD)) != NULL) {				strlcpy(vp->vp_strvalue, radclient->password,					sizeof(vp->vp_strvalue));				vp->length = strlen(vp->vp_strvalue);			} else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {			  /*			   *	FIXME: AND there's no CHAP-Challenge,			   *	       AND vp->length != 17			   *	       AND rad_chap_encode() != vp->vp_octets			   */				strlcpy(vp->vp_strvalue, radclient->password,					sizeof(vp->vp_strvalue));				vp->length = strlen(vp->vp_strvalue);				rad_chap_encode(radclient->request,						vp->vp_octets,						radclient->request->id, vp);				vp->length = 17;			}		}		radclient->timestamp = time(NULL);		radclient->tries = 1;		radclient->resend++;		/*		 *	Duplicate found.  Serious error!		 */		if (!fr_packet_list_insert(pl, &radclient->request)) {			assert(0 == 1);		}	} else {		/* radclient->request->id >= 0 */		time_t now = time(NULL);		/*		 *	FIXME: Accounting packets are never retried!		 *	The Acct-Delay-Time attribute is updated to		 *	reflect the delay, and the packet is re-sent		 *	from scratch!		 */		/*		 *	Not time for a retry, do so.		 */		if ((now - radclient->timestamp) < timeout) {			/*			 *	When we walk over the tree sending			 *	packets, we update the minimum time			 *	required to sleep.			 */			if ((sleep_time == -1) ||			    (sleep_time > (now - radclient->timestamp))) {				sleep_time = now - radclient->timestamp;			}			return 0;		}		/*		 *	We're not trying later, maybe the packet is done.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -