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

📄 rlm_perl.c

📁 freeradius-server-2.1.3.tar.gz安装源文件
💻 C
📖 第 1 页 / 共 2 页
字号:
	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);	}	*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	PerlInterpreter *interp;	interp = rlm_perl_clone(inst->perl);	{	  dTHXa(interp);	  PERL_SET_CONTEXT(interp);	}#else	PERL_SET_CONTEXT(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;	}	}	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;#if 0	/*	 *	FIXME: Call this in the destruct 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;		}		}#endif	{	dTHXa(inst->perl);	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;	}	}	xlat_unregister(inst->xlat_name, perl_xlat);	free(inst->xlat_name);#ifdef USE_ITHREADS	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 + -