28 RCSID(
"$Id: acefc287ac964fcefcd620f508b96fc7ea5a2e4e $")
30 #define LOG_PREFIX mctx->inst->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/table.h>
39 #include <freeradius-devel/unlang/function.h>
40 #include <freeradius-devel/unlang/xlat_func.h>
62 {
FR_CONF_OFFSET(
"safe_characters",
rlm_sql_config_t, allowed_chars), .dflt =
"@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /" },
117 char const *section_name1,
char const *section_name2,
void const *
data,
call_env_parser_t const *rule);
120 char const *section_name1,
char const *section_name2,
void const *
data,
call_env_parser_t const *rule);
156 #define SQL_AUTZ_STAGE_GROUP 0x20
157 #define SQL_AUTZ_STAGE_PROFILE 0x40
262 for (map = map_list_head(maps);
265 next = map_list_next(maps, map);
270 (void) map_list_remove(maps, map);
305 fr_value_box_entry_t entry;
327 if (!fr_sbuff_init_talloc(vb, &sbuff, &sbuff_ctx, vb->vb_length * 3, vb->vb_length * 3)) {
332 len =
inst->sql_escape_func(request,
fr_sbuff_buff(&sbuff), vb->vb_length * 3 + 1, vb->vb_strvalue, handle);
385 bool fetched =
false;
394 p = arg->vb_strvalue;
419 numaffected = (
inst->driver->sql_affected_rows)(handle, &
inst->config);
420 if (numaffected < 1) {
421 RDEBUG2(
"SQL query affected no rows");
422 (
inst->driver->sql_finish_query)(handle, &
inst->config);
428 fr_value_box_uint32(vb, NULL, (
uint32_t)numaffected,
false);
431 (
inst->driver->sql_finish_query)(handle, &
inst->config);
445 RDEBUG2(
"NULL value in first column of result");
452 RDEBUG2(
"SQL query returned no results");
459 (
inst->driver->sql_finish_select_query)(handle, &
inst->config);
472 (
inst->driver->sql_finish_select_query)(handle, &
inst->config);
495 char const *
value = uctx;
505 RPEDEBUG(
"Failed parsing value \"%pV\" for attribute %s",
542 fr_value_box_list_t *query, map_list_t
const *maps)
558 char const **fields = NULL, *map_rhs;
559 char map_rhs_buff[128];
561 char const *query_str = NULL;
564 #define MAX_SQL_FIELD_INDEX (64)
567 bool found_field =
false;
572 REDEBUG(
"Query cannot be (null)");
580 RPEDEBUG(
"Failed concatenating input string");
583 query_str = query_head->vb_strvalue;
602 if (
inst->driver->sql_num_rows) {
603 ret =
inst->driver->sql_num_rows(handle, &
inst->config);
605 RDEBUG2(
"Server returned an empty result");
607 (
inst->driver->sql_finish_select_query)(handle, &
inst->config);
612 RERROR(
"Failed retrieving row count");
615 (
inst->driver->sql_finish_select_query)(handle, &
inst->config);
623 ret = (
inst->driver->sql_fields)(&fields, handle, &
inst->config);
629 field_cnt = talloc_array_length(fields);
638 for (map = map_list_head(maps), i = 0;
640 map = map_list_next(maps, map), i++) {
644 if (
tmpl_expand(&map_rhs, map_rhs_buff,
sizeof(map_rhs_buff),
645 request, map->
rhs, NULL, NULL) < 0) {
646 RPERROR(
"Failed getting field name");
650 for (j = 0; j < field_cnt; j++) {
651 if (strcmp(fields[j], map_rhs) != 0)
continue;
662 RDEBUG2(
"No fields matching map found in query result");
664 (
inst->driver->sql_finish_select_query)(handle, &
inst->config);
677 for (map = map_list_head(maps), j = 0;
679 map = map_list_next(maps, map), j++) {
680 if (field_index[j] < 0)
continue;
688 RDEBUG2(
"SQL query returned no results");
692 (
inst->driver->sql_finish_select_query)(handle, &
inst->config);
719 if (outlen <= utf8_len)
break;
721 memcpy(
out,
in, utf8_len);
737 if (outlen <= 2)
break;
748 if (outlen <= 2)
break;
759 if (outlen <= 2)
break;
775 strchr(
inst->config.allowed_chars, *
in) == NULL) {
835 RDEBUG2(
"SQL-User-Name set to '%pV'", &
vp->data);
841 #define sql_unset_user(_i, _r) fr_pair_delete_by_da(&_r->request_pairs, _i->sql_user)
859 entry = *phead = NULL;
861 if (!query || !*query)
return 0;
868 RDEBUG2(
"row[0] returned NULL");
869 (
inst->driver->sql_finish_select_query)(*handle, &
inst->config);
874 if (!*phead || !entry) {
887 (
inst->driver->sql_finish_select_query)(*handle, &
inst->config);
906 REDEBUG(
"Failed getting connection handle");
915 REDEBUG(
"Error getting group membership");
920 for (entry =
head; entry != NULL; entry = entry->
next) {
921 if (strcmp(entry->
name,
name) == 0) {
944 char const *p = arg->vb_strvalue;
947 query = fr_value_box_list_head(&xlat_ctx->
query);
976 RWARN(
"Cannot check group membership - group_membership_query not set");
986 fr_value_box_list_init(&xlat_ctx->
query);
1009 for (map = map_list_head(check_map);
1012 next = map_list_next(check_map, map);
1015 (void) map_list_remove(check_map, map);
1016 map_list_insert_tail(reply_map, map);
1027 REDEBUG(
"Invalid comparison for structural type");
1034 map_list_talloc_free(check_map);
1035 map_list_talloc_free(reply_map);
1036 RDEBUG2(
"failed match: skipping this entry");
1047 map_list_talloc_free(&to_free->
check_tmp);
1048 map_list_talloc_free(&to_free->
reply_tmp);
1081 switch(autz_ctx->
status) {
1088 REDEBUG(
"Error retrieving group list");
1093 RDEBUG2(
"User not found in any groups");
1098 RDEBUG2(
"User found in the group table");
1128 goto group_reply_push;
1137 REDEBUG(
"Error retrieving check pairs for %s %pV",
1149 map_list_talloc_free(&autz_ctx->
check_tmp);
1150 goto next_group_find;
1152 RDEBUG2(
"%s \"%pV\": Conditional check items matched",
1155 RDEBUG2(
"%s \"%pV\": Conditional check items matched (empty)",
1161 map_list_talloc_free(&autz_ctx->
check_tmp);
1172 if (map_list_num_elements(&autz_ctx->
reply_tmp))
goto group_attr_cache;
1174 goto next_group_find;
1183 REDEBUG(
"Error retrieving reply pairs for %s %pV",
1190 goto group_attr_cache;
1202 if (map_list_num_elements(&autz_ctx->
reply_tmp) == 0)
goto next_group_find;
1203 RDEBUG2(
"%s \"%pV\": Merging control and reply items",
1209 RPEDEBUG(
"Failed applying reply item");
1214 map_list_talloc_free(&autz_ctx->
reply_tmp);
1220 if (autz_ctx->
profile)
goto next_profile;
1224 if (autz_ctx->
group)
goto next_group;
1238 RDEBUG3(
"... falling-through to profile processing");
1270 switch(autz_ctx->
status) {
1277 REDEBUG(
"Failed getting check attributes");
1281 if (rows == 0)
goto skip_reply;
1286 RDEBUG2(
"User found in radcheck table");
1290 RDEBUG2(
"Conditional check items matched");
1293 map_list_talloc_free(&autz_ctx->
check_tmp);
1308 REDEBUG(
"SQL query error getting reply attributes");
1312 if (rows == 0)
goto skip_reply;
1316 RDEBUG2(
"User found in radreply table");
1320 if (map_list_num_elements(&autz_ctx->
reply_tmp)) {
1321 RDEBUG2(
"Merging control and reply items");
1331 map_list_talloc_free(&autz_ctx->
reply_tmp);
1336 RDEBUG3(
"... falling-through to group processing");
1339 RWARN(
"Cannot check groups when group_membership_query is not set");
1344 RWARN(
"Cannot process groups when neither authorize_group_check_query nor authorize_group_check_query are set");
1357 RDEBUG3(
"... falling-through to profile processing");
1360 RWARN(
"Cannot process profiles when neither authorize_group_check_query nor authorize_group_check_query are set");
1365 if (!autz_ctx->
profile)
break;
1395 RWDEBUG(
"No authorization checks configured, returning noop");
1407 .call_env = call_env,
1432 fr_value_box_list_init(&autz_ctx->
query);
1485 int numaffected = 0;
1488 query = fr_value_box_list_pop_head(&redundant_ctx->
query);
1538 numaffected = (
inst->driver->sql_affected_rows)(redundant_ctx->
handle, &
inst->config);
1539 (
inst->driver->sql_finish_query)(redundant_ctx->
handle, &
inst->config);
1540 RDEBUG2(
"%i record(s) updated", numaffected);
1553 RDEBUG2(
"Trying next query...");
1572 if (!call_env->
query) {
1573 RWARN(
"No query configured");
1581 .call_env = call_env,
1596 fr_value_box_list_init(&redundant_ctx->
query);
1603 CONF_ITEM *ci,
char const *section_name1,
char const *section_name2,
1632 if (section_name2) {
1633 section2 = talloc_strdup(NULL, section_name2);
1635 while (*p !=
'\0') {
1641 if (subsubcs) to_parse =
cf_pair_find(subsubcs,
"logfile");
1643 if (!to_parse) to_parse =
cf_pair_find(subcs,
"logfile");
1648 if (!to_parse)
return 0;
1653 our_rules = *t_rules;
1678 CONF_ITEM *ci,
UNUSED char const *section_name1,
char const *section_name2,
1690 if (!section_name2)
return -1;
1698 section2 = talloc_strdup(NULL, section_name2);
1700 while (*p !=
'\0') {
1706 if (!subcs)
return 0;
1711 our_rules = *t_rules;
1759 talloc_free_children(
inst);
1779 char const *group_attribute;
1783 if (
inst->config.group_attribute) {
1784 group_attribute =
inst->config.group_attribute;
1787 group_attribute =
buffer;
1789 group_attribute =
"SQL-Group";
1800 if (!
inst->group_da) {
1812 cf_log_perr(
conf,
"Failed registering %s expansion", group_attribute);
1824 sql_xlat_arg[0].
concat =
true;
1825 sql_xlat_arg[0].
func = NULL;
1826 sql_xlat_arg[0].
uctx = NULL;
1851 sql_xlat_arg[0].
concat =
true;
1854 sql_xlat_arg[0].
uctx = uctx;
1881 WARN(
"Ignoring authorize_group_check_query as group_membership_query is not configured");
1885 WARN(
"Ignoring authorize_group_reply_query as group_membership_query is not configured");
1888 if (!
inst->config.read_groups) {
1889 WARN(
"Ignoring read_groups as group_membership_query is not configured");
1890 inst->config.read_groups =
false;
1911 inst->sql_escape_func =
inst->driver->sql_escape_func ?
1912 inst->driver->sql_escape_func :
1925 INFO(
"Attempting to connect to database \"%s\"",
inst->config.sql_db);
1928 if (!
inst->pool)
return -1;
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.
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
#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...
#define FR_CALL_ENV_SUBSECTION_FUNC(_name, _ident2, _flags, _func)
Specify a call_env_parser_t which parses a subsection using a callback function.
@ 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.
#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
#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
@ 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_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,...)
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.
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.
int fr_dict_attr_add(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, int attr, fr_type_t type, fr_dict_attr_flags_t const *flags))
Add an attribute to the dictionary.
Specifies an attribute which must be present for the module to function.
Values of the encryption flags.
Specifies a dictionary which must be loaded/loadable for the module to function.
char const *_CONST name
Instance name.
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
CONF_SECTION *_CONST conf
Module's instance configuration.
dl_module_inst_t const * inst
#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_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_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(void *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_STRING
String of printable characters.
@ 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)
void * env_data
Per call environment data.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Specifies a module method identifier.
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.
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.
static const conf_parser_t config[]
#define pair_update_request(_attr, _da)
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_RCODE(_rcode)
#define RETURN_MODULE_INVALID
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_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 int instantiate(module_inst_ctx_t const *mctx)
rlm_sql_t const * inst
Module instance.
static void * sql_escape_uctx_alloc(request_t *request, void const *uctx)
static int mod_detach(module_detach_ctx_t const *mctx)
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
static int logfile_call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *cc, char const *section_name1, char const *section_name2, void const *data, call_env_parser_t const *rule)
sql_redundant_call_env_t * call_env
Call environment data.
rlm_sql_grouplist_t * groups
List of groups returned by the group membership query.
tmpl_t * check_query
Tmpl to expand to form authorize_check_query.
static unlang_action_t mod_autz_group_resume(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
Resume function called after authorization group / profile expansion of check / reply query tmpl.
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 int _sql_escape_uxtx_free(void *uctx)
static fr_dict_attr_t const * attr_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, char const *section_name1, char const *section_name2, void const *data, call_env_parser_t const *rule)
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 fr_dict_t const * dict_freeradius
static void sql_set_user(rlm_sql_t const *inst, request_t *request, fr_value_box_t *user)
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.
#define SQL_AUTZ_STAGE_PROFILE
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 mod_bootstrap(module_inst_ctx_t const *mctx)
rlm_sql_handle_t * handle
Database connection handle in use for current authorization.
static xlat_action_t sql_group_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
sql_autz_call_env_t * call_env
Call environment data.
static int sql_map_verify(CONF_SECTION *cs, UNUSED void *mod_inst, UNUSED void *proc_inst, tmpl_t const *src, UNUSED map_list_t const *maps)
static const call_env_method_t xlat_method_env
static unlang_action_t mod_map_proc(rlm_rcode_t *p_result, void *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.
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_REPLY
Running user reply query.
@ SQL_AUTZ_GROUP_MEMB
Running group membership query.
@ SQL_AUTZ_PROFILE_START
Starting processing user profiles.
@ SQL_AUTZ_GROUP_CHECK
Running group check query.
@ SQL_AUTZ_PROFILE_CHECK
Running profile check query.
@ SQL_AUTZ_GROUP_REPLY
Running group reply 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.
static int sql_autz_ctx_free(sql_autz_ctx_t *to_free)
static int sql_get_grouplist(rlm_sql_t const *inst, rlm_sql_handle_t **handle, request_t *request, char const *query, rlm_sql_grouplist_t **phead)
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 bool sql_check_group(rlm_sql_t const *inst, request_t *request, char const *query, char const *name)
Check if a given group is in the SQL group for this user.
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
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[]
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_value_box_t user
Expansion of sql_user_name.
static size_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 tracking redundant SQL query sets.
Prototypes and functions for the SQL module.
rlm_sql_t const * inst
The rlm_sql instance this connection belongs to.
void rlm_sql_query_log(rlm_sql_t const *inst, char const *filename, char const *query)
sql_rcode_t rlm_sql_fetch_row(rlm_sql_row_t *out, rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle)
Call the driver's sql_fetch_row function.
int sql_get_map_list(TALLOC_CTX *ctx, rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle, map_list_t *out, char const *query, fr_dict_attr_t const *list)
rlm_sql_handle_t * handle
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.
struct sql_inst rlm_sql_t
sql_rcode_t rlm_sql_select_query(rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle, char const *query))
Call the driver's sql_select_query method, reconnecting if necessary.
void * sql_mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
sql_rcode_t rlm_sql_query(rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t **handle, char const *query))
Call the driver's sql_query method, reconnecting if necessary.
fr_table_num_sorted_t const sql_rcode_description_table[]
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.
@ MODULE_TYPE_THREAD_SAFE
Module is threadsafe.
#define MODULE_NAME_TERMINATOR
#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)
if(!subtype_vp) goto fail
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.
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_PRE_CONCAT
Pre-concatenation escaping is useful for DSLs where elements of the expansion are static,...
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.
const bool fr_assignment_op[T_TOKEN_LAST]
char const * fr_tokens[T_TOKEN_LAST]
const bool fr_comparison_op[T_TOKEN_LAST]
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.
void * uctx
Argument to pass to escape callback.
bool required
Argument must be present, and non-empty.
xlat_escape_func_t func
Function to handle tainted values.
bool concat
Concat boxes together.
fr_value_box_safe_for_t safe_for
Escaped value to set for boxes processed by this escape function.
#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)
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
void * rctx
Resume context.
module_ctx_t const * mctx
Synthesised module calling ctx.
void * env_data
Expanded call env data.
void xlat_func_call_env_set(xlat_t *x, call_env_method_t const *env_method)
Register call environment of an xlat.
int xlat_func_mono_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the argument of an xlat.
xlat_t * xlat_func_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function for a module.