28 RCSID(
"$Id: ed1f660f747bb8db21e3c225fdfc06d7676e1a01 $")
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.-_: /" },
159 #define SQL_AUTZ_STAGE_GROUP 0x20
160 #define SQL_AUTZ_STAGE_PROFILE 0x40
303 for (map = map_list_head(maps);
306 next = map_list_next(maps, map);
311 (void) map_list_remove(maps, map);
346 fr_value_box_entry_t entry;
368 if (
inst->sql_escape_arg) {
369 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;
438 while ((vb = fr_value_box_list_pop_head(
in))) {
460 switch (query_ctx->
rcode) {
465 query_ctx->
rcode,
"<INVALID>"));
474 numaffected = (
inst->driver->sql_affected_rows)(query_ctx, &
inst->config);
475 if (numaffected < 1) {
476 RDEBUG2(
"SQL query affected no rows");
481 fr_value_box_uint32(vb, NULL, (
uint32_t)numaffected,
false);
501 bool fetched =
false;
508 query_ctx->
rcode,
"<INVALID>"));
515 inst->fetch_row(&p_result, NULL, request, query_ctx);
516 row = query_ctx->
row;
517 switch (query_ctx->
rcode) {
521 RDEBUG2(
"NULL value in first column of result");
525 if (!fetched)
RDEBUG2(
"SQL query returned no results");
573 if (!
inst->driver->uses_trunks) {
582 p = arg->vb_strvalue;
600 query_ret =
inst->query(&p_result, NULL, request, query_ctx);
633 if (!
inst->driver->uses_trunks) {
670 if (!
inst->driver->uses_trunks) {
713 RPEDEBUG(
"Failed parsing value \"%pV\" for attribute %s",
736 #define MAX_SQL_FIELD_INDEX (64)
750 map_list_t
const *maps = map_ctx->
maps;
756 char const **fields = NULL, *map_rhs;
758 int i, j, field_cnt, rows = 0;
760 char map_rhs_buff[128];
761 bool found_field =
false;
772 if (
inst->driver->sql_num_rows) {
773 ret =
inst->driver->sql_num_rows(query_ctx, &
inst->config);
775 RDEBUG2(
"Server returned an empty result");
781 RERROR(
"Failed retrieving row count");
793 ret = (
inst->driver->sql_fields)(&fields, query_ctx, &
inst->config);
799 field_cnt = talloc_array_length(fields);
808 for (map = map_list_head(maps), i = 0;
810 map = map_list_next(maps, map), i++) {
814 if (
tmpl_expand(&map_rhs, map_rhs_buff,
sizeof(map_rhs_buff),
815 request, map->
rhs, NULL, NULL) < 0) {
816 RPERROR(
"Failed getting field name");
820 for (j = 0; j < field_cnt; j++) {
821 if (
strcasecmp(fields[j], map_rhs) != 0)
continue;
832 RDEBUG2(
"No fields matching map found in query result");
846 row = query_ctx->
row;
848 for (map = map_list_head(maps), j = 0;
850 map = map_list_next(maps, map), j++) {
851 if (field_index[j] < 0)
continue;
852 if (!row[field_index[j]]) {
853 RWARN(
"Database returned NULL for %s", fields[j]);
863 RDEBUG2(
"SQL query returned no results");
889 fr_value_box_list_t *query, map_list_t
const *maps)
902 REDEBUG(
"Query cannot be (null)");
906 while ((vb = fr_value_box_list_next(query, vb))) {
916 RPEDEBUG(
"Failed concatenating input string");
920 if (!
inst->driver->uses_trunks) {
956 if (outlen <= utf8_len)
break;
958 memcpy(
out,
in, utf8_len);
974 if (outlen <= 2)
break;
985 if (outlen <= 2)
break;
996 if (outlen <= 2)
break;
1012 strchr(
inst->config.allowed_chars, *
in) == NULL) {
1072 RDEBUG2(
"SQL-User-Name set to '%pV'", &
vp->data);
1078 #define sql_unset_user(_i, _r) fr_pair_delete_by_da(&_r->request_pairs, _i->sql_user)
1102 row = query_ctx->
row;
1104 RDEBUG2(
"row[0] returned NULL");
1110 entry = group_ctx->
groups;
1113 entry = entry->
next;
1159 char const *
name = arg->vb_strvalue;
1166 for (entry = group_ctx->
groups; entry != NULL; entry = entry->
next) {
1167 if (strcmp(entry->
name,
name) == 0) {
1192 query = fr_value_box_list_head(&
xlat_ctx->query);
1202 if (!
inst->driver->uses_trunks) {
1205 REDEBUG(
"Failed getting conneciton handle");
1235 RWARN(
"Cannot check group membership - group_membership_query not set");
1245 fr_value_box_list_init(&
xlat_ctx->query);
1268 for (map = map_list_head(check_map);
1271 next = map_list_next(check_map, map);
1274 (void) map_list_remove(check_map, map);
1275 map_list_insert_tail(reply_map, map);
1286 REDEBUG(
"Invalid comparison for structural type");
1293 map_list_talloc_free(check_map);
1294 map_list_talloc_free(reply_map);
1295 RDEBUG2(
"failed match: skipping this entry");
1306 map_list_talloc_free(&to_free->
check_tmp);
1307 map_list_talloc_free(&to_free->
reply_tmp);
1341 switch (*p_result) {
1349 switch(autz_ctx->
status) {
1371 RDEBUG2(
"User not found in any groups");
1376 RDEBUG2(
"User found in the group table");
1436 if (map_ctx->
rows > 0) {
1438 map_list_talloc_free(&autz_ctx->
check_tmp);
1439 goto next_group_find;
1441 RDEBUG2(
"%s \"%pV\": Conditional check items matched",
1444 RDEBUG2(
"%s \"%pV\": Conditional check items matched (empty)",
1450 map_list_talloc_free(&autz_ctx->
check_tmp);
1461 if (map_list_num_elements(&autz_ctx->
reply_tmp))
goto group_attr_cache;
1463 goto next_group_find;
1487 if (map_ctx->
rows == 0) {
1489 goto group_attr_cache;
1501 if (map_list_num_elements(&autz_ctx->
reply_tmp) == 0)
goto next_group_find;
1502 RDEBUG2(
"%s \"%pV\": Merging control and reply items",
1508 RPEDEBUG(
"Failed applying reply item");
1513 map_list_talloc_free(&autz_ctx->
reply_tmp);
1519 if (autz_ctx->
profile)
goto next_profile;
1523 if (autz_ctx->
group)
goto next_group;
1537 RDEBUG3(
"... falling-through to profile processing");
1572 switch (*p_result) {
1580 switch(autz_ctx->
status) {
1601 if (map_ctx->
rows == 0)
goto skip_reply;
1606 RDEBUG2(
"User found in radcheck table");
1610 RDEBUG2(
"Conditional check items matched");
1613 map_list_talloc_free(&autz_ctx->
check_tmp);
1642 if (map_ctx->
rows == 0)
goto skip_reply;
1646 RDEBUG2(
"User found in radreply table");
1650 if (map_list_num_elements(&autz_ctx->
reply_tmp)) {
1651 RDEBUG2(
"Merging control and reply items");
1661 map_list_talloc_free(&autz_ctx->
reply_tmp);
1666 RDEBUG3(
"... falling-through to group processing");
1669 RWARN(
"Cannot check groups when group_membership_query is not set");
1674 RWARN(
"Cannot process groups when neither authorize_group_check_query nor authorize_group_check_query are set");
1687 RDEBUG3(
"... falling-through to profile processing");
1690 RWARN(
"Cannot process profiles when neither authorize_group_check_query nor authorize_group_check_query are set");
1695 if (!autz_ctx->
profile)
break;
1726 RWDEBUG(
"No authorization checks configured, returning noop");
1738 .call_env = call_env,
1740 .trunk = thread->
trunk,
1753 if (!
inst->driver->uses_trunks) {
1759 autz_ctx->
handle,
false,
false,
false);
1769 fr_value_box_list_init(&autz_ctx->
query);
1823 int numaffected = 0;
1828 switch (query_ctx->
rcode) {
1869 numaffected = (
inst->driver->sql_affected_rows)(query_ctx, &
inst->config);
1870 TALLOC_FREE(query_ctx);
1871 RDEBUG2(
"%i record(s) updated", numaffected);
1885 RDEBUG2(
"Trying next query...");
1905 redundant_ctx->
query_vb = fr_value_box_list_pop_head(&redundant_ctx->
query);
1936 if (!call_env->
query) {
1937 RWARN(
"No query configured");
1945 .trunk = thread->
trunk,
1946 .call_env = call_env,
1951 if (!
inst->driver->uses_trunks) {
1957 redundant_ctx->
handle,
false,
false,
false);
1964 fr_value_box_list_init(&redundant_ctx->
query);
2003 section2 = talloc_strdup(NULL, cec->
asked->
name2);
2005 while (*p !=
'\0') {
2011 if (subsubcs) to_parse =
cf_pair_find(subsubcs,
"logfile");
2013 if (!to_parse) to_parse =
cf_pair_find(subcs,
"logfile");
2018 if (!to_parse)
return 0;
2023 our_rules = *t_rules;
2071 while (*p !=
'\0') {
2077 cf_log_debug(ci,
"No query found for \"%s\", this query will be disabled...", section2);
2086 our_rules = *t_rules;
2141 talloc_free_children(
inst);
2170 WARN(
"Ignoring authorize_group_check_query as group_membership_query is not configured");
2174 WARN(
"Ignoring authorize_group_reply_query as group_membership_query is not configured");
2177 if (!
inst->config.read_groups) {
2178 WARN(
"Ignoring read_groups as group_membership_query is not configured");
2179 inst->config.read_groups =
false;
2192 if (
inst->driver->uses_trunks) {
2206 if (
inst->driver->sql_escape_func) {
2207 inst->sql_escape_func =
inst->driver->sql_escape_func;
2220 if (
inst->driver->uses_trunks) {
2237 inst->config.trunk_conf.target_req_per_conn = 1;
2238 inst->config.trunk_conf.max_req_per_conn = 1;
2240 if (!
inst->driver->trunk_io_funcs.connection_notify) {
2241 inst->config.trunk_conf.always_writable =
true;
2265 if (
inst->driver->uses_trunks)
return 0;
2270 INFO(
"Attempting to connect to database \"%s\"",
inst->config.sql_db);
2273 if (!
inst->pool)
return -1;
2291 char const *group_attribute;
2294 if (
inst->config.group_attribute) {
2295 group_attribute =
inst->config.group_attribute;
2298 group_attribute =
buffer;
2300 group_attribute =
"SQL-Group";
2325 cf_log_perr(
conf,
"Failed registering %s expansion", group_attribute);
2427 if (
inst->driver->sql_escape_arg_alloc) {
2434 if (!
inst->driver->uses_trunks)
return 0;
2437 &
inst->config.trunk_conf,
inst->name, t,
false);
2438 if (!t->
trunk)
return -1;
2477 &our_rules) < 0)
return -1;
2478 *(
void **)
out = parsed_tmpl;
2482 #define QUERY_ESCAPE .pair.escape = { \
2483 .mode = TMPL_ESCAPE_PRE_CONCAT, \
2484 .uctx = { .func = { .alloc = sql_escape_uctx_alloc }, .type = TMPL_ESCAPE_UCTX_ALLOC_FUNC }, \
2485 }, .pair.func = call_env_parse
2506 .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...
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.
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
#define CONF_PARSER_TERMINATOR
#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 cf_section_rules_push(_cs, _rule)
#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
@ 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_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr)
Count the number of times an attribute occurs in a parent section.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a 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.
#define cf_log_err(_cf, _fmt,...)
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
#define cf_log_perr(_cf, _fmt,...)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
#define cf_log_debug(_cf, _fmt,...)
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
fr_dcursor_eval_t void const * uctx
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_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.
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 ** 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.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
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.
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.
fr_pool_t * module_rlm_connection_pool_init(CONF_SECTION *module, void *opaque, fr_pool_connection_create_t c, fr_pool_connection_alive_t a, char const *log_prefix, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific connection pool.
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)
module_t common
Common fields presented by all modules.
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.
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_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)
void fr_pool_connection_release(fr_pool_t *pool, request_t *request, void *conn)
Release a connection.
void fr_pool_free(fr_pool_t *pool)
Delete a connection pool.
void * fr_pool_connection_get(fr_pool_t *pool, request_t *request)
Reserve a connection in the connection pool.
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.
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.
void * request_data_reference(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request without removing it.
#define request_data_add(_request, _unique_ptr, _unique_int, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
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 void * sql_escape_uctx_alloc(request_t *request, void const *uctx)
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)
rlm_sql_handle_t * handle
Database connection handle.
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 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
rlm_sql_handle_t * handle
Database connection handle in use for current authorization.
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)
rlm_sql_handle_t * handle
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.
fr_sql_query_t * query_ctx
Query context for current query.
rlm_rcode_t rcode
Module return code.
static unlang_action_t sql_get_grouplist(sql_group_ctx_t *group_ctx, rlm_sql_handle_t **handle, trunk_t *trunk, request_t *request)
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[]
static xlat_action_t sql_group_xlat_query_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Compare list of groups returned from SQL query to xlat argument.
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 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.
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.
unlang_action_t rlm_sql_query(rlm_rcode_t *p_result, int *priority, request_t *request, void *uctx)
void rlm_sql_query_log(rlm_sql_t const *inst, char const *filename, char const *query)
unlang_action_t sql_get_map_list(request_t *request, fr_sql_map_ctx_t *map_ctx, rlm_sql_handle_t **handle, trunk_t *trunk)
Submit the query to get any user / group check or reply pairs.
unlang_action_t rlm_sql_select_query(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Call the driver's sql_select_query method, reconnecting if necessary.
rlm_sql_handle_t * handle
rlm_sql_t const * inst
Module instance for this query.
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.
rlm_sql_handle_t * handle
Connection handle this query is being run on.
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.
void * sql_mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
fr_value_box_t * query
Query string used for fetching pairs.
fr_sql_query_t * fr_sql_query_alloc(TALLOC_CTX *ctx, rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t *handle, trunk_t *trunk, char const *query_str, fr_sql_query_type_t type)
Allocate an sql query structure.
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.
static module_thread_instance_t * module_thread(module_instance_t const *mi)
Retrieve module/thread specific instance for a module.
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.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
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)
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
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.
#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.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_pair_value_bstrdup_buffer(vp, eap_session->identity, true)
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]
conf_parser_t const trunk_config[]
Config parser definitions to populate a trunk_conf_t.
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.
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.