The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_mruby.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 as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 9b3290940629e0a41f8e355bb87886c5e7c65805 $
19  * @file rlm_mruby.c
20  * @brief Translates requests between the server an an mruby interpreter.
21  *
22  * @copyright 2016 Herwin Weststrate (freeradius@herwinw.nl)
23  * @copyright 2016 The FreeRADIUS server project
24  */
25 RCSID("$Id: 9b3290940629e0a41f8e355bb87886c5e7c65805 $")
26 
27 #include <freeradius-devel/server/base.h>
28 #include <freeradius-devel/server/module_rlm.h>
29 #include <freeradius-devel/server/pairmove.h>
30 #include <freeradius-devel/util/debug.h>
31 
32 #include "rlm_mruby.h"
33 
34 /*
35  * Define a structure for our module configuration.
36  *
37  * These variables do not need to be in a structure, but it's
38  * a lot cleaner to do so, and a pointer to the structure can
39  * be used as the instance handle.
40  */
41 typedef struct {
42  char const *filename;
43  char const *module_name;
44 
45  mrb_state *mrb;
46 
47  struct RClass *mruby_module;
48  struct RClass *mruby_request;
49  mrb_value mrubyconf_hash;
50 } rlm_mruby_t;
51 
52 /*
53  * A mapping of configuration file names to internal variables.
54  */
55 static const conf_parser_t module_config[] = {
57  { FR_CONF_OFFSET("module", rlm_mruby_t, module_name), .dflt = "Radiusd" },
59 };
60 
61 static mrb_value mruby_log(mrb_state *mrb, UNUSED mrb_value self)
62 {
63  mrb_int level;
64  char *msg = NULL;
65 
66  mrb_get_args(mrb, "iz", &level, &msg);
67  fr_log(&default_log, level, __FILE__, __LINE__, "rlm_ruby: %s", msg);
68 
69  return mrb_nil_value();
70 }
71 
72 static void mruby_parse_config(mrb_state *mrb, CONF_SECTION *cs, int lvl, mrb_value hash)
73 {
74  int indent_section = (lvl + 1) * 4;
75  int indent_item = (lvl + 2) * 4;
76  CONF_ITEM *ci = NULL;
77 
78  if (!cs) return;
79 
80  DEBUG("%*s%s {", indent_section, " ", cf_section_name1(cs));
81 
82  while ((ci = cf_item_next(cs, ci))) {
83  if (cf_item_is_section(ci)) {
84  CONF_SECTION *sub_cs = cf_item_to_section(ci);
85  char const *key = cf_section_name1(sub_cs);
86  mrb_value sub_hash, mrubyKey;
87 
88  if (!key) continue;
89 
90  mrubyKey = mrb_str_new_cstr(mrb, key);
91 
92  if (!mrb_nil_p(mrb_hash_get(mrb, hash, mrubyKey))) {
93  WARN("rlm_mruby: Ignoring duplicate config section '%s'", key);
94  continue;
95  }
96 
97  sub_hash = mrb_hash_new(mrb);
98  mrb_hash_set(mrb, hash, mrubyKey, sub_hash);
99 
100  mruby_parse_config(mrb, sub_cs, lvl + 1, sub_hash);
101  } else if (cf_item_is_pair(ci)) {
102  CONF_PAIR *cp = cf_item_to_pair(ci);
103  const char *key = cf_pair_attr(cp);
104  const char *value = cf_pair_value(cp);
105  mrb_value mrubyKey, mrubyValue;
106 
107  if (!key || !value) continue;
108 
109  mrubyKey = mrb_str_new_cstr(mrb, key);
110  mrubyValue = mrb_str_new_cstr(mrb, value);
111 
112  if (!mrb_nil_p(mrb_hash_get(mrb, hash, mrubyKey))) {
113  WARN("rlm_mruby: Ignoring duplicate config item '%s'", key);
114  continue;
115  }
116 
117  mrb_hash_set(mrb, hash, mrubyKey, mrubyValue);
118 
119  DEBUG("%*s%s = %s", indent_item, " ", key, value);
120  }
121  }
122 
123  DEBUG("%*s}", indent_section, " ");
124 }
125 
126 /*
127  * Do any per-module initialization that is separate to each
128  * configured instance of the module. e.g. set up connections
129  * to external databases, read configuration files, set up
130  * dictionary entries, etc.
131  */
132 static int mod_instantiate(module_inst_ctx_t const *mctx)
133 {
134  rlm_mruby_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_mruby_t);
135  mrb_state *mrb;
136  CONF_SECTION *cs;
137  FILE *f;
138  mrb_value status;
139 
140  mrb = inst->mrb = mrb_open();
141  if (!mrb) {
142  ERROR("mruby initialization failed");
143  return -1;
144  }
145 
146  /* Define the freeradius module */
147  DEBUG("Creating module %s", inst->module_name);
148  inst->mruby_module = mrb_define_module(mrb, inst->module_name);
149  if (!inst->mruby_module) {
150  ERROR("Creating module %s failed", inst->module_name);
151  return -1;
152  }
153 
154  /* Define the log method */
155  mrb_define_class_method(mrb, inst->mruby_module, "log", mruby_log, MRB_ARGS_REQ(2));
156 
157 #define A(x) mrb_define_const(mrb, inst->mruby_module, #x, mrb_fixnum_value(x));
158  /* Define the logging constants */
159  A(L_DBG);
160  A(L_WARN);
161  A(L_INFO);
162  A(L_ERR);
163  A(L_WARN);
164  A(L_DBG_WARN);
165  A(L_DBG_ERR);
166  A(L_DBG_WARN_REQ);
167  A(L_DBG_ERR_REQ);
168 
169  /* Define the return value constants */
180 #undef A
181 
182  /* Convert a FreeRADIUS config structure into a mruby hash */
183  inst->mrubyconf_hash = mrb_hash_new(mrb);
184  cs = cf_section_find(mctx->mi->conf, "config", NULL);
185  if (cs) mruby_parse_config(mrb, cs, 0, inst->mrubyconf_hash);
186 
187  /* Define the Request class */
188  inst->mruby_request = mruby_request_class(mrb, inst->mruby_module);
189 
190  DEBUG("Loading file %s...", inst->filename);
191  f = fopen(inst->filename, "r");
192  if (!f) {
193  ERROR("Opening file failed");
194  return -1;
195  }
196 
197  status = mrb_load_file(mrb, f);
198  fclose(f);
199  if (mrb_undef_p(status)) {
200  ERROR("Parsing file failed");
201  return -1;
202  }
203 
204  status = mrb_funcall(mrb, mrb_obj_value(inst->mruby_module), "instantiate", 0);
205  if (mrb_undef_p(status)) {
206  ERROR("Running instantiate failed");
207  return -1;
208  }
209 
210  return 0;
211 }
212 
213 static int mruby_vps_to_array(request_t *request, mrb_value *out, mrb_state *mrb, fr_pair_list_t *vps)
214 {
215  mrb_value res;
216  fr_pair_t *vp;
217 
218  res = mrb_ary_new(mrb);
219  for (vp = fr_pair_list_head(vps); vp; vp = fr_pair_list_next(vps, vp)) {
220  mrb_value tmp, key, val, to_cast;
221 
222  tmp = mrb_ary_new_capa(mrb, 2);
223  key = mrb_str_new(mrb, vp->da->name, strlen(vp->da->name));
224 
225  /*
226  * The only way to create floats, doubles, bools etc,
227  * is to feed mruby the string representation and have
228  * it convert to its internal types.
229  */
230  switch (vp->vp_type) {
231  case FR_TYPE_STRING:
232  case FR_TYPE_OCTETS:
233  to_cast = mrb_str_new(mrb, vp->vp_ptr, vp->vp_length);
234  break;
235 
236  case FR_TYPE_BOOL:
237 #ifndef NDEBUG
238  to_cast = mrb_nil_value(); /* Not needed but clang flags it */
239 #endif
240  break;
241 
242  default:
243  {
244  char *in;
245  size_t len;
246 
247  len = fr_value_box_aprint(request, &in, &vp->data, NULL);
248  to_cast = mrb_str_new(mrb, in, len);
249  talloc_free(in);
250  }
251  break;
252  }
253 
254  switch (vp->vp_type) {
255  case FR_TYPE_STRING:
256  case FR_TYPE_OCTETS:
257  case FR_TYPE_IPV4_ADDR:
258  case FR_TYPE_IPV4_PREFIX:
259  case FR_TYPE_IPV6_ADDR:
260  case FR_TYPE_IPV6_PREFIX:
261  case FR_TYPE_IFID:
262  case FR_TYPE_ETHERNET:
265  val = to_cast; /* No conversions required */
266  break;
267 
268  case FR_TYPE_BOOL:
269  val = vp->vp_bool ? mrb_obj_value(mrb->true_class) : mrb_obj_value(mrb->false_class);
270  break;
271 
272  case FR_TYPE_UINT8:
273  case FR_TYPE_UINT16:
274  case FR_TYPE_UINT32:
275  case FR_TYPE_UINT64:
276  case FR_TYPE_INT8:
277  case FR_TYPE_INT16:
278  case FR_TYPE_INT32:
279  case FR_TYPE_INT64:
280  case FR_TYPE_DATE:
281  case FR_TYPE_TIME_DELTA:
282  case FR_TYPE_SIZE:
283  val = mrb_convert_type(mrb, to_cast, MRB_TT_FIXNUM, "Fixnum", "to_int");
284  break;
285 
286  case FR_TYPE_FLOAT32:
287  case FR_TYPE_FLOAT64:
288  val = mrb_convert_type(mrb, to_cast, MRB_TT_FLOAT, "Float", "to_f");
289  break;
290 
291  case FR_TYPE_NON_LEAF:
292  fr_assert(0);
293  return -1;
294  }
295 
296  mrb_ary_push(mrb, tmp, key);
297  mrb_ary_push(mrb, tmp, val);
298  mrb_ary_push(mrb, res, tmp);
299 
300  *out = res;
301  }
302 
303  return 0;
304 }
305 
306 static void add_vp_tuple(TALLOC_CTX *ctx, request_t *request, fr_pair_list_t *vps, mrb_state *mrb, mrb_value value, char const *function_name)
307 {
308  int i;
309  fr_pair_list_t tmp_list;
310 
311  fr_pair_list_init(&tmp_list);
312 
313  for (i = 0; i < RARRAY_LEN(value); i++) {
314  mrb_value tuple = mrb_ary_entry(value, i);
315  mrb_value key, val;
316  char const *ckey, *cval;
317  fr_pair_t *vp;
318  tmpl_t *dst;
319  fr_token_t op = T_OP_EQ;
320 
321  /* This tuple should be an array of length 2 */
322  if (mrb_type(tuple) != MRB_TT_ARRAY) {
323  REDEBUG("add_vp_tuple, %s: non-array passed at index %i", function_name, i);
324  continue;
325  }
326 
327  if (RARRAY_LEN(tuple) != 2 && RARRAY_LEN(tuple) != 3) {
328  REDEBUG("add_vp_tuple, %s: array with incorrect length passed at index "
329  "%i, expected 2 or 3, got %"PRId64, function_name, i, RARRAY_LEN(tuple));
330  continue;
331  }
332 
333  key = mrb_ary_entry(tuple, 0);
334  val = mrb_ary_entry(tuple, -1);
335  if (mrb_type(key) != MRB_TT_STRING) {
336  REDEBUG("add_vp_tuple, %s: tuple element %i must have a string as first element", function_name, i);
337  continue;
338  }
339 
340  ckey = mrb_str_to_cstr(mrb, key);
341  cval = mrb_str_to_cstr(mrb, mrb_obj_as_string(mrb, val));
342  if (ckey == NULL || cval == NULL) {
343  REDEBUG("%s: string conv failed", function_name);
344  continue;
345  }
346 
347 
348  if (RARRAY_LEN(tuple) == 3) {
349  if (mrb_type(mrb_ary_entry(tuple, 1)) != MRB_TT_STRING) {
350  REDEBUG("Invalid type for operator, expected string, falling back to =");
351  } else {
352  char const *cop = mrb_str_to_cstr(mrb, mrb_ary_entry(tuple, 1));
353  if (!(op = fr_table_value_by_str(fr_tokens_table, cop, 0))) {
354  REDEBUG("Invalid operator: %s, falling back to =", cop);
355  op = T_OP_EQ;
356  }
357  }
358  }
359  DEBUG("%s: %s %s %s", function_name, ckey, fr_table_str_by_value(fr_tokens_table, op, "="), cval);
360 
361  if (tmpl_afrom_attr_str(request, NULL, &dst, ckey,
362  &(tmpl_rules_t){
363  .attr = {
364  .dict_def = request->dict,
365  .list_def = request_attr_reply
366  }
367  }) <= 0) {
368  ERROR("Failed to find attribute %s", ckey);
369  continue;
370  }
371 
372  if (tmpl_request_ptr(&request, tmpl_request(dst)) < 0) {
373  ERROR("Attribute name %s refers to outer request but not in a tunnel, skipping...", ckey);
374  talloc_free(dst);
375  continue;
376  }
377 
379  talloc_free(dst);
380 
381  if (fr_pair_value_from_str(vp, cval, strlen(cval), NULL, false) < 0) {
382  REDEBUG("%s: %s = %s failed", function_name, ckey, cval);
383  } else {
384  DEBUG("%s: %s = %s OK", function_name, ckey, cval);
385  }
386 
387  fr_pair_append(&tmp_list, vp);
388  }
389  radius_pairmove(request, vps, &tmp_list);
390 }
391 
392 static inline int mruby_set_vps(request_t *request, mrb_state *mrb, mrb_value mruby_request,
393  char const *list_name, fr_pair_list_t *vps)
394 {
395  mrb_value res;
396 
397  memset(&res, 0, sizeof(res)); /* clang scan */
398 
399  if (mruby_vps_to_array(request, &res, mrb, vps) < 0) return -1;
400 
401  mrb_iv_set(mrb, mruby_request, mrb_intern_cstr(mrb, list_name), res);
402 
403  return 0;
404 }
405 
406 static unlang_action_t CC_HINT(nonnull) do_mruby(rlm_rcode_t *p_result, request_t *request, rlm_mruby_t const *inst,
407  char const *function_name)
408 {
409  mrb_state *mrb = inst->mrb;
410  mrb_value mruby_request, mruby_result;
411 
412  mruby_request = mrb_obj_new(mrb, inst->mruby_request, 0, NULL);
413  mrb_iv_set(mrb, mruby_request, mrb_intern_cstr(mrb, "@frconfig"), inst->mrubyconf_hash);
414  mruby_set_vps(request, mrb, mruby_request, "@request", &request->request_pairs);
415  mruby_set_vps(request, mrb, mruby_request, "@reply", &request->reply_pairs);
416  mruby_set_vps(request, mrb, mruby_request, "@control", &request->control_pairs);
417  mruby_set_vps(request, mrb, mruby_request, "@session_state", &request->session_state_pairs);
418 
420 DIAG_OFF(class-varargs)
421  mruby_result = mrb_funcall(mrb, mrb_obj_value(inst->mruby_module), function_name, 1, mruby_request);
422 DIAG_ON(class-varargs)
424 
425  /* Two options for the return value:
426  * - a fixnum: convert to rlm_rcode_t, and return that
427  * - an array: this should have exactly three items in it. The first one
428  * should be a fixnum, this will once again be converted to
429  * rlm_rcode_t and eventually returned. The other two items
430  * should be arrays. The items of the first array should be
431  * merged into reply, the second array into control.
432  */
433  switch (mrb_type(mruby_result)) {
434  /* If it is a Fixnum: return that value */
435  case MRB_TT_FIXNUM:
436  RETURN_MODULE_RCODE((rlm_rcode_t)mrb_int(mrb, mruby_result));
437 
438  case MRB_TT_ARRAY:
439  /* Must have exactly three items */
440  if (RARRAY_LEN(mruby_result) != 3) {
441  ERROR("Expected array to have exactly three values, got %" PRId64 " instead", RARRAY_LEN(mruby_result));
443  }
444 
445  /* First item must be a Fixnum, this will be the return type */
446  if (mrb_type(mrb_ary_entry(mruby_result, 0)) != MRB_TT_FIXNUM) {
447  ERROR("Expected first array element to be a Fixnum, got %s instead", RSTRING_PTR(mrb_obj_as_string(mrb, mrb_ary_entry(mruby_result, 0))));
449  }
450 
451  /* Second and third items must be Arrays, these will be the updates for reply and control */
452  if (mrb_type(mrb_ary_entry(mruby_result, 1)) != MRB_TT_ARRAY) {
453  ERROR("Expected second array element to be an Array, got %s instead", RSTRING_PTR(mrb_obj_as_string(mrb, mrb_ary_entry(mruby_result, 1))));
455  } else if (mrb_type(mrb_ary_entry(mruby_result, 2)) != MRB_TT_ARRAY) {
456  ERROR("Expected third array element to be an Array, got %s instead", RSTRING_PTR(mrb_obj_as_string(mrb, mrb_ary_entry(mruby_result, 2))));
458  }
459 
460  add_vp_tuple(request->reply_ctx, request, &request->reply_pairs, mrb, mrb_ary_entry(mruby_result, 1), function_name);
461  add_vp_tuple(request->control_ctx, request, &request->control_pairs, mrb, mrb_ary_entry(mruby_result, 2), function_name);
462  RETURN_MODULE_RCODE((rlm_rcode_t)mrb_int(mrb, mrb_ary_entry(mruby_result, 0)));
463 
464  default:
465  /* Invalid return type */
466  ERROR("Expected return to be a Fixnum or an Array, got %s instead", RSTRING_PTR(mrb_obj_as_string(mrb, mruby_result)));
468  }
469 }
470 
471 
472 #define RLM_MRUBY_FUNC(foo) static unlang_action_t CC_HINT(nonnull) mod_##foo(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request) \
473  { \
474  return do_mruby(p_result, \
475  request, \
476  (rlm_mruby_t const *)mctx->mi->data, \
477  #foo); \
478  }
479 
480 RLM_MRUBY_FUNC(authorize)
481 RLM_MRUBY_FUNC(authenticate)
482 RLM_MRUBY_FUNC(post_auth)
483 RLM_MRUBY_FUNC(preacct)
484 RLM_MRUBY_FUNC(accounting)
485 
486 
487 /*
488  * Only free memory we allocated. The strings allocated via
489  * cf_section_parse() do not need to be freed.
490  */
491 static int mod_detach(module_detach_ctx_t const *mctx)
492 {
493  rlm_mruby_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_mruby_t);
494 
495  mrb_close(inst->mrb);
496 
497  return 0;
498 }
499 
500 /*
501  * The module name should be the only globally exported symbol.
502  * That is, everything else should be 'static'.
503  *
504  * If the module needs to temporarily modify it's instantiation
505  * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
506  * The server will then take care of ensuring that the module
507  * is single-threaded.
508  */
509 extern module_rlm_t rlm_mruby;
511  .common = {
512  .magic = MODULE_MAGIC_INIT,
513  .name = "mruby",
514  .flags = MODULE_TYPE_THREAD_UNSAFE, /* Not sure */
515  .inst_size = sizeof(rlm_mruby_t),
518  .detach = mod_detach,
519  },
520  .method_group = {
521  .bindings = (module_method_binding_t[]){
522  /*
523  * Hack to support old configurations
524  */
525  { .section = SECTION_NAME("accounting", CF_IDENT_ANY), .method = mod_accounting },
526  { .section = SECTION_NAME("authenticate", CF_IDENT_ANY), .method = mod_authenticate },
527  { .section = SECTION_NAME("authorize", CF_IDENT_ANY), .method = mod_authorize },
528 
529  { .section = SECTION_NAME("recv", "accounting-request"), .method = mod_preacct },
530  { .section = SECTION_NAME("recv", CF_IDENT_ANY), .method = mod_authorize },
531 
532  { .section = SECTION_NAME("send", CF_IDENT_ANY), .method = mod_post_auth },
534  }
535  }
536 };
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 RCSID(id)
Definition: build.h:481
#define DIAG_UNKNOWN_PRAGMAS
Definition: build.h:454
#define DIAG_ON(_x)
Definition: build.h:456
#define UNUSED
Definition: build.h:313
#define DIAG_OFF(_x)
Definition: build.h:455
#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
Common header for all CONF_* types.
Definition: cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition: cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:101
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition: cf_util.c:632
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: cf_util.c:664
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition: cf_util.c:1578
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition: cf_util.c:1028
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1594
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:684
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition: cf_util.c:618
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1171
#define cf_item_next(_ci, _curr)
Definition: cf_util.h:92
#define CF_IDENT_ANY
Definition: cf_util.h:78
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
static fr_slen_t in
Definition: dict.h:821
Test enumeration values.
Definition: dict_test.h:92
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
talloc_free(reap)
fr_log_t default_log
Definition: log.c:291
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
Definition: log.c:583
@ L_DBG_WARN_REQ
Less severe warning only displayed when debugging is enabled.
Definition: log.h:63
@ L_WARN
Warning.
Definition: log.h:57
@ L_ERR
Error message.
Definition: log.h:56
@ L_DBG_ERR
Error only displayed when debugging is enabled.
Definition: log.h:62
@ L_DBG_ERR_REQ
Less severe error only displayed when debugging is enabled.
Definition: log.h:64
@ L_DBG_WARN
Warning only displayed when debugging is enabled.
Definition: log.h:61
@ L_INFO
Informational message.
Definition: log.h:55
@ L_DBG
Only displayed when debugging is enabled.
Definition: log.h:59
@ 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
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
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:39
struct RClass * mruby_request_class(mrb_state *mrb, struct RClass *parent)
Definition: mruby.c:73
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
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition: pair.c:1345
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition: pair.c:46
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
Definition: pair.c:2589
void radius_pairmove(request_t *request, fr_pair_list_t *to, fr_pair_list_t *from)
Definition: pairmove.c:45
static const conf_parser_t config[]
Definition: base.c:183
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define WARN(fmt,...)
Definition: radclient.h:47
#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_INVALID
The module considers the request invalid.
Definition: rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition: rcode.h:42
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition: rcode.h:46
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition: rcode.h:41
@ RLM_MODULE_NOTFOUND
User not found.
Definition: rcode.h:47
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition: rcode.h:49
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition: rcode.h:48
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
Definition: rcode.h:50
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition: rcode.h:44
fr_dict_attr_t const * request_attr_reply
Definition: request.c:46
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
static int mod_detach(module_detach_ctx_t const *mctx)
Definition: rlm_mruby.c:491
mrb_value mrubyconf_hash
Definition: rlm_mruby.c:49
char const * filename
Definition: rlm_mruby.c:42
mrb_state * mrb
Definition: rlm_mruby.c:45
static int mruby_vps_to_array(request_t *request, mrb_value *out, mrb_state *mrb, fr_pair_list_t *vps)
Definition: rlm_mruby.c:213
#define RLM_MRUBY_FUNC(foo)
Definition: rlm_mruby.c:472
#define A(x)
char const * module_name
Definition: rlm_mruby.c:43
static unlang_action_t do_mruby(rlm_rcode_t *p_result, request_t *request, rlm_mruby_t const *inst, char const *function_name)
Definition: rlm_mruby.c:406
struct RClass * mruby_request
Definition: rlm_mruby.c:48
struct RClass * mruby_module
Definition: rlm_mruby.c:47
static mrb_value mruby_log(mrb_state *mrb, UNUSED mrb_value self)
Definition: rlm_mruby.c:61
static void add_vp_tuple(TALLOC_CTX *ctx, request_t *request, fr_pair_list_t *vps, mrb_state *mrb, mrb_value value, char const *function_name)
Definition: rlm_mruby.c:306
static void mruby_parse_config(mrb_state *mrb, CONF_SECTION *cs, int lvl, mrb_value hash)
Definition: rlm_mruby.c:72
module_rlm_t rlm_mruby
Definition: rlm_mruby.c:510
static const conf_parser_t module_config[]
Definition: rlm_mruby.c:55
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_mruby.c:132
static int mruby_set_vps(request_t *request, mrb_state *mrb, mrb_value mruby_request, char const *list_name, fr_pair_list_t *vps)
Definition: rlm_mruby.c:392
Translates requests between the server an an mruby interpreter.
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:132
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1302
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
@ MODULE_TYPE_THREAD_UNSAFE
Module is not threadsafe.
Definition: module.h:48
CONF_SECTION * conf
Module's instance configuration.
Definition: module.h:329
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
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition: tmpl.h:812
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, char const *name, tmpl_rules_t const *rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
int tmpl_request_ptr(request_t **request, FR_DLIST_HEAD(tmpl_request_list) const *rql)
Resolve a tmpl_request_ref_t to a request_t.
Definition: tmpl_eval.c:169
Optional arguments passed to vp_tmpl functions.
Definition: tmpl.h:341
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_pair_t * vp
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
fr_table_num_ordered_t const fr_tokens_table[]
Definition: token.c:33
enum fr_token fr_token_t
@ T_OP_EQ
Definition: token.h:83
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition: pair_inline.c:43
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
Definition: pair_inline.c:70
#define FR_TYPE_NON_LEAF
Definition: types.h:298
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:997