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

📄 rlm_sqlcounter.c

📁 free radius编程。完成AAA的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	check_pairs = check_pairs; /* shut the compiler up */	reply_pairs = reply_pairs;	/* first, expand %k, %b and %e in query */	sqlcounter_expand(querystr, MAX_QUERY_LEN, data->query, instance);	/* second, xlat any request attribs in query */	radius_xlat(responsestr, MAX_QUERY_LEN, querystr, req, NULL);	/* third, wrap query with sql module call & expand */	sprintf(querystr, "%%{%%S:%s}", responsestr);	sqlcounter_expand(responsestr, MAX_QUERY_LEN, querystr, instance);	/* Finally, xlat resulting SQL query */	radius_xlat(querystr, MAX_QUERY_LEN, responsestr, req, NULL);	counter = atoi(querystr);	return counter - check->lvalue;}/* *	Do any per-module initialization that is separate to each *	configured instance of the module.  e.g. set up connections *	to external databases, read configuration files, set up *	dictionary entries, etc. * *	If configuration information is given in the config section *	that must be referenced in later calls, store a handle to it *	in *instance otherwise put a null pointer there. */static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance){	rlm_sqlcounter_t *data;	DICT_ATTR *dattr;	ATTR_FLAGS flags;	time_t now;	/*	 *	Set up a storage area for instance data	 */	data = rad_malloc(sizeof(*data));	if (!data) {		return -1;	}	memset(data, 0, sizeof(*data));	/*	 *	If the configuration parameters can't be parsed, then	 *	fail.	 */	if (cf_section_parse(conf, data, module_config) < 0) {		free(data);		return -1;	}	/*	 *	Discover the attribute number of the key.	 */	if (data->key_name == NULL) {		radlog(L_ERR, "rlm_sqlcounter: 'key' must be set.");		return -1;	}	dattr = dict_attrbyname(data->key_name);	if (dattr == NULL) {		radlog(L_ERR, "rlm_sqlcounter: No such attribute %s",				data->key_name);		return -1;	}	data->key_attr = dattr->attr;	/*	 *  Create a new attribute for the counter.	 */	if (data->counter_name == NULL) {		radlog(L_ERR, "rlm_sqlcounter: 'counter-name' must be set.");		return -1;	}	memset(&flags, 0, sizeof(flags));	dict_addattr(data->counter_name, 0, PW_TYPE_INTEGER, -1, flags);	dattr = dict_attrbyname(data->counter_name);	if (dattr == NULL) {		radlog(L_ERR, "rlm_sqlcounter: Failed to create counter attribute %s",				data->counter_name);		return -1;	}	data->dict_attr = dattr->attr;	DEBUG2("rlm_sqlcounter: Counter attribute %s is number %d",			data->counter_name, data->dict_attr);	/*	 * Create a new attribute for the check item.	 */	if (data->check_name == NULL) {		radlog(L_ERR, "rlm_sqlcounter: 'check-name' must be set.");		return -1;	}	dict_addattr(data->check_name, 0, PW_TYPE_INTEGER, -1, flags);	dattr = dict_attrbyname(data->check_name);	if (dattr == NULL) {		radlog(L_ERR, "rlm_sqlcounter: Failed to create check attribute %s",				data->counter_name);		return -1;	}	DEBUG2("rlm_sqlcounter: Check attribute %s is number %d",			data->check_name, dattr->attr);	/*	 *  Discover the end of the current time period.	 */	if (data->reset == NULL) {		radlog(L_ERR, "rlm_sqlcounter: 'reset' must be set.");		return -1;	}	now = time(NULL);	data->reset_time = 0;	if (find_next_reset(data,now) == -1)		return -1;	/*	 *  Discover the beginning of the current time period.	 */	data->last_reset = 0;	if (find_prev_reset(data,now) == -1)		return -1;	/*	 *	Register the counter comparison operation.	 */	paircompare_register(data->dict_attr, 0, sqlcounter_cmp, data);	*instance = data;	return 0;}/* *	Find the named user in this modules database.  Create the set *	of attribute-value pairs to check and reply with for this user *	from the database. The authentication code only needs to check *	the password, the rest is done here. */static int sqlcounter_authorize(void *instance, REQUEST *request){	rlm_sqlcounter_t *data = (rlm_sqlcounter_t *) instance;	int ret=RLM_MODULE_NOOP;	int counter=0;	int res=0;	DICT_ATTR *dattr;	VALUE_PAIR *key_vp, *check_vp;	VALUE_PAIR *reply_item;	char msg[128];	char querystr[MAX_QUERY_LEN];	char responsestr[MAX_QUERY_LEN];	/* quiet the compiler */	instance = instance;	request = request;	/*	 *	Before doing anything else, see if we have to reset	 *	the counters.	 */	if (data->reset_time && (data->reset_time <= request->timestamp)) {		/*		 *	Re-set the next time and prev_time for this counters range		 */		data->last_reset = data->reset_time;		find_next_reset(data,request->timestamp);	}	/*	 *      Look for the key.  User-Name is special.  It means	 *      The REAL username, after stripping.	 */	DEBUG2("rlm_sqlcounter: Entering module authorize code");	key_vp = (data->key_attr == PW_USER_NAME) ? request->username : pairfind(request->packet->vps, data->key_attr);	if (key_vp == NULL) {		DEBUG2("rlm_sqlcounter: Could not find Key value pair");		return ret;	}	/*	 *      Look for the check item	 */	if ((dattr = dict_attrbyname(data->check_name)) == NULL) {		return ret;	}	/* DEBUG2("rlm_sqlcounter: Found Check item attribute %d", dattr->attr); */	if ((check_vp= pairfind(request->config_items, dattr->attr)) == NULL) {		DEBUG2("rlm_sqlcounter: Could not find Check item value pair");		return ret;	}	/* first, expand %k, %b and %e in query */	sqlcounter_expand(querystr, MAX_QUERY_LEN, data->query, instance);	/* second, xlat any request attribs in query */	radius_xlat(responsestr, MAX_QUERY_LEN, querystr, request, NULL);	/* third, wrap query with sql module & expand */	sprintf(querystr, "%%{%%S:%s}", responsestr);	sqlcounter_expand(responsestr, MAX_QUERY_LEN, querystr, instance);	/* Finally, xlat resulting SQL query */	radius_xlat(querystr, MAX_QUERY_LEN, responsestr, request, NULL);	counter = atoi(querystr);	/*	 * Check if check item > counter	 */	res=check_vp->lvalue - counter;	if (res > 0) {		DEBUG2("rlm_sqlcounter: (Check item - counter) is greater than zero");		/*		 *	We are assuming that simultaneous-use=1. But		 *	even if that does not happen then our user		 *	could login at max for 2*max-usage-time Is		 *	that acceptable?		 */		/*		 *	User is allowed, but set Session-Timeout.		 *	Stolen from main/auth.c		 */		/*		 *	If we are near a reset then add the next		 *	limit, so that the user will not need to		 *	login again		 */		if (data->reset_time && (			res >= (data->reset_time - request->timestamp))) {			res += check_vp->lvalue;		}		if ((reply_item = pairfind(request->reply->vps, PW_SESSION_TIMEOUT)) != NULL) {			if (reply_item->lvalue > res)				reply_item->lvalue = res;		} else {			if ((reply_item = paircreate(PW_SESSION_TIMEOUT, PW_TYPE_INTEGER)) == NULL) {				radlog(L_ERR|L_CONS, "no memory");				return RLM_MODULE_NOOP;			}			reply_item->lvalue = res;			pairadd(&request->reply->vps, reply_item);		}		ret=RLM_MODULE_OK;		DEBUG2("rlm_sqlcounter: Authorized user %s, check_item=%d, counter=%d",				key_vp->strvalue,check_vp->lvalue,counter);		DEBUG2("rlm_sqlcounter: Sent Reply-Item for user %s, Type=Session-Timeout, value=%d",				key_vp->strvalue,reply_item->lvalue);	}	else{		char module_fmsg[MAX_STRING_LEN];		VALUE_PAIR *module_fmsg_vp;		DEBUG2("rlm_sqlcounter: (Check item - counter) is less than zero");		/*		 * User is denied access, send back a reply message		*/		sprintf(msg, "Your maximum %s usage time has been reached", data->reset);		reply_item=pairmake("Reply-Message", msg, T_OP_EQ);		pairadd(&request->reply->vps, reply_item);		snprintf(module_fmsg, sizeof(module_fmsg), "rlm_sqlcounter: Maximum %s usage time reached", data->reset);		module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);		pairadd(&request->packet->vps, module_fmsg_vp);		ret=RLM_MODULE_REJECT;		DEBUG2("rlm_sqlcounter: Rejected user %s, check_item=%d, counter=%d",				key_vp->strvalue,check_vp->lvalue,counter);	}	return ret;}static int sqlcounter_detach(void *instance){	rlm_sqlcounter_t *data = (rlm_sqlcounter_t *) instance;	paircompare_unregister(data->dict_attr, sqlcounter_cmp);	free(data->reset);	free(data->query);	free(data->check_name);	free(data->sqlmod_inst);	free(data->counter_name);	free(instance);	return 0;}/* *	The module name should be the only globally exported symbol. *	That is, everything else should be 'static'. * *	If the module needs to temporarily modify it's instantiation *	data, the type should be changed to RLM_TYPE_THREAD_UNSAFE. *	The server will then take care of ensuring that the module *	is single-threaded. */module_t rlm_sqlcounter = {	"SQL Counter",	RLM_TYPE_THREAD_SAFE,		/* type */	NULL,				/* initialization */	sqlcounter_instantiate,		/* instantiation */	{		NULL,			/* authentication */		sqlcounter_authorize, 	/* authorization */		NULL,			/* preaccounting */		NULL,			/* accounting */		NULL,			/* checksimul */		NULL,			/* pre-proxy */		NULL,			/* post-proxy */		NULL			/* post-auth */	},	sqlcounter_detach,		/* detach */	NULL,				/* destroy */};

⌨️ 快捷键说明

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