rlm_python: add missing default NULL
[freeradius.git] / src / modules / rlm_python / rlm_python.c
1 /*
2  *   This program is is free software; you can redistribute it and/or modify
3  *   it under the terms of the GNU General Public License as published by
4  *   the Free Software Foundation; either version 2 of the License, or (at
5  *   your option) any later version.
6  *
7  *   This program is distributed in the hope that it will be useful,
8  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *   GNU General Public License for more details.
11  *
12  *   You should have received a copy of the GNU General Public License
13  *   along with this program; if not, write to the Free Software
14  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16
17 /**
18  * $Id$
19  * @file rlm_python.c
20  * @brief Translates requests between the server an a python interpreter.
21  *
22  * @note Rewritten by Paul P. Komkoff Jr <i@stingr.net>.
23  *
24  * @copyright 2000,2006,2015-2016  The FreeRADIUS server project
25  * @copyright 2002  Miguel A.L. Paraz <mparaz@mparaz.com>
26  * @copyright 2002  Imperium Technology, Inc.
27  */
28 RCSID("$Id$")
29
30 #define LOG_PREFIX "rlm_python - "
31
32 #include <freeradius-devel/radiusd.h>
33 #include <freeradius-devel/modules.h>
34 #include <freeradius-devel/rad_assert.h>
35
36 #include <Python.h>
37 #include <dlfcn.h>
38
39 static uint32_t         python_instances = 0;
40 static void             *python_dlhandle;
41
42 static PyThreadState    *main_interpreter;      //!< Main interpreter (cext safe)
43 static PyObject         *main_module;           //!< Pthon configuration dictionary.
44
45 /** Specifies the module.function to load for processing a section
46  *
47  */
48 typedef struct python_func_def {
49         PyObject        *module;                //!< Python reference to module.
50         PyObject        *function;              //!< Python reference to function in module.
51
52         char const      *module_name;           //!< String name of module.
53         char const      *function_name;         //!< String name of function in module.
54 } python_func_def_t;
55
56 /** An instance of the rlm_python module
57  *
58  */
59 typedef struct rlm_python_t {
60         char const      *name;                  //!< Name of the module instance
61         PyThreadState   *sub_interpreter;       //!< The main interpreter/thread used for this instance.
62         char const      *python_path;           //!< Path to search for python files in.
63         PyObject        *module;                //!< Local, interpreter specific module, containing
64                                                 //!< FreeRADIUS functions.
65         bool            cext_compat;            //!< Whether or not to create sub-interpreters per module
66                                                 //!< instance.
67
68         python_func_def_t
69         instantiate,
70         authorize,
71         authenticate,
72         preacct,
73         accounting,
74         checksimul,
75         pre_proxy,
76         post_proxy,
77         post_auth,
78 #ifdef WITH_COA
79         recv_coa,
80         send_coa,
81 #endif
82         detach;
83
84         PyObject        *pythonconf_dict;       //!< Configuration parameters defined in the module
85                                                 //!< made available to the python script.
86 } rlm_python_t;
87
88 /** Tracks a python module inst/thread state pair
89  *
90  * Multiple instances of python create multiple interpreters and each
91  * thread must have a PyThreadState per interpreter, to track execution.
92  */
93 typedef struct python_thread_state {
94         PyThreadState           *state;         //!< Module instance/thread specific state.
95         rlm_python_t            *inst;          //!< Module instance that created this thread state.
96 } python_thread_state_t;
97
98 /*
99  *      A mapping of configuration file names to internal variables.
100  */
101 static CONF_PARSER module_config[] = {
102
103 #define A(x) { "mod_" #x, FR_CONF_OFFSET(PW_TYPE_STRING, rlm_python_t, x.module_name), "${.module}" }, \
104         { "func_" #x, FR_CONF_OFFSET(PW_TYPE_STRING, rlm_python_t, x.function_name), NULL },
105
106         A(instantiate)
107         A(authorize)
108         A(authenticate)
109         A(preacct)
110         A(accounting)
111         A(checksimul)
112         A(pre_proxy)
113         A(post_proxy)
114         A(post_auth)
115 #ifdef WITH_COA
116         A(recv_coa)
117         A(send_coa)
118 #endif
119         A(detach)
120
121 #undef A
122
123         { "python_path", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_python_t, python_path), NULL },
124         { "cext_compat", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_python_t, cext_compat), "yes" },
125
126         CONF_PARSER_TERMINATOR
127 };
128
129 static struct {
130         char const *name;
131         int  value;
132 } radiusd_constants[] = {
133
134 #define A(x) { #x, x },
135
136         A(L_DBG)
137         A(L_WARN)
138         A(L_AUTH)
139         A(L_INFO)
140         A(L_ERR)
141         A(L_PROXY)
142         A(L_WARN)
143         A(L_ACCT)
144         A(L_DBG_WARN)
145         A(L_DBG_ERR)
146         A(L_DBG_WARN_REQ)
147         A(L_DBG_ERR_REQ)
148         A(RLM_MODULE_REJECT)
149         A(RLM_MODULE_FAIL)
150         A(RLM_MODULE_OK)
151         A(RLM_MODULE_HANDLED)
152         A(RLM_MODULE_INVALID)
153         A(RLM_MODULE_USERLOCK)
154         A(RLM_MODULE_NOTFOUND)
155         A(RLM_MODULE_NOOP)
156         A(RLM_MODULE_UPDATED)
157         A(RLM_MODULE_NUMCODES)
158
159 #undef A
160
161         { NULL, 0 },
162 };
163
164 /*
165  *      This allows us to initialise PyThreadState on a per thread basis
166  */
167 fr_thread_local_setup(rbtree_t *, local_thread_state)   /* macro */
168
169 /*
170  *      radiusd Python functions
171  */
172
173 /** Allow radlog to be called from python
174  *
175  */
176 static PyObject *mod_radlog(UNUSED PyObject *module, PyObject *args)
177 {
178         int status;
179         char *msg;
180
181         if (!PyArg_ParseTuple(args, "is", &status, &msg)) {
182                 return NULL;
183         }
184
185         radlog(status, "%s", msg);
186         Py_INCREF(Py_None);
187
188         return Py_None;
189 }
190
191 static PyMethodDef module_methods[] = {
192         { "radlog", &mod_radlog, METH_VARARGS,
193           "radiusd.radlog(level, msg)\n\n" \
194           "Print a message using radiusd logging system. level should be one of the\n" \
195           "constants L_DBG, L_AUTH, L_INFO, L_ERR, L_PROXY\n"
196         },
197         { NULL, NULL, 0, NULL },
198 };
199
200 /** Print out the current error
201  *
202  * Must be called with a valid thread state set
203  */
204 static void python_error_log(void)
205 {
206         PyObject *pType = NULL, *pValue = NULL, *pTraceback = NULL, *pStr1 = NULL, *pStr2 = NULL;
207
208         PyErr_Fetch(&pType, &pValue, &pTraceback);
209         if (!pType || !pValue)
210                 goto failed;
211         if (((pStr1 = PyObject_Str(pType)) == NULL) ||
212             ((pStr2 = PyObject_Str(pValue)) == NULL))
213                 goto failed;
214
215         ERROR("%s (%s)", PyString_AsString(pStr1), PyString_AsString(pStr2));
216
217 failed:
218         Py_XDECREF(pStr1);
219         Py_XDECREF(pStr2);
220         Py_XDECREF(pType);
221         Py_XDECREF(pValue);
222         Py_XDECREF(pTraceback);
223 }
224
225 static void mod_vptuple(TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, PyObject *pValue,
226                         char const *funcname, char const *list_name)
227 {
228         int          i;
229         int          tuplesize;
230         vp_tmpl_t       dst;
231         VALUE_PAIR      *vp;
232         REQUEST         *current = request;
233
234         memset(&dst, 0, sizeof(dst));
235
236         /*
237          *      If the Python function gave us None for the tuple,
238          *      then just return.
239          */
240         if (pValue == Py_None) return;
241
242         if (!PyTuple_CheckExact(pValue)) {
243                 ERROR("%s - non-tuple passed to %s", funcname, list_name);
244                 return;
245         }
246         /* Get the tuple tuplesize. */
247         tuplesize = PyTuple_GET_SIZE(pValue);
248         for (i = 0; i < tuplesize; i++) {
249                 PyObject        *pTupleElement = PyTuple_GET_ITEM(pValue, i);
250                 PyObject        *pStr1;
251                 PyObject        *pStr2;
252                 PyObject        *pOp;
253                 int             pairsize;
254                 char const      *s1;
255                 char const      *s2;
256                 FR_TOKEN        op = T_OP_EQ;
257
258                 if (!PyTuple_CheckExact(pTupleElement)) {
259                         ERROR("%s - Tuple element %d of %s is not a tuple", funcname, i, list_name);
260                         continue;
261                 }
262                 /* Check if it's a pair */
263
264                 pairsize = PyTuple_GET_SIZE(pTupleElement);
265                 if ((pairsize < 2) || (pairsize > 3)) {
266                         ERROR("%s - Tuple element %d of %s is a tuple of size %d. Must be 2 or 3",
267                               funcname, i, list_name, pairsize);
268                         continue;
269                 }
270
271                 pStr1 = PyTuple_GET_ITEM(pTupleElement, 0);
272                 pStr2 = PyTuple_GET_ITEM(pTupleElement, pairsize-1);
273
274                 if ((!PyString_CheckExact(pStr1)) || (!PyString_CheckExact(pStr2))) {
275                         ERROR("%s - Tuple element %d of %s must be as (str, str)",
276                               funcname, i, list_name);
277                         continue;
278                 }
279                 s1 = PyString_AsString(pStr1);
280                 s2 = PyString_AsString(pStr2);
281
282                 if (pairsize == 3) {
283                         pOp = PyTuple_GET_ITEM(pTupleElement, 1);
284                         if (PyString_CheckExact(pOp)) {
285                                 if (!(op = fr_str2int(fr_tokens, PyString_AsString(pOp), 0))) {
286                                         ERROR("%s - Invalid operator %s:%s %s %s, falling back to '='",
287                                               funcname, list_name, s1, PyString_AsString(pOp), s2);
288                                         op = T_OP_EQ;
289                                 }
290                         } else if (PyInt_Check(pOp)) {
291                                 op      = PyInt_AsLong(pOp);
292                                 if (!fr_int2str(fr_tokens, op, NULL)) {
293                                         ERROR("%s - Invalid operator %s:%s %i %s, falling back to '='",
294                                               funcname, list_name, s1, op, s2);
295                                         op = T_OP_EQ;
296                                 }
297                         } else {
298                                 ERROR("%s - Invalid operator type for %s:%s ? %s, using default '='",
299                                       funcname, list_name, s1, s2);
300                         }
301                 }
302
303                 if (tmpl_from_attr_str(&dst, s1, REQUEST_CURRENT, PAIR_LIST_REPLY, false, false) <= 0) {
304                         ERROR("%s - Failed to find attribute %s:%s", funcname, list_name, s1);
305                         continue;
306                 }
307
308                 if (radius_request(&current, dst.tmpl_request) < 0) {
309                         ERROR("%s - Attribute name %s:%s refers to outer request but not in a tunnel, skipping...",
310                               funcname, list_name, s1);
311                         continue;
312                 }
313
314                 if (!(vp = fr_pair_afrom_da(ctx, dst.tmpl_da))) {
315                         ERROR("%s - Failed to create attribute %s:%s", funcname, list_name, s1);
316                         continue;
317                 }
318
319                 vp->op = op;
320                 if (fr_pair_value_from_str(vp, s2, -1) < 0) {
321                         DEBUG("%s - Failed: '%s:%s' %s '%s'", funcname, list_name, s1,
322                               fr_int2str(fr_tokens, op, "="), s2);
323                 } else {
324                         DEBUG("%s - '%s:%s' %s '%s'", funcname, list_name, s1,
325                               fr_int2str(fr_tokens, op, "="), s2);
326                 }
327
328                 radius_pairmove(current, vps, vp, false);
329         }
330 }
331
332
333 /*
334  *      This is the core Python function that the others wrap around.
335  *      Pass the value-pair print strings in a tuple.
336  *
337  *      FIXME: We're not checking the errors. If we have errors, what
338  *      do we do?
339  */
340 static int mod_populate_vptuple(PyObject *pPair, VALUE_PAIR *vp)
341 {
342         PyObject *pStr = NULL;
343         char buf[1024];
344
345         /* Look at the fr_pair_fprint_name? */
346
347         if (vp->da->flags.has_tag) {
348                 pStr = PyString_FromFormat("%s:%d", vp->da->name, vp->tag);
349         } else {
350                 pStr = PyString_FromString(vp->da->name);
351         }
352
353         if (!pStr) return -1;
354
355         PyTuple_SET_ITEM(pPair, 0, pStr);
356
357         vp_prints_value(buf, sizeof(buf), vp, '\0');    /* Python doesn't need any escaping */
358
359         pStr = PyString_FromString(buf);
360         if (pStr == NULL) return -1;
361
362         PyTuple_SET_ITEM(pPair, 1, pStr);
363
364         return 0;
365 }
366
367 static rlm_rcode_t do_python_single(REQUEST *request, PyObject *pFunc, char const *funcname)
368 {
369         vp_cursor_t     cursor;
370         VALUE_PAIR      *vp;
371         PyObject        *pRet = NULL;
372         PyObject        *pArgs = NULL;
373         int             tuplelen;
374         int             ret;
375
376         /* Default return value is "OK, continue" */
377         ret = RLM_MODULE_OK;
378
379         /*
380          *      We will pass a tuple containing (name, value) tuples
381          *      We can safely use the Python function to build up a
382          *      tuple, since the tuple is not used elsewhere.
383          *
384          *      Determine the size of our tuple by walking through the packet.
385          *      If request is NULL, pass None.
386          */
387         tuplelen = 0;
388         if (request != NULL) {
389                 for (vp = fr_cursor_init(&cursor, &request->packet->vps);
390                      vp;
391                      vp = fr_cursor_next(&cursor)) tuplelen++;
392         }
393
394         if (tuplelen == 0) {
395                 Py_INCREF(Py_None);
396                 pArgs = Py_None;
397         } else {
398                 int i = 0;
399                 if ((pArgs = PyTuple_New(tuplelen)) == NULL) {
400                         ret = RLM_MODULE_FAIL;
401                         goto finish;
402                 }
403
404                 for (vp = fr_cursor_init(&cursor, &request->packet->vps);
405                      vp;
406                      vp = fr_cursor_next(&cursor), i++) {
407                         PyObject *pPair;
408
409                         /* The inside tuple has two only: */
410                         if ((pPair = PyTuple_New(2)) == NULL) {
411                                 ret = RLM_MODULE_FAIL;
412                                 goto finish;
413                         }
414
415                         if (mod_populate_vptuple(pPair, vp) == 0) {
416                                 /* Put the tuple inside the container */
417                                 PyTuple_SET_ITEM(pArgs, i, pPair);
418                         } else {
419                                 Py_INCREF(Py_None);
420                                 PyTuple_SET_ITEM(pArgs, i, Py_None);
421                                 Py_DECREF(pPair);
422                         }
423                 }
424         }
425
426         /* Call Python function. */
427         pRet = PyObject_CallFunctionObjArgs(pFunc, pArgs, NULL);
428         if (!pRet) {
429                 ret = RLM_MODULE_FAIL;
430                 goto finish;
431         }
432
433         if (!request) {
434                 // check return code at module instantiation time
435                 if (PyInt_CheckExact(pRet)) ret = PyInt_AsLong(pRet);
436                 goto finish;
437         }
438
439         /*
440          *      The function returns either:
441          *  1. (returnvalue, replyTuple, configTuple), where
442          *   - returnvalue is one of the constants RLM_*
443          *   - replyTuple and configTuple are tuples of string
444          *      tuples of size 2
445          *
446          *  2. the function return value alone
447          *
448          *  3. None - default return value is set
449          *
450          * xxx This code is messy!
451          */
452         if (PyTuple_CheckExact(pRet)) {
453                 PyObject *pTupleInt;
454
455                 if (PyTuple_GET_SIZE(pRet) != 3) {
456                         ERROR("%s - Tuple must be (return, replyTuple, configTuple)", funcname);
457                         ret = RLM_MODULE_FAIL;
458                         goto finish;
459                 }
460
461                 pTupleInt = PyTuple_GET_ITEM(pRet, 0);
462                 if (!PyInt_CheckExact(pTupleInt)) {
463                         ERROR("%s - First tuple element not an integer", funcname);
464                         ret = RLM_MODULE_FAIL;
465                         goto finish;
466                 }
467                 /* Now have the return value */
468                 ret = PyInt_AsLong(pTupleInt);
469                 /* Reply item tuple */
470                 mod_vptuple(request->reply, request, &request->reply->vps,
471                             PyTuple_GET_ITEM(pRet, 1), funcname, "reply");
472                 /* Config item tuple */
473                 mod_vptuple(request, request, &request->config,
474                             PyTuple_GET_ITEM(pRet, 2), funcname, "config");
475
476         } else if (PyInt_CheckExact(pRet)) {
477                 /* Just an integer */
478                 ret = PyInt_AsLong(pRet);
479
480         } else if (pRet == Py_None) {
481                 /* returned 'None', return value defaults to "OK, continue." */
482                 ret = RLM_MODULE_OK;
483         } else {
484                 /* Not tuple or None */
485                 ERROR("%s - Function did not return a tuple or None", funcname);
486                 ret = RLM_MODULE_FAIL;
487                 goto finish;
488         }
489
490
491 finish:
492         Py_XDECREF(pArgs);
493         Py_XDECREF(pRet);
494
495         return ret;
496 }
497
498 static void python_interpreter_free(PyThreadState *interp)
499 {
500         PyEval_AcquireLock();
501         PyThreadState_Swap(interp);
502         Py_EndInterpreter(interp);
503         PyEval_ReleaseLock();
504 }
505
506 /** Destroy a thread state
507  *
508  * @param thread to destroy.
509  * @return 0
510  */
511 static int _python_thread_free(python_thread_state_t *thread)
512 {
513         PyEval_RestoreThread(thread->state);    /* Swap in our local thread state */
514         PyThreadState_Clear(thread->state);
515         PyEval_SaveThread();
516
517         PyThreadState_Delete(thread->state);    /* Don't need to hold lock for this */
518
519         return 0;
520 }
521
522 /** Callback for rbtree delete walker
523  *
524  */
525 static void _python_thread_entry_free(void *arg)
526 {
527         talloc_free(arg);
528 }
529
530 /** Cleanup any thread local storage on pthread_exit()
531  *
532  * @param arg The thread currently exiting.
533  */
534 static void _python_thread_tree_free(void *arg)
535 {
536         rad_assert(arg == local_thread_state);
537
538         rbtree_t *tree = talloc_get_type_abort(arg, rbtree_t);
539         rbtree_free(tree);      /* Needs to be this not talloc_free to execute delete walker */
540
541         local_thread_state = NULL;      /* Prevent double free in unittest env */
542 }
543
544 /** Compare instance pointers
545  *
546  */
547 static int _python_inst_cmp(const void *a, const void *b)
548 {
549         python_thread_state_t const *a_p = a, *b_p = b;
550
551         if (a_p->inst < b_p->inst) return -1;
552         if (a_p->inst > b_p->inst) return +1;
553         return 0;
554 }
555
556 /** Thread safe call to a python function
557  *
558  * Will swap in thread state specific to module/thread.
559  */
560 static rlm_rcode_t do_python(rlm_python_t *inst, REQUEST *request, PyObject *pFunc, char const *funcname)
561 {
562         int                     ret;
563         rbtree_t                *thread_tree;
564         python_thread_state_t   *this_thread;
565         python_thread_state_t   find;
566
567         /*
568          *      It's a NOOP if the function wasn't defined
569          */
570         if (!pFunc) return RLM_MODULE_NOOP;
571
572         /*
573          *      Check to see if we've got a thread state tree
574          *      If not, create one.
575          */
576         thread_tree = fr_thread_local_init(local_thread_state, _python_thread_tree_free);
577         if (!thread_tree) {
578                 thread_tree = rbtree_create(NULL, _python_inst_cmp, _python_thread_entry_free, 0);
579                 if (!thread_tree) {
580                         RERROR("Failed allocating thread state tree");
581                         return RLM_MODULE_FAIL;
582                 }
583
584                 ret = fr_thread_local_set(local_thread_state, thread_tree);
585                 if (ret != 0) {
586                         talloc_free(thread_tree);
587                         return RLM_MODULE_FAIL;
588                 }
589         }
590
591         find.inst = inst;
592         /*
593          *      Find the thread state associated with this instance
594          *      and this thread, or create a new thread state.
595          */
596         this_thread = rbtree_finddata(thread_tree, &find);
597         if (!this_thread) {
598                 PyThreadState *state;
599
600                 state = PyThreadState_New(inst->sub_interpreter->interp);
601
602                 RDEBUG3("Initialised new thread state %p", state);
603                 if (!state) {
604                         REDEBUG("Failed initialising local PyThreadState on first run");
605                         return RLM_MODULE_FAIL;
606                 }
607
608                 this_thread = talloc(NULL, python_thread_state_t);
609                 this_thread->inst = inst;
610                 this_thread->state = state;
611                 talloc_set_destructor(this_thread, _python_thread_free);
612
613                 if (!rbtree_insert(thread_tree, this_thread)) {
614                         RERROR("Failed inserting thread state into TLS tree");
615                         talloc_free(this_thread);
616
617                         return RLM_MODULE_FAIL;
618                 }
619         }
620         RDEBUG3("Using thread state %p", this_thread->state);
621
622         PyEval_RestoreThread(this_thread->state);       /* Swap in our local thread state */
623         ret = do_python_single(request, pFunc, funcname);
624         PyEval_SaveThread();
625
626         return ret;
627 }
628
629 #define MOD_FUNC(x) \
630 static rlm_rcode_t CC_HINT(nonnull) mod_##x(void *instance, REQUEST *request) { \
631         return do_python((rlm_python_t *) instance, request, ((rlm_python_t *)instance)->x.function, #x);\
632 }
633
634 MOD_FUNC(authenticate)
635 MOD_FUNC(authorize)
636 MOD_FUNC(preacct)
637 MOD_FUNC(accounting)
638 MOD_FUNC(checksimul)
639 MOD_FUNC(pre_proxy)
640 MOD_FUNC(post_proxy)
641 MOD_FUNC(post_auth)
642 #ifdef WITH_COA
643 MOD_FUNC(recv_coa)
644 MOD_FUNC(send_coa)
645 #endif
646 static void python_obj_destroy(PyObject **ob)
647 {
648         if (*ob != NULL) {
649                 Py_DECREF(*ob);
650                 *ob = NULL;
651         }
652 }
653
654 static void python_function_destroy(python_func_def_t *def)
655 {
656         python_obj_destroy(&def->function);
657         python_obj_destroy(&def->module);
658 }
659
660 /** Import a user module and load a function from it
661  *
662  */
663 static int python_function_load(python_func_def_t *def)
664 {
665         char const *funcname = "python_function_load";
666
667         if (def->module_name == NULL || def->function_name == NULL) return 0;
668
669         def->module = PyImport_ImportModule(def->module_name);
670         if (!def->module) {
671                 ERROR("%s - Module '%s' not found", funcname, def->module_name);
672
673         error:
674                 python_error_log();
675                 ERROR("%s - Failed to import python function '%s.%s'",
676                       funcname, def->module_name, def->function_name);
677                 Py_XDECREF(def->function);
678                 def->function = NULL;
679                 Py_XDECREF(def->module);
680                 def->module = NULL;
681
682                 return -1;
683         }
684
685         def->function = PyObject_GetAttrString(def->module, def->function_name);
686         if (!def->function) {
687                 ERROR("%s - Function '%s.%s' is not found", funcname, def->module_name, def->function_name);
688                 goto error;
689         }
690
691         if (!PyCallable_Check(def->function)) {
692                 ERROR("%s - Function '%s.%s' is not callable", funcname, def->module_name, def->function_name);
693                 goto error;
694         }
695
696         return 0;
697 }
698
699 /*
700  *      Parse a configuration section, and populate a dict.
701  *      This function is recursively called (allows to have nested dicts.)
702  */
703 static void python_parse_config(CONF_SECTION *cs, int lvl, PyObject *dict)
704 {
705         int             indent_section = (lvl + 1) * 4;
706         int             indent_item = (lvl + 2) * 4;
707         CONF_ITEM       *ci = NULL;
708
709         if (!cs || !dict) return;
710
711         DEBUG("%*s%s {", indent_section, " ", cf_section_name1(cs));
712
713         while ((ci = cf_item_find_next(cs, ci))) {
714                 /*
715                  *  This is a section.
716                  *  Create a new dict, store it in current dict,
717                  *  Then recursively call python_parse_config with this section and the new dict.
718                  */
719                 if (cf_item_is_section(ci)) {
720                         CONF_SECTION *sub_cs = cf_item_to_section(ci);
721                         char const *key = cf_section_name1(sub_cs); /* dict key */
722                         PyObject *sub_dict, *pKey;
723
724                         if (!key) continue;
725
726                         pKey = PyString_FromString(key);
727                         if (!pKey) continue;
728
729                         if (PyDict_Contains(dict, pKey)) {
730                                 WARN("rlm_python: Ignoring duplicate config section '%s'", key);
731                                 continue;
732                         }
733
734                         if (!(sub_dict = PyDict_New())) {
735                                 WARN("rlm_python: Unable to create subdict for config section '%s'", key);
736                         }
737
738                         (void)PyDict_SetItem(dict, pKey, sub_dict);
739
740                         python_parse_config(sub_cs, lvl + 1, sub_dict);
741                 } else if (cf_item_is_pair(ci)) {
742                         CONF_PAIR *cp = cf_item_to_pair(ci);
743                         char const  *key = cf_pair_attr(cp); /* dict key */
744                         char const  *value = cf_pair_value(cp); /* dict value */
745                         PyObject *pKey, *pValue;
746
747                         if (!key || !value) continue;
748
749                         pKey = PyString_FromString(key);
750                         pValue = PyString_FromString(value);
751                         if (!pKey || !pValue) continue;
752
753                         /*
754                          *  This is an item.
755                          *  Store item attr / value in current dict.
756                          */
757                         if (PyDict_Contains(dict, pKey)) {
758                                 WARN("rlm_python: Ignoring duplicate config item '%s'", key);
759                                 continue;
760                         }
761
762                         (void)PyDict_SetItem(dict, pKey, pValue);
763
764                         DEBUG("%*s%s = %s", indent_item, " ", key, value);
765                 }
766         }
767
768         DEBUG("%*s}", indent_section, " ");
769 }
770
771 /** Initialises a separate python interpreter for this module instance
772  *
773  */
774 static int python_interpreter_init(rlm_python_t *inst, CONF_SECTION *conf)
775 {
776         int i;
777
778         /*
779          *      Explicitly load libpython, so symbols will be available to lib-dynload modules
780          */
781         if (python_instances == 0) {
782                 INFO("Python version: %s", Py_GetVersion());
783
784                 python_dlhandle = dlopen("libpython" STRINGIFY(PY_MAJOR_VERSION) "." STRINGIFY(PY_MINOR_VERSION) ".so",
785                                          RTLD_NOW | RTLD_GLOBAL);
786                 if (!python_dlhandle) WARN("Failed loading libpython symbols into global symbol table: %s", dlerror());
787
788 #if PY_VERSION_HEX > 0x03050000
789                 {
790                         wchar_t *name;
791
792                         wide_name = Py_DecodeLocale(main_config.name, strlen(main_config.name));
793                         Py_SetProgramName(name);                /* The value of argv[0] as a wide char string */
794                         PyMem_RawFree(name);
795                 }
796 #else
797                 {
798                         char *name;
799
800                         name = talloc_strdup(NULL, main_config.name);
801                         Py_SetProgramName(name);                /* The value of argv[0] as a wide char string */
802                         talloc_free(name);
803                 }
804 #endif
805
806                 Py_InitializeEx(0);                     /* Don't override signal handlers - noop on subs calls */
807                 PyEval_InitThreads();                   /* This also grabs a lock (which we then need to release) */
808                 main_interpreter = PyThreadState_Get(); /* Store reference to the main interpreter */
809         }
810         rad_assert(PyEval_ThreadsInitialized());
811
812         /*
813          *      Increment the reference counter
814          */
815         python_instances++;
816
817         /*
818          *      This sets up a separate environment for each python module instance
819          *      These will be destroyed on Py_Finalize().
820          */
821         if (!inst->cext_compat) {
822                 inst->sub_interpreter = Py_NewInterpreter();
823         } else {
824                 inst->sub_interpreter = main_interpreter;
825         }
826
827         PyThreadState_Swap(inst->sub_interpreter);
828
829         /*
830          *      Due to limitations in Python, sub-interpreters don't work well
831          *      with Python C extensions if they use GIL lock functions.
832          */
833         if (!inst->cext_compat || !main_module) {
834                 CONF_SECTION *cs;
835
836                 /*
837                  *      Set the python search path
838                  */
839                 if (inst->python_path) {
840 #if PY_VERSION_HEX > 0x03050000
841                         {
842                                 wchar_t *name;
843
844                                 path = Py_DecodeLocale(inst->python_path, strlen(inst->python_path));
845                                 PySys_SetPath(path);
846                                 PyMem_RawFree(path);
847                         }
848 #else
849                         {
850                                 char *path;
851
852                                 path = talloc_strdup(NULL, inst->python_path);
853                                 PySys_SetPath(path);
854                                 talloc_free(path);
855                         }
856 #endif
857                 }
858
859                 /*
860                  *      Initialise a new module, with our default methods
861                  */
862                 inst->module = Py_InitModule3("radiusd", module_methods, "FreeRADIUS python module");
863                 if (!inst->module) {
864                 error:
865                         python_error_log();
866                         PyEval_SaveThread();
867                         return -1;
868                 }
869
870                 /*
871                  *      Py_InitModule3 returns a borrowed ref, the actual
872                  *      module is owned by sys.modules, so we also need
873                  *      to own the module to prevent it being freed early.
874                  */
875                 Py_IncRef(inst->module);
876
877                 if (inst->cext_compat) main_module = inst->module;
878
879                 for (i = 0; radiusd_constants[i].name; i++) {
880                         if ((PyModule_AddIntConstant(inst->module, radiusd_constants[i].name,
881                                                      radiusd_constants[i].value)) < 0)
882                                 goto error;
883                 }
884
885                 /*
886                  *      Convert a FreeRADIUS config structure into a python
887                  *      dictionary.
888                  */
889                 inst->pythonconf_dict = PyDict_New();
890                 if (!inst->pythonconf_dict) {
891                         ERROR("Unable to create python dict for config");
892                         python_error_log();
893                         return -1;
894                 }
895
896                 /*
897                  *      Add module configuration as a dict
898                  */
899                 if (PyModule_AddObject(inst->module, "config", inst->pythonconf_dict) < 0) goto error;
900
901                 cs = cf_section_sub_find(conf, "config");
902                 if (cs) python_parse_config(cs, 0, inst->pythonconf_dict);
903         } else {
904                 inst->module = main_module;
905                 Py_IncRef(inst->module);
906                 inst->pythonconf_dict = PyObject_GetAttrString(inst->module, "config");
907                 Py_IncRef(inst->pythonconf_dict);
908         }
909
910         PyEval_SaveThread();
911
912         return 0;
913 }
914
915 /*
916  *      Do any per-module initialization that is separate to each
917  *      configured instance of the module.  e.g. set up connections
918  *      to external databases, read configuration files, set up
919  *      dictionary entries, etc.
920  *
921  *      If configuration information is given in the config section
922  *      that must be referenced in later calls, store a handle to it
923  *      in *instance otherwise put a null pointer there.
924  *
925  */
926 static int mod_instantiate(CONF_SECTION *conf, void *instance)
927 {
928         rlm_python_t    *inst = instance;
929         int             code = 0;
930
931         inst->name = cf_section_name2(conf);
932         if (!inst->name) inst->name = cf_section_name1(conf);
933
934         /*
935          *      Load the python code required for this module instance
936          */
937         if (python_interpreter_init(inst, conf) < 0) return -1;
938
939         /*
940          *      Switch to our module specific main thread
941          */
942         PyEval_RestoreThread(inst->sub_interpreter);
943
944         /*
945          *      Process the various sections
946          */
947 #define PYTHON_FUNC_LOAD(_x) if (python_function_load(&inst->_x) < 0) goto error
948         PYTHON_FUNC_LOAD(instantiate);
949         PYTHON_FUNC_LOAD(authenticate);
950         PYTHON_FUNC_LOAD(authorize);
951         PYTHON_FUNC_LOAD(preacct);
952         PYTHON_FUNC_LOAD(accounting);
953         PYTHON_FUNC_LOAD(checksimul);
954         PYTHON_FUNC_LOAD(pre_proxy);
955         PYTHON_FUNC_LOAD(post_proxy);
956         PYTHON_FUNC_LOAD(post_auth);
957 #ifdef WITH_COA
958         PYTHON_FUNC_LOAD(recv_coa);
959         PYTHON_FUNC_LOAD(send_coa);
960 #endif
961         PYTHON_FUNC_LOAD(detach);
962
963         /*
964          *      Call the instantiate function.
965          */
966         code = do_python_single(NULL, inst->instantiate.function, "instantiate");
967         if (code < 0) {
968         error:
969                 python_error_log();     /* Needs valid thread with GIL */
970                 PyEval_SaveThread();
971                 return -1;
972         }
973         PyEval_SaveThread();
974
975         return 0;
976 }
977
978 static int mod_detach(void *instance)
979 {
980         rlm_python_t *inst = instance;
981         int          ret;
982
983         /*
984          *      Call module destructor
985          */
986         PyEval_RestoreThread(inst->sub_interpreter);
987
988         ret = do_python_single(NULL, inst->detach.function, "detach");
989
990 #define PYTHON_FUNC_DESTROY(_x) python_function_destroy(&inst->_x)
991         PYTHON_FUNC_DESTROY(instantiate);
992         PYTHON_FUNC_DESTROY(authorize);
993         PYTHON_FUNC_DESTROY(authenticate);
994         PYTHON_FUNC_DESTROY(preacct);
995         PYTHON_FUNC_DESTROY(accounting);
996         PYTHON_FUNC_DESTROY(checksimul);
997         PYTHON_FUNC_DESTROY(detach);
998
999         Py_DecRef(inst->pythonconf_dict);
1000         Py_DecRef(inst->module);
1001
1002         PyEval_SaveThread();
1003
1004         /*
1005          *      Force cleaning up of threads if this is *NOT* a worker
1006          *      thread, which happens if this is being called from
1007          *      unittest framework, and probably with the server running
1008          *      in debug mode.
1009          */
1010         rbtree_free(local_thread_state);
1011         local_thread_state = NULL;
1012
1013         /*
1014          *      Only destroy if it's a subinterpreter
1015          */
1016         if (!inst->cext_compat) python_interpreter_free(inst->sub_interpreter);
1017
1018         if ((--python_instances) == 0) {
1019                 PyThreadState_Swap(main_interpreter); /* Swap to the main thread */
1020                 Py_Finalize();
1021                 dlclose(python_dlhandle);
1022         }
1023
1024         return ret;
1025 }
1026
1027 /*
1028  *      The module name should be the only globally exported symbol.
1029  *      That is, everything else should be 'static'.
1030  *
1031  *      If the module needs to temporarily modify it's instantiation
1032  *      data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
1033  *      The server will then take care of ensuring that the module
1034  *      is single-threaded.
1035  */
1036 extern module_t rlm_python;
1037 module_t rlm_python = {
1038         .magic          = RLM_MODULE_INIT,
1039         .name           = "python",
1040         .type           = RLM_TYPE_THREAD_SAFE,
1041         .inst_size      = sizeof(rlm_python_t),
1042         .config         = module_config,
1043         .instantiate    = mod_instantiate,
1044         .detach         = mod_detach,
1045         .methods = {
1046                 [MOD_AUTHENTICATE]      = mod_authenticate,
1047                 [MOD_AUTHORIZE]         = mod_authorize,
1048                 [MOD_PREACCT]           = mod_preacct,
1049                 [MOD_ACCOUNTING]        = mod_accounting,
1050                 [MOD_SESSION]           = mod_checksimul,
1051                 [MOD_PRE_PROXY]         = mod_pre_proxy,
1052                 [MOD_POST_PROXY]        = mod_post_proxy,
1053                 [MOD_POST_AUTH]         = mod_post_auth,
1054 #ifdef WITH_COA
1055                 [MOD_RECV_COA]          = mod_recv_coa,
1056                 [MOD_SEND_COA]          = mod_send_coa
1057 #endif
1058         }
1059 };