|
| 1 | +# Test: Validate LDAP group-role mapping when user DN contains characters |
| 2 | +# that are special in LDAP filter syntax (RFC 4515). |
| 3 | +# |
| 4 | +# Background: |
| 5 | +# The plugin substitutes {UD} with the authenticated user's DN in |
| 6 | +# authentication_ldap_simple_group_search_filter. Per RFC 4515 §3, |
| 7 | +# five ASCII octets must be escaped as \XX hex when they appear inside |
| 8 | +# an LDAP filter assertion value: |
| 9 | +# NUL (0x00), '(' (0x28), ')' (0x29), '*' (0x2a), '\' (0x5c) |
| 10 | +# |
| 11 | +# Purpose of this test: |
| 12 | +# Verify that role mapping works for all of these users in the same LDAP group: |
| 13 | +# 1. Normal DN (no special chars in CN) |
| 14 | +# 2. DN containing double quote (cn=Test"User) |
| 15 | +# 3. DN containing parentheses (cn=Test(User)) |
| 16 | +# 4. DN containing asterisk (cn=Test*User) |
| 17 | +# 5. DN containing backslash (cn=Test\5cUser — LDAP-escaped form of Test\User) |
| 18 | +# |
| 19 | +# Expected result: |
| 20 | +# All five users authenticate successfully and are granted test_dn_role. |
| 21 | +# |
| 22 | +# Requires docker-test-openldap: |
| 23 | +# https://github.com/rroemhild/docker-test-openldap |
| 24 | + |
| 25 | +--source include/count_sessions.inc |
| 26 | + |
| 27 | +# ----------------------------------------------------------------- |
| 28 | +# LDAP Setup: add users with special chars in CN and a groupOfNames group |
| 29 | +# ----------------------------------------------------------------- |
| 30 | +--perl EOF |
| 31 | + use strict; |
| 32 | + use warnings; |
| 33 | + |
| 34 | + sub run_cmd { |
| 35 | + my @cmd = @_; |
| 36 | + my $pid = fork(); |
| 37 | + die "fork: $!" unless defined $pid; |
| 38 | + if ($pid == 0) { |
| 39 | + open(STDOUT, '>', '/dev/null'); |
| 40 | + open(STDERR, '>', '/dev/null'); |
| 41 | + exec(@cmd) or exit(127); |
| 42 | + } |
| 43 | + waitpid($pid, 0); |
| 44 | + return $? >> 8; |
| 45 | + } |
| 46 | + |
| 47 | + my $host = $ENV{'MTR_LDAP_HOST'} || 'localhost'; |
| 48 | + my $port = $ENV{'MTR_LDAP_PORT'} || '389'; |
| 49 | + my $ldap_uri = "ldap://$host:$port"; |
| 50 | + my $admin_dn = 'cn=admin,dc=planetexpress,dc=com'; |
| 51 | + my $admin_pw = 'GoodNewsEveryone'; |
| 52 | + my $test_dir = $ENV{'MYSQL_TEST_DIR'} . '/../plugin/auth_ldap/tests/mtr'; |
| 53 | + my $user_ldif = "$test_dir/quote_test_user.ldif"; |
| 54 | + my $paren_user_ldif = "$test_dir/paren_test_user.ldif"; |
| 55 | + my $asterisk_user_ldif = "$test_dir/asterisk_test_user.ldif"; |
| 56 | + my $backslash_user_ldif = "$test_dir/backslash_test_user.ldif"; |
| 57 | + my $group_ldif = "$test_dir/test_group.ldif"; |
| 58 | + |
| 59 | + # Remove leftover entries from any previous failed run |
| 60 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 61 | + "-w", $admin_pw, |
| 62 | + 'cn=dn_test_group,ou=people,dc=planetexpress,dc=com'); |
| 63 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 64 | + "-w", $admin_pw, |
| 65 | + 'cn=Test\"User,ou=people,dc=planetexpress,dc=com'); |
| 66 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 67 | + "-w", $admin_pw, |
| 68 | + 'cn=Test(User),ou=people,dc=planetexpress,dc=com'); |
| 69 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 70 | + "-w", $admin_pw, |
| 71 | + 'cn=Test*User,ou=people,dc=planetexpress,dc=com'); |
| 72 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 73 | + "-w", $admin_pw, |
| 74 | + 'cn=Test\5cUser,ou=people,dc=planetexpress,dc=com'); |
| 75 | + |
| 76 | + # Create the test entries |
| 77 | + my $rc; |
| 78 | + $rc = run_cmd("ldapadd", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 79 | + "-w", $admin_pw, "-f", $user_ldif); |
| 80 | + die "ldapadd (quote user) failed rc=$rc" if $rc != 0; |
| 81 | + |
| 82 | + $rc = run_cmd("ldapadd", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 83 | + "-w", $admin_pw, "-f", $paren_user_ldif); |
| 84 | + die "ldapadd (paren user) failed rc=$rc" if $rc != 0; |
| 85 | + |
| 86 | + $rc = run_cmd("ldapadd", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 87 | + "-w", $admin_pw, "-f", $asterisk_user_ldif); |
| 88 | + die "ldapadd (asterisk user) failed rc=$rc" if $rc != 0; |
| 89 | + |
| 90 | + $rc = run_cmd("ldapadd", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 91 | + "-w", $admin_pw, "-f", $backslash_user_ldif); |
| 92 | + die "ldapadd (backslash user) failed rc=$rc" if $rc != 0; |
| 93 | + |
| 94 | + $rc = run_cmd("ldapadd", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 95 | + "-w", $admin_pw, "-f", $group_ldif); |
| 96 | + die "ldapadd (group) failed rc=$rc" if $rc != 0; |
| 97 | +EOF |
| 98 | + |
| 99 | +# ----------------------------------------------------------------- |
| 100 | +# MySQL Setup |
| 101 | +# ----------------------------------------------------------------- |
| 102 | +SET GLOBAL authentication_ldap_simple_bind_base_dn = 'ou=people,dc=planetexpress,dc=com'; |
| 103 | + |
| 104 | +# Use a DN-based filter so {UD} substitution is exercised |
| 105 | +SET GLOBAL authentication_ldap_simple_group_search_filter = '(&(objectClass=groupOfNames)(member={UD}))'; |
| 106 | + |
| 107 | +CREATE ROLE 'test_dn_role'; |
| 108 | +SET GLOBAL authentication_ldap_simple_group_role_mapping = 'dn_test_group=test_dn_role'; |
| 109 | + |
| 110 | +SET GLOBAL authentication_ldap_simple_log_status = 6; |
| 111 | + |
| 112 | +# ----------------------------------------------------------------- |
| 113 | +# Test 1: Normal user whose DN has no special characters. |
| 114 | +# Expected: role IS granted. |
| 115 | +# ----------------------------------------------------------------- |
| 116 | +CREATE USER normaluser IDENTIFIED WITH authentication_ldap_simple BY 'cn=Hermes Conrad,ou=people,dc=planetexpress,dc=com'; |
| 117 | + |
| 118 | +--connect (con_normal,localhost,normaluser,hermes,,,,CLEARTEXT) |
| 119 | +--echo # Test 1: Normal user - role should be granted |
| 120 | +SHOW GRANTS FOR 'normaluser'; |
| 121 | +--disconnect con_normal |
| 122 | +--connection default |
| 123 | + |
| 124 | +# ----------------------------------------------------------------- |
| 125 | +# Test 2: User whose DN contains a double-quote. |
| 126 | +# Expected: role IS granted. |
| 127 | +# ----------------------------------------------------------------- |
| 128 | +CREATE USER quoteduser IDENTIFIED WITH authentication_ldap_simple BY 'cn=Test\\"User,ou=people,dc=planetexpress,dc=com'; |
| 129 | + |
| 130 | +--connect (con_quoted,localhost,quoteduser,testpass123,,,,CLEARTEXT) |
| 131 | +--echo # Test 2: Quoted-DN user - role should be granted |
| 132 | +SHOW GRANTS FOR 'quoteduser'; |
| 133 | +--disconnect con_quoted |
| 134 | +--connection default |
| 135 | + |
| 136 | +# ----------------------------------------------------------------- |
| 137 | +# Test 3: User whose DN contains parentheses. |
| 138 | +# Expected: role IS granted. |
| 139 | +# ----------------------------------------------------------------- |
| 140 | +CREATE USER parentheses_user IDENTIFIED WITH authentication_ldap_simple BY 'cn=Test(User),ou=people,dc=planetexpress,dc=com'; |
| 141 | + |
| 142 | +--connect (con_parentheses,localhost,parentheses_user,testpass123,,,,CLEARTEXT) |
| 143 | +--echo # Test 3: Parentheses-DN user - role should be granted |
| 144 | +SHOW GRANTS FOR 'parentheses_user'; |
| 145 | +--disconnect con_parentheses |
| 146 | +--connection default |
| 147 | + |
| 148 | +# ----------------------------------------------------------------- |
| 149 | +# Test 4: User whose DN contains an asterisk. |
| 150 | +# Expected: role IS granted. |
| 151 | +# ----------------------------------------------------------------- |
| 152 | +CREATE USER asterisk_user IDENTIFIED WITH authentication_ldap_simple BY 'cn=Test*User,ou=people,dc=planetexpress,dc=com'; |
| 153 | + |
| 154 | +--connect (con_asterisk,localhost,asterisk_user,testpass123,,,,CLEARTEXT) |
| 155 | +--echo # Test 4: Asterisk-DN user - role should be granted |
| 156 | +SHOW GRANTS FOR 'asterisk_user'; |
| 157 | +--disconnect con_asterisk |
| 158 | +--connection default |
| 159 | + |
| 160 | +# ----------------------------------------------------------------- |
| 161 | +# Test 5: User whose DN contains a backslash. |
| 162 | +# The LDAP DN uses \5c to represent a literal backslash in the CN. |
| 163 | +# Expected: role IS granted. |
| 164 | +# ----------------------------------------------------------------- |
| 165 | +CREATE USER backslash_user IDENTIFIED WITH authentication_ldap_simple BY 'cn=Test\\5cUser,ou=people,dc=planetexpress,dc=com'; |
| 166 | + |
| 167 | +--connect (con_backslash,localhost,backslash_user,testpass123,,,,CLEARTEXT) |
| 168 | +--echo # Test 5: Backslash-DN user - role should be granted |
| 169 | +SHOW GRANTS FOR 'backslash_user'; |
| 170 | +--disconnect con_backslash |
| 171 | +--connection default |
| 172 | + |
| 173 | +# ----------------------------------------------------------------- |
| 174 | +# MySQL Cleanup |
| 175 | +# ----------------------------------------------------------------- |
| 176 | +DROP USER normaluser; |
| 177 | +DROP USER quoteduser; |
| 178 | +DROP USER parentheses_user; |
| 179 | +DROP USER asterisk_user; |
| 180 | +DROP USER backslash_user; |
| 181 | +DROP ROLE test_dn_role; |
| 182 | +SET GLOBAL authentication_ldap_simple_bind_base_dn = ''; |
| 183 | +SET GLOBAL authentication_ldap_simple_log_status = 1; |
| 184 | +SET GLOBAL authentication_ldap_simple_group_role_mapping = ''; |
| 185 | +SET GLOBAL authentication_ldap_simple_group_search_filter = '(|(&(objectClass=posixGroup)(memberUid={UA}))(&(objectClass=group)(member={UD})))'; |
| 186 | + |
| 187 | +# ----------------------------------------------------------------- |
| 188 | +# LDAP Cleanup |
| 189 | +# ----------------------------------------------------------------- |
| 190 | +--perl EOF |
| 191 | + use strict; |
| 192 | + use warnings; |
| 193 | + |
| 194 | + sub run_cmd { |
| 195 | + my @cmd = @_; |
| 196 | + my $pid = fork(); |
| 197 | + die "fork: $!" unless defined $pid; |
| 198 | + if ($pid == 0) { |
| 199 | + open(STDOUT, '>', '/dev/null'); |
| 200 | + open(STDERR, '>', '/dev/null'); |
| 201 | + exec(@cmd) or exit(127); |
| 202 | + } |
| 203 | + waitpid($pid, 0); |
| 204 | + return $? >> 8; |
| 205 | + } |
| 206 | + |
| 207 | + my $host = $ENV{'MTR_LDAP_HOST'} || 'localhost'; |
| 208 | + my $port = $ENV{'MTR_LDAP_PORT'} || '389'; |
| 209 | + my $ldap_uri = "ldap://$host:$port"; |
| 210 | + my $admin_dn = 'cn=admin,dc=planetexpress,dc=com'; |
| 211 | + my $admin_pw = 'GoodNewsEveryone'; |
| 212 | + |
| 213 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 214 | + "-w", $admin_pw, |
| 215 | + 'cn=dn_test_group,ou=people,dc=planetexpress,dc=com'); |
| 216 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 217 | + "-w", $admin_pw, |
| 218 | + 'cn=Test\"User,ou=people,dc=planetexpress,dc=com'); |
| 219 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 220 | + "-w", $admin_pw, |
| 221 | + 'cn=Test(User),ou=people,dc=planetexpress,dc=com'); |
| 222 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 223 | + "-w", $admin_pw, |
| 224 | + 'cn=Test*User,ou=people,dc=planetexpress,dc=com'); |
| 225 | + run_cmd("ldapdelete", "-x", "-H", $ldap_uri, "-D", $admin_dn, |
| 226 | + "-w", $admin_pw, |
| 227 | + 'cn=Test\5cUser,ou=people,dc=planetexpress,dc=com'); |
| 228 | +EOF |
| 229 | + |
| 230 | +--source include/wait_until_count_sessions.inc |
0 commit comments