📄 rlm_python.c
字号:
tuplelen++; } gstate = PyGILState_Ensure(); if (tuplelen == 0) { Py_INCREF(Py_None); pArgs = Py_None; } else { int i = 0; if ((pArgs = PyTuple_New(tuplelen)) == NULL) goto failed; for (vp = request->packet->vps; vp != NULL; vp = vp->next, i++) { PyObject *pPair; PyObject *pStr; /* The inside tuple has two only: */ if ((pPair = PyTuple_New(2)) == NULL) goto failed; /* Put the tuple inside the container */ PyTuple_SET_ITEM(pArgs, i, pPair); /* The name. logic from vp_prints, lib/print.c */ if (vp->flags.has_tag) snprintf(buf, sizeof(buf), "%s:%d", vp->name, vp->flags.tag); else strcpy(buf, vp->name); if ((pStr = PyString_FromString(buf)) == NULL) goto failed; PyTuple_SET_ITEM(pPair, 0, pStr); vp_prints_value(buf, sizeof(buf), vp, 1); if ((pStr = PyString_FromString(buf)) == NULL) goto failed; PyTuple_SET_ITEM(pPair, 1, pStr); } } /* Call Python function. */ pRet = PyObject_CallFunctionObjArgs(pFunc, pArgs, NULL); if (pRet == NULL) goto failed; if (request == NULL) goto okay; /* The function returns either: * 1. tuple containing the integer return value, * then the integer reply code (or None to not set), * then the string tuples to build the reply with. * (returnvalue, (p1, s1), (p2, s2)) * * 2. the function return value alone * * 3. None - default return value is set * * xxx This code is messy! */ if (PyTuple_CheckExact(pRet)) { PyObject *pTupleInt; if (PyTuple_GET_SIZE(pRet) != 3) { radlog(L_ERR, "rlm_python:%s: tuple must be (return, replyTuple, configTuple)", funcname); goto failed; } pTupleInt = PyTuple_GET_ITEM(pRet, 0); if (!PyInt_CheckExact(pTupleInt)) { radlog(L_ERR, "rlm_python:%s: first tuple element not an integer", funcname); goto failed; } /* Now have the return value */ ret = PyInt_AsLong(pTupleInt); /* Reply item tuple */ python_vptuple(&request->reply->vps, PyTuple_GET_ITEM(pRet, 1), funcname); /* Config item tuple */ python_vptuple(&request->config_items, PyTuple_GET_ITEM(pRet, 2), funcname); } else if (PyInt_CheckExact(pRet)) { /* Just an integer */ ret = PyInt_AsLong(pRet); } else if (pRet == Py_None) { /* returned 'None', return value defaults to "OK, continue." */ ret = RLM_MODULE_OK; } else { /* Not tuple or None */ radlog(L_ERR, "rlm_python:%s: function did not return a tuple or None", funcname); goto failed; } if (ret == RLM_MODULE_REJECT && request != NULL) pairfree(&request->reply->vps);okay: Py_DECREF(pArgs); Py_DECREF(pRet); PyGILState_Release(gstate); return ret;failed: python_error(); Py_XDECREF(pArgs); Py_XDECREF(pRet); PyGILState_Release(gstate); return -1;}/* * Import a user module and load a function from it */static int python_load_function(char *module, const char *func, PyObject **pModule, PyObject **pFunc) { const char funcname[] = "python_load_function"; PyGILState_STATE gstate; *pFunc = NULL; *pModule = NULL; gstate = PyGILState_Ensure(); if (module != NULL && func != NULL) { if ((*pModule = PyImport_ImportModule(module)) == NULL) { radlog(L_ERR, "rlm_python:%s: module '%s' is not found", funcname, module); goto failed; } if ((*pFunc = PyObject_GetAttrString(*pModule, func)) == NULL) { radlog(L_ERR, "rlm_python:%s: function '%s.%s' is not found", funcname, module, func); goto failed; } if (!PyCallable_Check(*pFunc)) { radlog(L_ERR, "rlm_python:%s: function '%s.%s' is not callable", funcname, module, func); goto failed; } } PyGILState_Release(gstate); return 0;failed: python_error(); radlog(L_ERR, "rlm_python:%s: failed to import python function '%s.%s'", funcname, module, func); Py_XDECREF(*pFunc); *pFunc = NULL; Py_XDECREF(*pModule); PyGILState_Release(gstate); *pModule = NULL; return -1;}static void python_objclear(PyObject **ob) { if (*ob != NULL) { Pyx_BLOCK_THREADS Py_DECREF(*ob); Pyx_UNBLOCK_THREADS *ob = NULL; }}static void python_instance_clear(struct rlm_python_t *data) { python_objclear(&data->pFunc_instantiate); python_objclear(&data->pFunc_authorize); python_objclear(&data->pFunc_authenticate); python_objclear(&data->pFunc_preacct); python_objclear(&data->pFunc_accounting); python_objclear(&data->pFunc_checksimul); python_objclear(&data->pFunc_detach); python_objclear(&data->pModule_instantiate); python_objclear(&data->pModule_authorize); python_objclear(&data->pModule_authenticate); python_objclear(&data->pModule_preacct); python_objclear(&data->pModule_accounting); python_objclear(&data->pModule_checksimul); python_objclear(&data->pModule_detach);}/* * 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 python_instantiate(CONF_SECTION *conf, void **instance) { struct rlm_python_t *data = NULL; /* * Set up a storage area for instance data */ if ((data = malloc(sizeof(*data))) == NULL) return -1; bzero(data, 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; } /* * Import user modules. */ if (python_load_function(data->mod_instantiate, data->func_instantiate, &data->pModule_instantiate, &data->pFunc_instantiate) < 0) goto failed; if (python_load_function(data->mod_authenticate, data->func_authenticate, &data->pModule_authenticate, &data->pFunc_authenticate) < 0) goto failed; if (python_load_function(data->mod_authorize, data->func_authorize, &data->pModule_authorize, &data->pFunc_authorize) < 0) goto failed; if (python_load_function(data->mod_preacct, data->func_preacct, &data->pModule_preacct, &data->pFunc_preacct) < 0) goto failed; if (python_load_function(data->mod_accounting, data->func_accounting, &data->pModule_accounting, &data->pFunc_accounting) < 0) goto failed; if (python_load_function(data->mod_checksimul, data->func_checksimul, &data->pModule_checksimul, &data->pFunc_checksimul) < 0) goto failed; if (python_load_function(data->mod_detach, data->func_detach, &data->pModule_detach, &data->pFunc_detach) < 0) goto failed; *instance = data; /* Call the instantiate function. No request. Use the return value. */ return python_function(NULL, data->pFunc_instantiate, "instantiate");failed: python_error(); python_instance_clear(data); return -1;}static int python_detach(void *instance) { struct rlm_python_t *data = (struct rlm_python_t *) instance; int ret; ret = python_function(NULL, data->pFunc_detach, "detach"); python_instance_clear(data); free(data); return ret;}/* Wrapper functions */static int python_authorize(void *instance, REQUEST *request){ return python_function(request, ((struct rlm_python_t *)instance)->pFunc_authorize, "authorize");}static int python_authenticate(void *instance, REQUEST *request){ return python_function( request, ((struct rlm_python_t *)instance)->pFunc_authenticate, "authenticate");}static int python_preacct(void *instance, REQUEST *request){ return python_function( request, ((struct rlm_python_t *)instance)->pFunc_preacct, "preacct");}static int python_accounting(void *instance, REQUEST *request){ return python_function( request, ((struct rlm_python_t *)instance)->pFunc_accounting, "accounting");}static int python_checksimul(void *instance, REQUEST *request){ return python_function( request, ((struct rlm_python_t *)instance)->pFunc_checksimul, "checksimul");}/* * 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_python = { "python", RLM_TYPE_THREAD_SAFE, /* type */ python_init, /* initialization */ python_instantiate, /* instantiation */ { python_authenticate, /* authentication */ python_authorize, /* authorization */ python_preacct, /* preaccounting */ python_accounting, /* accounting */ python_checksimul, /* checksimul */ NULL, /* pre-proxy */ NULL, /* post-proxy */ NULL /* post-auth */ }, python_detach, /* detach */ python_destroy, /* destroy */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -