The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 3a15db339867f2107a0dd7f63fd65627a8dbe743 $
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  */
26 RCSID("$Id: 3a15db339867f2107a0dd7f63fd65627a8dbe743 $")
27 
28 #define LOG_PREFIX mctx->inst->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 
43 DIAG_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  */
55 static 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) {
97  case FR_TYPE_ETHERNET:
98  case FR_TYPE_IPV4_ADDR:
99  case FR_TYPE_IPV6_ADDR:
100  case FR_TYPE_IPV4_PREFIX:
101  case FR_TYPE_IPV6_PREFIX:
104  case FR_TYPE_IFID:
105  case FR_TYPE_TIME_DELTA:
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:
182  IN_RANGE_INTEGER_UNSIGNED(vp->vp_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 }
192 DIAG_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  */
209 static 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  {
218  fr_value_box_t vb;
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 
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  {
260  fr_value_box_t vb;
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  */
323 static int _lua_pair_get(lua_State *L)
324 {
325  request_t *request = fr_lua_util_get_request();
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  */
364 static 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->inst->data, rlm_lua_t);
368  request_t *request = fr_lua_util_get_request();
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 
420 static int _lua_pair_iterator(lua_State *L)
421 {
422  request_t *request = fr_lua_util_get_request();
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 
449 static int _lua_pair_iterator_init(lua_State *L)
450 {
451  request_t *request = fr_lua_util_get_request();
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 
478 static int _lua_list_iterator(lua_State *L)
479 {
480  request_t *request = fr_lua_util_get_request();
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  */
512 static int _lua_list_iterator_init(lua_State *L)
513 {
514  request_t *request = fr_lua_util_get_request();
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  */
534 static int _lua_pair_accessor_init(lua_State *L)
535 {
536  request_t *request = fr_lua_util_get_request();
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  */
591 bool 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;
599 done:
601 
602  return ret;
603 }
604 
605 char 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  */
634 static 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;
664 done:
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  */
679 static 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 
721 static 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 
754 unlang_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;
758  rlm_rcode_t rcode = RLM_MODULE_OK;
759 
760  fr_lua_util_set_mctx(mctx);
761  fr_lua_util_set_request(request);
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) {
771 error:
772  fr_lua_util_set_mctx(NULL);
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 
816 done:
817  fr_lua_util_set_mctx(NULL);
819 
820  RETURN_MODULE_RCODE(rcode);
821 }
822 
823 /*
824  * Initialise the table "fr." with all valid return codes.
825  */
826 static int _lua_rcode_table_newindex(UNUSED lua_State *L)
827 {
828  request_t *request = fr_lua_util_get_request();
829 
830  RWDEBUG("You can't modify the table 'fr.rcode.{}' (read-only)");
831 
832  return 1;
833 }
834 
835 static 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  */
854 static 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 
860 static 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  */
893 int 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;
916  fr_lua_util_set_mctx(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:165
#define RCSID(id)
Definition: build.h:444
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define DIAG_ON(_x)
Definition: build.h:419
#define static_assert
For systems with an old version libc, define static_assert.
Definition: build.h:35
#define SIZEOF_MEMBER(_t, _m)
Definition: build.h:334
#define UNUSED
Definition: build.h:313
#define DIAG_OFF(_x)
Definition: build.h:418
static void * fr_dcursor_remove(fr_dcursor_t *cursor)
Remove the current item.
Definition: dcursor.h:479
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition: dcursor.h:405
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition: dcursor.h:287
static void * fr_dcursor_replace(fr_dcursor_t *cursor, void *r)
Replace the current item.
Definition: dcursor.h:606
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
Definition: dcursor.h:336
#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:2860
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:1997
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#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
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
char const * fr_lua_version(lua_State *L)
Definition: lua.c:605
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.
module_ctx_t const * fr_lua_util_get_mctx(void)
Get the thread local instance.
Definition: util.c:330
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
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
request_t * fr_lua_util_get_request(void)
Get the thread local request.
Definition: util.c:348
int fr_lua_util_log_register(lua_State *L)
Register utililiary functions in the lua environment.
Definition: util.c:280
lua_State * interpreter
Thread specific interpreter.
Definition: lua.h:63
Definition: lua.h:43
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
Definition: merged_model.c:113
@ FR_TYPE_FLOAT32
Single precision floating point.
Definition: merged_model.c:108
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
Definition: merged_model.c:86
@ FR_TYPE_INT8
8 Bit signed integer.
Definition: merged_model.c:103
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
Definition: merged_model.c:93
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
Definition: merged_model.c:89
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ FR_TYPE_INT64
64 Bit signed integer.
Definition: merged_model.c:106
@ FR_TYPE_INT16
16 Bit signed integer.
Definition: merged_model.c:104
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
Definition: merged_model.c:111
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
Definition: merged_model.c:92
@ FR_TYPE_UINT8
8 Bit unsigned integer.
Definition: merged_model.c:97
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_INT32
32 Bit signed integer.
Definition: merged_model.c:105
@ FR_TYPE_UINT64
64 Bit unsigned integer.
Definition: merged_model.c:100
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
Definition: merged_model.c:88
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
Definition: merged_model.c:87
@ FR_TYPE_BOOL
A truth value.
Definition: merged_model.c:95
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
Definition: merged_model.c:115
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
Definition: merged_model.c:91
@ FR_TYPE_IFID
Interface ID.
Definition: merged_model.c:90
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
@ FR_TYPE_FLOAT64
Double precision floating point.
Definition: merged_model.c:109
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
void * thread
Thread specific instance data.
Definition: module_ctx.h:43
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
#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:133
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
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:51
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:278
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:2978
int8_t fr_pair_cmp_by_da(void const *a, void const *b)
Order attributes by their da, and tag.
Definition: pair.c:1841
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
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:41
static char const * name
#define FR_SBUFF_OUT(_start, _len_or_end)
static char buff[sizeof("18446744073709551615")+3]
Definition: size_tests.c:41
RETURN_MODULE_FAIL
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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:134
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:253
#define talloc_get_type_abort_const
Definition: talloc.h:270
static int64_t fr_unix_time_to_sec(fr_unix_time_t delta)
Definition: time.h:504
@ 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:627
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.
Definition: pair_inline.c:140
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:40
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition: pair.h:590
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition: types.h:433
#define fr_type_is_structural(_x)
Definition: types.h:371
#define FR_TYPE_NON_LEAF
Definition: types.h:298
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:3301
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:4181
#define vb_int64
Definition: value.h:254
#define vb_float64
Definition: value.h:257
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition: value.h:574
static size_t char ** out
Definition: value.h:984