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

📄 rlm_perl.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	count = call_pv(inst->func_xlat, G_SCALAR | G_EVAL);	SPAGAIN;	if (SvTRUE(ERRSV)) {		radlog(L_ERR, "rlm_perl: perl_xlat exit %s\n",		       SvPV(ERRSV,n_a));		POPs ;	} else if (count > 0) {		tmp = POPp;		strlcpy(out, tmp, freespace);		ret = strlen(out);		radlog(L_DBG,"rlm_perl: Len is %d , out is %s freespace is %d",		       ret, out,freespace);	}	PUTBACK ;	FREETMPS ;	LEAVE ;	}#ifdef USE_ITHREADS	pool_release(handle, instance);#endif	return ret;}/* *	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. * *	Boyan: *	Setup a hashes wich we will use later *	parse a module and give him a chance to live * */static int perl_instantiate(CONF_SECTION *conf, void **instance){	PERL_INST       *inst = (PERL_INST *) instance;	HV		*rad_reply_hv;	HV		*rad_check_hv;	HV		*rad_config_hv;	HV		*rad_request_hv;	HV		*rad_request_proxy_hv;	HV		*rad_request_proxy_reply_hv;	AV		*end_AV;	char *embed[4];	const char *xlat_name;	int exitstatus = 0, argc=0;	/*	 *	Set up a storage area for instance data	 */	inst = rad_malloc(sizeof(PERL_INST));	memset(inst, 0, sizeof(PERL_INST));	/*	 *	If the configuration parameters can't be parsed, then	 *	fail.	 */	if (cf_section_parse(conf, inst, module_config) < 0) {		free(inst);		return -1;	}	embed[0] = NULL;	if (inst->perl_flags) {		embed[1] = inst->perl_flags;		embed[2] = inst->module;		embed[3] = "0";		argc = 4;	} else {		embed[1] = inst->module;		embed[2] = "0";		argc = 3;	}#ifdef USE_ITHREADS	inst->perl = interp;	if ((inst->perl = perl_alloc()) == NULL) {		radlog(L_DBG, "rlm_perl: No memory for allocating new perl !");		return (-1);	}	perl_construct(inst->perl);	PL_perl_destruct_level = 2;	{	dTHXa(inst->perl);	}	PERL_SET_CONTEXT(inst->perl);#else	if ((inst->perl = perl_alloc()) == NULL) {		radlog(L_ERR, "rlm_perl: No memory for allocating new perl !");		return -1;	}	perl_construct(inst->perl);#endif#if PERL_REVISION >= 5 && PERL_VERSION >=8	PL_exit_flags |= PERL_EXIT_DESTRUCT_END;#endif	exitstatus = perl_parse(inst->perl, xs_init, argc, embed, NULL);	end_AV = PL_endav;	PL_endav = Nullav;	if(!exitstatus) {		exitstatus = perl_run(inst->perl);	} else {		radlog(L_ERR,"rlm_perl: perl_parse failed: %s not found or has syntax errors. \n", inst->module);		return (-1);	}	PL_endav = end_AV;        newXS("radiusd::radlog",XS_radiusd_radlog, "rlm_perl.c");	rad_reply_hv = newHV();	rad_check_hv = newHV();	rad_config_hv = newHV();	rad_request_hv = newHV();	rad_request_proxy_hv = newHV();	rad_request_proxy_reply_hv = newHV();	rad_reply_hv = get_hv("RAD_REPLY",1);        rad_check_hv = get_hv("RAD_CHECK",1);	rad_config_hv = get_hv("RAD_CONFIG",1);        rad_request_hv = get_hv("RAD_REQUEST",1);	rad_request_proxy_hv = get_hv("RAD_REQUEST_PROXY",1);	rad_request_proxy_reply_hv = get_hv("RAD_REQUEST_PROXY_REPLY",1);	xlat_name = cf_section_name2(conf);	if (xlat_name == NULL)		xlat_name = cf_section_name1(conf);	if (xlat_name){		inst->xlat_name = strdup(xlat_name);		xlat_register(xlat_name, perl_xlat, inst);	}#ifdef USE_ITHREADS	if ((init_pool(conf, inst)) == -1) {		radlog(L_ERR,"Couldn't init a pool of perl clones. Exiting");		return -1;	}#endif	*instance = inst;	return 0;}/* *  	get the vps and put them in perl hash *  	If one VP have multiple values it is added as array_ref *  	Example for this is Cisco-AVPair that holds multiple values. *  	Which will be available as array_ref in $RAD_REQUEST{'Cisco-AVPair'} */static void perl_store_vps(VALUE_PAIR *vp, HV *rad_hv){        VALUE_PAIR	*nvp, *vpa, *vpn;	AV		*av;	char            buffer[1024];	int		attr, len;	hv_undef(rad_hv);	nvp = paircopy(vp);	while (nvp != NULL) {		attr = nvp->attribute;		vpa = paircopy2(nvp,attr);		if (vpa->next) {			av = newAV();			vpn = vpa;			while (vpn) {				len = vp_prints_value(buffer, sizeof(buffer),						vpn, FALSE);				av_push(av, newSVpv(buffer, len));				vpn = vpn->next;			}			hv_store(rad_hv, nvp->name, strlen(nvp->name),					newRV_noinc((SV *) av), 0);		} else {			len = vp_prints_value(buffer, sizeof(buffer),					vpa, FALSE);			hv_store(rad_hv, vpa->name, strlen(vpa->name),					newSVpv(buffer, len), 0);		}		pairfree(&vpa);		vpa = nvp; while ((vpa != NULL) && (vpa->attribute == attr))			vpa = vpa->next;		pairdelete(&nvp, attr);		nvp = vpa;	}}/* * *     Verify that a Perl SV is a string and save it in FreeRadius *     Value Pair Format * */static int pairadd_sv(VALUE_PAIR **vp, char *key, SV *sv, int operator) {       char            *val;       VALUE_PAIR      *vpp;       if (SvOK(sv)) {               val = SvPV_nolen(sv);               vpp = pairmake(key, val, operator);               if (vpp != NULL) {                       pairadd(vp, vpp);                       radlog(L_DBG,                         "rlm_perl: Added pair %s = %s", key, val);		       return 1;               } else {                       radlog(L_DBG,                         "rlm_perl: ERROR: Failed to create pair %s = %s",                         key, val);               }        }       return 0;}/*  *     Boyan :  *     Gets the content from hashes  */static int get_hv_content(HV *my_hv, VALUE_PAIR **vp){       SV		*res_sv, **av_sv;       AV		*av;       char		*key;       I32		key_len, len, i, j;       int		ret=0;       *vp = NULL;       for (i = hv_iterinit(my_hv); i > 0; i--) {               res_sv = hv_iternextsv(my_hv,&key,&key_len);               if (SvROK(res_sv) && (SvTYPE(SvRV(res_sv)) == SVt_PVAV)) {                       av = (AV*)SvRV(res_sv);                       len = av_len(av);                       for (j = 0; j <= len; j++) {                               av_sv = av_fetch(av, j, 0);                               ret = pairadd_sv(vp, key, *av_sv, T_OP_ADD) + ret;                       }               } else ret = pairadd_sv(vp, key, res_sv, T_OP_EQ) + ret;        }        return ret;}/* * 	Call the function_name inside the module * 	Store all vps in hashes %RAD_CHECK %RAD_REPLY %RAD_REQUEST * */static int rlmperl_call(void *instance, REQUEST *request, char *function_name){	PERL_INST	*inst = instance;	VALUE_PAIR	*vp;	int		exitstatus=0, count;	STRLEN		n_a;	HV		*rad_reply_hv;	HV		*rad_check_hv;	HV		*rad_config_hv;	HV		*rad_request_hv;	HV		*rad_request_proxy_hv;	HV		*rad_request_proxy_reply_hv;#ifdef USE_ITHREADS	POOL_HANDLE	*handle;	if ((handle = pool_pop(instance)) == NULL) {		return RLM_MODULE_FAIL;	}	radlog(L_DBG,"found interpetator at address 0x%lx",(unsigned long) handle->clone);	{	dTHXa(handle->clone);	PERL_SET_CONTEXT(handle->clone);	}#else	PERL_SET_CONTEXT(inst->perl);	radlog(L_DBG,"Using perl at 0x%lx",(unsigned long) inst->perl);#endif	{	dSP;	ENTER;	SAVETMPS;	/*	 *	Radius has told us to call this function, but none	 *	is defined.	 */	if (!function_name) {		return RLM_MODULE_FAIL;	}	rad_reply_hv = get_hv("RAD_REPLY",1);	rad_check_hv = get_hv("RAD_CHECK",1);	rad_config_hv = get_hv("RAD_CONFIG",1);	rad_request_hv = get_hv("RAD_REQUEST",1);	rad_request_proxy_hv = get_hv("RAD_REQUEST_PROXY",1);	rad_request_proxy_reply_hv = get_hv("RAD_REQUEST_PROXY_REPLY",1);	perl_store_vps(request->reply->vps, rad_reply_hv);	perl_store_vps(request->config_items, rad_check_hv);	perl_store_vps(request->packet->vps, rad_request_hv);	perl_store_vps(request->config_items, rad_config_hv);	if (request->proxy != NULL) {		perl_store_vps(request->proxy->vps, rad_request_proxy_hv);	} else {		hv_undef(rad_request_proxy_hv);	}	if (request->proxy_reply !=NULL) {		perl_store_vps(request->proxy_reply->vps, rad_request_proxy_reply_hv);	} else {		hv_undef(rad_request_proxy_reply_hv);	}	PUSHMARK(SP);	/*	* This way %RAD_xx can be pushed onto stack as sub parameters.	* XPUSHs( newRV_noinc((SV *)rad_request_hv) );	* XPUSHs( newRV_noinc((SV *)rad_reply_hv) );	* XPUSHs( newRV_noinc((SV *)rad_check_hv) );	* PUTBACK;	*/	count = call_pv(function_name, G_SCALAR | G_EVAL | G_NOARGS);	SPAGAIN;	if (SvTRUE(ERRSV)) {		radlog(L_ERR, "rlm_perl: perl_embed:: module = %s , func = %s exit status= %s\n",		       inst->module,		       function_name, SvPV(ERRSV,n_a));		POPs;	}	if (count == 1) {		exitstatus = POPi;		if (exitstatus >= 100 || exitstatus < 0) {			exitstatus = RLM_MODULE_FAIL;		}	}	PUTBACK;	FREETMPS;	LEAVE;	vp = NULL;	if ((get_hv_content(rad_request_hv, &vp)) > 0 ) {		pairfree(&request->packet->vps);		request->packet->vps = vp;		vp = NULL;		/*		 *	Update cached copies		 */		request->username = pairfind(request->packet->vps,					     PW_USER_NAME);		request->password = pairfind(request->packet->vps,					     PW_USER_PASSWORD);		if (!request->password)			request->password = pairfind(request->packet->vps,						     PW_CHAP_PASSWORD);	}	if ((get_hv_content(rad_reply_hv, &vp)) > 0 ) {		pairfree(&request->reply->vps);		request->reply->vps = vp;		vp = NULL;	}	if ((get_hv_content(rad_check_hv, &vp)) > 0 ) {		pairfree(&request->config_items);		request->config_items = vp;		vp = NULL;	}	if (request->proxy &&	    (get_hv_content(rad_request_proxy_hv, &vp) > 0)) {		pairfree(&request->proxy->vps);		request->proxy->vps = vp;		vp = NULL;	}	if (request->proxy_reply &&	    (get_hv_content(rad_request_proxy_reply_hv, &vp) > 0)) {		pairfree(&request->proxy_reply->vps);		request->proxy_reply->vps = vp;		vp = NULL;	}	}#ifdef USE_ITHREADS	pool_release(handle,instance);	radlog(L_DBG,"Unreserve perl at address 0x%lx", (unsigned long) handle->clone);#endif	return exitstatus;}/* *	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 perl_authorize(void *instance, REQUEST *request){	return rlmperl_call(instance, request,			    ((PERL_INST *)instance)->func_authorize);}/* *	Authenticate the user with the given password. */static int perl_authenticate(void *instance, REQUEST *request){	return rlmperl_call(instance, request,			    ((PERL_INST *)instance)->func_authenticate);}/* *	Massage the request before recording it or proxying it */static int perl_preacct(void *instance, REQUEST *request){	return rlmperl_call(instance, request,			    ((PERL_INST *)instance)->func_preacct);}/* *	Write accounting information to this modules database. */static int perl_accounting(void *instance, REQUEST *request){	VALUE_PAIR	*pair;	int 		acctstatustype=0;	if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) {		acctstatustype = pair->vp_integer;        } else {                radlog(L_ERR, "Invalid Accounting Packet");                return RLM_MODULE_INVALID;        }	switch (acctstatustype) {		case PW_STATUS_START:			if (((PERL_INST *)instance)->func_start_accounting) {				return rlmperl_call(instance, request,					    ((PERL_INST *)instance)->func_start_accounting);			} else {				return rlmperl_call(instance, request,					    ((PERL_INST *)instance)->func_accounting);			}			break;		case PW_STATUS_STOP:			if (((PERL_INST *)instance)->func_stop_accounting) {				return rlmperl_call(instance, request,					    ((PERL_INST *)instance)->func_stop_accounting);			} else {				return rlmperl_call(instance, request,					    ((PERL_INST *)instance)->func_accounting);			}			break;		default:			return rlmperl_call(instance, request,					    ((PERL_INST *)instance)->func_accounting);	}}/* *	Check for simultaneouse-use */static int perl_checksimul(void *instance, REQUEST *request){	return rlmperl_call(instance, request,			((PERL_INST *)instance)->func_checksimul);}/* *	Pre-Proxy request */static int perl_pre_proxy(void *instance, REQUEST *request){	return rlmperl_call(instance, request,			((PERL_INST *)instance)->func_pre_proxy);}/* *	Post-Proxy request */static int perl_post_proxy(void *instance, REQUEST *request){	return rlmperl_call(instance, request,			((PERL_INST *)instance)->func_post_proxy);}/* *	Pre-Auth request */static int perl_post_auth(void *instance, REQUEST *request){	return rlmperl_call(instance, request,			((PERL_INST *)instance)->func_post_auth);}/* * Detach a instance give a chance to a module to make some internal setup ... */static int perl_detach(void *instance){	PERL_INST	*inst = (PERL_INST *) instance;	int 		exitstatus = 0, count = 0;#ifdef USE_ITHREADS	POOL_HANDLE	*handle, *tmp, *tmp2;	MUTEX_LOCK(&inst->perl_pool->mutex);	inst->perl_pool->detach = yes;	MUTEX_UNLOCK(&inst->perl_pool->mutex);	for (handle = inst->perl_pool->head; handle != NULL; handle = handle->next) {		radlog(L_DBG,"Detach perl 0x%lx", (unsigned long) handle->clone);		/*		 * Wait until clone becomes idle		 */		MUTEX_LOCK(&handle->lock);		/*		 * Give a clones chance to run detach function		 */		{		dTHXa(handle->clone);		PERL_SET_CONTEXT(handle->clone);		{		dSP; ENTER; SAVETMPS; PUSHMARK(SP);		count = call_pv(inst->func_detach, G_SCALAR | G_EVAL );		SPAGAIN;		if (count == 1) {			exitstatus = POPi;			/*			 * FIXME: bug in perl			 *			 */			if (exitstatus >= 100 || exitstatus < 0) {				exitstatus = RLM_MODULE_FAIL;			}		}		PUTBACK;		FREETMPS;		LEAVE;		radlog(L_DBG,"detach at 0x%lx returned status %d",				(unsigned long) handle->clone, exitstatus);		}		}		MUTEX_UNLOCK(&handle->lock);	}	/*	 * Free handles	 */	for (tmp = inst->perl_pool->head; tmp !=NULL  ; tmp = tmp2) {		tmp2 = tmp->next;		radlog(L_DBG,"rlm_perl:: Destroy perl");		rlm_perl_destruct(tmp->clone);		delete_pool_handle(tmp,inst);	}	{	dTHXa(inst->perl);#endif /* USE_ITHREADS */	PERL_SET_CONTEXT(inst->perl);	{	dSP; ENTER; SAVETMPS;	PUSHMARK(SP);	count = call_pv(inst->func_detach, G_SCALAR | G_EVAL );	SPAGAIN;	if (count == 1) {		exitstatus = POPi;		if (exitstatus >= 100 || exitstatus < 0) {			exitstatus = RLM_MODULE_FAIL;		}	}	PUTBACK;	FREETMPS;	LEAVE;	}#ifdef USE_ITHREADS	}#endif	xlat_unregister(inst->xlat_name, perl_xlat);	free(inst->xlat_name);#ifdef USE_ITHREADS	free(inst->perl_pool->head);	free(inst->perl_pool->tail);	MUTEX_DESTROY(&inst->perl_pool->mutex);	free(inst->perl_pool);	rlm_perl_destruct(inst->perl);#else	perl_destruct(inst->perl);	perl_free(inst->perl);#endif	free(inst);	return exitstatus;}/* *	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_perl = {	RLM_MODULE_INIT,	"perl",				/* Name */#ifdef USE_ITHREADS	RLM_TYPE_THREAD_SAFE,		/* type */#else	RLM_TYPE_THREAD_UNSAFE,#endif	perl_instantiate,		/* instantiation */	perl_detach,			/* detach */	{		perl_authenticate,	/* authenticate */		perl_authorize,		/* authorize */		perl_preacct,		/* preacct */		perl_accounting,	/* accounting */		perl_checksimul,      	/* check simul */		perl_pre_proxy,		/* pre-proxy */		perl_post_proxy,	/* post-proxy */		perl_post_auth		/* post-auth */	},};

⌨️ 快捷键说明

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