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

📄 rlm_perl.c

📁 freeradius-server-2.1.3.tar.gz安装源文件
💻 C
📖 第 1 页 / 共 2 页
字号:
 /* * rlm_perl.c * * Version:    $Id$ * *   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 2002,2006  The FreeRADIUS server project * Copyright 2002  Boian Jordanov <bjordanov@orbitel.bg> */#include <freeradius-devel/ident.h>RCSID("$Id$")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/modules.h>#ifdef DEBUG#undef DEBUG#endif#ifdef INADDR_ANY#undef INADDR_ANY#endif#include <EXTERN.h>#include <perl.h>#include <XSUB.h>#include <dlfcn.h>#include <semaphore.h>#ifdef __APPLE__extern char **environ;#endif/* *	Define a structure for our module configuration. * *	These variables do not need to be in a structure, but it's *	a lot cleaner to do so, and a pointer to the structure can *	be used as the instance handle. */typedef struct perl_inst {	/* Name of the perl module */	char	*module;	/* Name of the functions for each module method */	char	*func_authorize;	char	*func_authenticate;	char	*func_accounting;	char	*func_start_accounting;	char	*func_stop_accounting;	char	*func_preacct;	char	*func_checksimul;	char	*func_detach;	char	*func_xlat;	char	*func_pre_proxy;	char	*func_post_proxy;	char	*func_post_auth;	char	*xlat_name;	char	*perl_flags;	PerlInterpreter *perl;} PERL_INST;/* *	A mapping of configuration file names to internal variables. * *	Note that the string is dynamically allocated, so it MUST *	be freed.  When the configuration file parse re-reads the string, *	it free's the old one, and strdup's the new one, placing the pointer *	to the strdup'd string into 'config.string'.  This gets around *	buffer over-flows. */static const CONF_PARSER module_config[] = {	{ "module",  PW_TYPE_FILENAME,	  offsetof(PERL_INST,module), NULL,  "module"},	{ "func_authorize", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_authorize), NULL, "authorize"},	{ "func_authenticate", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_authenticate), NULL, "authenticate"},	{ "func_accounting", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_accounting), NULL, "accounting"},	{ "func_preacct", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_preacct), NULL, "preacct"},	{ "func_checksimul", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_checksimul), NULL, "checksimul"},	{ "func_detach", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_detach), NULL, "detach"},	{ "func_xlat", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_xlat), NULL, "xlat"},	{ "func_pre_proxy", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_pre_proxy), NULL, "pre_proxy"},	{ "func_post_proxy", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_post_proxy), NULL, "post_proxy"},	{ "func_post_auth", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_post_auth), NULL, "post_auth"},	{ "perl_flags", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,perl_flags), NULL, NULL},	{ "func_start_accounting", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_start_accounting), NULL, NULL},	{ "func_stop_accounting", PW_TYPE_STRING_PTR,	  offsetof(PERL_INST,func_stop_accounting), NULL, NULL},	{ NULL, -1, 0, NULL, NULL }		/* end the list */};/* * man perlembed */EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);#ifdef USE_ITHREADS#define dl_librefs "DynaLoader::dl_librefs"#define dl_modules "DynaLoader::dl_modules"static void rlm_perl_clear_handles(pTHX){	AV *librefs = get_av(dl_librefs, FALSE);	if (librefs) {		av_clear(librefs);	}}static void **rlm_perl_get_handles(pTHX){	I32 i;	AV *librefs = get_av(dl_librefs, FALSE);	AV *modules = get_av(dl_modules, FALSE);	void **handles;	if (!librefs) {		radlog(L_ERR,		   "Could not get @%s for unloading.\n",		   dl_librefs);		return NULL;	}	if (!(AvFILL(librefs) >= 0)) {		return NULL;	}	handles = (void **)rad_malloc(sizeof(void *) * (AvFILL(librefs)+2));	for (i=0; i<=AvFILL(librefs); i++) {		void *handle;		SV *handle_sv = *av_fetch(librefs, i, FALSE);		if(!handle_sv) {		    radlog(L_ERR,			       "Could not fetch $%s[%d]!\n",			       dl_librefs, (int)i);		    continue;		}		handle = (void *)SvIV(handle_sv);		if (handle) {		    handles[i] = handle;		}	}	av_clear(modules);	av_clear(librefs);	handles[i] = (void *)0;	return handles;}static void rlm_perl_close_handles(void **handles){	int i;	if (!handles) {		return;	}	for (i=0; handles[i]; i++) {		radlog(L_DBG, "close %p\n", handles[i]);		dlclose(handles[i]);	}	free(handles);}static void rlm_perl_destruct(PerlInterpreter *perl){	char **orig_environ = NULL;	dTHXa(perl);	PERL_SET_CONTEXT(perl);	PL_perl_destruct_level = 2;	PL_origenviron = environ;	{		dTHXa(perl);	}	/*	 * FIXME: This shouldn't happen	 *	 */	while (PL_scopestack_ix > 1 ){		LEAVE;	}	perl_destruct(perl);	perl_free(perl);	if (orig_environ) {		environ = orig_environ;	}}static void rlm_destroy_perl(PerlInterpreter *perl){	void	**handles;	dTHXa(perl);	PERL_SET_CONTEXT(perl);	handles = rlm_perl_get_handles(aTHX);	rlm_perl_destruct(perl);	rlm_perl_close_handles(handles);}static pthread_key_t  rlm_perl_key;static pthread_once_t rlm_perl_once = PTHREAD_ONCE_INIT;/* Create Key */static void rlm_perl_make_key(void){	pthread_key_create(&rlm_perl_key, rlm_destroy_perl);}static PerlInterpreter *rlm_perl_clone(PerlInterpreter *perl){	PerlInterpreter *interp;	UV clone_flags = 0;	PERL_SET_CONTEXT(perl);	pthread_once(&rlm_perl_once, rlm_perl_make_key);	interp = pthread_getspecific(rlm_perl_key);	if (interp) return interp;	interp = perl_clone(perl, clone_flags);	{		dTHXa(interp);	}#if PERL_REVISION >= 5 && PERL_VERSION <8	call_pv("CLONE",0);#endif	ptr_table_free(PL_ptr_table);	PL_ptr_table = NULL;	PERL_SET_CONTEXT(aTHX);    	rlm_perl_clear_handles(aTHX);	pthread_setspecific(rlm_perl_key, interp);	fprintf(stderr, "GOT CLONE %d %p\n", pthread_self(), interp);	return interp;}#endifstatic void xs_init(pTHX){	char *file = __FILE__;	/* DynaLoader is a special case */	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);}/* * * This is wrapper for radlog * Now users can call radiusd::radlog(level,msg) wich is the same * calling radlog from C code. * Boyan */static XS(XS_radiusd_radlog){       dXSARGS;       if (items !=2)	       croak("Usage: radiusd::radlog(level, message)");       {	       int     level;	       char    *msg;	       level = (int) SvIV(ST(0));	       msg   = (char *) SvPV(ST(1), PL_na);	       /*		*	Because 'msg' is a 'char *', we don't want '%s', etc.		*	in it to give us printf-style vulnerabilities.		*/	       radlog(level, "rlm_perl: %s", msg);	}       XSRETURN_NO;}/* * The xlat function */static size_t perl_xlat(void *instance, REQUEST *request, char *fmt, char *out,			size_t freespace, RADIUS_ESCAPE_STRING func){	PERL_INST	*inst= (PERL_INST *) instance;	PerlInterpreter *perl;	char		params[1024], *ptr, *tmp;	int		count;	size_t		ret = 0;	STRLEN		n_a;	/*	 * Do an xlat on the provided string (nice recursive operation).	*/	if (!radius_xlat(params, sizeof(params), fmt, request, func)) {		radlog(L_ERR, "rlm_perl: xlat failed.");		return 0;	}#ifndef WITH_ITHREADS	perl = inst->perl;#else	perl = rlm_perl_clone(inst->perl);	{	  dTHXa(perl);	}#endif	PERL_SET_CONTEXT(perl);	{	dSP;	ENTER;SAVETMPS;	ptr = strtok(params, " ");	PUSHMARK(SP);	while (ptr != NULL) {		XPUSHs(sv_2mortal(newSVpv(ptr,0)));		ptr = strtok(NULL, " ");	}	PUTBACK;	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 ;	}	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	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();

⌨️ 快捷键说明

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