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

📄 rlm_fastusers.c

📁 RADIUS认证协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * rlm_fastusers.c	authorization: Find a user in the hashed "users" file. *                	accounting:    Do nothing.  Auth module only. * * Version:	$Id: rlm_fastusers.c,v 1.33 2004/05/15 15:09:44 mgriego 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2000  The FreeRADIUS server project * Copyright 2000  Jeff Carneal <jeff@apex.net> */#include        "autoconf.h"#include        "libradius.h"#include	<sys/socket.h>#include	<sys/time.h>#include	<sys/stat.h>#include	<stdio.h>#include	<stdlib.h>#include	<string.h>#include	<pwd.h>#include	<grp.h>#include	<ctype.h>#include	<fcntl.h>#include	<limits.h>#include	"radiusd.h"#include	"modules.h"struct fastuser_instance {	char *compat_mode;	int hash_reload;	/* hash table */	int hashsize;	PAIR_LIST **hashtable;	PAIR_LIST *defaults;	PAIR_LIST *acctusers;	int stats;	char *usersfile;	char *acctusersfile;	time_t next_reload;	time_t lastusersload;	time_t lastacctusersload;};/* Function declarations */static int fallthrough(VALUE_PAIR *vp);static int fastuser_buildhash(struct fastuser_instance *inst);static int fastuser_getfile(struct fastuser_instance *inst, const char *filename,														PAIR_LIST **default_list, PAIR_LIST **pair_list,														int isacctfile);static int fastuser_hash(const char *s, int hashtablesize);static int fastuser_store(PAIR_LIST **hashtable, PAIR_LIST *entry, int idx);static PAIR_LIST *fastuser_find(REQUEST *request, PAIR_LIST *user,																const char *username);static void fastuser_tablestats(PAIR_LIST **hashtable, int size);static int fastuser_passcheck(REQUEST *request, PAIR_LIST *user, const char *name);static CONF_PARSER module_config[] = {	{ "usersfile",     PW_TYPE_STRING_PTR,	  offsetof(struct fastuser_instance,usersfile), NULL, "${raddbdir}/users_fast" },	{ "acctusersfile",     PW_TYPE_STRING_PTR,	  offsetof(struct fastuser_instance,acctusersfile), NULL, "${raddbdir}/acct_users" },	{ "hashsize",     PW_TYPE_INTEGER,	  offsetof(struct fastuser_instance,hashsize), NULL, "100000" },	{ "stats",     PW_TYPE_BOOLEAN,	  offsetof(struct fastuser_instance,stats), NULL, "no" },	{ "compat",        PW_TYPE_STRING_PTR,	  offsetof(struct fastuser_instance,compat_mode), NULL, "cistron" },	{ "hash_reload",     PW_TYPE_INTEGER,	  offsetof(struct fastuser_instance,hash_reload), NULL, "600" },	{ NULL, -1, 0, NULL, NULL }};/* * See if a VALUE_PAIR list contains Fall-Through = Yes */static int fallthrough(VALUE_PAIR *vp){	VALUE_PAIR *tmp;	tmp = pairfind(vp, PW_FALL_THROUGH);	return tmp ? tmp->lvalue : 0;}/* *       returncheck - Check for Auth-Type = Reject and return appropriate *                     module return code if it is found. */static int rad_check_return(VALUE_PAIR *list){      VALUE_PAIR      *authtype;      /*       * We check for Auth-Type = Reject here       */      authtype = pairfind(list, PW_AUTHTYPE);      if((authtype) && authtype->lvalue == PW_AUTHTYPE_REJECT)  {              DEBUG2("rad_check_return:  Auth-Type is Reject");              return RLM_MODULE_REJECT;      }      return RLM_MODULE_UPDATED;}static int fastuser_buildhash(struct fastuser_instance *inst) {	int memsize=0;	int rcode, hashindex;	PAIR_LIST **newhash=NULL, **oldhash=NULL;	PAIR_LIST *newdefaults=NULL, *newacctusers, *cur=NULL;	PAIR_LIST *olddefaults=NULL, *oldacctusers=NULL;	struct stat statbuf;	int reloadusers = 1;	int reloadacctusers = 1;	/*	 * Allocate space for hash table here	 */	memsize = sizeof(PAIR_LIST *) * inst->hashsize;	newhash = (PAIR_LIST **) rad_malloc(memsize);	memset((PAIR_LIST *)newhash, 0, memsize);	/* Check acct_users last modification time */	if ((stat(inst->acctusersfile, &statbuf) != -1)	 && (statbuf.st_mtime <= inst->lastacctusersload)) {		DEBUG2("rlm_fastusers:  File %s was unchanged. Not reloading.",			inst->acctusersfile);		reloadacctusers = 0;		rcode = 0;	}	else	/* Read acct_users */	rcode = fastuser_getfile(inst, inst->acctusersfile, NULL, &newacctusers, 1);	if (rcode != 0) {		radlog(L_ERR|L_CONS, "rlm_fastusers:  Errors reading %s", inst->usersfile);		return -1;	}	/* Check users last modification time */	if ((stat(inst->usersfile, &statbuf) != -1)	 && (statbuf.st_mtime <= inst->lastusersload)) {		DEBUG2("rlm_fastusers:  File %s was unchanged. Not reloading.",			inst->usersfile);		reloadusers = 0;		rcode = 0;		/* This was allocated earlier but will remain unused */		free(newhash);	}	else	/* Read users */	rcode = fastuser_getfile(inst, inst->usersfile, &newdefaults, newhash, 0);	if (rcode != 0) {		radlog(L_ERR|L_CONS, "rlm_fastusers:  Errors reading %s", inst->usersfile);		return -1;	}	if (reloadusers) {		/*		 * We need to do this now so that users auths		 * aren't blocked while we free the old table		 * below		 */		inst->lastusersload = time(NULL);		oldhash = inst->hashtable;		inst->hashtable = newhash;		olddefaults = inst->defaults;		inst->defaults = newdefaults;		/*		 * When we get here, we assume the hash built properly.		 * So we begin to tear down the old one		 */		if (oldhash) {			for(hashindex=0; hashindex<inst->hashsize; hashindex++) {				if(oldhash[hashindex]) {					cur = oldhash[hashindex];					pairlist_free(&cur);				}			}			free(oldhash);		}		pairlist_free(&olddefaults);	}	if (reloadacctusers) {		inst->lastacctusersload = time(NULL);		oldacctusers = inst->acctusers;		inst->acctusers = newacctusers;		pairlist_free(&oldacctusers);	}	if(inst->stats)		fastuser_tablestats(inst->hashtable, inst->hashsize);	return 0;}static int fastuser_getfile(struct fastuser_instance *inst, const char *filename,														PAIR_LIST **default_list, PAIR_LIST **pair_list,														int isacctfile) {	int rcode;	PAIR_LIST *users = NULL;	PAIR_LIST *entry=NULL, *next=NULL, *cur=NULL, *defaults=NULL, *lastdefault=NULL;	int compat_mode = FALSE;	VALUE_PAIR *vp=NULL;	int hashindex = 0;	int numdefaults = 0, numusers=0;	radlog(L_INFO, " fastusers:  Reading %s", filename);	rcode = pairlist_read(filename, &users, 1);	if (rcode < 0) {		return -1;	}	if (strcmp(inst->compat_mode, "cistron") == 0) {		compat_mode = TRUE;	}	entry = users;	while (entry) {		if (compat_mode) {			DEBUG("[%s]:%d Cistron compatibility checks for entry %s ...",				filename, entry->lineno, entry->name);		}		/*		 *	Look for improper use of '=' in the		 *	check items.  They should be using		 *	'==' for on-the-wire RADIUS attributes,		 *	and probably ':=' for server		 *	configuration items.		 */		for (vp = entry->check; vp != NULL; vp = vp->next) {			/*			 *	Ignore attributes which are set			 *	properly.			 */			if (vp->operator != T_OP_EQ)				continue;			/*			 *	If it's a vendor attribute,			 *	or it's a wire protocol,			 *	ensure it has '=='.			 */			if (((vp->attribute & ~0xffff) != 0) ||				(vp->attribute < 0x100)) {				if (!compat_mode) {					DEBUG("[%s]:%d WARNING! Changing '%s =' to '%s =='\n\tfor comparing RADIUS attribute in check item list for user %s",					filename, entry->lineno, vp->name, vp->name, entry->name);				} else {					DEBUG("\tChanging '%s =' to '%s =='",						vp->name, vp->name);				}				vp->operator = T_OP_CMP_EQ;				continue;			}			/*			 *	Cistron Compatibility mode.			 *			 *	Re-write selected attributes			 *	to be '+=', instead of '='.			 *			 *	All others get set to '=='			 */			if (compat_mode) {				/*				 *	Non-wire attributes become +=				 *				 *	On the write attributes				 *	become ==				 */				if ((vp->attribute >= 0x100) &&					(vp->attribute <= 0xffff) &&					(vp->attribute != PW_HINT) &&					(vp->attribute != PW_HUNTGROUP_NAME)) {					DEBUG("\tChanging '%s =' to '%s +='",						vp->name, vp->name);						vp->operator = T_OP_ADD;				} else {					DEBUG("\tChanging '%s =' to '%s =='",						vp->name, vp->name);					vp->operator = T_OP_CMP_EQ;				}			}		} /* end of loop over check items */		/*		 *	Look for server configuration items		 *	in the reply list.		 *		 *	It's a common enough mistake, that it's		 *	worth doing.		 */		for (vp = entry->reply; vp != NULL; vp = vp->next) {			/*			 *	If it's NOT a vendor attribute,			 *	and it's NOT a wire protocol			 *	and we ignore Fall-Through,			 *	then bitch about it, giving a			 *	good warning message.			 */			if (!(vp->attribute & ~0xffff) &&				(vp->attribute > 0xff) &&				(vp->attribute > 1000)) {				log_debug("[%s]:%d WARNING! Check item \"%s\"\n"					"\tfound in reply item list for user \"%s\".\n"					"\tThis attribute MUST go on the first line"					" with the other check items",					filename, entry->lineno, vp->name,					entry->name);			}		}		/*		 * Ok, we've done all the same BS as		 * rlm_users, so here we tear apart the		 * linked list, and store our users in		 * the hashtable we've built instead		 */		/* Save what was next */		next = entry->next;		if(!isacctfile) {			/* Save the DEFAULT entry specially */			if(strcmp(entry->name, "DEFAULT")==0) {				/* Save this as the last default we've seen */				lastdefault = entry;				numdefaults++;				/* put it at the end of the list */				if(defaults) {					for(cur=defaults; cur->next; cur=cur->next);					cur->next = entry;					entry->next = NULL;				} else {					defaults = entry;					defaults->next = NULL;				}			} else {				numusers++;				/* Hash the username */				hashindex = fastuser_hash(entry->name, inst->hashsize);				/* Store the last default before this entry */				entry->lastdefault = lastdefault;				/* Store user in the hash */				fastuser_store(pair_list, entry, hashindex);			}		}		/* Restore entry to next pair_list */		entry = next;	} /* while(entry) loop */	if(!isacctfile && (default_list)) {		*default_list = defaults;		radlog(L_INFO, "rlm_fastusers:  Loaded %d users and %d defaults",					numusers, numdefaults);	} else {		*pair_list = users;	}	return 0;}/* Hashes the username sent to it and returns index into hashtable */int fastuser_hash(const char *s, int hashtablesize) {	unsigned int hash = 0;	while (*s != '\0') {		hash = hash * 7907 + (unsigned char)*s++;	}	return (hash % hashtablesize);}/* Stores the username sent into the hashtable */static int fastuser_store(PAIR_LIST **hashtable, PAIR_LIST *new, int idx) {	PAIR_LIST *cur;	cur = hashtable[idx];	/* store new record at end of list */	if(cur) {		while (cur->next != NULL)			cur=cur->next;		cur->next = new;		new->next = NULL;	} else {		new->next = hashtable[idx];		hashtable[idx] = new;	}	return 1;}/* * Looks up user in hashtable.  If user can't be found, returns 0. * Otherwise returns a pointer to the structure for the user */static PAIR_LIST *fastuser_find(REQUEST *request, PAIR_LIST *user,		                            const char *username){	PAIR_LIST *cur=user;

⌨️ 快捷键说明

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