Skip to content

Commit

Permalink
Move loading of rlm_files data to call_env
Browse files Browse the repository at this point in the history
  • Loading branch information
ndptech committed Feb 9, 2024
1 parent 9d99821 commit e127d7a
Showing 1 changed file with 91 additions and 53 deletions.
144 changes: 91 additions & 53 deletions src/modules/rlm_files/rlm_files.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,36 @@ RCSID("$Id$")
#include <freeradius-devel/server/users_file.h>
#include <freeradius-devel/util/htrie.h>
#include <freeradius-devel/unlang/call_env.h>
#include <freeradius-devel/unlang/function.h>
#include <freeradius-devel/unlang/transaction.h>

#include <ctype.h>
#include <fcntl.h>

typedef struct {
tmpl_t *key;
fr_type_t key_data_type;

char const *common_filename;
fr_htrie_t *common_htrie;
PAIR_LIST_LIST *common_def;
char const *filename;
} rlm_files_t;

/** Structure produced by custom call_env parser
*/
typedef struct {
tmpl_t *key_tmpl; //<! tmpl used to evaluate lookup key.
fr_htrie_t *htrie; //!< parsed files "user" data.
PAIR_LIST_LIST *def; //!< parsed files DEFAULT data.
} rlm_files_data_t;

/** Call_env structure
*/
typedef struct {
fr_value_box_t key;
rlm_files_data_t *data; //<! Data from parsed call_env
fr_value_box_list_t values; //<! Where the expanded tmpl value will be written.
} rlm_files_env_t;

static fr_dict_t const *dict_freeradius;
static fr_dict_t const *dict_radius;

extern fr_dict_autoload_t rlm_files_dict[];
fr_dict_autoload_t rlm_files_dict[] = {
{ .out = &dict_freeradius, .proto = "freeradius" },
{ .out = &dict_radius, .proto = "radius" },
{ NULL }
};

Expand All @@ -69,10 +74,8 @@ fr_dict_attr_autoload_t rlm_files_dict_attr[] = {
{ NULL }
};


static const conf_parser_t module_config[] = {
{ FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT, rlm_files_t, common_filename) },
{ FR_CONF_OFFSET_FLAGS("key", CONF_FLAG_NOT_EMPTY, rlm_files_t, key), .dflt = "%{%{Stripped-User-Name} || %{User-Name}}", .quote = T_DOUBLE_QUOTED_STRING },
{ FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_REQUIRED | CONF_FLAG_FILE_INPUT, rlm_files_t, filename) },
CONF_PARSER_TERMINATOR
};

Expand All @@ -95,7 +98,8 @@ static int pairlist_to_key(uint8_t **out, size_t *outlen, void const *a)
return fr_value_box_to_key(out, outlen, ((PAIR_LIST_LIST const *)a)->box);
}

static int getrecv_filename(TALLOC_CTX *ctx, char const *filename, fr_htrie_t **ptree, PAIR_LIST_LIST **pdefault, fr_type_t data_type)
static int getrecv_filename(TALLOC_CTX *ctx, char const *filename, fr_htrie_t **ptree, PAIR_LIST_LIST **pdefault,
fr_type_t data_type, fr_dict_t const *dict)
{
int rcode;
PAIR_LIST_LIST users;
Expand All @@ -113,7 +117,7 @@ static int getrecv_filename(TALLOC_CTX *ctx, char const *filename, fr_htrie_t **
}

pairlist_list_init(&users);
rcode = pairlist_read(ctx, dict_radius, filename, &users);
rcode = pairlist_read(ctx, dict, filename, &users);
if (rcode < 0) {
return -1;
}
Expand Down Expand Up @@ -387,54 +391,38 @@ static int getrecv_filename(TALLOC_CTX *ctx, char const *filename, fr_htrie_t **
return 0;
}



/*
* (Re-)read the "users" file into memory.
/** Lookup the expanded key value in files data.
*
*/
static int mod_instantiate(module_inst_ctx_t const *mctx)
static unlang_action_t CC_HINT(nonnull) mod_files_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
{
rlm_files_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_files_t);

inst->key_data_type = tmpl_expanded_type(inst->key);
if (fr_htrie_hint(inst->key_data_type) == FR_HTRIE_INVALID) {
cf_log_err(mctx->inst->conf, "Invalid data type '%s' for 'files' module.",
fr_type_to_str(inst->key_data_type));
return -1;
}

#undef READFILE
#define READFILE(_x, _y, _d) if (getrecv_filename(inst, inst->_x, &inst->_y, &inst->_d, inst->key_data_type) != 0) do { ERROR("Failed reading %s", inst->_x); return -1;} while (0)

READFILE(common_filename, common_htrie, common_def);

return 0;
}

