27RCSID(
"$Id: aa79d131dbd05dcfab0dcda7ec322bddcf6b534a $")
31#include <freeradius-devel/util/debug.h>
32#include <freeradius-devel/server/rcode.h>
34#define LOG_PREFIX "rlm_ldap groups"
119 if (!
inst->group.obj_name_attr) {
120 REDEBUG(
"Told to convert group names to DNs but missing 'group.name_attribute' directive");
124 REDEBUG(
"Missing group base_dn");
128 RDEBUG2(
"Converting group name(s) to group DN(s)");
135 inst->group.obj_filter ?
"(&" :
"",
136 inst->group.obj_filter ?
inst->group.obj_filter :
"",
140 filter = talloc_asprintf_append_buffer(filter,
"(%s=%s)",
inst->group.obj_name_attr,
buffer);
144 filter = talloc_asprintf_append_buffer(filter,
"%s%s",
145 inst->group.obj_filter ?
")" :
"",
149 group_ctx->
base_dn->vb_strvalue,
inst->group.obj_scope, filter,
166 unsigned int entry_cnt;
172 switch (query->
ret) {
178 RDEBUG2(
"Tried to resolve group name(s) to DNs but got no results");
187 if (entry_cnt > group_ctx->
name_cnt) {
188 REDEBUG(
"Number of DNs exceeds number of names, group and/or dn should be more restrictive");
194 if (entry_cnt < group_ctx->name_cnt) {
195 RWDEBUG(
"Got partial mapping of group names (%i) to DNs (%i), membership information may be incomplete",
201 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
202 REDEBUG(
"Failed retrieving entry: %s", ldap_err2string(ldap_errno));
211 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
212 REDEBUG(
"Retrieving object DN from entry failed: %s", ldap_err2string(ldap_errno));
219 RDEBUG2(
"Got group DN \"%s\"", dn);
252 if (!
inst->group.obj_name_attr) {
253 REDEBUG(
"Told to resolve group DN to name but missing 'group.name_attribute' directive");
257 RDEBUG2(
"Resolving group DN \"%s\" to group name", *group_ctx->
dn);
260 LDAP_SCOPE_BASE, NULL, group_ctx->
attrs, NULL, NULL);
284 switch (query->
ret) {
290 REDEBUG(
"Group DN \"%s\" did not resolve to an object", *group_ctx->
dn);
301 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
302 REDEBUG(
"Failed retrieving entry: %s", ldap_err2string(ldap_errno));
308 REDEBUG(
"No %s attributes found in object",
inst->group.obj_name_attr);
316 RDEBUG2(
"Group DN \"%s\" resolves to name \"%pV\"", *group_ctx->
dn, &
vp->data);
346 RDEBUG2(
"Adding cacheable user object memberships");
380 switch (p_result->
rcode) {
394 if (*group_ctx->
dn) {
442 LDAPMessage *entry = autz_ctx->
entry;
446 struct berval *
value;
450 int is_dn, iter_err = 0, name2dn = 0, dn2name = 0;
451 size_t count = 0, strings_len = 0;
453 inst->group.profile_attr_suspend,
464 RPERROR(
"Failed parsing user object");
468 RDEBUG2(
"No cacheable group memberships found in user object");
490 group_ctx->
ttrunk = ttrunk;
518 if (want_profiles && is_dn) {
522 if (
inst->group.cacheable_dn) {
536 REDEBUG(
"Too many groups require name to DN resolution");
546 if (
inst->group.cacheable_name) {
560 REDEBUG(
"Too many groups require DN to name resolution");
569 RPERROR(
"Failed parsing user object");
580 group_ctx->
attrs[0] =
inst->group.obj_name_attr;
617 group_ctx->
attrs[0] =
inst->group.obj_name_attr;
619 group_ctx->
base_dn->vb_strvalue,
inst->group.obj_scope,
620 filter->vb_strvalue, group_ctx->
attrs, NULL, NULL);
657 inst->group.profile_attr_suspend,
660 switch (query->
ret) {
666 RDEBUG2(
"No cacheable group memberships found in group objects");
677 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
678 REDEBUG(
"Failed retrieving entry: %s", ldap_err2string(ldap_errno));
693 RDEBUG2(
"Adding cacheable group object memberships");
695 if (
inst->group.cacheable_dn || want_profiles) {
698 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
699 REDEBUG(
"Retrieving object DN from entry failed: %s", ldap_err2string(ldap_errno));
709 if (
inst->group.cacheable_dn) {
720 if (
inst->group.cacheable_name) {
724 inst->group.obj_name_attr) <= 0)
continue;
753 if (!
inst->group.obj_membership_filter) {
754 RDEBUG2(
"Skipping caching group objects as directive 'group.membership_filter' is not set");
759 REDEBUG(
"Missing group base_dn");
767 group_ctx->
uctx = autz_ctx;
794 char const *attrs[2];
812 switch (query->
ret) {
818 RDEBUG2(
"No profiles found in group objects");
830 RPERROR(
"Failed parsing profiles from group objects");
857 inst->group.profile_attr_suspend,
867 RWDEBUG(
"Skipping group profiles, no naming context contains every group DN");
871 dn_attr =
inst->dn_attr;
877 group_ctx->
attrs[0] = profile_attr;
896 base, LDAP_SCOPE_SUB, group_ctx->
filter, group_ctx->
attrs, NULL, NULL);
913 switch (query->
ret) {
917 LDAPMessage *entry = NULL;
969 char const *filters[] = { name_filter,
inst->group.obj_filter,
inst->group.obj_membership_filter };
972 if (!
inst->group.obj_name_attr) {
973 REDEBUG(
"Told to search for group by name, but missing 'group.name_attribute' "
992 .always_escape =
false,
999 snprintf(name_filter,
sizeof(name_filter),
"(%s=%s)",
1000 inst->group.obj_name_attr,
xlat_ctx->group->vb_strvalue);
1035 if (!
inst->group.obj_name_attr) {
1036 REDEBUG(
"Told to resolve group DN to name but missing 'group.name_attribute' directive");
1071 LDAP_SCOPE_BASE, NULL,
xlat_ctx->attrs, NULL, NULL);
1087 bool value_is_dn =
false;
1089 char *value_name = NULL;
1095 if (!group_ctx->
values) {
1098 ldap_get_option(query->
ldap_conn->
handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
1099 REDEBUG(
"Failed retrieving entry: %s", ldap_err2string(ldap_errno));
1104 if (!group_ctx->
values) {
1105 RDEBUG2(
"User object contains no group membership information in attribute \"%s\"",
1106 inst->group.userobj_membership_attr);
1114 group_ctx->
count = ldap_count_values_len(group_ctx->
values);
1121 if (group_ctx->
query) {
1123 struct berval name_value;
1131 REDEBUG(
"Group DN \"%pV\" did not resolve to an object",
1142 REDEBUG(
"Failed retrieving entry: %s", ldap_err2string(ldap_errno));
1147 inst->group.obj_name_attr) <= 0) {
1148 REDEBUG(
"No %s attributes found in object",
inst->group.obj_name_attr);
1175 (memcmp(group->vb_strvalue, value_name, group->vb_length) == 0)) {
1176 RDEBUG2(
"User found in group \"%pV\". Comparison between membership: name "
1177 "(resolved from DN \"%pV\"), check: name", group,
1183 TALLOC_FREE(value_name);
1191 RDEBUG2(
"Processing %s value \"%pV\" as a %s",
inst->group.userobj_membership_attr,
1193 value_is_dn ?
"DN" :
"group name");
1198 if (!
xlat_ctx->group_is_dn && !value_is_dn) {
1199 if ((group->vb_length ==
value->bv_len) &&
1200 (memcmp(
value->bv_val, group->vb_strvalue,
value->bv_len) == 0)) {
1201 RDEBUG2(
"User found in group \"%pV\". Comparison between membership: name, check: name",
1212 if (
xlat_ctx->group_is_dn && value_is_dn) {
1214 RDEBUG2(
"User found in group DN \"%pV\". "
1215 "Comparison between membership: dn, check: dn", group);
1226 if (!value_is_dn &&
xlat_ctx->group_is_dn) {
1232 group_ctx->
lookup_dn = group->vb_strvalue;
1248 RDEBUG2(
"User found in group \"%pV\". Comparison between membership: "
1249 "name, check: name (resolved from DN \"%pV\")",
1261 if (value_is_dn && !
xlat_ctx->group_is_dn) {
1290 if (group_ctx->
values) ldap_value_free_len(group_ctx->
values);
1311 .
attrs = {
inst->group.obj_name_attr, NULL }
1314 RDEBUG2(
"Checking user object's %s attributes",
inst->group.userobj_membership_attr);
1362 RDEBUG2(
"User found. Matched cached membership");
1369 RDEBUG2(
"Cached membership not found");
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_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
static int const char char buffer[256]
#define USES_APPLE_DEPRECATED_API
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
#define unlang_function_push_with_result(_result_p, _request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack that produces a result.
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
fr_ldap_query_t * query
Current query performing group lookup.
static unlang_action_t ldap_check_userobj_start(UNUSED unlang_result_t *p_result, request_t *request, void *uctx)
Initiate a user lookup to check membership.
unlang_action_t rlm_ldap_cacheable_groupobj(unlang_result_t *p_result, request_t *request, ldap_autz_ctx_t *autz_ctx)
Convert group membership information into attributes.
static char const * null_attrs[]
char const * attrs[2]
For retrieving the group name.
static unlang_action_t ldap_cacheable_groupobj_start(unlang_result_t *p_result, request_t *request, void *uctx)
Initiate an LDAP search for group membership looking at the group objects.
static unlang_action_t ldap_group_name2dn_start(unlang_result_t *p_result, request_t *request, void *uctx)
Convert multiple group names into a DNs.
char const * attrs[2]
For retrieving the profile attribute.
ldap_group_xlat_ctx_t * xlat_ctx
Xlat context being evaluated.
int count
How many entries there are in values.
unlang_action_t rlm_ldap_check_groupobj_dynamic(unlang_result_t *p_result, request_t *request, ldap_group_xlat_ctx_t *xlat_ctx)
Initiate an LDAP search to determine group membership, querying group objects.
void * uctx
Optional context for use in results parsing.
static int userobj_dyn_free(ldap_group_userobj_dyn_ctx_t *group_ctx)
Ensure retrieved LDAP values are cleared up.
char * group_name[LDAP_MAX_CACHEABLE+1]
List of group names which need resolving.
char * group_dn[LDAP_MAX_CACHEABLE+1]
List of group DNs which need resolving.
struct berval ** values
Values of the membership attribute to check.
static unlang_action_t ldap_check_userobj_resume(unlang_result_t *p_result, request_t *request, void *uctx)
Process the results of evaluating a user object when checking group membership.
unlang_action_t rlm_ldap_cacheable_userobj(unlang_result_t *p_result, request_t *request, ldap_autz_ctx_t *autz_ctx, char const *attr)
Convert group membership information into attributes.
static unlang_action_t ldap_cacheable_userobj_resolve(unlang_result_t *p_result, request_t *request, void *uctx)
Initiate DN to name and name to DN group lookups.
tmpl_t * filter_tmpl
Tmpl to expand into LDAP filter.
char const * attrs[2]
For retrieving the group name.
rlm_ldap_t const * inst
Module instance.
unlang_action_t rlm_ldap_check_userobj_dynamic(unlang_result_t *p_result, request_t *request, ldap_group_xlat_ctx_t *xlat_ctx)
Query the LDAP directory to check if a user object is a member of a group.
fr_value_box_list_t expanded_filter
Values produced by expanding filter xlat.
fr_value_box_t * base_dn
The base DN to search for groups in.
fr_ldap_thread_trunk_t * ttrunk
Trunk on which to perform additional queries.
fr_pair_list_t groups
Temporary list to hold pairs.
static unlang_action_t ldap_cacheable_groupobj_resume(unlang_result_t *p_result, request_t *request, void *uctx)
Process the results of a group object lookup.
fr_ldap_thread_trunk_t * ttrunk
Trunk on which to perform additional queries.
char ** dn
Current DN being resolved.
static unlang_action_t ldap_cacheable_userobj_store(unlang_result_t *p_result, request_t *request, ldap_group_userobj_ctx_t *group_ctx)
Move user object group attributes to the control list.
static unlang_action_t ldap_group_name2dn_resume(unlang_result_t *p_result, request_t *request, void *uctx)
Process the results of looking up group DNs from names.
char const * attrs[2]
For resolving name from DN.
char const * filter
Filter matching profile bearing group objects.
static unlang_action_t ldap_group_dn2name_resume(unlang_result_t *p_result, request_t *request, void *uctx)
Process the results of a group DN -> name lookup.
TALLOC_CTX * list_ctx
In which to allocate pairs.
bool resolving_value
Is the current query resolving a DN from values.
unsigned int name_cnt
How many names need resolving.
static unlang_action_t ldap_dn2name_start(unlang_result_t *p_result, request_t *request, void *uctx)
Initiate resolving a group DN to its name.
static void ldap_group_userobj_cancel(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
Cancel a pending group lookup query.
static unlang_action_t ldap_group_profile_resume(unlang_result_t *p_result, request_t *request, void *uctx)
Harvest profile DNs from the group objects returned by the profile search.
static void ldap_group_groupobj_cancel(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
Cancel a pending group object lookup.
static unlang_action_t ldap_check_groupobj_resume(unlang_result_t *p_result, request_t *request, void *uctx)
Process the results of a group object lookup.
fr_value_box_t * base_dn
The base DN to search for groups in.
static void ldap_dn2name_cancel(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
Cancel an in-progress DN to name lookup.
unlang_action_t rlm_ldap_group_profiles(unlang_result_t *p_result, request_t *request, ldap_autz_ctx_t *autz_ctx)
Search for profile DNs in the group objects the user is a member of.
unlang_action_t rlm_ldap_check_cached(unlang_result_t *p_result, rlm_ldap_t const *inst, request_t *request, fr_value_box_t const *check)
Check group membership attributes to see if a user is a member.
static unlang_action_t ldap_group_dn2name_start(unlang_result_t *p_result, request_t *request, void *uctx)
Initiate an LDAP search to turn a group DN into it's name.
fr_ldap_query_t * query
Current query performing group resolution.
ldap_autz_ctx_t * autz_ctx
Authorization context profile DNs are harvested into.
char const * profile_attr
Attribute holding profile DNs.
char const * lookup_dn
The DN currently being looked up, when resolving DN to name.
fr_ldap_query_t * query
Current query retrieving the group objects.
int value_no
The current entry in values being processed.
rlm_ldap_t const * inst
Module instance.
char * group_name
Result of resolving the provided group DN as to a name.
fr_ldap_query_t * query
Current query doing a DN to name resolution.
Context to use when looking up group membership using group objects.
Context used when searching for profiles in the user's group objects.
Context to use when resolving group membership from the user object.
Context to use when evaluating group membership from the user object in an xlat.
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
struct berval * fr_ldap_value_iter_init(int *err, fr_ldap_value_iter_t *iter, LDAP *handle, LDAPMessage *entry, char const *attr)
Start an in place iteration over an attribute's values in an entry.
size_t fr_ldap_util_normalise_dn(char *out, char const *in)
Normalise escape sequences in a DN.
char const * fr_ldap_directory_common_base_find(fr_ldap_directory_t const *directory, char const *const *dn_list)
Find the naming context which contains a set of DNs.
int fr_ldap_filter_to_tmpl(TALLOC_CTX *ctx, tmpl_rules_t const *t_rules, char const **sub, size_t sublen, tmpl_t **out))
Combine filters and tokenize to a tmpl.
#define LDAP_MAX_FILTER_STR_LEN
Maximum length of an xlat expanded filter.
int fr_ldap_entry_value_find(struct berval *out, LDAP *handle, LDAPMessage *entry, char const *attr)
Find an attribute in an entry, returning its first value referenced in place.
int fr_ldap_filter_box_escape(fr_value_box_t *vb, UNUSED void *uctx)
void fr_ldap_value_iter_done(fr_ldap_value_iter_t *iter)
Release value iteration state.
bool fr_ldap_util_is_dn(char const *in, size_t inlen)
Check whether a string looks like a DN.
size_t fr_ldap_filter_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg))
Escape a string for use as an RFC 4515 filter assertion value.
struct berval * fr_ldap_value_iter_next(int *err, fr_ldap_value_iter_t *iter)
Return the next value of the iterated attribute.
LDAP * handle
libldap handle.
fr_ldap_result_code_t ret
Result code.
#define LDAP_MAX_CACHEABLE
Maximum number of groups we retrieve from the server for a given user which need resolving from name ...
trunk_request_t * treq
Trunk request this query is associated with.
int fr_ldap_result_values_len(size_t *num, size_t *strings_len, LDAP *handle, LDAPMessage *result, char const *attr)
Sum the lengths of an attribute's values across every entry of a result.
char * fr_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in)
Convert a berval to a talloced string.
talloc_str_list_t * fr_ldap_str_list_afrom_result(TALLOC_CTX *ctx, LDAP *handle, LDAPMessage *result, char const *attr, size_t extra)
Copy an attribute's values from every entry of a result into a string list.
fr_ldap_connection_t * ldap_conn
LDAP connection this query is running on.
@ LDAP_RESULT_SUCCESS
Successfully got LDAP results.
@ LDAP_RESULT_NO_RESULT
No results returned.
@ LDAP_RESULT_BAD_DN
The requested DN does not exist.
static int fr_ldap_berval_strncasecmp(struct berval *value, char const *str, size_t strlen)
Compare a berval with a C string of a known length using case insensitive comparison.
LDAPMessage * result
Head of LDAP results list.
fr_ldap_directory_t * directory
The type of directory we're connected to.
char const * dn_attr
Attribute to match an entry's DN in a search filter.
#define LDAP_MAX_GROUP_NAME_LEN
Maximum name of a group name.
char * fr_ldap_filter_afrom_dn_list(TALLOC_CTX *ctx, char const *dn_attr, char const *filter, char const *const *dn_list)
Build a filter matching a set of objects by DN.
Thread LDAP trunk structure.
State of an in place iteration over an attribute's values.
LDAP * fr_ldap_handle_thread_local(void)
Get a thread local dummy LDAP handle.
unlang_action_t fr_ldap_trunk_search(TALLOC_CTX *ctx, fr_ldap_query_t **out, request_t *request, fr_ldap_thread_trunk_t *ttrunk, char const *base_dn, int scope, char const *filter, char const *const *attrs, LDAPControl **serverctrls, LDAPControl **clientctrls)
Run an async search LDAP query on a trunk connection.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RINDENT()
Indent R* messages by one level.
@ FR_TYPE_STRING
String of printable characters.
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
#define RDEBUG_ENABLED2()
#define RETURN_UNLANG_INVALID
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_NOTFOUND
#define RETURN_UNLANG_FAIL
#define RETURN_UNLANG_REJECT
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
fr_dict_attr_t const * request_attr_request
fr_dict_attr_t const * request_attr_control
LDAP authorization and authentication module headers.
static char const * rlm_ldap_profile_attr_select(char const *attr, char const *attr_suspend, ldap_access_state_t access_state)
Return the profile attribute matching the user's access state.
ldap_autz_call_env_t * call_env
fr_ldap_thread_trunk_t * ttrunk
tmpl_t * group_filter
tmpl to expand as group membership filter.
struct rlm_ldap_t::@177 group
fr_value_box_t group_base
Base DN in which to search for groups.
ldap_access_state_t access_state
What state a user's account is in.
talloc_str_list_t * group_profile_dn_list
Profile DNs found in the user's group objects.
talloc_str_list_t * group_dn_list
DNs of the group objects the user is a member of.
Holds state of in progress async authorization.
Holds state of in progress group membership check xlat.
#define pair_append_control(_attr, _da)
Allocate and append a fr_pair_t to the control list.
fr_pair_list_t * tmpl_list_head(request_t *request, fr_dict_attr_t const *list)
Resolve attribute fr_pair_list_t value to an attribute list.
TALLOC_CTX * tmpl_list_ctx(request_t *request, fr_dict_attr_t const *list)
Return the correct TALLOC_CTX to alloc fr_pair_t in, for a list.
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
struct tmpl_rules_s tmpl_rules_t
Optional arguments passed to vp_tmpl functions.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
@ FR_SIGNAL_CANCEL
Request has been cancelled.
static char buff[sizeof("18446744073709551615")+3]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
eap_aka_sim_process_conf_t * inst
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.
int talloc_str_list_realloc(talloc_str_list_t *list, size_t extra)
Extend a string list to hold additional strings.
talloc_str_list_t * talloc_str_list_alloc(TALLOC_CTX *ctx, size_t num, size_t strings_len)
Allocate a list to hold num strings of strings_len total length.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
char const * talloc_str_list_append(talloc_str_list_t *list, char const *str, size_t len)
Append a copy of a string to a string list.
static int talloc_const_free(void const *ptr)
Free const'd memory.
char const ** strings
NULL terminated array of strings.
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
int unlang_tmpl_push(TALLOC_CTX *ctx, unlang_result_t *p_result, fr_value_box_list_t *out, request_t *request, tmpl_t const *tmpl, unlang_tmpl_args_t *args, bool top_frame)
Push a tmpl onto the stack for evaluation.
@ TMPL_ESCAPE_PRE_CONCAT
Pre-concatenation escaping is useful for DSLs where elements of the expansion are static,...
void trunk_request_signal_cancel(trunk_request_t *treq)
Cancel a trunk request.
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
int fr_value_box_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b)
Compare two attributes using an operator.
#define fr_box_strvalue_buffer(_val)
#define fr_box_strvalue_len(_val, _len)
#define fr_box_strvalue(_val)
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
static TALLOC_CTX * xlat_ctx