]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
rlm_ldap: fix call_env safe_for token mismatch causing double-escape of DN/filter...
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 5 May 2026 17:33:10 +0000 (13:33 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 5 May 2026 17:33:10 +0000 (13:33 -0400)
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.

src/modules/rlm_ldap/rlm_ldap.c
src/tests/modules/ldap/profile_injection.attrs

index dcdd09c02a141085ed94cd3d507d261c9e3d5568..c0d655f5b306b652a422808cf22b3ae720bd1a3c 100644 (file)
@@ -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
index d319290b6c4866d944ffc4870a2a0f7f2facd4ba..60b3b4e50c4ad7b1f8ab44b87248242c2d08a3ce 100644 (file)
@@ -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"