From: Arran Cudbard-Bell Date: Tue, 5 May 2026 17:33:10 +0000 (-0400) Subject: rlm_ldap: fix call_env safe_for token mismatch causing double-escape of DN/filter... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25e5b2affbe8449dfbc236a787fb51db9ba3028b;p=thirdparty%2Ffreeradius-server.git rlm_ldap: fix call_env safe_for token mismatch causing double-escape of DN/filter values LDAP_DN_CALL_ENV_ESCAPE and LDAP_FILTER_CALL_ENV_ESCAPE were using fr_ldap_dn_box_escape and fr_ldap_filter_box_escape as their safe_for tokens, but %ldap.dn.safe and %ldap.filter.safe mark values with LDAP_DN_SAFE_FOR (fr_ldap_dn_escape_func) and LDAP_FILTER_SAFE_FOR (fr_ldap_filter_escape_func) respectively. The mismatched tokens meant pre-marked-safe values (e.g. dc=example,dc=com passed through %ldap.dn.safe) were not recognised as safe by the call_env escape check and got re-escaped to dc\3dexample\2cdc\3dcom, producing an invalid DN syntax error. Fix: move LDAP_DN_SAFE_FOR / LDAP_FILTER_SAFE_FOR before the call_env macros and use them consistently in .safe_for and .literals_safe_for. Also add missing radprofile attributes to profile_injection.attrs: the filter listed only Idle-Timeout but radprofile for user "john" also sets Session-Timeout, Acct-Interim-Interval and Framed-IP-Netmask. --- diff --git a/src/modules/rlm_ldap/rlm_ldap.c b/src/modules/rlm_ldap/rlm_ldap.c index dcdd09c02a1..c0d655f5b30 100644 --- a/src/modules/rlm_ldap/rlm_ldap.c +++ b/src/modules/rlm_ldap/rlm_ldap.c @@ -181,27 +181,30 @@ static const conf_parser_t module_config[] = { CONF_PARSER_TERMINATOR }; +#define LDAP_DN_SAFE_FOR (fr_value_box_safe_for_t)fr_ldap_dn_escape_func +#define LDAP_FILTER_SAFE_FOR (fr_value_box_safe_for_t)fr_ldap_filter_escape_func + #define LDAP_DN_CALL_ENV_ESCAPE \ .pair.escape = { \ .box_escape = { \ .func = fr_ldap_dn_box_escape, \ - .safe_for = (fr_value_box_safe_for_t)fr_ldap_dn_box_escape, \ + .safe_for = LDAP_DN_SAFE_FOR, \ .always_escape = false, \ }, \ .mode = TMPL_ESCAPE_PRE_CONCAT \ }, \ - .pair.literals_safe_for = (fr_value_box_safe_for_t)fr_ldap_dn_box_escape + .pair.literals_safe_for = LDAP_DN_SAFE_FOR #define LDAP_FILTER_CALL_ENV_ESCAPE \ .pair.escape = { \ .box_escape = { \ .func = fr_ldap_filter_box_escape, \ - .safe_for = (fr_value_box_safe_for_t)fr_ldap_filter_box_escape, \ + .safe_for = LDAP_FILTER_SAFE_FOR, \ .always_escape = false, \ }, \ .mode = TMPL_ESCAPE_PRE_CONCAT \ }, \ - .pair.literals_safe_for = (fr_value_box_safe_for_t)fr_ldap_filter_box_escape + .pair.literals_safe_for = LDAP_FILTER_SAFE_FOR #define USER_CALL_ENV_COMMON(_struct) \ { FR_CALL_ENV_OFFSET("base_dn", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, _struct, user_base), \ @@ -409,11 +412,6 @@ static fr_table_num_sorted_t const ldap_uri_scheme_table[] = { }; static size_t ldap_uri_scheme_table_len = NUM_ELEMENTS(ldap_uri_scheme_table); -/** This is the common function that actually ends up doing all the URI escaping - */ -#define LDAP_DN_SAFE_FOR (fr_value_box_safe_for_t)fr_ldap_dn_escape_func -#define LDAP_FILTER_SAFE_FOR (fr_value_box_safe_for_t)fr_ldap_filter_escape_func - static xlat_arg_parser_t const ldap_escape_xlat_arg[] = { { .required=true, .type = FR_TYPE_STRING }, XLAT_ARG_PARSER_TERMINATOR diff --git a/src/tests/modules/ldap/profile_injection.attrs b/src/tests/modules/ldap/profile_injection.attrs index d319290b6c4..60b3b4e50c4 100644 --- a/src/tests/modules/ldap/profile_injection.attrs +++ b/src/tests/modules/ldap/profile_injection.attrs @@ -15,3 +15,6 @@ NAS-IP-Address = 1.2.3.5 # Packet-Type == Access-Accept Idle-Timeout == 3600 +Session-Timeout == 7200 +Acct-Interim-Interval == 1800 +Framed-IP-Netmask == "255.255.0.0"