28RCSID(
"$Id: 7af78654e40e5b40632e33eba7229b47291a4261 $")
30#define LOG_PREFIX mctx->mi->name
32#include <freeradius-devel/server/base.h>
33#include <freeradius-devel/server/exfile.h>
34#include <freeradius-devel/server/map_proc.h>
35#include <freeradius-devel/server/module_rlm.h>
36#include <freeradius-devel/server/pairmove.h>
37#include <freeradius-devel/util/debug.h>
38#include <freeradius-devel/util/dict.h>
39#include <freeradius-devel/util/table.h>
40#include <freeradius-devel/unlang/function.h>
41#include <freeradius-devel/unlang/xlat_func.h>
47#define SQL_SAFE_FOR (fr_value_box_safe_for_t)inst->driver
71 {
FR_CONF_OFFSET(
"safe_characters",
rlm_sql_config_t, allowed_chars), .dflt =
"@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /" },
164#define SQL_AUTZ_STAGE_GROUP 0x20
165#define SQL_AUTZ_STAGE_PROFILE 0x40
305 for (map = map_list_head(maps);
308 next = map_list_next(maps, map);
313 (void) map_list_remove(maps, map);
348 fr_value_box_entry_t entry;
370 if (
inst->sql_escape_arg) {
371 arg =
inst->sql_escape_arg;
389 if (!fr_sbuff_init_talloc(vb, &sbuff, &sbuff_ctx, vb->vb_length * 3, vb->vb_length * 3)) {
394 len =
inst->sql_escape_func(request,
fr_sbuff_buff(&sbuff), vb->vb_length * 3 + 1, vb->vb_strvalue, arg);
395 if (len < 0)
goto error;
437 while ((vb = fr_value_box_list_pop_head(
in))) {
458 switch (query_ctx->
rcode) {
463 query_ctx->
rcode,
"<INVALID>"));
472 numaffected = (
inst->driver->sql_affected_rows)(query_ctx, &
inst->config);
473 if (numaffected < 1) {
474 RDEBUG2(
"SQL query affected no rows");
479 fr_value_box_uint32(vb, NULL, (
uint32_t)numaffected,
false);
497 bool fetched =
false;
504 query_ctx->
rcode,
"<INVALID>"));
511 inst->fetch_row(&p_result, NULL, request, query_ctx);
512 row = query_ctx->
row;
513 switch (query_ctx->
rcode) {
517 RDEBUG2(
"NULL value in first column of result");
521 if (!fetched)
RDEBUG2(
"SQL query returned no results");
571 p = arg->vb_strvalue;
589 query_ret =
inst->query(&p_result, NULL, request, query_ctx);
680 char const *
value = uctx;
690 RPEDEBUG(
"Failed parsing value \"%pV\" for attribute %s",
713#define MAX_SQL_FIELD_INDEX (64)
727 map_list_t
const *maps = map_ctx->
maps;
732 char const **fields = NULL, *map_rhs;
734 int i, j, field_cnt, rows = 0;
736 char map_rhs_buff[128];
737 bool found_field =
false;
748 if (
inst->driver->sql_num_rows) {
749 ret =
inst->driver->sql_num_rows(query_ctx, &
inst->config);
751 RDEBUG2(
"Server returned an empty result");
757 RERROR(
"Failed retrieving row count");
769 ret = (
inst->driver->sql_fields)(&fields, query_ctx, &
inst->config);
775 field_cnt = talloc_array_length(fields);
784 for (map = map_list_head(maps), i = 0;
786 map = map_list_next(maps, map), i++) {
790 if (
tmpl_expand(&map_rhs, map_rhs_buff,
sizeof(map_rhs_buff),
791 request, map->
rhs, NULL, NULL) < 0) {
792 RPERROR(
"Failed getting field name");
796 for (j = 0; j < field_cnt; j++) {
797 if (
strcasecmp(fields[j], map_rhs) != 0)
continue;
808 RDEBUG2(
"No fields matching map found in query result");
822 row = query_ctx->
row;
824 for (map = map_list_head(maps), j = 0;
826 map = map_list_next(maps, map), j++) {
827 if (field_index[j] < 0)
continue;
828 if (!row[field_index[j]]) {
829 RWARN(
"Database returned NULL for %s", fields[j]);
839 RDEBUG2(
"SQL query returned no results");
864 fr_value_box_list_t *query, map_list_t
const *maps)
876 REDEBUG(
"Query cannot be (null)");
880 while ((vb = fr_value_box_list_next(query, vb))) {
890 RPEDEBUG(
"Failed concatenating input string");
925 if (outlen <= utf8_len)
break;
927 memcpy(
out,
in, utf8_len);
943 if (outlen <= 2)
break;
954 if (outlen <= 2)
break;
965 if (outlen <= 2)
break;
981 strchr(
inst->config.allowed_chars, *
in) == NULL) {
1041 RDEBUG2(
"SQL-User-Name set to '%pV'", &
vp->data);
1047#define sql_unset_user(_i, _r) fr_pair_delete_by_da(&_r->request_pairs, _i->sql_user)
1071 row = query_ctx->
row;
1073 RDEBUG2(
"row[0] returned NULL");
1079 entry = group_ctx->
groups;
1082 entry = entry->
next;
1125 char const *
name = arg->vb_strvalue;
1132 for (entry = group_ctx->
groups; entry != NULL; entry = entry->
next) {
1133 if (strcmp(entry->
name,
name) == 0) {
1157 query = fr_value_box_list_head(&
xlat_ctx->query);
1192 RWARN(
"Cannot check group membership - group_membership_query not set");
1202 fr_value_box_list_init(&
xlat_ctx->query);
1225 for (map = map_list_head(check_map);
1228 next = map_list_next(check_map, map);
1231 (void) map_list_remove(check_map, map);
1232 map_list_insert_tail(reply_map, map);
1243 REDEBUG(
"Invalid comparison for structural type");
1250 map_list_talloc_free(check_map);
1251 map_list_talloc_free(reply_map);
1252 RDEBUG2(
"failed match: skipping this entry");
1262 map_list_talloc_free(&to_free->
check_tmp);
1263 map_list_talloc_free(&to_free->
reply_tmp);
1297 switch (*p_result) {
1305 switch(autz_ctx->
status) {
1327 RDEBUG2(
"User not found in any groups");
1332 RDEBUG2(
"User found in the group table");
1392 if (map_ctx->
rows > 0) {
1394 map_list_talloc_free(&autz_ctx->
check_tmp);
1395 goto next_group_find;
1397 RDEBUG2(
"%s \"%pV\": Conditional check items matched",
1400 RDEBUG2(
"%s \"%pV\": Conditional check items matched (empty)",
1406 map_list_talloc_free(&autz_ctx->
check_tmp);
1417 if (map_list_num_elements(&autz_ctx->
reply_tmp))
goto group_attr_cache;
1419 goto next_group_find;
1443 if (map_ctx->
rows == 0) {
1445 goto group_attr_cache;
1457 if (map_list_num_elements(&autz_ctx->
reply_tmp) == 0)
goto next_group_find;
1458 RDEBUG2(
"%s \"%pV\": Merging control and reply items",
1464 RPEDEBUG(
"Failed applying reply item");
1469 map_list_talloc_free(&autz_ctx->
reply_tmp);
1475 if (autz_ctx->
profile)
goto next_profile;
1479 if (autz_ctx->
group)
goto next_group;
1493 RDEBUG3(
"... falling-through to profile processing");
1528 switch (*p_result) {
1536 switch(autz_ctx->
status) {
1557 if (map_ctx->
rows == 0)
goto skip_reply;
1562 RDEBUG2(
"User found in radcheck table");
1566 RDEBUG2(
"Conditional check items matched");
1569 map_list_talloc_free(&autz_ctx->
check_tmp);
1598 if (map_ctx->
rows == 0)
goto skip_reply;
1602 RDEBUG2(
"User found in radreply table");
1606 if (map_list_num_elements(&autz_ctx->
reply_tmp)) {
1607 RDEBUG2(
"Merging control and reply items");
1617 map_list_talloc_free(&autz_ctx->
reply_tmp);
1622 RDEBUG3(
"... falling-through to group processing");
1625 RWARN(
"Cannot check groups when group_membership_query is not set");
1630 RWARN(
"Cannot process groups when neither authorize_group_check_query nor authorize_group_check_query are set");
1643 RDEBUG3(
"... falling-through to profile processing");
1646 RWARN(
"Cannot process profiles when neither authorize_group_check_query nor authorize_group_check_query are set");
1651 if (!autz_ctx->
profile)
break;
1682 RWDEBUG(
"No authorization checks configured, returning noop");
1694 .call_env = call_env,
1696 .trunk = thread->
trunk,
1712 fr_value_box_list_init(&autz_ctx->
query);
1765 int numaffected = 0;
1770 switch (query_ctx->
rcode) {
1810 numaffected = (
inst->driver->sql_affected_rows)(query_ctx, &
inst->config);
1811 TALLOC_FREE(query_ctx);
1812 RDEBUG2(
"%i record(s) updated", numaffected);
1826 RDEBUG2(
"Trying next query...");
1846 redundant_ctx->
query_vb = fr_value_box_list_pop_head(&redundant_ctx->
query);
1876 if (!call_env->
query) {
1877 RWARN(
"No query configured");
1885 .trunk = thread->
trunk,
1886 .call_env = call_env,
1896 fr_value_box_list_init(&redundant_ctx->
query);
1935 section2 = talloc_strdup(NULL, cec->
asked->
name2);
1937 while (*p !=
'\0') {
1943 if (subsubcs) to_parse =
cf_pair_find(subsubcs,
"logfile");
1945 if (!to_parse) to_parse =
cf_pair_find(subcs,
"logfile");
1950 if (!to_parse)
return 0;
1955 our_rules = *t_rules;
2003 while (*p !=
'\0') {
2010 cf_log_warn(ci,
"No query found for \"%s.%s\", this query will be disabled",
2016 if (
count == 0)
goto no_query;
2023 our_rules = *t_rules;
2074 talloc_free_children(
inst);
2103 WARN(
"Ignoring authorize_group_check_query as group_membership_query is not configured");
2107 WARN(
"Ignoring authorize_group_reply_query as group_membership_query is not configured");
2110 if (!
inst->config.read_groups) {
2111 WARN(
"Ignoring read_groups as group_membership_query is not configured");
2112 inst->config.read_groups =
false;
2134 if (
inst->driver->sql_escape_func) {
2135 inst->sql_escape_func =
inst->driver->sql_escape_func;
2152 inst->config.trunk_conf.target_req_per_conn = 1;
2153 inst->config.trunk_conf.max_req_per_conn = 1;
2155 if (!
inst->driver->trunk_io_funcs.connection_notify) {
2156 inst->config.trunk_conf.always_writable =
true;
2183 char const *group_attribute;
2186 if (
inst->config.group_attribute) {
2187 group_attribute =
inst->config.group_attribute;
2190 group_attribute =
buffer;
2192 group_attribute =
"SQL-Group";
2217 cf_log_perr(
conf,
"Failed registering %s expansion", group_attribute);
2319 if (
inst->driver->sql_escape_arg_alloc) {
2327 &
inst->config.trunk_conf,
inst->name, t,
false);
2328 if (!t->
trunk)
return -1;
2367 &our_rules) < 0)
return -1;
2368 *(
void **)
out = parsed_tmpl;
2372#define QUERY_ESCAPE .pair.escape = { \
2373 .mode = TMPL_ESCAPE_PRE_CONCAT, \
2374 .uctx = { .func = { .alloc = sql_escape_uctx_alloc }, .type = TMPL_ESCAPE_UCTX_ALLOC_FUNC }, \
2375}, .pair.func = call_env_parse
2396 .boot_type =
"rlm_sql_boot_t",
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
static int const char char buffer[256]
#define fr_atexit_thread_local(_name, _free, _uctx)
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
void call_env_parsed_free(call_env_parsed_head_t *parsed, call_env_parsed_t *ptr)
Remove a call_env_parsed_t from the list of parsed call envs.
call_env_parsed_t * call_env_parsed_add(TALLOC_CTX *ctx, call_env_parsed_head_t *head, call_env_parser_t const *rule)
Allocate a new call_env_parsed_t structure and add it to the list of parsed call envs.
void call_env_parsed_set_multi_index(call_env_parsed_t *parsed, size_t count, size_t index)
Assign a count and index to a call_env_parsed_t.
void call_env_parsed_set_data(call_env_parsed_t *parsed, void const *data)
Assign data to a call_env_parsed_t.
void call_env_parsed_set_tmpl(call_env_parsed_t *parsed, tmpl_t const *tmpl)
Assign a tmpl to a call_env_parsed_t.
#define CALL_ENV_TERMINATOR
call_env_ctx_type_t type
Type of callenv ctx.
@ CALL_ENV_CTX_TYPE_MODULE
The callenv is registered to a module method.
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
call_env_parser_t const * env
Parsing rules for call method env.
section_name_t const * asked
The actual name1/name2 that resolved to a module_method_binding_t.
@ CALL_ENV_FLAG_CONCAT
If the tmpl produced multiple boxes they should be concatenated.
@ CALL_ENV_FLAG_SUBSECTION
This is a subsection.
@ CALL_ENV_FLAG_PARSE_ONLY
The result of parsing will not be evaluated at runtime.
@ CALL_ENV_FLAG_MULTI
Multiple instances of the conf pairs are allowed.
module_instance_t const * mi
Module instance that the callenv is registered to.
#define FR_CALL_ENV_SUBSECTION_FUNC(_name, _name2, _flags, _func)
Specify a call_env_parser_t which parses a subsection using a callback function.
#define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field)
Specify a call_env_parser_t which writes out runtime results to the specified field.
#define FR_CALL_ENV_PARSE_ONLY_OFFSET(_name, _cast_type, _flags, _struct, _parse_field)
Specify a call_env_parser_t which writes out the result of the parsing phase to the field specified.
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
#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
#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
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
CONF_PAIR * cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
Find a pair with a name matching attr, after specified pair.
unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr)
Count the number of times an attribute occurs in a parent section.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
#define cf_log_perr(_cf, _fmt,...)
#define cf_log_warn(_cf, _fmt,...)
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
fr_dict_attr_t const * fr_dict_attr_search_by_qualified_oid(fr_dict_attr_err_t *err, fr_dict_t const *dict_def, char const *attr, bool internal, bool foreign))
Locate a qualified fr_dict_attr_t by its name and a dictionary qualifier.
int fr_dict_attr_add_name_only(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, fr_type_t type, fr_dict_attr_flags_t const *flags))
Add an attribute to the dictionary.
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
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.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
static xlat_action_t sql_escape_xlat(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Escape a value to make it SQL safe.
static xlat_action_t sql_group_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Check if the user is a member of a particular group.
static xlat_action_t sql_modify_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Execute an arbitrary SQL query, returning the number of rows affected.
static xlat_action_t sql_fetch_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Execute an arbitrary SQL query, expecting results to be returned.
static xlat_action_t sql_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Execute an arbitrary SQL query.
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define RPEDEBUG(fmt,...)
#define RINDENT()
Indent R* messages by one level.
int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert map_t to fr_pair_t (s) and add them to a request_t.
int rad_filename_box_make_safe(fr_value_box_t *vb, UNUSED void *uxtc)
int map_proc_register(TALLOC_CTX *ctx, void const *mod_inst, char const *name, map_proc_func_t evaluate, map_proc_instantiate_t instantiate, size_t inst_size, fr_value_box_safe_for_t literals_safe_for)
Register a map processor.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_BOOL
A truth value.
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
int strncasecmp(char *s1, char *s2, int n)
int strcasecmp(char *s1, char *s2)
void * env_data
Per call environment data.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
module_instance_t * mi
Module instance to detach.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for detach calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
exfile_t * module_rlm_exfile_init(TALLOC_CTX *ctx, CONF_SECTION *module, uint32_t max_entries, fr_time_delta_t max_idle, bool locking, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific exfile handle.
int module_rlm_submodule_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic conf_parser_t func for loading drivers.
module_t common
Common fields presented by all modules.
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
fr_pair_t * fr_pair_afrom_da_nested(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *da)
Create a pair (and all intermediate parents), and append it to the list.
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.
int radius_legacy_map_cmp(request_t *request, map_t const *map)
int radius_legacy_map_list_apply(request_t *request, map_list_t const *list, fr_edit_list_t *el)
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
#define pair_update_request(_attr, _da)
static void thread_detach(UNUSED void *uctx)
Explicitly cleanup module/xlat resources.
static int thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el, UNUSED void *uctx)
Create module and xlat per-thread instances.
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_RCODE(_rcode)
#define RETURN_MODULE_INVALID
#define RLM_MODULE_USER_SECTION_REJECT
Rcodes that translate to a user configurable section failing overall.
#define RETURN_MODULE_FAIL
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
#define RETURN_MODULE_NOTFOUND
fr_dict_attr_t const * request_attr_request
fr_dict_attr_t const * request_attr_reply
void * request_data_get(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request.
static unlang_action_t mod_autz_group_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Resume function called after authorization group / profile expansion of check / reply query tmpl.
rlm_sql_t const * inst
Module instance.
static int sql_map_verify(CONF_SECTION *cs, UNUSED void const *mod_inst, UNUSED void *proc_inst, tmpl_t const *src, UNUSED map_list_t const *maps)
static int mod_detach(module_detach_ctx_t const *mctx)
fr_sql_query_t * query_ctx
Query context.
sql_group_ctx_t * group_ctx
static unlang_action_t mod_sql_redundant_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Resume function called after expansion of next query in a redundant list of queries.
tmpl_t * membership_query
rlm_sql_t const * inst
Module instance.
sql_redundant_call_env_t * call_env
Call environment data.
tmpl_t * check_query
Tmpl to expand to form authorize_check_query.
static sql_fall_through_t fall_through(map_list_t *maps)
rlm_sql_grouplist_t * group
Current group being processed.
fr_value_box_t filename
File name to write SQL logs to.
static int _sql_map_proc_get_value(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
Converts a string value into a fr_pair_t.
request_t * request
Request being processed.
size_t query_no
Current query number.
static const call_env_method_t authorize_method_env
tmpl_t * reply_query
Tmpl to expand to form authorize_reply_query.
static unlang_action_t mod_map_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Process the results of an SQL map query.
static int _sql_escape_uxtx_free(void *uctx)
static fr_dict_attr_t const * attr_sql_user_name
static int check_map_process(request_t *request, map_list_t *check_map, map_list_t *reply_map)
Process a "check" map.
#define sql_unset_user(_i, _r)
static fr_dict_attr_t const * attr_fall_through
static int logfile_call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *cc, call_env_ctx_t const *cec, call_env_parser_t const *rule)
static fr_dict_t const * dict_freeradius
static xlat_action_t sql_group_xlat_resume(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Run SQL query for group membership to return list of groups.
fr_sql_map_ctx_t * map_ctx
Context used for retrieving attribute value pairs as a map list.
static xlat_action_t sql_xlat_select_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
static void sql_set_user(rlm_sql_t const *inst, request_t *request, fr_value_box_t *user)
static int call_env_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
Custom parser for sql call env queries.
rlm_sql_grouplist_t * groups
List of groups retrieved.
static xlat_action_t sql_group_xlat_query_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
Compare list of groups returned from SQL query to xlat argument.
static fr_dict_attr_t const * attr_expr_bool_enum
fr_value_box_t user
Expansion of the sql_user_name.
fr_pair_t * sql_group
Pair to update with group being processed.
trunk_t * trunk
Trunk connection for queries.
#define SQL_AUTZ_STAGE_PROFILE
static xlat_action_t sql_xlat_query_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
static unlang_action_t mod_sql_redundant(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Generic module call for failing between a bunch of queries.
map_list_t check_tmp
List to store check items before processing.
static int submodule_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int mod_bootstrap(module_inst_ctx_t const *mctx)
fr_value_box_t * query
Query string used for evaluating group membership.
fr_sql_query_t * query_ctx
sql_autz_call_env_t * call_env
Call environment data.
static const call_env_method_t xlat_method_env
sql_autz_status_t
Status of the authorization process.
@ SQL_AUTZ_PROFILE_REPLY
Running profile reply query.
@ SQL_AUTZ_CHECK
Running user check query.
@ SQL_AUTZ_GROUP_MEMB_RESUME
Completed group membership query.
@ SQL_AUTZ_REPLY
Running user reply query.
@ SQL_AUTZ_GROUP_MEMB
Running group membership query.
@ SQL_AUTZ_PROFILE_REPLY_RESUME
Completed profile reply query.
@ SQL_AUTZ_PROFILE_CHECK_RESUME
Completed profile check query.
@ SQL_AUTZ_CHECK_RESUME
Completed user check query.
@ SQL_AUTZ_PROFILE_START
Starting processing user profiles.
@ SQL_AUTZ_GROUP_REPLY_RESUME
Completed group reply query.
@ SQL_AUTZ_REPLY_RESUME
Completed user reply query.
@ SQL_AUTZ_GROUP_CHECK
Running group check query.
@ SQL_AUTZ_PROFILE_CHECK
Running profile check query.
@ SQL_AUTZ_GROUP_REPLY
Running group reply query.
@ SQL_AUTZ_GROUP_CHECK_RESUME
Completed group check query.
static int sql_xlat_escape(request_t *request, fr_value_box_t *vb, void *uctx)
Escape a tainted VB used as an xlat argument.
rlm_sql_t const * inst
Module instance.
#define SQL_AUTZ_STAGE_GROUP
tmpl_t * group_reply_query
Tmpl to expand to form authorize_group_reply_query.
tmpl_t * group_check_query
Tmpl to expand to form authorize_group_check_query.
int num_groups
How many groups have been retrieved.
static int sql_autz_ctx_free(sql_autz_ctx_t *to_free)
static unlang_action_t mod_sql_redundant_query_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Resume function called after executing an SQL query in a redundant list of queries.
static unlang_action_t mod_map_proc(rlm_rcode_t *p_result, void const *mod_inst, UNUSED void *proc_inst, request_t *request, fr_value_box_list_t *query, map_list_t const *maps)
Executes a SELECT query and maps the result to server attributes.
trunk_t * trunk
Trunk connection for current authorization.
fr_value_box_t * query_vb
Current query string.
fr_value_box_list_t query
Where expanded query tmpl will be written.
map_list_t reply_tmp
List to store reply items before processing.
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Start of module authorize method.
sql_autz_status_t status
Current status of the authorization.
request_t * request
Request being processed.
fr_pair_t * profile
Current profile being processed.
#define MAX_SQL_FIELD_INDEX
fr_dict_attr_autoload_t rlm_sql_dict_attr[]
fr_value_box_list_t query
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Initialise thread specific data structure.
static void * sql_escape_uctx_alloc(UNUSED request_t *request, void const *uctx)
fr_sql_query_t * query_ctx
Query context for current query.
rlm_rcode_t rcode
Module return code.
tmpl_t ** query
Array of tmpls for list of queries to run.
rlm_sql_grouplist_t * next
static const call_env_method_t accounting_method_env
static int sql_redundant_ctx_free(sql_redundant_ctx_t *to_free)
Tidy up when freeing an SQL redundant context.
static const call_env_method_t group_xlat_method_env
sql_group_ctx_t * group_ctx
Context used for retrieving user group membership.
tmpl_t * membership_query
Tmpl to expand to form group_membership_query.
static int sql_box_escape(fr_value_box_t *vb, void *uctx)
static const conf_parser_t module_config[]
fr_value_box_list_t query
Where expanded query tmpls will be written.
bool user_found
Has the user been found anywhere?
static fr_dict_attr_t const * attr_user_profile
static const call_env_method_t send_method_env
fr_dict_autoload_t rlm_sql_dict[]
fr_dict_attr_t const * group_da
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_value_box_t user
Expansion of sql_user_name.
static int query_call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *cc, call_env_ctx_t const *cec, call_env_parser_t const *rule)
static unlang_action_t sql_get_grouplist_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
static ssize_t sql_escape_func(request_t *, char *out, size_t outlen, char const *in, void *arg)
static unlang_action_t sql_get_grouplist(sql_group_ctx_t *group_ctx, trunk_t *trunk, request_t *request)
static unlang_action_t mod_authorize_resume(rlm_rcode_t *p_result, int *priority, request_t *request, void *uctx)
Resume function called after authorization check / reply tmpl expansion.
Context for SQL authorization.
Context for group membership query evaluation.
Context for tracking redundant SQL query sets.
Prototypes and functions for the SQL module.
fr_sql_query_t * fr_sql_query_alloc(TALLOC_CTX *ctx, rlm_sql_t const *inst, request_t *request, trunk_t *trunk, char const *query_str, fr_sql_query_type_t type)
Allocate an sql query structure.
trunk_t * trunk
Trunk connection for this thread.
rlm_sql_t const * inst
Module instance data.
#define RLM_SQL_MULTI_QUERY_CONN
Can support multiple queries on a single connection.
fr_sql_query_type_t type
Type of query.
unlang_action_t rlm_sql_fetch_row(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Call the driver's sql_fetch_row function.
void rlm_sql_query_log(rlm_sql_t const *inst, char const *filename, char const *query)
rlm_sql_t const * inst
Module instance for this query.
unlang_action_t sql_get_map_list(request_t *request, fr_sql_map_ctx_t *map_ctx, trunk_t *trunk)
Submit the query to get any user / group check or reply pairs.
sql_rcode_t
Action to take at end of an SQL query.
@ RLM_SQL_QUERY_INVALID
Query syntax error.
@ RLM_SQL_ALT_QUERY
Key constraint violation, use an alternative query.
@ RLM_SQL_RECONNECT
Stale connection, should reconnect.
@ RLM_SQL_ERROR
General connection/server error.
@ RLM_SQL_NO_MORE_ROWS
No more rows available.
unlang_action_t rlm_sql_trunk_query(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Submit an SQL query using a trunk connection.
TALLOC_CTX * ctx
To allocate map entries in.
void * sql_escape_arg
Thread specific argument to be passed to escape function.
int rows
How many rows the query returned.
void rlm_sql_print_error(rlm_sql_t const *inst, request_t *request, fr_sql_query_t *query_ctx, bool force_debug)
Retrieve any errors from the SQL driver.
rlm_sql_row_t row
Row data from the last query.
sql_rcode_t rcode
Result code.
fr_value_box_t * query
Query string used for fetching pairs.
fr_table_num_sorted_t const sql_rcode_description_table[]
Context used when fetching attribute value pairs as a map list.
int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len)
Trim a talloced sbuff to the minimum length required to represent the contained string.
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_buff(_sbuff_or_marker)
Talloc sbuff extension structure.
static char const * section_name_str(char const *name)
Return a printable string for the section name.
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
char const * name2
Second section name. Usually a packet type like 'access-request', 'access-accept',...
char const * name1
First section name. Usually a verb like 'recv', 'send', etc...
char const * name
Instance name e.g. user_database.
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
void * data
Thread specific instance data.
static module_thread_instance_t * module_thread(module_instance_t const *mi)
Retrieve module/thread specific instance for a module.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
size_t boot_size
Size of the module's bootstrap data.
module_t * exported
Public module structure.
Named methods exported by a module.
#define pair_append_control(_attr, _da)
Allocate and append a fr_pair_t to the control list.
#define pair_delete_request(_pair_or_da)
Delete a fr_pair_t in the request list.
tmpl_escape_t escape
How escaping should be handled during evaluation.
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
#define tmpl_value(_tmpl)
fr_value_box_safe_for_t literals_safe_for
safe_for value assigned to literal values in xlats, execs, and data.
#define tmpl_is_attr(vpt)
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
#define tmpl_is_data(vpt)
#define tmpl_value_type(_tmpl)
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
#define tmpl_expand(_out, _buff, _buff_len, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, using existing storage to hold variably sized types.
#define tmpl_needs_resolving(vpt)
Similar to tmpl_rules_t, but used to specify parameters that may change during subsequent resolution ...
Optional arguments passed to vp_tmpl functions.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
eap_aka_sim_process_conf_t * inst
fr_pair_value_bstrdup_buffer(vp, eap_session->identity, true)
eap_type_t type
The preferred EAP-Type of this instance of the EAP-SIM/AKA/AKA' state machine.
fr_token_t op
The operator that controls insertion of the dst attribute.
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
void * sql_escape_arg
Instance specific argument to be passed to escape function.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
#define talloc_get_type_abort_const
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *tmpl, unlang_tmpl_args_t *args)
Push a tmpl onto the stack for evaluation.
fr_value_box_escape_t func
How to escape when returned from evaluation.
@ TMPL_ESCAPE_UCTX_ALLOC_FUNC
A new uctx of the specified size and type is allocated and pre-populated by memcpying uctx....
@ TMPL_ESCAPE_PRE_CONCAT
Pre-concatenation escaping is useful for DSLs where elements of the expansion are static,...
struct tmpl_escape_t::@74 uctx
fr_value_box_safe_for_t safe_for
Value to set on boxes which have been escaped by the fr_value_box_escape_t function.
tmpl_escape_mode_t mode
Whether to apply escape function after concatenation, i.e.
Escaping rules for tmpls.
const bool fr_assignment_op[T_TOKEN_LAST]
char const * fr_tokens[T_TOKEN_LAST]
const bool fr_comparison_op[T_TOKEN_LAST]
trunk_t * trunk_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, trunk_io_funcs_t const *funcs, trunk_conf_t const *conf, char const *log_prefix, void const *uctx, bool delay_start)
Allocate a new collection of connections.
conf_parser_t const trunk_config[]
Config parser definitions to populate a trunk_conf_t.
Main trunk management handle.
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
fr_type_t type
Type to cast argument to.
xlat_action_t xlat_transparent(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_YIELD
An xlat function pushed a resume frame onto the stack.
@ XLAT_ACTION_PUSH_UNLANG
An xlat function pushed an unlang frame onto the unlang stack.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_type_is_structural(_x)
fr_sbuff_parse_rules_t const * value_parse_rules_quoted[T_TOKEN_LAST]
Parse rules for quoted strings.
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
#define fr_value_box_mark_safe_for(_box, _safe_for)
#define fr_box_strvalue_buffer(_val)
#define fr_value_box_is_safe_for(_box, _safe_for)
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out
static TALLOC_CTX * xlat_ctx
void * rctx
Resume context.
void * env_data
Expanded call env data.
module_ctx_t const * mctx
Synthesised module calling ctx.
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
void xlat_func_call_env_set(xlat_t *x, call_env_method_t const *env_method)
Register call environment of an xlat.
#define xlat_func_safe_for_set(_xlat, _escaped)
Set the escaped values for output boxes.