The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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 */
25RCSID("$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 */
41typedef 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;
51
52/*
53 * A mapping of configuration file names to internal variables.
54 */
55static const conf_parser_t module_config[] = {
57 { FR_CONF_OFFSET("module", rlm_mruby_t, module_name), .dflt = "Radiusd" },
59};
60
61static 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
72static 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 */
132static 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);
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
213static 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);
250 }
251 break;
252 }
253
254 switch (vp->vp_type) {
255 case FR_TYPE_STRING:
256 case FR_TYPE_OCTETS:
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:
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
306static 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
392static 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
406static 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
420DIAG_OFF(class-varargs)
421 mruby_result = mrb_funcall(mrb, mrb_obj_value(inst->mruby_module), function_name, 1, mruby_request);
422DIAG_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
480RLM_MRUBY_FUNC(authorize)
481RLM_MRUBY_FUNC(authenticate)
482RLM_MRUBY_FUNC(post_auth)
483RLM_MRUBY_FUNC(preacct)
484RLM_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 */
491static 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 */
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:483
#define DIAG_UNKNOWN_PRAGMAS
Definition build.h:456
#define DIAG_ON(_x)
Definition build.h:458
#define UNUSED
Definition build.h:315
#define DIAG_OFF(_x)
Definition build.h:457
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
#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:418
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition cf_parse.h:424
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
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
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1171
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
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
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_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1578
#define cf_item_next(_ci, _curr)
Definition cf_util.h:92
#define CF_IDENT_ANY
Definition cf_util.h:78
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
static fr_slen_t in
Definition dict.h:824
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.
@ 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.
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
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
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
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 fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define WARN(fmt,...)
Definition radclient.h:47
#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_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:375
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:1310
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
module_flags_t flags
Flags that control how a module starts up and how a module is called.
Definition module.h:227
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
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
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:812
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:341
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_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
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
#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