30RCSID(
"$Id: c0a37651a589e441a9d60cd7ef4e3d84b933e523 $")
34#include <freeradius-devel/util/debug.h>
35#include <freeradius-devel/util/table.h>
36#include <freeradius-devel/util/uri.h>
38#include <freeradius-devel/ldap/conf.h>
40#include <freeradius-devel/server/map_proc.h>
41#include <freeradius-devel/server/module_rlm.h>
43#include <freeradius-devel/unlang/xlat_func.h>
44#include <freeradius-devel/unlang/map.h>
171#ifdef LDAP_CONTROL_X_SESSION_TRACKING
199#define LDAP_DN_SAFE_FOR (fr_value_box_safe_for_t)fr_ldap_dn_escape_func
200#define LDAP_FILTER_SAFE_FOR (fr_value_box_safe_for_t)fr_ldap_filter_escape_func
202#define LDAP_DN_CALL_ENV_ESCAPE \
205 .func = fr_ldap_dn_box_escape, \
206 .safe_for = LDAP_DN_SAFE_FOR, \
207 .always_escape = false, \
209 .mode = TMPL_ESCAPE_PRE_CONCAT \
211 .pair.literals_safe_for = LDAP_DN_SAFE_FOR
213#define LDAP_FILTER_CALL_ENV_ESCAPE \
216 .func = fr_ldap_filter_box_escape, \
217 .safe_for = LDAP_FILTER_SAFE_FOR, \
218 .always_escape = false, \
220 .mode = TMPL_ESCAPE_PRE_CONCAT \
222 .pair.literals_safe_for = LDAP_FILTER_SAFE_FOR
224#define USER_CALL_ENV_COMMON(_struct) \
225 { FR_CALL_ENV_OFFSET("base_dn", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, _struct, user_base), \
226 .pair.dflt = "", .pair.dflt_quote = T_SINGLE_QUOTED_STRING, LDAP_DN_CALL_ENV_ESCAPE }, \
227 { FR_CALL_ENV_OFFSET("filter", FR_TYPE_STRING, CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_CONCAT, _struct, user_filter), \
228 .pair.dflt = "(&)", .pair.dflt_quote = T_SINGLE_QUOTED_STRING, LDAP_FILTER_CALL_ENV_ESCAPE }
238 .pair.dflt =
"User-Password", .pair.dflt_quote =
T_BARE_WORD },
291#define USERMOD_ENV(_section) static const call_env_method_t _section ## _usermod_method_env = { \
292 FR_CALL_ENV_METHOD_OUT(ldap_usermod_call_env_t), \
293 .env = (call_env_parser_t[]) { \
294 { FR_CALL_ENV_SUBSECTION("user", NULL, CALL_ENV_FLAG_REQUIRED, \
295 ((call_env_parser_t[]) { \
296 USER_CALL_ENV_COMMON(ldap_usermod_call_env_t), CALL_ENV_TERMINATOR \
298 { FR_CALL_ENV_SUBSECTION_FUNC(STRINGIFY(_section), CF_IDENT_ANY, CALL_ENV_FLAG_SUBSECTION | CALL_ENV_FLAG_PARSE_MISSING, ldap_mod_section_parse) }, \
299 CALL_ENV_TERMINATOR \
334 .expect_password_offset = -1
457 while ((in_vb = fr_value_box_list_pop_head(&in_group->vb_group))) {
465 if (!fr_sbuff_init_talloc(vb, &sbuff, &sbuff_ctx, in_vb->vb_length * 3, in_vb->vb_length * 3)) {
466 REDEBUG(
"Failed to allocate buffer for escaped string");
497 while ((in_vb = fr_value_box_list_pop_head(&in_group->vb_group))) {
505 if (!fr_sbuff_init_talloc(vb, &sbuff, &sbuff_ctx, in_vb->vb_length * 3, in_vb->vb_length * 3)) {
506 REDEBUG(
"Failed to allocate buffer for escaped string");
542 while ((in_vb = fr_value_box_list_next(&in_group->vb_group, in_vb))) {
548 if (!fr_sbuff_init_talloc(vb, &sbuff, &sbuff_ctx, in_vb->vb_length, in_vb->vb_length)) {
549 REDEBUG(
"Failed to allocate buffer for unescaped string");
583 if (!fr_sbuff_init_talloc(vb, &sbuff, &sbuff_ctx, vb->vb_length * 3, vb->vb_length * 3)) {
612 if (!query->
treq)
return;
615 request = treq->request;
644 char *attrs_fixed, **attr, port[6];
646 LDAPURLDesc *ldap_url;
652#ifdef STATIC_ANALYZER
656 if (option_vb->vb_length < 1) {
657 RERROR(
"LDAP attriubte option must not be blank");
661 if (!ldap_is_ldap_url(uri->vb_strvalue)) {
662 REDEBUG(
"String passed does not look like an LDAP URL");
666 ret = ldap_url_parse(uri->vb_strvalue, &ldap_url);
667 if (ret != LDAP_URL_SUCCESS){
675 if (!ldap_url->lud_attrs || !ldap_url->lud_attrs[0] || !*ldap_url->lud_attrs[0]) {
680 if (option_vb->vb_strvalue[0] !=
';') {
683 option = option_vb->vb_strvalue;
689 attr = ldap_url->lud_attrs;
691 attrs_fixed = talloc_strdup_append(attrs_fixed, *attr);
692 if (!strstr(*attr, option)) attrs_fixed = talloc_strdup_append(attrs_fixed, option);
694 if (*attr) attrs_fixed = talloc_strdup_append(attrs_fixed,
",");
697 snprintf(port,
sizeof(port),
"%d", ldap_url->lud_port);
699 ldap_url->lud_scheme,
700 ldap_url->lud_host ? ldap_url->lud_host :
"",
701 ldap_url->lud_host ?
":" :
"",
702 ldap_url->lud_host ? port :
"",
703 ldap_url->lud_dn, attrs_fixed,
705 ldap_url->lud_filter ? ldap_url->lud_filter :
"");
709 ldap_free_urldesc(ldap_url);
724 struct berval **values;
734 for (attr = query->search.attrs; *attr; attr++) {
735 values = ldap_get_values_len(ldap_conn->
handle,
msg, *attr);
737 RDEBUG2(
"No \"%s\" attributes found in specified object", *attr);
741 count = ldap_count_values_len(values);
742 for (i = 0; i <
count; i++) {
746 RPERROR(
"Failed creating value from LDAP response");
751 ldap_value_free_len(values);
767 if (!query->
treq)
return;
769 RDEBUG2(
"Forcefully cancelling pending LDAP query");
806static inline CC_HINT(always_inline)
811 LDAPURLDesc tmp_desc = {
812 .lud_scheme = url_parsed->lud_scheme,
813 .lud_host = url_parsed->lud_host,
814 .lud_port = url_parsed->lud_port,
817 host = ldap_url_desc2str(&tmp_desc);
818 if (
unlikely(host == NULL))
REDEBUG(
"Invalid LDAP URL - %pV", url_in); \
844 *free_host_out =
false;
847 RPERROR(
"Failed to escape LDAP URI");
856 uri = fr_value_box_list_head(&uri_in->vb_group);
860 RPEDEBUG(
"Failed concatenating input");
864 if (!ldap_is_ldap_url(uri->vb_strvalue)) {
865 REDEBUG(
"String passed does not look like an LDAP URL");
869 ldap_url_ret = ldap_url_parse(uri->vb_strvalue, uri_parsed);
870 if (ldap_url_ret != LDAP_URL_SUCCESS){
878 if (!(*uri_parsed)->lud_host) {
879 *host_out = host_default;
883 ldap_free_urldesc(*uri_parsed);
887 *free_host_out =
true;
904 bool free_host =
false;
909 LDAPURLDesc *ldap_url;
918 if (!ldap_url->lud_attrs || !ldap_url->lud_attrs[0] || !*ldap_url->lud_attrs[0] ||
919 (strcmp(ldap_url->lud_attrs[0],
"*") == 0) || ldap_url->lud_attrs[1]) {
920 REDEBUG(
"Bad attributes list in LDAP URL. URL must specify exactly one attribute to retrieve");
921 ldap_free_urldesc(ldap_url);
926 ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter,
927 (
char const *
const*)ldap_url->lud_attrs, NULL, NULL);
930 if (ldap_url->lud_exts) {
934 serverctrls[0] = NULL;
938 RPERROR(
"Parsing URL extensions failed");
939 if (free_host) ldap_memfree(host);
947 if (!serverctrls[i])
break;
963 if (free_host) ldap_memfree(host);
965 REDEBUG(
"Unable to get LDAP query for xlat");
975 REDEBUG(
"Unable to enqueue LDAP query for xlat");
981 REDEBUG(
"Unable to set timeout for LDAP query");
1020#define REPEAT_LDAP_MEMBEROF_XLAT_RESULTS \
1021 if (unlang_function_repeat_set(request, ldap_group_xlat_results) < 0) do { \
1022 RETURN_UNLANG_FAIL; \
1046 RDEBUG3(
"Entered GROUP_XLAT_FIND_USER with user DN \"%s\"",
xlat_ctx->dn);
1047 if (
inst->group.obj_membership_filter) {
1049 RDEBUG3(
"Checking for user in group objects");
1060 RDEBUG3(
"Entered GROUP_XLAT_MEMB_FILTER with user DN \"%s\"",
xlat_ctx->dn);
1061 if (
inst->group.userobj_membership_attr) {
1071 RDEBUG3(
"Entered GROUP_XLAT_MEMB_ATTR with user DN \"%s\"",
xlat_ctx->dn);
1114 RDEBUG2(
"Searching for user in group \"%pV\"", group_vb);
1116 if (group_vb->vb_length == 0) {
1117 REDEBUG(
"Cannot do comparison (group name is empty)");
1126 MEM(norm = talloc_array(group_vb,
char, talloc_array_length(group_vb->vb_strvalue)));
1140 if ((group_is_dn &&
inst->group.cacheable_dn) || (!group_is_dn &&
inst->group.cacheable_name)) {
1144 switch (our_result.
rcode) {
1146 RDEBUG2(
"User is not a member of \"%pV\"", group_vb);
1169 .attrs = {
inst->group.userobj_membership_attr, NULL },
1170 .group_is_dn = group_is_dn,
1171 .env_data = env_data
1175 inst->handle_config.admin_password, request, &
inst->handle_config);
1178 REDEBUG(
"Unable to get LDAP trunk for group membership check");
1223 ldap_free_urldesc(to_free->
url);
1224 to_free->
url = NULL;
1243 char *host_url, *host = NULL;
1266 RPERROR(
"Failed to escape LDAP profile DN");
1271 RPERROR(
"Failed to escape LDAP profile URI");
1279 uri = fr_value_box_list_head(&uri_components->vb_group);
1282 RPEDEBUG(
"Failed concatenating input");
1293 host_url = handle_config->
server;
1296 scope =
inst->profile.obj_scope;
1298 ldap_url_ret = ldap_url_parse(uri->vb_strvalue, &
xlat_ctx->url);
1299 if (ldap_url_ret != LDAP_URL_SUCCESS){
1310 REDEBUG(
"LDAP URI must specify a profile DN");
1324 scope =
xlat_ctx->url->lud_scope == LDAP_SCOPE_DEFAULT ?
inst->profile.obj_scope :
xlat_ctx->url->lud_scope;
1330 host_url = handle_config->
server;
1333 if (
unlikely(host_url == NULL))
goto error;
1341 inst->valuepair_attr,
inst->profile.check_attr,
inst->profile.fallthrough_attr) < 0)
goto error;
1344 if (host) ldap_memfree(host);
1346 REDEBUG(
"Unable to get LDAP query for xlat");
1356 scope, filter, &
xlat_ctx->expanded) < 0)
goto error;
1378 struct berval *authz_id = NULL;
1384 REDEBUG(
"Whoami extended operation failed");
1389 if (
err != LDAP_SUCCESS) {
1390 REDEBUG(
"Failed parsing whoami response: %s", ldap_err2string(
err));
1397 if (!authz_id || (authz_id->bv_len == 0)) {
1398 if (authz_id) ber_bvfree(authz_id);
1407 p = authz_id->bv_val;
1408 len = authz_id->bv_len;
1409 if ((len >= 3) && (memcmp(p,
"dn:", 3) == 0)) {
1418 ber_bvfree(authz_id);
1441 REDEBUG(
"Unable to get LDAP trunk for whoami");
1496 switch (query->
ret) {
1521 RDEBUG2(
"Processing \"%s\"", dn);
1525 for (map = map_list_head(
map_ctx->maps), i = 0;
1527 map = map_list_next(
map_ctx->maps, map), i++) {
1529 int ret, iter_err = 0;
1532 expanded->
attrs[i])) {
1535 RPERROR(
"Failed parsing entry");
1558 RDEBUG3(
"Attribute \"%s\" not found in LDAP object", expanded->
attrs[i]);
1586 ldap_free_urldesc(
map_ctx->ldap_url);
1588 ldap_control_free(
map_ctx->serverctrls[i]);
1612 fr_value_box_list_t *
url, map_list_t
const *maps)
1617 LDAPURLDesc *ldap_url;
1623 char *host_url, *host = NULL;
1626 RPERROR(
"Failed to escape LDAP map URI");
1630 url_head = fr_value_box_list_head(
url);
1632 REDEBUG(
"LDAP URL cannot be empty");
1638 RPEDEBUG(
"Failed concatenating input");
1642 if (!ldap_is_ldap_url(url_head->vb_strvalue)) {
1643 REDEBUG(
"Map query string does not look like a valid LDAP URI");
1651 ldap_url_ret = ldap_url_parse(url_head->vb_strvalue, &
map_ctx->ldap_url);
1652 if (ldap_url_ret != LDAP_URL_SUCCESS){
1660 if (ldap_url->lud_exts) {
1662 ldap_url->lud_exts) < 0) {
1663 RPERROR(
"Parsing URL extensions failed");
1676 if (!ldap_url->lud_host) {
1677 host_url =
inst->handle_config.server;
1680 if (
unlikely(host_url == NULL))
goto fail;
1684 inst->handle_config.admin_password, request, &
inst->handle_config);
1685 if (host) ldap_memfree(host);
1686 if (!ttrunk)
goto fail;
1691 ldap_url->lud_scope, ldap_url->lud_filter,
map_ctx->expanded.attrs,
1703 RWDEBUG(
"You have set \"Auth-Type := LDAP\" somewhere");
1705 RWDEBUG(
"*********************************************");
1706 RWDEBUG(
"* THAT CONFIGURATION IS WRONG. DELETE IT. ");
1707 RWDEBUG(
"* YOU ARE PREVENTING THE SERVER FROM WORKING");
1708 RWDEBUG(
"*********************************************");
1719 .call_env = call_env
1731 REDEBUG(
"No DN found for authentication. Populate control.%s with the DN to use in authentication.",
1732 inst->user.da->name);
1733 REDEBUG(
"You should call %s in the recv section and check its return.",
inst->mi->name);
1742 RDEBUG(
"Login attempt with password \"%pV\"", &call_env->
password);
1744 RDEBUG2(
"Login attempt with password");
1759 RDEBUG(
"Configuration item 'sasl.mech' is not supported. "
1760 "The linked version of libldap does not provide ldap_sasl_bind( function");
1765 RDEBUG2(
"Login attempt as \"%s\"", auth_ctx->
dn);
1779 for (
n = 0; dn_list[
n];
n++);
1781 for (i = 1; i <
n; i++) {
1782 for (j = 0; j < i; j++) {
1783 if (
strcasecmp(dn_list[i], dn_list[j]) != 0)
continue;
1785 memmove(&dn_list[i], &dn_list[i + 1], (
n - i) *
sizeof(dn_list[0]));
1793#define REPEAT_MOD_AUTHORIZE_RESUME \
1794 if (unlang_module_yield(request, mod_authorize_resume, NULL, 0, autz_ctx) == UNLANG_ACTION_FAIL) do { \
1795 p_result->rcode = RLM_MODULE_FAIL; \
1823 switch (p_result->
rcode) {
1835 switch (autz_ctx->
status) {
1843 if (!autz_ctx->
entry) {
1844 ldap_get_option(handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
1845 REDEBUG(
"Failed retrieving entry: %s", ldap_err2string(ldap_errno));
1853 if (
inst->user.obj_access_attr) {
1860 if (
inst->group.skip_on_suspend)
goto post_group;
1873 if ((
inst->group.cacheable_dn ||
inst->group.cacheable_name ||
1876 (
inst->group.userobj_membership_attr)) {
1888 if (
inst->group.cacheable_dn ||
inst->group.cacheable_name ||
1931 autz_ctx->
status = LDAP_AUTZ_EDIR_BIND;
1937 case LDAP_AUTZ_EDIR_BIND:
1938 if (
inst->edir &&
inst->edir_autz) {
1945 REDEBUG(
"Failed to find control.Password.Cleartext");
1950 RDEBUG2(
"Binding as %s for eDirectory authorization checks", autz_ctx->
dn);
1956 autz_ctx->
status = LDAP_AUTZ_POST_EDIR;
1961 case LDAP_AUTZ_POST_EDIR:
1977 if (!map_list_empty(call_env->
user_map) ||
inst->valuepair_attr) {
1978 RDEBUG2(
"Processing user attributes");
1990 char const *profile_attr;
1993 size_t count = 0, strings_len = 0, group_count = 0, i;
2004 RPERROR(
"Failed parsing user object");
2009 RDEBUG2(
"Processing %zu profile(s) found in attribute \"%s\"",
count, profile_attr);
2011 RDEBUG2(
"No profile(s) found in attribute \"%s\"", profile_attr);
2017 RDEBUG2(
"Processing %zu profile(s) found in group objects", group_count);
2020 if (!have_default && (group_count == 0) && (
count == 0))
break;
2028 count ? profile_attr : NULL,
2029 (have_default ? 1 : 0) + group_count));
2039 for (dn_p = list->
strings; *dn_p; dn_p++) {
2052 RDEBUG3(
"Will evaluate profile with DN \"%s\"", *dn_p);
2123 inst->profile.check_attr,
inst->profile.fallthrough_attr) < 0) {
2130 inst->handle_config.admin_password, request, &
inst->handle_config);
2131 if (!autz_ctx->
ttrunk)
goto fail;
2133#define CHECK_EXPANDED_SPACE(_expanded) fr_assert((size_t)_expanded->count < (NUM_ELEMENTS(_expanded->attrs) - 1));
2138 if (
inst->user.obj_access_attr) {
2143 if (
inst->group.userobj_membership_attr &&
2144 (
inst->group.cacheable_dn ||
inst->group.cacheable_name ||
2145 inst->group.profile_attr ||
inst->group.profile_attr_suspend)) {
2147 expanded->
attrs[expanded->
count++] =
inst->group.userobj_membership_attr;
2150 if (
inst->user.profile_attr) {
2155 if (
inst->user.profile_attr_suspend) {
2157 expanded->
attrs[expanded->
count++] =
inst->user.profile_attr_suspend;
2202 switch (query->
ret) {
2208 RDEBUG2(
"User object \"%s\" not modified", usermod_ctx->
dn);
2233 struct berval **value_refs;
2234 struct berval *values;
2242 RDEBUG2(
"Expansion \"%s\" produced no value, skipping attribute \"%s\"", mod->
tmpl->name, mod->
attr);
2255 usermod_ctx->
mod_s[mod_no].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
2259 usermod_ctx->
mod_s[mod_no].mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
2264 usermod_ctx->
mod_s[mod_no].mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
2268 usermod_ctx->
mod_s[mod_no].mod_op = LDAP_MOD_INCREMENT | LDAP_MOD_BVALUES;
2272 REDEBUG(
"Operator '%s' is not supported for LDAP modify operations",
2279 MEM(value_refs = talloc_zero_array(usermod_ctx,
struct berval *, 1));
2281 MEM(value_refs = talloc_zero_array(usermod_ctx,
struct berval *,
2282 fr_value_box_list_num_elements(&usermod_ctx->
expanded) + 1));
2283 MEM(values = talloc_zero_array(usermod_ctx,
struct berval,
2284 fr_value_box_list_num_elements(&usermod_ctx->
expanded)));
2285 while ((vb = fr_value_box_list_pop_head(&usermod_ctx->
expanded))) {
2288 if (vb->vb_length == 0)
continue;
2289 memcpy(&values[i].bv_val, &vb->vb_octets,
sizeof(values[i].bv_val));
2290 values[i].bv_len = vb->vb_length;
2295 if (vb->vb_length == 0)
continue;
2296 memcpy(&values[i].bv_val, &vb->vb_strvalue,
sizeof(values[i].bv_val));
2297 values[i].bv_len = vb->vb_length;
2305 RPEDEBUG(
"Failed concatenating update value");
2309 goto populate_string;
2314 RPEDEBUG(
"Failed casting update value");
2317 goto populate_string;
2323 value_refs[i] = &values[i];
2327 RDEBUG2(
"Expansion \"%s\" produced zero length value, skipping attribute \"%s\"", mod->
tmpl->name, mod->
attr);
2335 memcpy(&(usermod_ctx->
mod_s[mod_no].mod_type), &mod->
attr,
sizeof(usermod_ctx->
mod_s[mod_no].mod_type));
2336 usermod_ctx->
mod_s[mod_no].mod_bvalues = value_refs;
2337 usermod_ctx->
mod_p[mod_no] = &usermod_ctx->
mod_s[mod_no];
2355 modify = usermod_ctx->
mod_p;
2360 usermod_ctx->
dn, modify, NULL, NULL);
2376 if (!usermod_ctx->
dn) {
2385 MEM(usermod_ctx->
mod_p = talloc_zero_array(usermod_ctx, LDAPMod *, usermod_ctx->
num_mods + 1));
2386 MEM(usermod_ctx->
mod_s = talloc_array(usermod_ctx, LDAPMod, usermod_ctx->
num_mods));
2387 fr_value_box_list_init(&usermod_ctx->
expanded);
2410 size_t num_mods = talloc_array_length(call_env->
mod);
2419 (
sizeof(
struct berval) + (
sizeof(
struct berval *) * 2) +
2420 (
sizeof(LDAPMod) +
sizeof(LDAPMod *))) * num_mods));
2423 .call_env = call_env,
2424 .num_mods = num_mods
2428 inst->handle_config.admin_identity,
2429 inst->handle_config.admin_password,
2430 request, &
inst->handle_config);
2431 if (!usermod_ctx->
ttrunk) {
2432 REDEBUG(
"Unable to get LDAP trunk for update");
2441 if (!usermod_ctx->
dn) {
2450 usermod_ctx->
inst, request,
2462 our_mctx.
rctx = usermod_ctx;
2475 if (
inst->user.obj_sort_ctrl) ldap_control_free(
inst->user.obj_sort_ctrl);
2476 if (
inst->profile.obj_sort_ctrl) ldap_control_free(
inst->profile.obj_sort_ctrl);
2489 bool expect_password =
false;
2495 map_t const *map = NULL;
2511 MEM(maps = talloc(parsed, map_list_t));
2512 map_list_init(maps);
2524 while ((map = map_list_next(maps, map))) {
2527 expect_password =
true;
2543 .name =
"expect_password",
2553 vb->vb_bool = expect_password;
2575 while (*p !=
'\0') {
2582 cf_log_warn(ci,
"No section found for \"%s.%s\" in module \"%s\", this call will have no effect.",
2590 if (!subcs)
goto not_found;
2594 cf_log_warn(ci,
"No update found inside \"%s -> %s\" in module \"%s\"",
2601 cf_log_warn(ci,
"No modifications found for \"%s.%s\" in module \"%s\"",
2617 cf_log_perr(to_parse,
"Invalid operator for LDAP modification");
2647 mod->
tmpl = parsed_tmpl;
2661 char const *filters[] = {
inst->group.obj_filter,
inst->group.obj_membership_filter };
2666 *(
void **)
out = parsed;
2676 void **trunks_to_free;
2681 for (i = talloc_array_length(trunks_to_free) - 1; i >= 0; i--)
talloc_free(trunks_to_free[i]);
2713 inst->handle_config.admin_password, NULL, &
inst->handle_config);
2715 ERROR(
"Unable to launch LDAP trunk");
2757 inst->bind_trunk_conf.target_req_per_conn = 1;
2758 inst->bind_trunk_conf.max_req_per_conn = 1;
2763 inst->bind_trunk_conf.req_pool_headers = 2;
2767 if (!options || !
cf_pair_find(options,
"chase_referrals")) {
2768 inst->handle_config.chase_referrals_unset =
true;
2774 if (
inst->group.cacheable_name &&
inst->group.obj_membership_filter) {
2775 if (!
inst->group.obj_name_attr) {
2776 cf_log_err(
conf,
"Configuration item 'group.name_attribute' must be set if cacheable "
2777 "group names are enabled");
2789 if (!
inst->handle_config.server_str) {
2790 cf_log_err(
conf,
"Configuration item 'server' must have a value");
2796 if (
inst->handle_config.admin_sasl.mech) {
2797 cf_log_err(
conf,
"Configuration item 'sasl.mech' not supported. "
2798 "Linked libldap does not provide ldap_sasl_interactive_bind function");
2812 for (i = 0; i < talloc_array_length(
inst->handle_config.server_str); i++) {
2813 char const *
value =
inst->handle_config.server_str[i];
2825 cf_log_err(
conf,
"Invalid character '%c' found in 'server' configuration item",
2839 if (ldap_is_ldap_url(
value)) {
2853 if (
inst->handle_config.server) {
2854 inst->handle_config.server[talloc_array_length(
inst->handle_config.server) - 2] =
'\0';
2855 DEBUG4(
"rlm_ldap (%s) - LDAP server string: %s", mctx->
mi->
name,
inst->handle_config.server);
2861 if (
inst->handle_config.port == LDAPS_PORT ||
inst->handle_config.tls_mode) {
2862 inst->handle_config.tls_mode = LDAP_OPT_X_TLS_HARD;
2864 inst->handle_config.tls_mode = 0;
2870 if (
inst->handle_config.dereference_str) {
2872 inst->handle_config.dereference_str, -1);
2873 if (
inst->handle_config.dereference < 0) {
2874 cf_log_err(
conf,
"Invalid 'dereference' value \"%s\", expected 'never', 'searching', "
2875 "'finding' or 'always'",
inst->handle_config.dereference_str);
2883#define SSS_CONTROL_BUILD(_obj) if (inst->_obj.obj_sort_by) { \
2884 LDAPSortKey **keys; \
2886 ret = ldap_create_sort_keylist(&keys, UNCONST(char *, inst->_obj.obj_sort_by)); \
2887 if (ret != LDAP_SUCCESS) { \
2888 cf_log_err(conf, "Invalid " STRINGIFY(_obj) ".sort_by value \"%s\": %s", \
2889 inst->_obj.obj_sort_by, ldap_err2string(ret)); \
2896 ret = ldap_create_sort_control(ldap_global_handle, keys, 1, &inst->_obj.obj_sort_ctrl); \
2897 ldap_free_sort_keylist(keys); \
2898 if (ret != LDAP_SUCCESS) { \
2899 ERROR("Failed creating server sort control: %s", ldap_err2string(ret)); \
2911 switch (
inst->profile.search_mode) {
2913 if (
inst->profile.obj_sort_ctrl && (
inst->profile.obj_scope == LDAP_SCOPE_BASE)) {
2921 if (
inst->profile.obj_scope != LDAP_SCOPE_BASE) {
2922 cf_log_err(
conf,
"'profile.search_mode = bulk' requires 'profile.scope = base'");
2925 if (!
inst->profile.obj_sort_ctrl) {
2926 cf_log_err(
conf,
"'profile.search_mode = bulk' requires 'profile.sort_by', "
2927 "else profile evaluation order is non-deterministic");
2936 if (
inst->handle_config.tls_require_cert_str) {
2941 inst->handle_config.tls_require_cert_str, -1);
2942 if (
inst->handle_config.tls_require_cert < 0) {
2943 cf_log_err(
conf,
"Invalid 'tls.require_cert' value \"%s\", expected 'never', "
2944 "'demand', 'allow', 'try' or 'hard'",
inst->handle_config.tls_require_cert_str);
2949 if (
inst->handle_config.tls_min_version_str) {
2950#ifdef LDAP_OPT_X_TLS_PROTOCOL_TLS1_3
2951 if (strcmp(
inst->handle_config.tls_min_version_str,
"1.3") == 0) {
2952 inst->handle_config.tls_min_version = LDAP_OPT_X_TLS_PROTOCOL_TLS1_3;
2956 if (strcmp(
inst->handle_config.tls_min_version_str,
"1.2") == 0) {
2957 inst->handle_config.tls_min_version = LDAP_OPT_X_TLS_PROTOCOL_TLS1_2;
2959 }
else if (strcmp(
inst->handle_config.tls_min_version_str,
"1.1") == 0) {
2960 inst->handle_config.tls_min_version = LDAP_OPT_X_TLS_PROTOCOL_TLS1_1;
2962 }
else if (strcmp(
inst->handle_config.tls_min_version_str,
"1.0") == 0) {
2963 inst->handle_config.tls_min_version = LDAP_OPT_X_TLS_PROTOCOL_TLS1_0;
2966 cf_log_err(
conf,
"Invalid 'tls.tls_min_version' value \"%s\"",
inst->handle_config.tls_min_version_str);
2971 if (
inst->trunk_conf.conn_triggers) {
2975 .module = mctx->
mi->module->
name,
2977 .server =
inst->handle_config.server,
2978 .port =
inst->handle_config.port
2982 if (
inst->bind_trunk_conf.conn_triggers) {
2986 .module = mctx->
mi->module->
name,
2988 .server =
inst->handle_config.server,
2989 .port =
inst->handle_config.port
3010 char const *group_attribute;
3013 if (
inst->group.attribute) {
3014 group_attribute =
inst->group.attribute;
3017 group_attribute =
buffer;
3019 group_attribute =
"LDAP-Group";
3030 PERROR(
"Error creating group attribute");
3040 if (
inst->group.cache_attr_str) {
3045 PERROR(
"Error creating cache attribute");
3055 if (
inst->user.dn_attr_str) {
3060 PERROR(
"Error creating user DN cache attribute");
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.
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
static int const char char buffer[256]
#define USES_APPLE_DEPRECATED_API
#define L(_str)
Helper for initialising arrays of string literals.
#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_value(call_env_parsed_t *parsed, fr_value_box_t const *vb)
Assign a value box 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_PARSE_OFFSET(_name, _cast_type, _flags, _struct, _field, _parse_field)
Specify a call_env_parser_t which writes out runtime results and the result of the parsing phase to t...
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
call_env_parser_t const * env
Parsing rules for call method env.
section_name_t const * asked
The actual name1/name2 that resolved to a module_method_binding_t.
void const * uctx
User context for callback functions.
#define FR_CALL_ENV_SUBSECTION(_name, _name2, _flags, _subcs)
Specify a call_env_parser_t which defines a nested subsection.
@ CALL_ENV_FLAG_CONCAT
If the tmpl produced multiple boxes they should be concatenated.
@ CALL_ENV_FLAG_ATTRIBUTE
Tmpl MUST contain an attribute reference.
@ 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.
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
@ CALL_ENV_FLAG_PARSE_MISSING
If this subsection is missing, still parse it.
@ CALL_ENV_FLAG_BARE_WORD_ATTRIBUTE
bare words are treated as an attribute, but strings may be xlats.
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
@ CALL_ENV_PARSE_TYPE_VALUE_BOX
Output of the parsing phase is a single value box (static data).
@ CALL_ENV_PARSE_TYPE_VOID
Output of the parsing phase is undefined (a custom structure).
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_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
#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_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
#define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct,...
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
@ CONF_FLAG_XLAT
string will be dynamically expanded.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
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.
unsigned int cf_pair_count_descendents(CONF_SECTION const *cs)
Count the number of conf pairs beneath a section.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
CONF_PAIR * cf_pair_next(CONF_SECTION const *cs, CONF_PAIR const *curr)
Return the next child that's a CONF_PAIR.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
#define cf_log_perr(_cf, _fmt,...)
#define cf_log_warn(_cf, _fmt,...)
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
int fr_dict_attr_add_name_only(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, fr_type_t type, fr_dict_attr_flags_t const *flags))
Add an attribute to the dictionary.
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
#define DICT_AUTOLOAD_TERMINATOR
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_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 GLOBAL_LIB_TERMINATOR
Structure to define how to initialise libraries with global configuration.
static xlat_action_t ldap_filter_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Escape a string for use as an RFC 4515 filter assertion value.
static xlat_action_t ldap_dn_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Escape a string for use in an RFC 4514 DN attribute value.
static xlat_action_t ldap_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Expand an LDAP URL into a query, and return a string result from that query.
static xlat_action_t ldap_whoami_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Return the authorization identity from the whoami response.
static xlat_action_t ldap_group_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Check for a user being in a LDAP group.
static xlat_action_t ldap_whoami_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)
Perform the RFC 4532 whoami extended operation.
static xlat_action_t ldap_profile_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Expand an LDAP URL into a query, applying the results using the user update map.
static xlat_action_t ldap_xlat_uri_attr_option(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Modify an LDAP URI to append an option to all attributes.
static xlat_action_t ldap_uri_unescape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Unescape LDAP string.
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.
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.
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.
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.
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.
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
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.
char const * fr_ldap_url_err_to_str(int ldap_url_err)
Translate the error code emitted from ldap_url_parse and friends into something accessible with fr_st...
int fr_ldap_map_verify(map_t *map, void *instance)
size_t fr_ldap_uri_unescape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg))
Converts escaped DNs and filter strings into normal.
size_t fr_ldap_util_normalise_dn(char *out, char const *in)
Normalise escape sequences in a DN.
int fr_ldap_map_getvalue(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
Callback for map_to_request.
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.
fr_ldap_control_t serverctrls[LDAP_MAX_CONTROLS]
Server controls specific to this query.
int fr_ldap_map_do(request_t *request, char const *check_attr, char const *valuepair_attr, fr_ldap_map_exp_t const *expanded, LDAPMessage *entry)
Convert attribute map into valuepairs.
fr_time_delta_t res_timeout
How long we wait for results.
char const * admin_password
Password used in administrative bind.
fr_ldap_config_t * config
Module instance config.
int count
Index on next free element.
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.
char * server
Initial server to bind to.
static int8_t fr_ldap_bind_auth_cmp(void const *one, void const *two)
Compare two ldap bind auth structures on msgid.
LDAP * handle
libldap handle.
char const * admin_identity
Identity we bind as when we need to query the LDAP directory.
fr_ldap_result_code_t ret
Result code.
bool freeit
Whether the control should be freed after we've finished using it.
fr_rb_tree_t * trunks
Tree of LDAP trunks used by this thread.
trunk_conf_t * trunk_conf
Module trunk config.
trunk_request_t * treq
Trunk request this query is associated with.
int fr_ldap_map_getdn(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
Callback for map_to_request.
size_t fr_ldap_dn_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 4514 DN attribute value.
fr_ldap_thread_trunk_t * fr_thread_ldap_trunk_get(fr_ldap_thread_t *thread, char const *uri, char const *bind_dn, char const *bind_password, request_t *request, fr_ldap_config_t const *config)
Find a thread specific LDAP connection for a specific URI / bind DN.
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.
int fr_ldap_server_url_check(fr_ldap_config_t *handle_config, char const *server, CONF_SECTION const *cs)
Check an LDAP server entry in URL format is valid.
#define LDAP_MAX_ATTRMAP
Maximum number of mappings between LDAP and FreeRADIUS attributes.
static int8_t fr_ldap_trunk_cmp(void const *one, void const *two)
Compare two ldap trunk structures on connection URI / DN.
int fr_ldap_server_config_check(fr_ldap_config_t *handle_config, char const *server, CONF_SECTION *cs)
Check an LDAP server config in server:port format is valid.
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.
unlang_action_t fr_ldap_edir_get_password(unlang_result_t *p_result, request_t *request, char const *dn, fr_ldap_thread_trunk_t *ttrunk, fr_dict_attr_t const *password_da)
Initiate retrieval of the universal password from Novell eDirectory.
fr_pair_list_t * bind_trigger_args
Passed to trigger request for bind trunks.
fr_ldap_connection_t * ldap_conn
LDAP connection this query is running on.
fr_ldap_result_code_t
LDAP query result codes.
@ LDAP_RESULT_TIMEOUT
The query timed out.
@ LDAP_RESULT_SUCCESS
Successfully got LDAP results.
@ LDAP_RESULT_NO_RESULT
No results returned.
@ LDAP_RESULT_BAD_DN
The requested DN does not exist.
fr_ldap_thread_trunk_t * fr_thread_ldap_bind_trunk_get(fr_ldap_thread_t *thread)
Find the thread specific trunk to use for LDAP bind auths.
int fr_ldap_map_expand(TALLOC_CTX *ctx, fr_ldap_map_exp_t *expanded, request_t *request, map_list_t const *maps, char const *generic_attr, char const *check_attr, char const *fallthrough_attr)
Expand values in an attribute map where needed.
#define LDAP_MAX_CONTROLS
Maximum number of client/server controls.
trunk_conf_t * bind_trunk_conf
Trunk config for bind auth trunk.
#define LDAP_VIRTUAL_DN_ATTR
'Virtual' attribute which maps to the DN of the object.
int fr_ldap_parse_url_extensions(LDAPControl **sss, size_t sss_len, char *extensions[])
Parse a subset (just server side sort and virtual list view for now) of LDAP URL extensions.
LDAPMessage * result
Head of LDAP results list.
fr_event_list_t * el
Thread event list for callbacks / timeouts.
LDAPControl * control
LDAP control.
char const * attrs[LDAP_MAX_ATTRMAP+LDAP_MAP_RESERVED+1]
Reserve some space for access attributes.
fr_ldap_thread_trunk_t * bind_trunk
LDAP trunk used for bind auths.
trunk_t * trunk
Connection trunk.
fr_pair_list_t * trigger_args
Passed to trigger request for normal trunks.
unlang_action_t fr_ldap_bind_auth_async(unlang_result_t *p_result, request_t *request, fr_ldap_thread_t *thread, char const *bind_dn, char const *password)
Initiate an async LDAP bind for authentication.
fr_timer_t * ev
Event for timing out the query.
TALLOC_CTX * ctx
Context to allocate new attributes in.
fr_rb_tree_t * binds
Tree of outstanding bind auths.
struct berval * fr_ldap_value_iter_alloc(int *err, fr_ldap_value_iter_t **out, TALLOC_CTX *ctx, LDAP *handle, LDAPMessage *entry, char const *attr)
Allocate a value iterator, released when the iterator is freed.
LDAPURLDesc * ldap_url
parsed URL for current query if the source of the query was a URL.
Holds arguments for async bind auth requests.
Connection configuration.
Tracks the state of a libldap connection handle.
Result of expanding the RHS of a set of maps.
Holds arguments for the async SASL bind operation.
Thread specific structure to manage LDAP trunk connections.
Thread LDAP trunk structure.
State of an in place iteration over an attribute's values.
#define FR_LDAP_COMMON_CONF(_conf)
LDAP * fr_ldap_handle_thread_local(void)
Get a thread local dummy LDAP handle.
global_lib_autoinst_t fr_libldap_global_config
unlang_action_t fr_ldap_trunk_modify(TALLOC_CTX *ctx, fr_ldap_query_t **out, request_t *request, fr_ldap_thread_trunk_t *ttrunk, char const *dn, LDAPMod *mods[], LDAPControl **serverctrls, LDAPControl **clientctrls)
Run an async modification LDAP query on a trunk connection.
fr_table_num_sorted_t const fr_ldap_tls_require_cert[]
fr_table_num_sorted_t const fr_ldap_dereference[]
fr_ldap_query_t * fr_ldap_search_alloc(TALLOC_CTX *ctx, char const *base_dn, int scope, char const *filter, char const *const *attrs, LDAPControl **serverctrls, LDAPControl **clientctrls)
Allocate a new search object.
unlang_action_t fr_ldap_trunk_extended(TALLOC_CTX *ctx, fr_ldap_query_t **out, request_t *request, fr_ldap_thread_trunk_t *ttrunk, char const *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls)
Run an async LDAP "extended operation" query on a trunk connection.
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.
fr_table_num_sorted_t const fr_ldap_scope[]
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
#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_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION const *cs, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules, map_validate_t validate, void *uctx, unsigned int max)
Convert a config section into an attribute map.
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.
unlang_action_t unlang_map_yield(request_t *request, map_proc_func_t resume, unlang_map_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
static TALLOC_CTX * map_ctx
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.
void * rctx
Resume ctx that a module previously set.
void const * moi
Map module instance.
Temporary structure to hold arguments for map calls.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
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.
void * rctx
Resume ctx that a module previously set.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
module_instance_t * mi
Module instance to detach.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for detach calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
module_t common
Common fields presented by all modules.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
fr_pair_list_t * fr_pair_list_alloc(TALLOC_CTX *ctx)
Allocate a new pair list on the heap.
unlang_action_t rlm_ldap_map_profiles(fr_ldap_result_code_t *ret, int *applied, rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t *ttrunk, char const *const *dn_list, char const *filter, fr_ldap_map_exp_t const *expanded)
Search for and apply a set of LDAP profiles.
unlang_action_t rlm_ldap_map_profile(fr_ldap_result_code_t *ret, int *applied, rlm_ldap_t const *inst, request_t *request, fr_ldap_thread_trunk_t *ttrunk, char const *dn, int scope, char const *filter, fr_ldap_map_exp_t const *expanded)
Search for and apply an LDAP profile.
static char const * url[FR_RADIUS_FAIL_MAX+1]
#define RDEBUG_ENABLED2()
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
int fr_rb_flatten_inorder(TALLOC_CTX *ctx, void **out[], fr_rb_tree_t *tree)
#define RETURN_UNLANG_INVALID
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_NOTFOUND
#define RETURN_UNLANG_FAIL
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_DISALLOW
Reject the request (user is locked out).
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
#define RETURN_UNLANG_NOOP
static unlang_action_t mod_map_proc(unlang_result_t *p_result, map_ctx_t const *mpctx, request_t *request, fr_value_box_list_t *url, map_list_t const *maps)
Perform a search and map the result of the search to server attributes.
static void mod_authorize_cancel(module_ctx_t const *mctx, UNUSED request_t *request, UNUSED fr_signal_t action)
Clear up when cancelling a mod_authorize call.
static const call_env_method_t xlat_memberof_method_env
static int mod_detach(module_detach_ctx_t const *mctx)
Detach from the LDAP server and cleanup internal state.
static int mod_load(void)
static xlat_action_t ldap_profile_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
Return whether evaluating the profile was successful.
map_list_t * profile_map
List of maps to apply to the profile.
#define REPEAT_LDAP_MEMBEROF_XLAT_RESULTS
static conf_parser_t profile_config[]
static int ldap_map_verify(CONF_SECTION *cs, UNUSED void const *mod_inst, UNUSED void *proc_inst, tmpl_t const *src, UNUSED map_list_t const *maps)
fr_dict_attr_t const * attr_nt_password
static xlat_arg_parser_t const ldap_safe_xlat_arg[]
ldap_auth_call_env_t * call_env
static const call_env_method_t authenticate_method_env
fr_ldap_result_code_t ret
global_lib_autoinst_t const * rlm_ldap_lib[]
static const call_env_method_t authorize_method_env
#define USERMOD_ENV(_section)
#define SSS_CONTROL_BUILD(_obj)
static xlat_arg_parser_t const ldap_uri_unescape_xlat_arg[]
static const call_env_method_t xlat_profile_method_env
static xlat_arg_parser_t const ldap_uri_attr_option_xlat_arg[]
static int ldap_mod_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, call_env_parser_t const *rule)
#define CHECK_EXPANDED_SPACE(_expanded)
static unlang_action_t mod_map_resume(unlang_result_t *p_result, map_ctx_t const *mpctx, request_t *request, UNUSED fr_value_box_list_t *url, UNUSED map_list_t const *maps)
Process the results of an LDAP map query.
static unlang_action_t mod_authorize_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Resume function called after each potential yield in LDAP authorization.
#define LDAP_FILTER_CALL_ENV_ESCAPE
static size_t profile_search_mode_table_len
fr_dict_attr_t const * attr_crypt_password
fr_value_box_t user_filter
static int ldap_group_filter_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)
static fr_dict_t const * dict_freeradius
static int map_ctx_free(ldap_map_ctx_t *map_ctx)
Ensure map context is properly cleared up.
fr_dict_attr_t const * cache_da
static void ldap_query_timeout(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *uctx)
Callback when LDAP query times out.
static unlang_action_t user_modify_mod_build_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
fr_ldap_query_t * query
Current query performing the whoami operation.
static conf_parser_t user_config[]
static fr_dict_attr_t const * attr_expr_bool_enum
#define LDAP_FILTER_SAFE_FOR
static fr_table_num_sorted_t const ldap_uri_scheme_table[]
static xlat_arg_parser_t const ldap_xlat_arg[]
static unlang_action_t mod_modify(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Modify user's object in LDAP.
static int ldap_uri_part_escape(fr_value_box_t *vb, UNUSED void *uctx)
Escape function for a part of an LDAP URI.
static xlat_arg_parser_t const ldap_escape_xlat_arg[]
fr_dict_attr_t const * group_da
static unlang_action_t ldap_group_xlat_user_find(UNUSED unlang_result_t *p_result, request_t *request, void *uctx)
User object lookup as part of group membership xlat.
fr_dict_attr_t const * attr_password
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Bootstrap the module.
#define REPEAT_MOD_AUTHORIZE_RESUME
fr_value_box_t user_sasl_proxy
fr_ldap_thread_trunk_t * ttrunk
fr_value_box_t user_sasl_authname
fr_dict_attr_t const * attr_password_with_header
static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, call_env_parser_t const *rule)
static unlang_action_t mod_authorize(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static conf_parser_t group_config[]
static void mod_unload(void)
fr_dict_attr_autoload_t rlm_ldap_dict_attr[]
#define LDAP_DN_CALL_ENV_ESCAPE
static xlat_action_t ldap_group_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
Process the results of evaluating LDAP group membership.
static unlang_action_t ldap_group_xlat_results(unlang_result_t *p_result, request_t *request, void *uctx)
Run the state machine for the LDAP membership xlat.
static void ldap_group_xlat_cancel(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
Cancel an in-progress query for the LDAP group membership xlat.
ssize_t expect_password_offset
static int ldap_xlat_uri_parse(LDAPURLDesc **uri_parsed, char **host_out, bool *free_host_out, request_t *request, char *host_default, fr_value_box_t *uri_in)
Utility function for parsing LDAP URLs.
static unlang_action_t user_modify_final(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Handle results of user modification.
static int ldap_xlat_profile_ctx_free(ldap_xlat_profile_ctx_t *to_free)
static char * host_uri_canonify(request_t *request, LDAPURLDesc *url_parsed, fr_value_box_t *url_in)
Produce canonical LDAP host URI for finding trunks.
fr_dict_attr_t const * attr_cleartext_password
tmpl_t const * password_tmpl
static xlat_action_t ldap_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Callback when resuming after async ldap query is completed.
fr_value_box_t user_sasl_mech
fr_dict_autoload_t rlm_ldap_dict[]
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Initialise thread specific data structure.
static unlang_action_t mod_authenticate(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static int autz_ctx_free(ldap_autz_ctx_t *autz_ctx)
Ensure authorization context is properly cleared up.
fr_ldap_map_exp_t expanded
static void ldap_xlat_signal(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
Callback for signalling async ldap query.
static fr_table_num_sorted_t const profile_search_mode_table[]
fr_ldap_thread_t * thread
static size_t ldap_uri_scheme_table_len
static fr_uri_part_t const ldap_dn_parts[]
static const conf_parser_t module_config[]
#define USER_CALL_ENV_COMMON(_struct)
ldap_usermod_call_env_t * call_env
fr_value_box_t profile_filter
Filter to use when searching for users.
static void user_modify_cancel(module_ctx_t const *mctx, UNUSED request_t *request, UNUSED fr_signal_t action)
Cancel an in progress user modification.
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Clean up thread specific data structure.
static int mod_instantiate(module_inst_ctx_t const *mctx)
Instantiate the module.
fr_ldap_map_exp_t expanded
static const call_env_parser_t sasl_call_env[]
fr_value_box_t user_sasl_realm
fr_value_box_list_t expanded
static fr_uri_part_t const ldap_uri_parts[]
fr_dict_attr_t const * user_da
static unlang_action_t user_modify_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Take the retrieved user DN and launch the async tmpl expansion of mod_values.
static void profile_dn_list_dedupe(char const **dn_list)
Remove duplicate DNs from a NULL terminated list, keeping the first occurrence.
static xlat_arg_parser_t const ldap_group_xlat_arg[]
Holds state of in progress async authentication.
Holds state of in progress LDAP map.
Parameters to allow ldap_update_section_parse to be reused.
Holds state of in progress ldap user modifications.
Call environment used in the profile xlat.
State of an in progress whoami extended operation.
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_PROFILE_SEARCH_MODE_AUTO
Resolved at instantiation, LDAP_PROFILE_SEARCH_MODE_BULK when server side sorting is configured and t...
@ LDAP_PROFILE_SEARCH_MODE_BULK
A single search retrieving every profile object, applied in result order.
@ LDAP_PROFILE_SEARCH_MODE_SEQ
One search per profile DN, applied in list order.
fr_ldap_map_exp_t expanded
ldap_autz_call_env_t * call_env
@ LDAP_ACCESS_SUSPENDED
User account has been suspended.
@ LDAP_ACCESS_ALLOWED
User is allowed to login.
@ LDAP_ACCESS_DISALLOWED
User it not allow to login (disabled)
fr_ldap_thread_trunk_t * ttrunk
fr_value_box_t profile_filter
Filter to use when searching for profiles.
fr_value_box_t user_filter
Filter to use when searching for users.
@ LDAP_AUTZ_POST_PROFILES
@ LDAP_AUTZ_GROUP_PROFILES
char const ** profile_dn_list
List of profile DNs to apply, default profile first, then group profiles, then profiles from the user...
ldap_autz_status_t status
fr_value_box_t profile_child_rdn
RDN of a child object to evaluate below each profile.
ldap_access_state_t access_state
What state a user's account is in.
unlang_action_t rlm_ldap_find_user_async(TALLOC_CTX *ctx, unlang_result_t *p_result, rlm_ldap_t const *inst, request_t *request, fr_value_box_t *base, fr_value_box_t *filter_box, fr_ldap_thread_trunk_t *ttrunk, char const *attrs[], fr_ldap_query_t **query_out)
Initiate asynchronous retrieval of the DN of a user object.
fr_value_box_t user_base
Base DN in which to search for users.
int profiles_applied
Number of profile maps applied.
map_list_t * user_map
Attribute map applied to users and profiles.
rlm_rcode_t rcode
What rcode we'll finally respond with.
static char const * rlm_find_user_dn_cached(rlm_ldap_t const *inst, request_t *request)
talloc_str_list_t * group_profile_dn_list
Profile DNs found in the user's group objects.
void rlm_ldap_check_reply(request_t *request, rlm_ldap_t const *inst, char const *inst_name, bool expect_password, fr_ldap_thread_trunk_t const *ttrunk)
Verify we got a password from the search.
fr_value_box_t const * expect_password
True if the user_map included a mapping between an LDAP attribute and one of our password reference a...
fr_value_box_t default_profile
If this is set, we will search for a profile object with this name, and map any attributes it contain...
talloc_str_list_t * group_dn_list
DNs of the group objects the user is a member of.
module_instance_t const * dlinst
ldap_access_state_t rlm_ldap_check_access(rlm_ldap_t const *inst, request_t *request, LDAPMessage *entry)
Check for presence of access attribute in result.
Call environment used in LDAP authorization.
Holds state of in progress async authorization.
Holds state of in progress group membership check xlat.
Call environment used in group membership xlat.
unlang_action_t fr_ldap_sasl_bind_auth_async(unlang_result_t *p_result, request_t *request, fr_ldap_thread_t *thread, char const *mechs, char const *identity, char const *password, char const *proxy, char const *realm)
Initiate an async SASL LDAP bind for authentication.
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_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
#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...
#define MODULE_THREAD_INST(_ctype)
char const * name
Instance name e.g. user_database.
module_flags_t flags
Flags that control how a module starts up and how a module is called.
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
#define MODULE_BOOT(_ctype)
void * boot
Data allocated during the boostrap phase.
void * data
Thread specific instance data.
static module_thread_instance_t * module_thread(module_instance_t const *mi)
Retrieve module/thread specific instance for a module.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
#define MODULE_INST(_ctype)
Named methods exported by a module.
static tmpl_attr_t const * tmpl_attr_tail(tmpl_t const *vpt)
Return the last attribute reference.
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
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.
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
#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.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
@ FR_SIGNAL_CANCEL
Request has been cancelled.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
eap_aka_sim_process_conf_t * inst
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
An element in a list of nested attribute references.
fr_dict_attr_t const *_CONST da
Resolved dictionary attribute.
Stores an attribute, a value and various bits of other data.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
char * talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
Call talloc_strndup, setting the type on the new chunk correctly.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
#define talloc_get_type_abort_const
char const ** strings
NULL terminated array of strings.
static size_t talloc_str_list_num(talloc_str_list_t const *list)
Return the number of strings in a string list.
#define talloc_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
#define talloc_strdup(_ctx, _str)
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
A NULL terminated array of strings with an append cursor.
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.
fr_table_num_ordered_t const fr_tokens_table[]
int module_trigger_args_build(TALLOC_CTX *ctx, fr_pair_list_t *list, CONF_SECTION const *cs, module_trigger_args_t *args)
Build trigger args pair list for modules.
Common values used by modules when building trigger args.
trunk_enqueue_t trunk_request_enqueue(trunk_request_t **treq_out, trunk_t *trunk, request_t *request, void *preq, void *rctx)
Enqueue a request that needs data written to the trunk.
void trunk_request_signal_cancel(trunk_request_t *treq)
Cancel a trunk request.
conf_parser_t const trunk_config[]
Config parser definitions to populate a trunk_conf_t.
@ TRUNK_ENQUEUE_OK
Operation was successful.
@ TRUNK_ENQUEUE_IN_BACKLOG
Request should be enqueued in backlog.
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.
void xlat_arg_copy_out(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_value_box_list_t *in, fr_value_box_t *vb)
Copy an argument from the input list to the output cursor.
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_ARGS(_list,...)
Populate local variables with value boxes from the input list.
unsigned int required
Argument must be present, and non-empty.
#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 consumed by an xlat function.
int fr_uri_escape_list(fr_value_box_list_t *uri, fr_uri_part_t const *uri_parts, void *uctx)
Parse a list of value boxes representing a URI.
int fr_uri_has_scheme(fr_value_box_list_t *uri, fr_table_num_sorted_t const *schemes, size_t schemes_len, int def)
Searches for a matching scheme in the table of schemes, using a list of value boxes representing the ...
#define XLAT_URI_PART_TERMINATOR
char const * name
Name of this part of the URI.
Definition for a single part of a URI.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define FR_TYPE_FIXED_SIZE
int fr_value_box_asprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted, char const *fmt,...)
Print a formatted string using our internal printf wrapper and assign it to a value box.
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_strdup_shallow_replace(fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one.
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_bstr_realloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
int fr_value_box_bstrdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a talloced 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_is_safe_for_only(_box, _safe_for)
#define fr_box_is_null(_x)
#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.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
void xlat_func_unregister(char const *name)
Unregister an xlat function.
#define xlat_func_safe_for_set(_xlat, _escaped)
Set the escaped values for output boxes.