The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_lua.c
Go to the documentation of this file.
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, version 2 if the
4  * License as published by the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program; if not, write to the Free Software
13  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
14  */
15 
16 /**
17  * $Id: f65d06bfcf8297adb3e158d97fefe2ade77acd77 $
18  * @file rlm_lua.c
19  * @brief Translates requests between the server an a Lua interpreter.
20  *
21  * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
22  *
23  * @copyright 2016 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24  * @copyright 2016 The FreeRADIUS Server Project.
25  */
26 RCSID("$Id: f65d06bfcf8297adb3e158d97fefe2ade77acd77 $")
27 
28 #define LOG_PREFIX mctx->mi->name
29 
30 #include <freeradius-devel/server/base.h>
31 #include <freeradius-devel/util/debug.h>
32 #include <freeradius-devel/server/module_rlm.h>
33 
34 #include "lua.h"
35 /*
36  * A mapping of configuration file names to internal variables.
37  *
38  * Note that the string is dynamically allocated, so it MUST
39  * be freed. When the configuration file parse re-reads the string,
40  * it free's the old one, and strdup's the new one, placing the pointer
41  * to the strdup'd string into 'config.string'. This gets around
42  * buffer over-flows.
43  */
44 static const conf_parser_t module_config[] = {
46  { FR_CONF_OFFSET("func_instantiate", rlm_lua_t, func_instantiate), NULL},
47  { FR_CONF_OFFSET("func_detach", rlm_lua_t, func_detach), NULL},
48  { FR_CONF_OFFSET("func_authorize", rlm_lua_t, func_authorize), NULL},
49  { FR_CONF_OFFSET("func_authenticate", rlm_lua_t, func_authenticate), NULL},
50  { FR_CONF_OFFSET("func_accounting", rlm_lua_t, func_accounting), NULL},
51  { FR_CONF_OFFSET("func_preacct", rlm_lua_t, func_preacct), NULL},
52  { FR_CONF_OFFSET("func_xlat", rlm_lua_t, func_xlat), NULL},
53  { FR_CONF_OFFSET("func_post_auth", rlm_lua_t, func_post_auth), NULL},
54 
56 };
57 
58 #define DO_LUA(_s)\
59 static unlang_action_t mod_##_s(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request) \
60 {\
61  rlm_lua_t const *inst = talloc_get_type_abort_const(mctx->mi->data, rlm_lua_t);\
62  if (!inst->func_##_s) RETURN_MODULE_NOOP;\
63  return fr_lua_run(p_result, mctx, request, inst->func_##_s);\
64 }
65 
66 DO_LUA(authorize)
67 DO_LUA(authenticate)
68 DO_LUA(preacct)
69 DO_LUA(accounting)
70 DO_LUA(post_auth)
71 
72 
73 /** Free any thread specific interpreters
74  *
75  */
77 {
78  rlm_lua_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_lua_thread_t);
79 
80  /*
81  * May be NULL if fr_lua_init failed
82  */
83  if (t->interpreter) lua_close(t->interpreter);
84 
85  return 0;
86 }
87 
88 /** Create thread-specific connections and buffers
89  *
90  * @param[in] mctx specific data (where we write the interpreter).
91  * @return
92  * - 0 on success.
93  * - -1 on failure.
94  */
96 {
97  rlm_lua_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_lua_thread_t);
98 
99  if (fr_lua_init(&t->interpreter, (module_inst_ctx_t const *)mctx) < 0) return -1;
100 
101  return 0;
102 }
103 
104 /** Close the global interpreter
105  *
106  */
107 static int mod_detach(module_detach_ctx_t const *mctx)
108 {
109  rlm_lua_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_lua_t);
110  rlm_rcode_t ret = 0;
111 
112  /*
113  * May be NULL if fr_lua_init failed
114  */
115  if (inst->interpreter) {
116  if (inst->func_detach) {
117  fr_lua_run(&ret,
118  MODULE_CTX(mctx->mi,
119  &(rlm_lua_thread_t){
120  .interpreter = inst->interpreter
121  },
122  NULL, NULL),
123  NULL, inst->func_detach);
124  }
125  lua_close(inst->interpreter);
126  }
127 
128  return ret;
129 }
130 
131 static int mod_instantiate(module_inst_ctx_t const *mctx)
132 {
133  rlm_lua_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_lua_t);
134  rlm_rcode_t rcode;
135 
136  /*
137  * Get an instance global interpreter to use with various things...
138  */
139  if (fr_lua_init(&inst->interpreter, mctx) < 0) return -1;
140  inst->jit = fr_lua_isjit(inst->interpreter);
141  if (!inst->jit) WARN("Using standard Lua interpreter, performance will be suboptimal");
142 
143  DEBUG("Using %s interpreter", fr_lua_version(inst->interpreter));
144 
145  if (inst->func_instantiate) {
146  fr_lua_run(&rcode,
147  MODULE_CTX(mctx->mi,
148  &(rlm_lua_thread_t){
149  .interpreter = inst->interpreter
150  },
151  NULL, NULL),
152  NULL, inst->func_instantiate);
153  }
154 
155  return 0;
156 }
157 
158 /*
159  * The module name should be the only globally exported symbol.
160  * That is, everything else should be 'static'.
161  *
162  * If the module needs to temporarily modify it's instantiation
163  * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
164  * The server will then take care of ensuring that the module
165  * is single-threaded.
166  */
167 extern module_rlm_t rlm_lua;
169  .common = {
170  .magic = MODULE_MAGIC_INIT,
171  .name = "lua",
172  .inst_size = sizeof(rlm_lua_t),
173 
174  .thread_inst_size = sizeof(rlm_lua_thread_t),
175 
176  .config = module_config,
177  .instantiate = mod_instantiate,
178  .thread_instantiate = mod_thread_instantiate,
179 
180  .detach = mod_detach,
181  .thread_detach = mod_thread_detach
182  },
183  .method_group = {
184  .bindings = (module_method_binding_t[]){
185  /*
186  * Hack to support old configurations
187  */
188  { .section = SECTION_NAME("accounting", CF_IDENT_ANY), .method = mod_accounting },
189  { .section = SECTION_NAME("authenticate", CF_IDENT_ANY), .method = mod_authenticate },
190  { .section = SECTION_NAME("authorize", CF_IDENT_ANY), .method = mod_authorize },
191 
192  { .section = SECTION_NAME("recv", "accounting-request"), .method = mod_preacct },
193  { .section = SECTION_NAME("recv", CF_IDENT_ANY), .method = mod_authorize },
194  { .section = SECTION_NAME("send", CF_IDENT_ANY), .method = mod_post_auth },
196  }
197  }
198 };
#define RCSID(id)
Definition: build.h:481
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:627
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:268
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:256
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition: cf_parse.h:405
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition: cf_parse.h:411
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:564
#define CF_IDENT_ANY
Definition: cf_util.h:78
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
unlang_action_t fr_lua_run(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *funcname)
Definition: lua.c:754
char const * fr_lua_version(lua_State *L)
Definition: lua.c:605
bool fr_lua_isjit(lua_State *L)
Check whether the Lua interpreter were actually linked to is LuaJIT.
Definition: lua.c:591
int fr_lua_init(lua_State **out, module_inst_ctx_t const *mctx)
Initialise a new Lua/LuaJIT interpreter.
Definition: lua.c:893
Library function signatures for lua module.
lua_State * interpreter
Thread specific interpreter.
Definition: lua.h:63
Definition: lua.h:43
module_instance_t * mi
Module instance to detach.
Definition: module_ctx.h:57
void * thread
Thread instance data.
Definition: module_ctx.h:67
#define MODULE_CTX(_mi, _thread, _env_data, _rctx)
Wrapper to create a module_ctx_t as a compound literal.
Definition: module_ctx.h:128
module_instance_t * mi
Instance of the module being instantiated.
Definition: module_ctx.h:51
Temporary structure to hold arguments for detach calls.
Definition: module_ctx.h:56
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:50
Temporary structure to hold arguments for thread_instantiation calls.
Definition: module_ctx.h:63
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:39
#define WARN(fmt,...)
Definition: radclient.h:47
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_chap.c:228
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_chap.c:176
static unlang_action_t mod_accounting(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Write accounting data to Couchbase documents.
static unlang_action_t mod_post_auth(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_detail.c:400
module_rlm_t rlm_lua
Definition: rlm_lua.c:168
static int mod_detach(module_detach_ctx_t const *mctx)
Close the global interpreter.
Definition: rlm_lua.c:107
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Create thread-specific connections and buffers.
Definition: rlm_lua.c:95
#define DO_LUA(_s)
Definition: rlm_lua.c:58
static const conf_parser_t module_config[]
Definition: rlm_lua.c:44
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Free any thread specific interpreters.
Definition: rlm_lua.c:76
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_lua.c:131
static unlang_action_t mod_preacct(rlm_rcode_t *p_result, module_ctx_t const *mctx, UNUSED request_t *request)
Definition: rlm_test.c:246
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition: section.h:40
void * data
Module's instance data.
Definition: module.h:271
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition: module.h:151
Named methods exported by a module.
Definition: module.h:173
eap_aka_sim_process_conf_t * inst