>From our testing it appears that slapd's usage of the crypt function, to check
a user's password on a bind request, is single threaded, rather than being
distributed across all of slapds thread. We encountered this problem when
bumping the number of hashing rounds for our password hashes from 5,000 to
500,000 as was suggested by our security team.
Is it expected that the hashing of a users password would be bound to one
thread?
We ran our tests on a default install of of slapd 2.4.44 on Debian Jessie box
with 8 cores.
# Running script with butter user and 10,000,000 rounds of hashing:
$ pidstat -t -p $(pgrep slapd) 5 3
<snip>
Average: UID TGID TID %usr %system %guest
%CPU CPU Command
Average: 108 28458 - 100.00 0.00 0.00
100.00 - slapd
Average: 108 - 28458 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 28459 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 28460 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 10679 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 10680 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 17988 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 17993 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 17998 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 18007 22.53 0.00 0.00
22.53 - |__slapd
Average: 108 - 19109 16.80 0.00 0.00
16.80 - |__slapd
Average: 108 - 19110 0.07 0.00 0.00
0.07 - |__slapd
Average: 108 - 19111 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 19112 60.73 0.00 0.00
60.73 - |__slapd
Average: 108 - 19113 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 27438 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 27439 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 27440 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 27441 0.00 0.00 0.00
0.00 - |__slapd
# Running script with bubbles user and 5,000 rounds of hashing:
$ pidstat -t -p $(pgrep slapd) 5 3
<snip>
Average: UID TGID TID %usr %system %guest
%CPU CPU Command
Average: 108 28458 - 109.59 0.87 0.00
110.46 - slapd
Average: 108 - 28458 0.00 0.00 0.00
0.00 - |__slapd
Average: 108 - 28459 0.80 2.80 0.00
3.60 - |__slapd
Average: 108 - 28460 8.79 0.07 0.00
8.86 - |__slapd
Average: 108 - 10679 7.00 0.07 0.00
7.06 - |__slapd
Average: 108 - 10680 8.19 0.07 0.00
8.26 - |__slapd
Average: 108 - 17988 3.80 0.07 0.00
3.86 - |__slapd
Average: 108 - 17993 3.73 0.00 0.00
3.73 - |__slapd
Average: 108 - 17998 7.46 0.00 0.00
7.46 - |__slapd
Average: 108 - 18007 7.66 0.00 0.00
7.66 - |__slapd
Average: 108 - 19109 8.93 0.07 0.00
8.99 - |__slapd
Average: 108 - 19110 4.73 0.07 0.00
4.80 - |__slapd
Average: 108 - 19111 9.33 0.00 0.00
9.33 - |__slapd
Average: 108 - 19112 9.26 0.13 0.00
9.39 - |__slapd
Average: 108 - 19113 2.40 0.00 0.00
2.40 - |__slapd
Average: 108 - 27438 8.13 0.07 0.00
8.19 - |__slapd
Average: 108 - 27439 1.87 0.07 0.00
1.93 - |__slapd
Average: 108 - 27440 7.79 0.00 0.00
7.79 - |__slapd
Average: 108 - 27441 7.00 0.00 0.00
7.00 - |__slapd
# Test ldif:
$ cat example.ldif
dn: o=example
o: example
objectclass: organization
dn: ou=people, o=example
ou: people
objectclass: organizationalunit
dn: ou=groups, o=example
ou: groups
objectclass: organizationalunit
dn: cn=butter, ou=people, o=example
objectclass: inetOrgPerson
cn: butter
sn: butter
# {CRYPT}$6$rounds=10000000$ykk4zGD3ODNR$iMP/zYeisoWTYgxLtPv1qzoo/dVrYQLAb9sKlRMBgPTfFrr9lTzEEkJ9NcFdGI/MiRxHSx/1x3rnw3RkNRMer/
# 'everyone loves butter'
userPassword::
e0NSWVBUfSQ2JHJvdW5kcz0xMDAwMDAwMCR5a2s0ekdEM09ETlIkaU1QL3pZZWlzb1dUWWd4THRQdjFxem9vL2RWcllRTEFiOXNLbFJNQmdQVGZGcnI5bFR6RUVrSjlOY0ZkR0kvTWlSeEhTeC8xeDNybnczUmtOUk1lci8=
uid: butter
dn: cn=bubbles, ou=people, o=example
objectclass: inetOrgPerson
cn: bubbles
sn: bubbles
# {CRYPT}$6$rounds=5000$vY9dl4.rTyasVXCH$nlSXEZFnMn31NThCBWmfDy8EhaaZz6amUI8iukO8dpAnxMUaKK/78FqMVSi5iRbMvwkS6RNYhh4WhNzxDe.8r0
# 'everyone loves bubbles'
userPassword::
e0NSWVBUfSQ2JHJvdW5kcz01MDAwJHZZOWRsNC5yVHlhc1ZYQ0gkbmxTWEVaRm5NbjMxTlRoQ0JXbWZEeThFaGFhWno2YW1VSThpdWtPOGRwQW54TVVhS0svNzhGcU1WU2k1aVJiTXZ3a1M2Uk5ZaGg0V2hOenhEZS44cjA=
uid: bubbles
dn: cn=admin,o=example
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9SmFDaTRvZkRqQ2F3RHR2VVJQZWdleFoxZHFWNWRENUo=
structuralObjectClass: organizationalRole
# Test script:
$ cat whoamis
#!/bin/bash
USER=$1
trap cleanup SIGINT
cleanup() {
kill -9 $(jobs -p)
exit 1
}
while true; do
if [[ $(jobs | wc -l) -lt 8 ]]; then
ldapwhoami -x -D cn=${USER},ou=people,o=example -H
ldap://localhost -w "everyone loves ${USER}" >/dev/null &
else
wait -n
fi
done