static int mod_init(void) { int i; static char name[] = "radiusd"; if (radiusd_module) return 0; Py_SetProgramName(name); 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 */ DEBUG("mod_init done"); return 0; failed: mod_error(); Py_XDECREF(radiusd_module); radiusd_module = NULL; Py_Finalize(); return -1; }
static int mod_init(rlm_python_t *inst) { int i; static char name[] = "radiusd"; if (radiusd_module) return 0; /* * Explicitly load libpython, so symbols will be available to lib-dynload modules */ inst->libpython = dlopen("libpython" STRINGIFY(PY_MAJOR_VERSION) "." STRINGIFY(PY_MINOR_VERSION) ".so", RTLD_NOW | RTLD_GLOBAL); if (!inst->libpython) { WARN("Failed loading libpython symbols into global symbol table: %s", dlerror()); } Py_SetProgramName(name); #ifdef HAVE_PTHREAD_H Py_InitializeEx(0); /* Don't override signal handlers */ PyEval_InitThreads(); /* This also grabs a lock */ inst->main_thread_state = PyThreadState_Get(); /* We need this for setting up thread local stuff */ #endif if (inst->python_path) { PySys_SetPath(inst->python_path); } 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; } } #ifdef HAVE_PTHREAD_H PyThreadState_Swap(NULL); /* We have to swap out the current thread else we get deadlocks */ PyEval_ReleaseLock(); /* Drop lock grabbed by InitThreads */ #endif DEBUG("mod_init done"); return 0; failed: Py_XDECREF(radiusd_module); #ifdef HAVE_PTHREAD_H PyEval_ReleaseLock(); #endif Pyx_BLOCK_THREADS mod_error(); Pyx_UNBLOCK_THREADS radiusd_module = NULL; Py_Finalize(); return -1; }
static int mod_init(rlm_python_t *inst) { int i; static char name[] = "radiusd"; if (radiusd_module) return 0; Py_SetProgramName(name); #ifdef HAVE_PTHREAD_H Py_InitializeEx(0); /* Don't override signal handlers */ PyEval_InitThreads(); /* This also grabs a lock */ inst->main_thread_state = PyThreadState_Get(); /* We need this for setting up thread local stuff */ #endif if (inst->python_path) { PySys_SetPath(inst->python_path); } 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; } } #ifdef HAVE_PTHREAD_H PyThreadState_Swap(NULL); /* We have to swap out the current thread else we get deadlocks */ PyEval_ReleaseLock(); /* Drop lock grabbed by InitThreads */ #endif DEBUG("mod_init done"); return 0; failed: Py_XDECREF(radiusd_module); #ifdef HAVE_PTHREAD_H PyEval_ReleaseLock(); #endif Pyx_BLOCK_THREADS mod_error(); Pyx_UNBLOCK_THREADS radiusd_module = NULL; Py_Finalize(); return -1; }
/* uam_load. uams must have a uam_setup function. */ struct uam_mod *uam_load(const char *path, const char *name) { char buf[MAXPATHLEN + 1], *p; struct uam_mod *mod; void *module; if ((module = mod_open(path)) == NULL) { LOG(log_error, logtype_afpd, "uam_load(%s): failed to load: %s", name, mod_error()); return NULL; } if ((mod = (struct uam_mod *) malloc(sizeof(struct uam_mod))) == NULL) { LOG(log_error, logtype_afpd, "uam_load(%s): malloc failed", name); goto uam_load_fail; } strlcpy(buf, name, sizeof(buf)); if ((p = strchr(buf, '.'))) *p = '\0'; if ((mod->uam_fcn = mod_symbol(module, buf)) == NULL) { LOG(log_error, logtype_afpd, "uam_load(%s): mod_symbol error for symbol %s", name, buf); goto uam_load_err; } if (mod->uam_fcn->uam_type != UAM_MODULE_SERVER) { LOG(log_error, logtype_afpd, "uam_load(%s): attempted to load a non-server module", name); goto uam_load_err; } /* version check would go here */ if (!mod->uam_fcn->uam_setup || ((*mod->uam_fcn->uam_setup)(name) < 0)) { LOG(log_error, logtype_afpd, "uam_load(%s): uam_setup failed", name); goto uam_load_err; } mod->uam_module = module; return mod; uam_load_err: free(mod); uam_load_fail: mod_close(module); return NULL; }
/* * 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 mod_instantiate(UNUSED CONF_SECTION *conf, void *instance) { rlm_python_t *inst = instance; if (mod_init(inst) != 0) { return -1; } #define A(x) if (mod_load_function(&inst->x) < 0) goto failed A(instantiate); A(authenticate); A(authorize); A(preacct); A(accounting); A(checksimul); A(pre_proxy); A(post_proxy); A(post_auth); #ifdef WITH_COA A(recv_coa); A(send_coa); #endif A(detach); #undef A /* * Call the instantiate function. No request. Use the * return value. */ return do_python(inst, NULL, inst->instantiate.function, "instantiate", false); failed: Pyx_BLOCK_THREADS mod_error(); Pyx_UNBLOCK_THREADS mod_instance_clear(inst); return -1; }
static int mod_load_function(struct py_function_def *def) { char const *funcname = "mod_load_function"; PyGILState_STATE gstate; gstate = PyGILState_Ensure(); if (def->module_name != NULL && def->function_name != NULL) { if ((def->module = PyImport_ImportModule(def->module_name)) == NULL) { ERROR("rlm_python:%s: module '%s' is not found", funcname, def->module_name); goto failed; } if ((def->function = PyObject_GetAttrString(def->module, def->function_name)) == NULL) { ERROR("rlm_python:%s: function '%s.%s' is not found", funcname, def->module_name, def->function_name); goto failed; } if (!PyCallable_Check(def->function)) { ERROR("rlm_python:%s: function '%s.%s' is not callable", funcname, def->module_name, def->function_name); goto failed; } } PyGILState_Release(gstate); return 0; failed: mod_error(); ERROR("rlm_python:%s: failed to import python function '%s.%s'", funcname, def->module_name, def->function_name); Py_XDECREF(def->function); def->function = NULL; Py_XDECREF(def->module); def->module = NULL; PyGILState_Release(gstate); return -1; }
static int do_python(REQUEST *request, PyObject *pFunc, char const *funcname) { vp_cursor_t cursor; 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) 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 = paircursor(&cursor, &request->packet->vps); vp; vp = pairnext(&cursor)) { 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 = paircursor(&cursor, &request->packet->vps); vp; vp = pairnext(&cursor), i++) { PyObject *pPair; /* The inside tuple has two only: */ if ((pPair = PyTuple_New(2)) == NULL) goto failed; if (mod_populate_vptuple(pPair, vp) == 0) { /* Put the tuple inside the container */ PyTuple_SET_ITEM(pArgs, i, pPair); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(pArgs, i, Py_None); Py_DECREF(pPair); } } } /* Call Python function. */ pRet = PyObject_CallFunctionObjArgs(pFunc, pArgs, NULL); if (!pRet) goto failed; if (!request) goto okay; /* * The function returns either: * 1. (returnvalue, replyTuple, configTuple), where * - returnvalue is one of the constants RLM_* * - replyTuple and configTuple are tuples of string * tuples of size 2 * * 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) { ERROR("rlm_python:%s: tuple must be (return, replyTuple, configTuple)", funcname); goto failed; } pTupleInt = PyTuple_GET_ITEM(pRet, 0); if (!PyInt_CheckExact(pTupleInt)) { ERROR("rlm_python:%s: first tuple element not an integer", funcname); goto failed; } /* Now have the return value */ ret = PyInt_AsLong(pTupleInt); /* Reply item tuple */ mod_vptuple(request->reply, &request->reply->vps, PyTuple_GET_ITEM(pRet, 1), funcname); /* Config item tuple */ mod_vptuple(request, &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 */ ERROR("rlm_python:%s: function did not return a tuple or None", funcname); goto failed; } okay: Py_DECREF(pArgs); Py_DECREF(pRet); PyGILState_Release(gstate); return ret; failed: mod_error(); Py_XDECREF(pArgs); Py_XDECREF(pRet); PyGILState_Release(gstate); return -1; }