📄 rlm_python.c
字号:
/* * rlm_python.c * * * 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 2002 Miguel A.L. Paraz <mparaz@mparaz.com> * Copyright 2002 Imperium Technology, Inc. */#include <Python.h>#include "autoconf.h"#include "libradius.h"#include <stdio.h>#include <stdlib.h>#include "radiusd.h"#include "modules.h"#include "conffile.h"#define Pyx_BLOCK_THREADS {PyGILState_STATE __gstate = PyGILState_Ensure();#define Pyx_UNBLOCK_THREADS PyGILState_Release(__gstate);}static const char rcsid[] = "$Id: rlm_python.c,v 1.6.4.1 2007/03/05 14:15:28 pnixon Exp $";/* * 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. */struct rlm_python_t { char *mod_instantiate; char *mod_authorize; char *mod_authenticate; char *mod_preacct; char *mod_accounting; char *mod_checksimul; char *mod_detach; /* Names of functions */ char *func_instantiate; char *func_authorize; char *func_authenticate; char *func_preacct; char *func_accounting; char *func_checksimul; char *func_detach; PyObject *pModule_instantiate; PyObject *pModule_authorize; PyObject *pModule_authenticate; PyObject *pModule_preacct; PyObject *pModule_accounting; PyObject *pModule_checksimul; PyObject *pModule_detach; /* Functions */ PyObject *pFunc_instantiate; PyObject *pFunc_authorize; PyObject *pFunc_authenticate; PyObject *pFunc_preacct; PyObject *pFunc_accounting; PyObject *pFunc_checksimul; PyObject *pFunc_detach;};/* * 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 CONF_PARSER module_config[] = { { "mod_instantiate", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, mod_instantiate), NULL, NULL}, { "func_instantiate", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, func_instantiate), NULL, NULL}, { "mod_authorize", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, mod_authorize), NULL, NULL}, { "func_authorize", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, func_authorize), NULL, NULL}, { "mod_authenticate", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, mod_authenticate), NULL, NULL}, { "func_authenticate", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, func_authenticate), NULL, NULL}, { "mod_preacct", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, mod_preacct), NULL, NULL}, { "func_preacct", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, func_preacct), NULL, NULL}, { "mod_accounting", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, mod_accounting), NULL, NULL}, { "func_accounting", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, func_accounting), NULL, NULL}, { "mod_checksimul", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, mod_checksimul), NULL, NULL}, { "func_checksimul", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, func_checksimul), NULL, NULL}, { "mod_detach", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, mod_detach), NULL, NULL}, { "func_detach", PW_TYPE_STRING_PTR, offsetof(struct rlm_python_t, func_detach), NULL, NULL}, { NULL, -1, 0, NULL, NULL } /* end the list */};static struct { const char* name; int value;} radiusd_constants[] = { { "L_DBG", L_DBG }, { "L_AUTH", L_AUTH }, { "L_INFO", L_INFO }, { "L_ERR", L_ERR }, { "L_PROXY", L_PROXY }, { "L_CONS", L_CONS }, { "RLM_MODULE_REJECT", RLM_MODULE_REJECT }, { "RLM_MODULE_FAIL", RLM_MODULE_FAIL }, { "RLM_MODULE_OK", RLM_MODULE_OK }, { "RLM_MODULE_HANDLED", RLM_MODULE_HANDLED }, { "RLM_MODULE_INVALID", RLM_MODULE_INVALID }, { "RLM_MODULE_USERLOCK",RLM_MODULE_USERLOCK }, { "RLM_MODULE_NOTFOUND",RLM_MODULE_NOTFOUND }, { "RLM_MODULE_NOOP", RLM_MODULE_NOOP }, { "RLM_MODULE_UPDATED", RLM_MODULE_UPDATED }, { "RLM_MODULE_NUMCODES",RLM_MODULE_NUMCODES }, { NULL, 0 },};/* Let assume that radiusd module is only one since we have only one intepreter */static PyObject *radiusd_module = NULL;/* * radiusd Python functions *//* radlog wrapper */static PyObject *python_radlog(const PyObject *module, PyObject *args) { int status; char *msg; if (!PyArg_ParseTuple(args, "is", &status, &msg)) { return NULL; } radlog(status, "%s", msg); Py_INCREF(Py_None); return Py_None;}static PyMethodDef radiusd_methods[] = { {"radlog", (PyCFunction) &python_radlog, METH_VARARGS, "freeradius radlog()."}, {NULL, NULL, 0, NULL}};static void python_error() { PyObject *pType = NULL; PyObject *pValue = NULL; PyObject *pTraceback = NULL; PyObject *pStr1 = NULL; PyObject *pStr2 = NULL; Pyx_BLOCK_THREADS PyErr_Fetch(&pType, &pValue, &pTraceback); if (pType == NULL || pValue == NULL) goto failed; if ((pStr1 = PyObject_Str(pType)) == NULL || (pStr2 = PyObject_Str(pValue)) == NULL) goto failed; radlog(L_ERR, "rlm_python:EXCEPT:%s: %s", PyString_AsString(pStr1), PyString_AsString(pStr2));failed: Py_XDECREF(pStr1); Py_XDECREF(pStr2); Py_XDECREF(pType); Py_XDECREF(pValue); Py_XDECREF(pTraceback); Pyx_UNBLOCK_THREADS}static int python_init(){ int i; Py_SetProgramName("radiusd"); Py_Initialize(); PyEval_InitThreads(); // This also grabs a lock if ((radiusd_module = Py_InitModule3("radiusd", radiusd_methods, "FreeRADIUS Module.")) == NULL) goto failed; for (i = 0; radiusd_constants[i].name; i++) if ((PyModule_AddIntConstant(radiusd_module, radiusd_constants[i].name, radiusd_constants[i].value)) < 0) goto failed; PyEval_ReleaseLock(); // Drop lock grabbed by InitThreads radlog(L_DBG, "python_init done"); return 0;failed: python_error(); Py_Finalize(); return -1;}static int python_destroy() { Pyx_BLOCK_THREADS Py_XDECREF(radiusd_module); Py_Finalize(); Pyx_UNBLOCK_THREADS return 0;}static void python_vptuple(VALUE_PAIR **vpp, PyObject *pValue, const char *funcname) { int i; int tuplesize; VALUE_PAIR *vp; /* If the Python function gave us None for the tuple, then just return. */ if (pValue == Py_None) return; if (!PyTuple_CheckExact(pValue)) { radlog(L_ERR, "rlm_python:%s: non-tuple passed", funcname); return; } /* Get the tuple tuplesize. */ tuplesize = PyTuple_GET_SIZE(pValue); for (i = 0; i < tuplesize; i++) { PyObject *pTupleElement = PyTuple_GET_ITEM(pValue, i); PyObject *pStr1; PyObject *pStr2; int pairsize; const char *s1; const char *s2; if (!PyTuple_CheckExact(pTupleElement)) { radlog(L_ERR, "rlm_python:%s: tuple element %d is not a tuple", funcname, i); continue; } /* Check if it's a pair */ if ((pairsize = PyTuple_GET_SIZE(pTupleElement)) != 2) { radlog(L_ERR, "rlm_python:%s: tuple element %d is a tuple of size %d. Must be 2", funcname, i, pairsize); continue; } pStr1 = PyTuple_GET_ITEM(pTupleElement, 0); pStr2 = PyTuple_GET_ITEM(pTupleElement, 1); if ((!PyString_CheckExact(pStr1)) || (!PyString_CheckExact(pStr2))) { radlog(L_ERR, "rlm_python:%s: tuple element %d must be as (str, str)", funcname, i); continue; } s1 = PyString_AsString(pStr1); s2 = PyString_AsString(pStr2); /* xxx Might need to support other T_OP */ vp = pairmake(s1, s2, T_OP_EQ); if (vp != NULL) { pairadd(vpp, vp); radlog(L_DBG, "rlm_python:%s: '%s' = '%s'", funcname, s1, s2); } else { radlog(L_DBG, "rlm_python:%s: Failed: '%s' = '%s'", funcname, s1, s2); } }}/* This is the core Python function that the others wrap around. * Pass the value-pair print strings in a tuple. * xxx We're not checking the errors. If we have errors, what do we do? */static int python_function(REQUEST *request, PyObject *pFunc, const char *funcname) { char buf[1024]; VALUE_PAIR *vp; PyObject *pRet = NULL; PyObject *pArgs = NULL; int tuplelen; int ret; PyGILState_STATE gstate; /* Return with "OK, continue" if the function is not defined. */ if (pFunc == NULL) return RLM_MODULE_OK; /* Default return value is "OK, continue" */ ret = RLM_MODULE_OK; /* We will pass a tuple containing (name, value) tuples * We can safely use the Python function to build up a tuple, * since the tuple is not used elsewhere. * * Determine the size of our tuple by walking through the packet. * If request is NULL, pass None. */ tuplelen = 0; if (request != NULL) { for (vp = request->packet->vps; vp; vp = vp->next)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -