5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 * Copyright 2000,2006 The FreeRADIUS server project
20 * Copyright 2002 Miguel A.L. Paraz <mparaz@mparaz.com>
21 * Copyright 2002 Imperium Technology, Inc.
24 #include <freeradius-devel/ident.h>
29 #include <freeradius-devel/autoconf.h>
34 #include <freeradius-devel/radiusd.h>
35 #include <freeradius-devel/modules.h>
36 #include <freeradius-devel/conffile.h>
39 * Define a structure for our module configuration.
41 * These variables do not need to be in a structure, but it's
42 * a lot cleaner to do so, and a pointer to the structure can
43 * be used as the instance handle.
45 typedef struct rlm_python_t {
48 /* Names of modules */
58 /* Names of functions */
68 /* End Config section */
71 /* Python objects for modules */
76 *pModule_authenticate,
96 * A mapping of configuration file names to internal variables.
98 * Note that the string is dynamically allocated, so it MUST
99 * be freed. When the configuration file parse re-reads the string,
100 * it free's the old one, and strdup's the new one, placing the pointer
101 * to the strdup'd string into 'config.string'. This gets around
104 static const CONF_PARSER module_config[] = {
105 { "mod_instantiate", PW_TYPE_STRING_PTR,
106 offsetof(rlm_python_t, mod_instantiate), NULL, NULL},
107 { "func_instantiate", PW_TYPE_STRING_PTR,
108 offsetof(rlm_python_t, func_instantiate), NULL, NULL},
110 { "mod_authorize", PW_TYPE_STRING_PTR,
111 offsetof(rlm_python_t, mod_authorize), NULL, NULL},
112 { "func_authorize", PW_TYPE_STRING_PTR,
113 offsetof(rlm_python_t, func_authorize), NULL, NULL},
115 { "mod_authenticate", PW_TYPE_STRING_PTR,
116 offsetof(rlm_python_t, mod_authenticate), NULL, NULL},
117 { "func_authenticate", PW_TYPE_STRING_PTR,
118 offsetof(rlm_python_t, func_authenticate), NULL, NULL},
120 { "mod_preacct", PW_TYPE_STRING_PTR,
121 offsetof(rlm_python_t, mod_preacct), NULL, NULL},
122 { "func_preacct", PW_TYPE_STRING_PTR,
123 offsetof(rlm_python_t, func_preacct), NULL, NULL},
125 { "mod_accounting", PW_TYPE_STRING_PTR,
126 offsetof(rlm_python_t, mod_accounting), NULL, NULL},
127 { "func_accounting", PW_TYPE_STRING_PTR,
128 offsetof(rlm_python_t, func_accounting), NULL, NULL},
130 { "mod_checksimul", PW_TYPE_STRING_PTR,
131 offsetof(rlm_python_t, mod_checksimul), NULL, NULL},
132 { "func_checksimul", PW_TYPE_STRING_PTR,
133 offsetof(rlm_python_t, func_checksimul), NULL, NULL},
135 { "mod_detach", PW_TYPE_STRING_PTR,
136 offsetof(rlm_python_t, mod_detach), NULL, NULL},
137 { "func_detach", PW_TYPE_STRING_PTR,
138 offsetof(rlm_python_t, func_detach), NULL, NULL},
141 { NULL, -1, 0, NULL, NULL } /* end the list */
145 * radiusd Python functions
149 static PyObject *radlog_py(const PyObject *self, PyObject *args) {
153 if (!PyArg_ParseTuple(args, "is", &status, &msg)) {
161 static PyMethodDef radiusd_methods[] = {
162 {"radlog", (PyCFunction)radlog_py, METH_VARARGS, "freeradius radlog()."},
163 {NULL, NULL, 0, NULL}
167 /* Extract string representation of Python error. */
168 static void python_error(void) {
169 PyObject *pType, *pValue, *pTraceback, *pStr1, *pStr2;
171 PyErr_Fetch(&pType, &pValue, &pTraceback);
172 pStr1 = PyObject_Str(pType);
173 pStr2 = PyObject_Str(pValue);
175 radlog(L_ERR, "%s: %s\n",
176 PyString_AsString(pStr1), PyString_AsString(pStr2));
179 /* Tuple to value pair conversion */
180 static void add_vp_tuple(VALUE_PAIR **vpp, PyObject *pValue,
181 const char *function_name) {
182 int i, outertuplesize;
185 /* If the Python function gave us None for the tuple, then just return. */
186 if (pValue == Py_None) {
190 if (!PyTuple_Check(pValue)) {
191 radlog(L_ERR, "%s: non-tuple passed", function_name);
194 /* Get the tuple size. */
195 outertuplesize = PyTuple_Size(pValue);
197 for (i = 0; i < outertuplesize; i++) {
198 PyObject *pTupleElement = PyTuple_GetItem(pValue, i);
200 if ((pTupleElement != NULL) &&
201 (PyTuple_Check(pTupleElement))) {
203 /* Check if it's a pair */
206 if ((tuplesize = PyTuple_Size(pTupleElement)) != 2) {
207 radlog(L_ERR, "%s: tuple element %d is a tuple "
208 " of size %d. must be 2\n", function_name,
212 PyObject *pString1, *pString2;
214 pString1 = PyTuple_GetItem(pTupleElement, 0);
215 pString2 = PyTuple_GetItem(pTupleElement, 1);
217 /* xxx PyString_Check does not compile here */
218 if ((pString1 != NULL) &&
219 (pString2 != NULL) &&
220 PyObject_TypeCheck(pString1,&PyString_Type) &&
221 PyObject_TypeCheck(pString2,&PyString_Type)) {
226 /* pairmake() will convert and find any
227 * errors in the pair.
230 s1 = PyString_AsString(pString1);
231 s2 = PyString_AsString(pString2);
233 if ((s1 != NULL) && (s2 != NULL)) {
234 radlog(L_DBG, "%s: %s = %s ",
235 function_name, s1, s2);
237 /* xxx Might need to support other T_OP */
238 vp = pairmake(s1, s2, T_OP_EQ);
241 radlog(L_DBG, "%s: s1, s2 OK\n",
245 radlog(L_DBG, "%s: s1, s2 FAILED\n",
250 radlog(L_ERR, "%s: string conv failed\n",
256 radlog(L_ERR, "%s: tuple element %d must be "
257 "(string, string)", function_name, i);
262 radlog(L_ERR, "%s: tuple element %d is not a tuple\n",
269 /* This is the core Python function that the others wrap around.
270 * Pass the value-pair print strings in a tuple.
271 * xxx We're not checking the errors. If we have errors, what do we do?
274 static int python_function(REQUEST *request,
275 PyObject *pFunc, const char *function_name)
277 #define BUF_SIZE 1024
279 char buf[BUF_SIZE]; /* same size as vp_print buffer */
283 PyObject *pValue, *pValuePairContainer, **pValueHolder, **pValueHolderPtr;
284 int i, n_tuple, return_value;
286 /* Return with "OK, continue" if the function is not defined. */
288 return RLM_MODULE_OK;
291 /* Default return value is "OK, continue" */
292 return_value = RLM_MODULE_OK;
294 /* We will pass a tuple containing (name, value) tuples
295 * We can safely use the Python function to build up a tuple,
296 * since the tuple is not used elsewhere.
298 * Determine the size of our tuple by walking through the packet.
299 * If request is NULL, pass None.
303 if (request != NULL) {
304 for (vp = request->packet->vps; vp; vp = vp->next) {
309 /* Create the tuple and a holder for the pointers, so that we can
310 * decref more efficiently later without the overhead of reading
313 * We use malloc() instead of the Python memory allocator since we
317 if (NULL == (pValueHolder = pValueHolderPtr =
318 malloc(sizeof(PyObject *) * n_tuple))) {
320 radlog(L_ERR, "%s: malloc of %d bytes failed\n",
321 function_name, sizeof(PyObject *) * n_tuple);
327 pValuePairContainer = Py_None;
330 pValuePairContainer = PyTuple_New(n_tuple);
333 for (vp = request->packet->vps; vp; vp = vp->next) {
334 PyObject *pValuePair, *pString1, *pString2;
336 /* The inside tuple has two only: */
337 pValuePair = PyTuple_New(2);
339 /* The name. logic from vp_prints, lib/print.c */
340 if (vp->flags.has_tag) {
341 snprintf(buf, BUF_SIZE, "%s:%d", vp->name, vp->flags.tag);
344 strcpy(buf, vp->name);
347 pString1 = PyString_FromString(buf);
348 PyTuple_SetItem(pValuePair, 0, pString1);
351 /* The value. Use delimiter - don't know what that means */
352 vp_prints_value(buf, sizeof(buf), vp, 1);
353 pString2 = PyString_FromString(buf);
354 PyTuple_SetItem(pValuePair, 1, pString2);
356 /* Put the tuple inside the container */
357 PyTuple_SetItem(pValuePairContainer, i++, pValuePair);
359 /* Store the pointer in our malloc() storage */
360 *pValueHolderPtr++ = pValuePair;
365 /* Call Python function.
368 if (pFunc && PyCallable_Check(pFunc)) {
371 /* call the function with a singleton tuple containing the
375 if ((pArgs = PyTuple_New(1)) == NULL) {
376 radlog(L_ERR, "%s: could not create tuple", function_name);
379 if ((PyTuple_SetItem(pArgs, 0, pValuePairContainer)) != 0) {
380 radlog(L_ERR, "%s: could not set tuple item", function_name);
384 if ((pValue = PyObject_CallObject(pFunc, pArgs)) == NULL) {
385 radlog(L_ERR, "%s: function call failed", function_name);
390 /* The function returns either:
391 * 1. tuple containing the integer return value,
392 * then the integer reply code (or None to not set),
393 * then the string tuples to build the reply with.
394 * (returnvalue, (p1, s1), (p2, s2))
396 * 2. the function return value alone
398 * 3. None - default return value is set
400 * xxx This code is messy!
403 if (PyTuple_Check(pValue)) {
406 if (PyTuple_Size(pValue) != 3) {
407 radlog(L_ERR, "%s: tuple must be " \
408 "(return, replyTuple, configTuple)",
413 pTupleInt = PyTuple_GetItem(pValue, 0);
415 if ((pTupleInt == NULL) || !PyInt_Check(pTupleInt)) {
416 radlog(L_ERR, "%s: first tuple element not an integer",
420 /* Now have the return value */
421 return_value = PyInt_AsLong(pTupleInt);
423 /* Reply item tuple */
424 add_vp_tuple(&request->reply->vps,
425 PyTuple_GetItem(pValue, 1), function_name);
427 /* Config item tuple */
428 add_vp_tuple(&request->config_items,
429 PyTuple_GetItem(pValue, 2), function_name);
433 else if (PyInt_Check(pValue)) {
434 /* Just an integer */
435 return_value = PyInt_AsLong(pValue);
437 else if (pValue == Py_None) {
438 /* returned 'None', return value defaults to "OK, continue." */
439 return_value = RLM_MODULE_OK;
442 /* Not tuple or None */
443 radlog(L_ERR, "%s function did not return a tuple or None\n",
448 /* Decrease reference counts for the argument and return tuple */
453 /* Decrease reference count for the tuples passed, the
454 * container tuple, and the return value.
457 pValueHolderPtr = pValueHolder;
460 /* Can't write as pValueHolderPtr since Py_DECREF is a macro */
461 Py_DECREF(*pValueHolderPtr);
465 Py_DECREF(pValuePairContainer);
467 /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */
469 /* Free pairs if we are rejecting.
470 * xxx Shouldn't the core do that?
473 if ((return_value == RLM_MODULE_REJECT) && (request != NULL)) {
474 pairfree(&(request->reply->vps));
477 /* Return the specified by the Python module */
482 static struct varlookup {
487 { "L_AUTH", L_AUTH },
488 { "L_INFO", L_INFO },
490 { "L_PROXY", L_PROXY },
491 { "L_CONS", L_CONS },
492 { "RLM_MODULE_REJECT", RLM_MODULE_REJECT },
493 { "RLM_MODULE_FAIL", RLM_MODULE_FAIL },
494 { "RLM_MODULE_OK", RLM_MODULE_OK },
495 { "RLM_MODULE_HANDLED", RLM_MODULE_HANDLED },
496 { "RLM_MODULE_INVALID", RLM_MODULE_INVALID },
497 { "RLM_MODULE_USERLOCK",RLM_MODULE_USERLOCK },
498 { "RLM_MODULE_NOTFOUND",RLM_MODULE_NOTFOUND },
499 { "RLM_MODULE_NOOP", RLM_MODULE_NOOP },
500 { "RLM_MODULE_UPDATED", RLM_MODULE_UPDATED },
501 { "RLM_MODULE_NUMCODES",RLM_MODULE_NUMCODES },
506 * Import a user module and load a function from it
508 static int load_python_function(const char* module, const char* func,
509 PyObject** pyModule, PyObject** pyFunc) {
511 if ((module==NULL) || (func==NULL)) {
517 pName = PyString_FromString(module);
519 *pyModule = PyImport_Import(pName);
521 if (*pyModule != NULL) {
524 pDict = PyModule_GetDict(*pyModule);
525 /* pDict: borrowed reference */
527 *pyFunc = PyDict_GetItemString(pDict, func);
528 /* pFunc: Borrowed reference */
532 radlog(L_ERR, "Failed to import python module \"%s\"\n", module);
542 * Do any per-module initialization that is separate to each
543 * configured instance of the module. e.g. set up connections
544 * to external databases, read configuration files, set up
545 * dictionary entries, etc.
547 * If configuration information is given in the config section
548 * that must be referenced in later calls, store a handle to it
549 * in *instance otherwise put a null pointer there.
552 static int python_instantiate(CONF_SECTION *conf, void **instance)
559 * Initialize Python interpreter. Fatal error if this fails.
564 * Set up a storage area for instance data
566 data = rad_malloc(sizeof(*data));
570 memset(data, 0, sizeof(*data));
573 * If the configuration parameters can't be parsed, then
576 if (cf_section_parse(conf, data, module_config) < 0) {
583 * Setup our 'radiusd' module.
587 if ((module = data->pModule_builtin =
588 Py_InitModule3("radiusd", radiusd_methods,
589 "FreeRADIUS Module.")) == NULL) {
591 radlog(L_ERR, "Python Py_InitModule3 failed");
597 * Load constants into module
599 for (idx=0; constants[idx].name; idx++)
600 if ((PyModule_AddIntConstant(module, constants[idx].name, constants[idx].value)) == -1) {
602 radlog(L_ERR, "Python AddIntConstant failed");
607 * Import user modules.
610 if (load_python_function(data->mod_instantiate, data->func_instantiate,
611 &data->pModule_instantiate, &data->pFunc_instantiate)==-1) {
612 /* TODO: check if we need to cleanup data */
616 if (load_python_function(data->mod_authenticate, data->func_authenticate,
617 &data->pModule_authenticate, &data->pFunc_authenticate)==-1) {
618 /* TODO: check if we need to cleanup data */
622 if (load_python_function(data->mod_authorize, data->func_authorize,
623 &data->pModule_authorize, &data->pFunc_authorize)==-1) {
624 /* TODO: check if we need to cleanup data */
628 if (load_python_function(data->mod_preacct, data->func_preacct,
629 &data->pModule_preacct, &data->pFunc_preacct)==-1) {
630 /* TODO: check if we need to cleanup data */
634 if (load_python_function(data->mod_accounting, data->func_accounting,
635 &data->pModule_accounting, &data->pFunc_accounting)==-1) {
636 /* TODO: check if we need to cleanup data */
640 if (load_python_function(data->mod_checksimul, data->func_checksimul,
641 &data->pModule_checksimul, &data->pFunc_checksimul)==-1) {
642 /* TODO: check if we need to cleanup data */
646 if (load_python_function(data->mod_detach, data->func_detach,
647 &data->pModule_detach, &data->pFunc_detach)==-1) {
648 /* TODO: check if we need to cleanup data */
654 /* Call the instantiate function. No request. Use the return value. */
655 return python_function(NULL, data->pFunc_instantiate, "instantiate");
658 /* Wrapper functions */
659 static int python_authorize(void *instance, REQUEST *request)
661 return python_function(request,
662 ((struct rlm_python_t *)instance)->pFunc_authorize,
666 static int python_authenticate(void *instance, REQUEST *request)
668 return python_function(
670 ((struct rlm_python_t *)instance)->pFunc_authenticate,
674 static int python_preacct(void *instance, REQUEST *request)
676 return python_function(
678 ((struct rlm_python_t *)instance)->pFunc_preacct,
682 static int python_accounting(void *instance, REQUEST *request)
684 return python_function(
686 ((struct rlm_python_t *)instance)->pFunc_accounting,
690 static int python_checksimul(void *instance, REQUEST *request)
692 return python_function(
694 ((struct rlm_python_t *)instance)->pFunc_checksimul,
699 static int python_detach(void *instance)
703 /* Default return value is failure */
706 if (((rlm_python_t *)instance)->pFunc_detach &&
707 PyCallable_Check(((rlm_python_t *)instance)->pFunc_detach)) {
709 PyObject *pArgs, *pValue;
711 /* call the function with an empty tuple */
713 pArgs = PyTuple_New(0);
714 pValue = PyObject_CallObject(((rlm_python_t *)instance)->pFunc_detach,
717 if (pValue == NULL) {
722 if (!PyInt_Check(pValue)) {
723 radlog(L_ERR, "detach: return value not an integer");
726 return_value = PyInt_AsLong(pValue);
730 /* Decrease reference counts for the argument and return tuple */
738 /* xxx test delete module object so it will be reloaded later.
739 * xxx useless since we can't SIGHUP reliably, anyway.
741 PyObject_Del(((struct rlm_python_t *)instance)->pModule_accounting);
744 radlog(L_DBG, "python_detach done");
746 /* Return the specified by the Python module */
751 * The module name should be the only globally exported symbol.
752 * That is, everything else should be 'static'.
754 * If the module needs to temporarily modify it's instantiation
755 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
756 * The server will then take care of ensuring that the module
757 * is single-threaded.
759 module_t rlm_python = {
762 RLM_TYPE_THREAD_SAFE, /* type */
763 python_instantiate, /* instantiation */
764 python_detach, /* detach */
766 python_authenticate, /* authentication */
767 python_authorize, /* authorization */
768 python_preacct, /* preaccounting */
769 python_accounting, /* accounting */
770 python_checksimul, /* checksimul */
771 NULL, /* pre-proxy */
772 NULL, /* post-proxy */