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: 10ed6f412b481fbeb7bb1cb9a3fc5b67ecf7bc86 $
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: 10ed6f412b481fbeb7bb1cb9a3fc5b67ecf7bc86 $")
27 
28 #define LOG_PREFIX mctx->inst->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->inst->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->inst->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->inst,
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->inst->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->inst,
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  .flags = MODULE_TYPE_THREAD_SAFE,
173  .inst_size = sizeof(rlm_lua_t),
174 
175  .thread_inst_size = sizeof(rlm_lua_thread_t),
176 
177  .config = module_config,
178  .instantiate = mod_instantiate,
179  .thread_instantiate = mod_thread_instantiate,
180 
181  .detach = mod_detach,
182  .thread_detach = mod_thread_detach
183  },
184  .method_names = (module_method_name_t[]){
185  /*
186  * Hack to support old configurations
187  */
188  { .name1 = "authorize", .name2 = CF_IDENT_ANY, .method = mod_authorize },
189 
190  { .name1 = "recv", .name2 = "accounting-request", .method = mod_preacct },
191  { .name1 = "recv", .name2 = CF_IDENT_ANY, .method = mod_authorize },
192  { .name1 = "accounting", .name2 = CF_IDENT_ANY, .method = mod_accounting },
193  { .name1 = "authenticate", .name2 = CF_IDENT_ANY, .method = mod_authenticate },
194  { .name1 = "send", .name2 = CF_IDENT_ANY, .method = mod_post_auth },
196  }
197 };
#define RCSID(id)
Definition: build.h:444
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#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:406
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition: cf_parse.h:412
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
#define CF_IDENT_ANY
Definition: cf_util.h:78
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
dl_module_inst_t const * inst
Definition: dl_module.h:87
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
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
void * thread
Thread instance data.
Definition: module_ctx.h:62
#define MODULE_CTX(_dl_inst, _thread, _env_data, _rctx)
Wrapper to create a module_ctx_t as a compound literal.
Definition: module_ctx.h:123
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
Temporary structure to hold arguments for thread_instantiation calls.
Definition: module_ctx.h:58
Specifies a module method identifier.
Definition: module_method.c:36
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:37
#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:248
@ MODULE_TYPE_THREAD_SAFE
Module is threadsafe.
Definition: module.h:49
#define MODULE_NAME_TERMINATOR
Definition: module.h:135
eap_aka_sim_process_conf_t * inst