The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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: 40c93863c0c8d0913633f4b1d04ab1f3a1c0881d $
18 * @file lua.c
19 * @brief Library functions for the lua module.
20 *
21 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
22 * @author Artur Malinowski (artur@wow.com)
23 *
24 * @copyright 2015 The FreeRADIUS Server Project.
25 */
26RCSID("$Id: 40c93863c0c8d0913633f4b1d04ab1f3a1c0881d $")
27
28#define LOG_PREFIX mctx->mi->name
29
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/util/debug.h>
32
33#include "config.h"
34#include "lua.h"
35
36#include <float.h>
37#include <lauxlib.h>
38#include <lualib.h>
39
40#define RLM_LUA_STACK_SET() int _fr_lua_stack_state = lua_gettop(L)
41#define RLM_LUA_STACK_RESET() lua_settop(L, _fr_lua_stack_state)
42
43DIAG_OFF(type-limits)
44/** Convert fr_pair_ts to Lua values
45 *
46 * Pushes a Lua representation of an attribute value onto the stack.
47 *
48 * @param[in] request The current request.
49 * @param[in] L Lua interpreter.
50 * @param[in] vp to convert.
51 * @return
52 * - 0 on success.
53 * - -1 on failure.
54 */
55static int fr_lua_marshall(request_t *request, lua_State *L, fr_pair_t const *vp)
56{
57 if (!vp) return -1;
58
59#if PTRDIFF_MAX < INT64_MAX
60#define IN_RANGE_INTEGER_SIGNED(_x) \
61 do { \
62 if ((((int64_t)(_x)) < PTRDIFF_MIN) || (((int64_t)(_x)) > PTRDIFF_MAX)) { \
63 REDEBUG("Value (%" PRId64 ") cannot be represented as Lua integer. Must be between %td-%td", \
64 (int64_t)(_x), (ptrdiff_t)PTRDIFF_MIN, (ptrdiff_t)PTRDIFF_MAX); \
65 return -1; \
66 } \
67 } while (0)
68
69#define IN_RANGE_INTEGER_UNSIGNED(_x) \
70 do { \
71 if (((uint64_t)(_x)) > PTRDIFF_MAX) { \
72 REDEBUG("Value (%" PRIu64 ") cannot be represented as Lua integer. Must be between 0-%td", \
73 (uint64_t)(_x), (ptrdiff_t)PTRDIFF_MAX); \
74 return -1; \
75 } \
76 } while (0)
77#else
78#define IN_RANGE_INTEGER_SIGNED(_x) \
79 do { \
80 } while (0)
81
82#define IN_RANGE_INTEGER_UNSIGNED(_x) \
83 do { \
84 } while (0)
85#endif
86
87#define IN_RANGE_FLOAT_SIGNED(_x) \
88 do { \
89 if ((((double)(_x)) < DBL_MIN) || (((double)(_x)) > DBL_MAX)) { \
90 REDEBUG("Value (%f) cannot be represented as Lua number. Must be between %f-%f", \
91 (double)(_x), DBL_MIN, DBL_MAX); \
92 return -1; \
93 } \
94 } while (0)
95
96 switch (vp->vp_type) {
104 case FR_TYPE_IFID:
106 {
107 char buff[128];
108 ssize_t slen;
109
111 if (slen < 0) {
112 REDEBUG("Cannot convert %s to Lua type, insufficient buffer space",
113 fr_type_to_str(vp->vp_type));
114 return -1;
115 }
116
117 lua_pushlstring(L, buff, (size_t)slen);
118 }
119 break;
120
121 case FR_TYPE_STRING:
122 lua_pushlstring(L, vp->vp_strvalue, vp->vp_length);
123 break;
124
125 case FR_TYPE_OCTETS:
126 lua_pushlstring(L, (char const *)vp->vp_octets, vp->vp_length); /* lstring variant is embedded NULL safe */
127 break;
128
129 case FR_TYPE_BOOL:
130 lua_pushinteger(L, (lua_Integer)(vp->vp_bool ? 1 : 0));
131 break;
132
133 case FR_TYPE_UINT8:
134 lua_pushinteger(L, (lua_Integer)vp->vp_uint8);
135 break;
136
137 case FR_TYPE_UINT16:
138 lua_pushinteger(L, (lua_Integer)vp->vp_uint16);
139 break;
140
141 case FR_TYPE_UINT32:
142 lua_pushinteger(L, (lua_Integer)vp->vp_uint32);
143 break;
144
145 case FR_TYPE_UINT64:
146 IN_RANGE_INTEGER_UNSIGNED(vp->vp_uint64);
147 lua_pushinteger(L, (lua_Integer)vp->vp_uint64);
148 break;
149
150 case FR_TYPE_INT8:
151 lua_pushinteger(L, (lua_Integer)vp->vp_int8);
152 break;
153
154 case FR_TYPE_INT16:
155 lua_pushinteger(L, (lua_Integer)vp->vp_int16);
156 break;
157
158 case FR_TYPE_INT32:
159 lua_pushinteger(L, (lua_Integer)vp->vp_int32);
160 break;
161
162 case FR_TYPE_INT64:
163 IN_RANGE_INTEGER_SIGNED(vp->vp_int64);
164 lua_pushinteger(L, (lua_Integer)vp->vp_int64);
165 break;
166
167 case FR_TYPE_DATE:
168 lua_pushinteger(L, (lua_Integer) fr_unix_time_to_sec(vp->vp_date));
169 break;
170
171 case FR_TYPE_FLOAT32:
172 IN_RANGE_FLOAT_SIGNED(vp->vp_float32);
173 lua_pushnumber(L, (lua_Number)vp->vp_float32);
174 break;
175
176 case FR_TYPE_FLOAT64:
177 IN_RANGE_FLOAT_SIGNED(vp->vp_float64);
178 lua_pushnumber(L, (lua_Number)vp->vp_float64);
179 break;
180
181 case FR_TYPE_SIZE:
183 lua_pushinteger(L, (lua_Integer)vp->vp_size);
184 break;
185
186 case FR_TYPE_NON_LEAF:
187 REDEBUG("Cannot convert %s to Lua type", fr_type_to_str(vp->vp_type));
188 return -1;
189 }
190 return 0;
191}
192DIAG_ON(type-limits)
193
194/** Convert Lua values to fr_pair_ts
195 *
196 * Convert Lua values back to fr_pair_ts. How the Lua value is converted is dependent
197 * on the type of the DA.
198 *
199 * @param[in] ctx To allocate new fr_pair_t in.
200 * @param[out] out Where to write a pointer to the new fr_pair_t.
201 * @param[in] inst the current instance.
202 * @param[in] request the current request.
203 * @param[in] L Lua interpreter.
204 * @param[in] da specifying the type of attribute to create.
205 * @return
206 * - 0 on success.
207 * - -1 on failure.
208 */
209static int fr_lua_unmarshall(TALLOC_CTX *ctx, fr_pair_t **out,
210 UNUSED rlm_lua_t const *inst, request_t *request, lua_State *L, fr_dict_attr_t const *da)
211{
212 fr_pair_t *vp;
213
214 MEM(vp = fr_pair_afrom_da(ctx, da));
215 switch (lua_type(L, -1)) {
216 case LUA_TNUMBER:
217 {
219
220 /*
221 * lua_tonumber actually returns ptrdiff_t
222 * so we need to check if our input box
223 * type is the same width or greater.
224 */
225 static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int64) >= sizeof(ptrdiff_t),
226 "fr_value_box_t field smaller than return from lua_tointeger");
227
228 static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_float64) >= sizeof(double),
229 "fr_value_box_t field smaller than return from lua_tonumber");
230
231 switch (vp->vp_type) {
232 /*
233 * Preserve decimal precision.
234 *
235 * Our FR_TYPE_FLOAT64 is a double, which is apparently
236 * what lua_tonumber returns on most platforms.
237 */
238 case FR_TYPE_FLOAT32:
239 case FR_TYPE_FLOAT64:
240 fr_value_box_init(&vb, FR_TYPE_FLOAT64, NULL, true);
241 vb.vb_float64 = lua_tonumber(L, -1);
242 break;
243
244 default:
245 fr_value_box_init(&vb, FR_TYPE_INT64, NULL, true);
246 vb.vb_int64 = lua_tointeger(L, -1);
247 break;
248 }
249
250
251 if (fr_value_box_cast(vp, &vp->data, vp->vp_type, vp->da, &vb) < 0) {
252 RPEDEBUG("Failed unmarshalling Lua number for \"%s\"", vp->da->name);
253 return -1;
254 }
255 }
256 break;
257
258 case LUA_TSTRING:
259 {
261 char const *p;
262 size_t len;
263
264 p = (char const *)lua_tolstring(L, -1, &len);
265 if (!p) {
266 REDEBUG("Unmarshalling failed, Lua bstring was NULL");
267 return -1;
268 }
269
270 fr_value_box_bstrndup_shallow(&vb, NULL, p, len, true);
271
272 if (fr_value_box_cast(vp, &vp->data, vp->vp_type, vp->da, &vb) < 0) {
273 RPEDEBUG("Failed unmarshalling Lua string for \"%s\"", vp->da->name);
274 return -1;
275 }
276 }
277 break;
278
279 case LUA_TLIGHTUSERDATA:
280 case LUA_TUSERDATA:
281 {
282 size_t len;
283 uint8_t *p;
284
285 len = lua_objlen(L, -1);
286 if (len == 0) {
287 REDEBUG("Unmarshalling failed, can't determine length of user data");
288 return -1;
289 }
290 p = lua_touserdata(L, -1);
291 if (!p) {
292 REDEBUG("Unmarshalling failed, user data was NULL");
293 }
294 fr_pair_value_memdup(vp, p, len, true);
295 }
296 break;
297
298 default:
299 {
300 int type = lua_type(L, -1);
301 REDEBUG("Unmarshalling failed, unsupported Lua type %s (%i)", lua_typename(L, type), type);
302
303 return -1;
304 }
305 }
306
307 *out = vp;
308 return 0;
309}
310
311/** Get an instance of an attribute
312 *
313 * @note Should only be present in the Lua environment as a closure.
314 * @note Takes one upvalue - the fr_dict_attr_t to search for as light user data.
315 * @note Is called as an __index metamethod, so takes the table (can be ignored)
316 * and the field (an integer index value)
317 *
318 * @param[in] L Lua interpreter.
319 * @return
320 * - 0 (no results) on success.
321 * - 1 on success with the fr_pair_t value on the stack.
322 */
323static int _lua_pair_get(lua_State *L)
324{
326
327 fr_dcursor_t cursor;
328 fr_dict_attr_t const *da;
329 fr_pair_t *vp = NULL;
330 int index;
331
332 fr_assert(lua_islightuserdata(L, lua_upvalueindex(1)));
333
334 da = lua_touserdata(L, lua_upvalueindex(1));
335 fr_assert(da);
336
337 /*
338 * @fixme Packet list should be light user data too at some point
339 */
340 fr_pair_dcursor_by_da_init(&cursor, &request->request_pairs, da);
341
342 for (index = (int) lua_tointeger(L, -1); index >= 0; index--) {
343 vp = fr_dcursor_next(&cursor);
344 if (!vp) return 0;
345 }
346
347 if (fr_lua_marshall(request, L, vp) < 0) return -1;
348
349 return 1;
350}
351
352/** Set an instance of an attribute
353 *
354 * @note Should only be present in the Lua environment as a closure.
355 * @note Takes one upvalue - the fr_dict_attr_t to search for as light user data.
356 * @note Is called as an __newindex metamethod, so takes the table (can be ignored),
357 * the field (an integer index value) and the new value.
358 *
359 * @param[in] L Lua interpreter.
360 * @return
361 * - 0 on success.
362 * - -1 on failure.
363 */
364static int _lua_pair_set(lua_State *L)
365{
366 module_ctx_t const *mctx = fr_lua_util_get_mctx();
367 rlm_lua_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_lua_t);
369 fr_dcursor_t cursor;
370 fr_dict_attr_t const *da;
371 fr_pair_t *vp = NULL, *new;
372 lua_Integer index;
373 bool delete = false;
374
375 /*
376 * This function should only be called as a closure.
377 * As we control the upvalues, we should assert on errors.
378 */
379 fr_assert(lua_islightuserdata(L, lua_upvalueindex(1)));
380
381 da = lua_touserdata(L, lua_upvalueindex(1));
382 fr_assert(da);
383
384 delete = lua_isnil(L, -1);
385
386 /*
387 * @fixme Packet list should be light user data too at some point
388 */
389 fr_pair_dcursor_by_da_init(&cursor, &request->request_pairs, da);
390
391 for (index = lua_tointeger(L, -2); index >= 0; index--) {
392 vp = fr_dcursor_next(&cursor);
393 if (vp) break;
394 }
395
396 /*
397 * If the value of the Lua stack was nil, we delete the
398 * attribute the cursor is currently positioned at.
399 */
400 if (delete) {
401 fr_dcursor_remove(&cursor);
402 return 0;
403 }
404
405 if (fr_lua_unmarshall(request->request_ctx, &new, inst, request, L, da) < 0) return -1;
406
407 /*
408 * If there was already a VP at that index we replace it
409 * else we add a new VP to the list.
410 */
411 if (vp) {
412 fr_dcursor_replace(&cursor, new);
413 } else {
414 fr_dcursor_append(&cursor, new);
415 }
416
417 return 0;
418}
419
420static int _lua_pair_iterator(lua_State *L)
421{
423
424 fr_dcursor_t *cursor;
425 fr_pair_t *vp;
426
427 /*
428 * This function should only be called as a closure.
429 * As we control the upvalues, we should assert on errors.
430 */
431
432 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
433
434 cursor = lua_touserdata(L, lua_upvalueindex(1));
435 fr_assert(cursor);
436
437 /* Packet list should be light user data too at some point... */
438 vp = fr_dcursor_next(cursor);
439 if (!vp) {
440 lua_pushnil(L);
441 return 1;
442 }
443
444 if (fr_lua_marshall(request, L, vp) < 0) return -1;
445
446 return 1;
447}
448
449static int _lua_pair_iterator_init(lua_State *L)
450{
452
453 fr_dcursor_t *cursor;
454 fr_dict_attr_t const *da;
455
456
457 /*
458 * This function should only be called as a closure.
459 * As we control the upvalues, we should assert on errors.
460 */
461 fr_assert(lua_isuserdata(L, lua_upvalueindex(2)));
462
463 da = lua_touserdata(L, lua_upvalueindex(2));
464 fr_assert(da);
465
466 cursor = (fr_dcursor_t*) lua_newuserdata(L, sizeof(fr_dcursor_t));
467 if (!cursor) {
468 REDEBUG("Failed allocating user data to hold cursor");
469 return -1;
470 }
471 fr_pair_dcursor_by_da_init(cursor, &request->request_pairs, da); /* @FIXME: Shouldn't use list head */
472
473 lua_pushcclosure(L, _lua_pair_iterator, 1);
474
475 return 1;
476}
477
478static int _lua_list_iterator(lua_State *L)
479{
481
482 fr_dcursor_t *cursor;
483 fr_pair_t *vp;
484
485 fr_assert(lua_isuserdata(L, lua_upvalueindex(1)));
486
487 cursor = lua_touserdata(L, lua_upvalueindex(1));
488 fr_assert(cursor);
489
490 /* Packet list should be light user data too at some point... */
491 vp = fr_dcursor_current(cursor);
492
493 /* Nested attributes are not currently supported */
494 while (vp && fr_type_is_structural(vp->da->type)) vp = fr_dcursor_next(cursor);
495 if(!vp) {
496 lua_pushnil(L);
497 return 1;
498 }
499
500 lua_pushstring(L, vp->da->name);
501
502 if (fr_lua_marshall(request, L, vp) < 0) return -1;
503
504 fr_dcursor_next(cursor);
505
506 return 2;
507}
508
509/** Initialise a new top level list iterator
510 *
511 */
512static int _lua_list_iterator_init(lua_State *L)
513{
515 fr_dcursor_t *cursor;
516
517 cursor = (fr_dcursor_t*) lua_newuserdata(L, sizeof(fr_dcursor_t));
518 if (!cursor) {
519 REDEBUG("Failed allocating user data to hold cursor");
520 return -1;
521 }
522 fr_pair_dcursor_init(cursor, &request->request_pairs); /* @FIXME: Shouldn't use list head */
523
524 lua_pushlightuserdata(L, cursor);
525 lua_pushcclosure(L, _lua_list_iterator, 1);
526
527 return 1;
528}
529
530/** Initialise and return a new accessor table
531 *
532 *
533 */
534static int _lua_pair_accessor_init(lua_State *L)
535{
537 char const *attr;
538 fr_dict_attr_t const *da;
539 fr_dict_attr_t *up;
540
541 attr = lua_tostring(L, -1);
542 if (!attr) {
543 REDEBUG("Failed retrieving field name from lua stack");
544 return -1;
545 }
546
547 da = fr_dict_attr_by_name(NULL, fr_dict_root(request->dict), attr);
548 if (!da) {
549 REDEBUG("Unknown or invalid attribute name \"%s\"", attr);
550 return -1;
551 }
552 up = UNCONST(fr_dict_attr_t *, da);
553
554 /*
555 * Add the pairs method to the main table, this allows
556 * easy iteration over multiple values of the same
557 * attribute.
558 *
559 * for v in request[User-Name].pairs() do
560 */
561 lua_newtable(L);
562 lua_pushlightuserdata(L, &request->request_pairs);
563 lua_pushlightuserdata(L, up);
564 lua_pushcclosure(L, _lua_pair_iterator_init, 2);
565 lua_setfield(L, -2, "pairs");
566
567 /*
568 * Metatable methods for getting and setting
569 */
570 lua_newtable(L);
571 lua_pushlightuserdata(L, up);
572 lua_pushcclosure(L, _lua_pair_get, 1);
573 lua_setfield(L, -2, "__index");
574
575 lua_pushlightuserdata(L, up);
576 lua_pushcclosure(L, _lua_pair_set, 1);
577 lua_setfield(L, -2, "__newindex");
578
579 lua_setmetatable(L, -2);
580 lua_settable(L, -3); /* Cache the attribute manipulation object */
581 lua_getfield(L, -1, attr); /* and return it */
582
583 return 1;
584}
585
586/** Check whether the Lua interpreter were actually linked to is LuaJIT
587 *
588 * @param L Lua interpreter.
589 * @return true if were running with LuaJIT else false.
590 */
591bool fr_lua_isjit(lua_State *L)
592{
593 bool ret = false;
595 lua_getglobal(L, "jit");
596 if (lua_isnil(L, -1)) goto done;
597
598 ret = true;
599done:
601
602 return ret;
603}
604
605char const *fr_lua_version(lua_State *L)
606{
607 char const *version;
608
610 lua_getglobal(L, "jit");
611 if (!lua_isnil(L, -1)) {
612 lua_getfield(L, -1, "version"); /* Version field in jit table */
613 } else {
614 lua_getglobal(L, "_VERSION"); /* Version global */
615 }
616
617 if (lua_isnil(L, -1) || !(version = lua_tostring(L, -1))) {
618 return "unknown version";
619 }
621
622 return version;
623}
624
625/** Check if a given function was loaded into an index in the global table
626 *
627 * Also check what was loaded there is a function and that it accepts the correct arguments.
628 *
629 * @param[in] mctx module instantiation data.
630 * @param[in] L the lua state.
631 * @param[in] name of function to check.
632 * @returns 0 on success (function is present and correct), or -1 on failure.
633 */
634static int fr_lua_check_func(module_inst_ctx_t const *mctx, lua_State *L, char const *name)
635{
636 int ret;
637 int type;
638
640
641 if (name == NULL) return 0;
642
643 lua_getglobal(L, name);
644
645 /*
646 * Check the global is a function.
647 */
648 type = lua_type(L, -1);
649 switch (type) {
650 case LUA_TFUNCTION:
651 break;
652
653 case LUA_TNIL:
654 ERROR("Function \"%s\" not found ", name);
655 ret = -1;
656 goto done;
657
658 default:
659 ERROR("Value found at index \"%s\" is not a function (is a %s)", name, lua_typename(L, type));
660 ret = -1;
661 goto done;
662 }
663 ret = 0;
664done:
666 return ret;
667}
668
669/** Resolve a path string to a field value in Lua
670 *
671 * Parses a string in the format
672 * @verbatim obj0[.obj1][.objN] @endverbatim, adding all tables it traverses
673 * to the stack.
674 *
675 * All paths are assumed to start at a global, so the first field
676 * will be looked up in the global table.
677 *
678 */
679static int fr_lua_get_field(lua_State *L, request_t *request, char const *field)
680{
681 char buff[512];
682 char const *p = field, *q;
683
684 q = strchr(p, '.');
685 if (!q) { /* No field, just global */
686 lua_getglobal(L, p);
687 if (lua_isnil(L, -1)) {
688 does_not_exist:
689 REMARKER(field, p - field, "Field does not exist");
690 return -1;
691 }
692 return 0;
693 }
694
695 if ((size_t) (q - p) >= sizeof(buff)) {
696 too_long:
697 REDEBUG("Field name too long, expected < %zu, got %zu", q - p, sizeof(buff));
698 return -1;
699 }
700
701 strlcpy(buff, p, (q - p) + 1);
702 lua_getglobal(L, buff);
703 if (lua_isnil(L, -1)) goto does_not_exist;
704 p = q + 1; /* Skip the '.' */
705
706 while ((q = strchr(p, '.'))) {
707 if ((size_t) (q - p) >= sizeof(buff)) goto too_long;
708
709 strlcpy(buff, p, (q - p) + 1);
710 lua_getfield(L, -1, buff);
711 if (lua_isnil(L, -1)) goto does_not_exist;
712 p = q + 1;
713 }
714
715 lua_getfield(L, -1, p);
716 if (lua_isnil(L, -1)) goto does_not_exist;
717
718 return 0;
719}
720
721static void _lua_fr_request_register(lua_State *L, request_t *request)
722{
723 /* fr = {} */
724 lua_getglobal(L, "fr");
725 luaL_checktype(L, -1, LUA_TTABLE);
726
727 /* fr = { request {} } */
728 lua_newtable(L);
729
730 if (request) {
731 fr_dcursor_t cursor;
732
733 /* Attribute list table */
734 fr_pair_list_sort(&request->request_pairs, fr_pair_cmp_by_da);
735 fr_pair_dcursor_init(&cursor, &request->request_pairs);
736
737 /*
738 * Setup the environment
739 */
740 lua_pushlightuserdata(L, &cursor);
741 lua_pushcclosure(L, _lua_list_iterator_init, 1);
742 lua_setfield(L, -2, "pairs");
743
744 lua_newtable(L); /* Attribute list meta-table */
745 lua_pushinteger(L, request_attr_request->attr);
746 lua_pushcclosure(L, _lua_pair_accessor_init, 1);
747 lua_setfield(L, -2, "__index");
748 lua_setmetatable(L, -2);
749 }
750
751 lua_setfield(L, -2, "request");
752}
753
754unlang_action_t fr_lua_run(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *funcname)
755{
756 rlm_lua_thread_t *thread = talloc_get_type_abort(mctx->thread, rlm_lua_thread_t);
757 lua_State *L = thread->interpreter;
759
762
763 ROPTIONAL(RDEBUG2, DEBUG2, "Calling %s() in interpreter %p", funcname, L);
764
765 _lua_fr_request_register(L, request);
766
767 /*
768 * Get the function were going to be calling
769 */
770 if (fr_lua_get_field(L, request, funcname) < 0) {
771error:
774
776 }
777
778 if (!lua_isfunction(L, -1)) {
779 int type = lua_type(L, -1);
780
781 ROPTIONAL(RDEBUG2, DEBUG2, "'%s' is not a function, is a %s (%i)", funcname, lua_typename(L, type), type);
782 goto error;
783 }
784
785 if (lua_pcall(L, 0, 1, 0) != 0) {
786 char const *msg = lua_tostring(L, -1);
787
788 ROPTIONAL(RDEBUG2, DEBUG2, "Call to %s failed: %s", funcname, msg ? msg : "unknown error");
789 goto error;
790 }
791
792 /*
793 * functions without rcodeurn or rcodeurning none/nil will be RLM_MODULE_OK
794 */
795 if (!lua_isnoneornil(L, -1)) {
796 /*
797 * e.g: rcodeurn 2, rcodeurn "2", rcodeurn fr.handled, fr.fail, ...
798 */
799 if (lua_isnumber(L, -1)) {
800 rcode = lua_tointeger(L, -1);
801 if (fr_table_str_by_value(rcode_table, rcode, NULL) != NULL) goto done;
802 }
803
804 /*
805 * e.g: rcodeurn "handled", "ok", "fail", ...
806 */
807 if (lua_isstring(L, -1)) {
808 rcode = fr_table_value_by_str(rcode_table, lua_tostring(L, -1), -1);
809 if ((int)rcode != -1) goto done;
810 }
811
812 ROPTIONAL(RDEBUG2, DEBUG2, "Lua function %s() rcodeurned invalid rcode \"%s\"", funcname, lua_tostring(L, -1));
813 goto error;
814 }
815
816done:
819
820 RETURN_MODULE_RCODE(rcode);
821}
822
823/*
824 * Initialise the table "fr." with all valid return codes.
825 */
826static int _lua_rcode_table_newindex(UNUSED lua_State *L)
827{
829
830 RWDEBUG("You can't modify the table 'fr.rcode.{}' (read-only)");
831
832 return 1;
833}
834
835static int _lua_rcode_table_index(lua_State *L)
836{
837 char const *key = lua_tostring(L, -1);
838 int ret;
839
840 ret = fr_table_value_by_str(rcode_table, key, -1);
841 if (ret != -1) {
842 lua_pushinteger(L, ret);
843 return 1;
844 }
845
846 lua_pushfstring(L, "The fr.rcode.%s is not found", key);
847 return -1;
848}
849
850/*
851 * As can be seen in http://luajit.org/extensions.html, the pairs() is disabled by default.
852 * ps: We add pairs() method just to inform the user that it does not work.
853 */
854static int _lua_rcode_table_pairs(lua_State *L)
855{
856 lua_pushfstring(L, "The pairs(fr.rcode) is not available. Access directly! e.g: 'fr.rcode.reject'");
857 return -1;
858}
859
860static void fr_lua_rcode_register(lua_State *L, char const *name)
861{
862 const luaL_Reg metatable[] = {
863 { "__index", _lua_rcode_table_index },
864 { "__newindex", _lua_rcode_table_newindex },
865 { "__pairs", _lua_rcode_table_pairs },
866#ifdef HAVE_LUAJIT_H
867 { "pairs", _lua_rcode_table_pairs },
868#endif
869 { NULL, NULL }
870 };
871
872 /* fr = {} */
873 lua_getglobal(L, "fr");
874 luaL_checktype(L, -1, LUA_TTABLE);
875
876 /* fr = { rcode = {} } */
877 lua_newtable(L);
878 {
879 luaL_register(L, name, metatable);
880 lua_setmetatable(L, -2);
881 lua_setfield(L, -2, name);
882 }
883}
884
885/** Initialise a new Lua/LuaJIT interpreter
886 *
887 * Creates a new lua_State and verifies all required functions have been loaded correctly.
888 *
889 * @param[in] out Where to write a pointer to the new state.
890 * @param[in] mctx configuration data for the
891 * @return 0 on success else -1.
892 */
893int fr_lua_init(lua_State **out, module_inst_ctx_t const *mctx)
894{
896 lua_State *L;
897
899
900 L = luaL_newstate();
901 if (!L) {
902 ERROR("Failed initialising Lua state");
903 return -1;
904 }
905
906 luaL_openlibs(L);
907
908 /*
909 * Load the Lua file into our environment.
910 */
911 if (luaL_loadfile(L, inst->module) != 0) {
912 ERROR("Failed loading file: %s", lua_gettop(L) ? lua_tostring(L, -1) : "Unknown error");
913
914 error:
915 *out = NULL;
917 lua_close(L);
918 return -1;
919 }
920
921 if (lua_pcall(L, 0, LUA_MULTRET, 0) != 0) {
922 ERROR("Failed executing script: %s", lua_gettop(L) ? lua_tostring(L, -1) : "Unknown error");
923
924 goto error;
925 }
926
927 /*
928 * Setup "fr.{}"
929 */
931
932 /*
933 * Setup "fr.log.{}"
934 */
935 if (inst->jit) {
936 DEBUG4("Initialised new LuaJIT interpreter %p", L);
937 if (fr_lua_util_jit_log_register(L) < 0) goto error;
938 } else {
939 DEBUG4("Initialised new Lua interpreter %p", L);
940 if (fr_lua_util_log_register(L) < 0) goto error;
941 }
942
943 /*
944 * Setup the "fr.rcode.{}" with all RLM_MODULE_*
945 * e.g: "fr.rcode.reject", "fr.rcode.ok", ...
946 */
947 fr_lua_rcode_register(L, "rcode");
948
949 /*
950 * Verify all the functions were provided.
951 */
952 if (fr_lua_check_func(mctx, L, inst->func_authorize)
953 || fr_lua_check_func(mctx, L, inst->func_authenticate)
954 || fr_lua_check_func(mctx, L, inst->func_preacct)
955 || fr_lua_check_func(mctx, L, inst->func_accounting)
956 || fr_lua_check_func(mctx, L, inst->func_post_auth)
957 || fr_lua_check_func(mctx, L, inst->func_instantiate)
958 || fr_lua_check_func(mctx, L, inst->func_detach)
959 || fr_lua_check_func(mctx, L, inst->func_xlat)) {
960 goto error;
961 }
962
963 *out = L;
964 return 0;
965}
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
log_entry msg
Definition acutest.h:794
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define RCSID(id)
Definition build.h:483
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define DIAG_ON(_x)
Definition build.h:458
#define SIZEOF_MEMBER(_t, _m)
Definition build.h:336
#define UNUSED
Definition build.h:315
#define DIAG_OFF(_x)
Definition build.h:457
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
static void * fr_dcursor_replace(fr_dcursor_t *cursor, void *r)
Replace the current item.
Definition dcursor.h:610
static void * fr_dcursor_remove(fr_dcursor_t *cursor)
Remove the current item.
Definition dcursor.h:480
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
Definition dcursor.h:337
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
Definition dict_util.c:3263
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2400
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition log.h:528
#define RWDEBUG(fmt,...)
Definition log.h:361
#define DEBUG4(_fmt,...)
Definition log.h:267
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:498
#define RPEDEBUG(fmt,...)
Definition log.h:376
#define RLM_LUA_STACK_RESET()
Definition lua.c:41
static int _lua_rcode_table_newindex(UNUSED lua_State *L)
Definition lua.c:826
static void _lua_fr_request_register(lua_State *L, request_t *request)
Definition lua.c:721
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
static int fr_lua_get_field(lua_State *L, request_t *request, char const *field)
Resolve a path string to a field value in Lua.
Definition lua.c:679
static int _lua_pair_set(lua_State *L)
Set an instance of an attribute.
Definition lua.c:364
#define RLM_LUA_STACK_SET()
Definition lua.c:40
char const * fr_lua_version(lua_State *L)
Definition lua.c:605
static int fr_lua_marshall(request_t *request, lua_State *L, fr_pair_t const *vp)
Convert fr_pair_ts to Lua values.
Definition lua.c:55
static int fr_lua_unmarshall(TALLOC_CTX *ctx, fr_pair_t **out, UNUSED rlm_lua_t const *inst, request_t *request, lua_State *L, fr_dict_attr_t const *da)
Convert Lua values to fr_pair_ts.
Definition lua.c:209
static int _lua_list_iterator(lua_State *L)
Definition lua.c:478
static int _lua_pair_iterator_init(lua_State *L)
Definition lua.c:449
static int _lua_list_iterator_init(lua_State *L)
Initialise a new top level list iterator.
Definition lua.c:512
bool fr_lua_isjit(lua_State *L)
Check whether the Lua interpreter were actually linked to is LuaJIT.
Definition lua.c:591
static int _lua_pair_get(lua_State *L)
Get an instance of an attribute.
Definition lua.c:323
static int _lua_rcode_table_pairs(lua_State *L)
Definition lua.c:854
static int _lua_pair_iterator(lua_State *L)
Definition lua.c:420
#define IN_RANGE_FLOAT_SIGNED(_x)
#define IN_RANGE_INTEGER_UNSIGNED(_x)
static int fr_lua_check_func(module_inst_ctx_t const *mctx, lua_State *L, char const *name)
Check if a given function was loaded into an index in the global table.
Definition lua.c:634
int fr_lua_init(lua_State **out, module_inst_ctx_t const *mctx)
Initialise a new Lua/LuaJIT interpreter.
Definition lua.c:893
static int _lua_rcode_table_index(lua_State *L)
Definition lua.c:835
static int _lua_pair_accessor_init(lua_State *L)
Initialise and return a new accessor table.
Definition lua.c:534
#define IN_RANGE_INTEGER_SIGNED(_x)
static void fr_lua_rcode_register(lua_State *L, char const *name)
Definition lua.c:860
Library function signatures for lua module.
int fr_lua_util_jit_log_register(lua_State *L)
Insert cdefs into the lua environment.
Definition util.c:202
void fr_lua_util_set_mctx(module_ctx_t const *mctx)
Set the thread local instance.
Definition util.c:321
request_t * fr_lua_util_get_request(void)
Get the thread local request.
Definition util.c:348
void fr_lua_util_set_request(request_t *request)
Set the thread local request.
Definition util.c:339
void fr_lua_util_fr_register(lua_State *L)
Definition util.c:40
int fr_lua_util_log_register(lua_State *L)
Register utililiary functions in the lua environment.
Definition util.c:280
module_ctx_t const * fr_lua_util_get_mctx(void)
Get the thread local instance.
Definition util.c:330
lua_State * interpreter
Thread specific interpreter.
Definition lua.h:63
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_FLOAT64
Double precision floating point.
long int ssize_t
unsigned char uint8_t
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
void * thread
Thread specific instance data.
Definition module_ctx.h:43
#define MODULE_CTX_FROM_INST(_mctx)
Wrapper to create a module_ctx_t as a compound literal from a module_inst_ctx_t.
Definition module_ctx.h:138
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition pair.c:2981
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition pair.c:283
int8_t fr_pair_cmp_by_da(void const *a, void const *b)
Order attributes by their da, and tag.
Definition pair.c:1844
#define fr_assert(_expr)
Definition rad_assert.h:38
static bool done
Definition radclient.c:80
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define DEBUG2(fmt,...)
Definition radclient.h:43
fr_table_num_sorted_t const rcode_table[]
Definition rcode.c:35
#define RETURN_MODULE_RCODE(_rcode)
Definition rcode.h:64
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:43
fr_dict_attr_t const * request_attr_request
Definition request.c:45
static char const * name
#define FR_SBUFF_OUT(_start, _len_or_end)
void * data
Module's instance data.
Definition module.h:271
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:41
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
fr_pair_t * vp
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition strlcpy.c:34
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
#define talloc_get_type_abort_const
Definition talloc.h:282
static int64_t fr_unix_time_to_sec(fr_unix_time_t delta)
Definition time.h:506
@ T_BARE_WORD
Definition token.h:120
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
Definition pair.h:628
void fr_pair_list_sort(fr_pair_list_t *list, fr_cmp_t cmp)
Sort a doubly linked list of fr_pair_ts using merge sort.
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
Definition pair_print.c:53
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:591
#define fr_type_is_structural(_x)
Definition types.h:371
#define FR_TYPE_NON_LEAF
Definition types.h:298
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:433
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition value.c:3352
void fr_value_box_bstrndup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Assign a string to to a fr_value_box_t.
Definition value.c:4232
#define vb_int64
Definition value.h:261
#define vb_float64
Definition value.h:264
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:587
static size_t char ** out
Definition value.h:997