static unlang_action_t CC_HINT(nonnull) mod_files(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
{
rlm_files_t const *inst = talloc_get_type_abort_const(mctx->inst->data, rlm_files_t);
rlm_files_env_t *env = talloc_get_type_abort(mctx->env_data, rlm_files_env_t);
rlm_files_env_t *env = talloc_get_type_abort(uctx, rlm_files_env_t);
PAIR_LIST_LIST const *user_list;
PAIR_LIST const *user_pl, *default_pl;
bool found = false, trie = false;
PAIR_LIST_LIST my_list;
uint8_t key_buffer[16], *key;
size_t keylen = 0;
fr_edit_list_t *el, *child;
fr_htrie_t *tree = inst->common_htrie;
PAIR_LIST_LIST *default_list = inst->common_def;
fr_htrie_t *tree = env->data->htrie;
PAIR_LIST_LIST *default_list = env->data->def;
fr_value_box_t *key_vb = fr_value_box_list_head(&env->values);

if (!key_vb) {
ERROR("Missing key value");
RETURN_MODULE_FAIL;
}

if (!tree && !default_list) RETURN_MODULE_NOOP;

RDEBUG2("Looking for key \"%pV\"", &env->key);
RDEBUG2("Looking for key \"%pV\"", key_vb);

el = unlang_interpret_edit_list(request);
MEM(child = fr_edit_list_alloc(request, 50, el));

if (tree) {
my_list.name = NULL;
my_list.box = &env->key;
my_list.box = key_vb;
user_list = fr_htrie_find(tree, &my_list);

trie = (tree->type == FR_HTRIE_TRIE);
Expand All @@ -449,7 +437,7 @@ static unlang_action_t CC_HINT(nonnull) mod_files(rlm_rcode_t *p_result, module_
key = key_buffer;
keylen = sizeof(key_buffer) * 8;

(void) fr_value_box_to_key(&key, &keylen, &env->key);
(void) fr_value_box_to_key(&key, &keylen, key_vb);

RDEBUG3("Keylen %ld", keylen);
RHEXDUMP3(key, (keylen + 7) >> 3, "KEY ");
Expand Down Expand Up @@ -607,19 +595,70 @@ static unlang_action_t CC_HINT(nonnull) mod_files(rlm_rcode_t *p_result, module_
RETURN_MODULE_OK;
}

/** Initiate a files data lookup
*
* The results of call_env parsing are a structure containing the
* tmpl_t representing the key and the parsed files data, meaning tmpl
* expansion does not happen by default.
* First we push the tmpl onto the stack for evaluation, then the lookup
* is done in mod_files_resume.
*/
static unlang_action_t CC_HINT(nonnull) mod_files(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
{
rlm_files_env_t *env = talloc_get_type_abort(mctx->env_data, rlm_files_env_t);

fr_value_box_list_init(&env->values);

/*
* @todo - Whilst this causes `key` to be evaluated on a per-call basis,
* it is still evaluated during module instantiation to determine the tree type in use
* so more restructuring is needed to make the module protocol agnostic.
/*
* Set mod_files_resume as the repeat function
*/
if (unlang_function_push(request, NULL, mod_files_resume, NULL, 0, UNLANG_SUB_FRAME, env) < 0) RETURN_MODULE_FAIL;

/*
* Push evaluation of the key tmpl onto the stack
*/
if (unlang_tmpl_push(env, &env->values, request, env->data->key_tmpl, NULL) < 0) RETURN_MODULE_FAIL;
return UNLANG_ACTION_PUSHED_CHILD;
}

/** Custom call_env parser for loading files data
*
* Or we need to regenerate the tree on every call.
*/
static int call_env_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci,
void const *data, UNUSED call_env_parser_t const *rule)
{
rlm_files_t const *inst = talloc_get_type_abort_const(data, rlm_files_t);
CONF_PAIR const *to_parse = cf_item_to_pair(ci);
rlm_files_data_t *files_data;
fr_type_t keytype;

MEM(files_data = talloc_zero(ctx, rlm_files_data_t));

if (tmpl_afrom_substr(ctx, &files_data->key_tmpl,
&FR_SBUFF_IN(cf_pair_value(to_parse), talloc_array_length(cf_pair_value(to_parse)) - 1),
cf_pair_value_quote(to_parse), NULL, t_rules) < 0) return -1;

keytype = tmpl_expanded_type(files_data->key_tmpl);
if (fr_htrie_hint(keytype) == FR_HTRIE_INVALID) {
cf_log_err(ci, "Invalid data type '%s' for 'files' module", fr_type_to_str(keytype));
error:
talloc_free(files_data);
return -1;
}

if (getrecv_filename(files_data, inst->filename, &files_data->htrie, &files_data->def,
keytype, t_rules->attr.dict_def) < 0) goto error;

*(void **)out = files_data;
return 0;
}

static const call_env_method_t method_env = {
FR_CALL_ENV_METHOD_OUT(rlm_files_env_t),
.env = (call_env_parser_t[]){
{ FR_CALL_ENV_OFFSET("key", FR_TYPE_VOID, CALL_ENV_FLAG_REQUIRED, rlm_files_env_t, key),
.pair.dflt = "%{%{Stripped-User-Name} || %{User-Name}}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING },
{ FR_CALL_ENV_PARSE_ONLY_OFFSET("key", FR_TYPE_VOID, CALL_ENV_FLAG_PARSE_ONLY, rlm_files_env_t, data),
.pair.dflt = "%{%{Stripped-User-Name} || %{User-Name}}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING,
.pair.func = call_env_parse },
CALL_ENV_TERMINATOR
},
};
Expand All @@ -632,7 +671,6 @@ module_rlm_t rlm_files = {
.name = "files",
.inst_size = sizeof(rlm_files_t),
.config = module_config,
.instantiate = mod_instantiate
},
.method_names = (module_method_name_t[]){
{ .name1 = CF_IDENT_ANY, .name2 = CF_IDENT_ANY, .method = mod_files,
Expand Down

0 comments on commit e127d7a

Please sign in to comment.