OpenLDAP support for SHA-2 (SHA-256, SHA-384, SHA-512) and atlassian-sha1 passwords

Updated 18/Aug/08
Now rewritten to use BSD-licenced code, and support SHA256 and SHA384 as well as SHA512 hash algorithms

This page contains source code and instructions on how to modify OpenLDAP to support SHA-256, SHA-384 and SHA-512 password hashes (collectively known as SHA-2). SHA-512 is the password format used by JIRA, Confluence and some other Atlassian applications.

Background

Atlassian applications store passwords hashed with the SHA-512 algorithm. This applies to:

  • JIRA, storing hashes in the userbase table. The hashes are written/compared using the OSUser library's PasswordDigester.java.
  • Confluence (via atlassian-user or OSUser)
  • Crowd (via the 'atlassian-sha1' hash option).

Unfortunately SHA-512 is an uncommonly used algorithm (SHA-1 is much more common). This raises problems when, for instance, we wish to migrate users from JIRA or Confluence to Crowd, and wish to use an LDAP directory to store the users and passwords.

Following the lead of Pier Fumagalli and others on Integration of Jira User Management with Apache, I have written an OpenLDAP plugin to support SHA-512 passwords.

For instance, one could have the LDAP attribute:

userPassword: {SHA512}uQieO/1CGMUIXXftw3ynrsaYLShI+GTcPS4LdUGWbIusFvHPfUzD7CZvms6yMMvA8I7FViHVEqr6Mj4pCLKAFQ==

Which is a hash of the password 'sphere'

Download

Available as source download or from Subversion at https://svn.atlassian.com/svn/public/atlassian/openldap-sha2

License

BSD, based on code by Aaron Gifford, which appears also to have been adopted by OpenBSD.

Building

  1. Find which version of OpenLDAP you have installed. Eg.
    $ dpkg -l | grep slapd
    ii  slapd                   2.3.30-2ubuntu0.2 OpenLDAP server (slapd)
    

    (Ubuntu/Debian) or:

    $ rpm -qi openldap
    Name        : openldap                     Relocations: (not
    relocatable)
    Version     : 2.2.13                            Vendor: Red Hat, Inc.
    Release     : 8.el4_6.2                     Build Date: Wed 28 Nov 2007
    09:31:53 AM CST
    

    (Redhat/Fedora)

  2. Get the source (actually we just need the headers). Eg:
    $ apt-get source slapd
    

    (Ubuntu/Debian), or:

    $ wget 'ftp://ftp.openldap.org/pub/OpenLDAP/openldap-release/openldap-2.2.13.tgz'
    $ tar zxvf openldap-2.2.13.tgz
    
  3. Customize the OPENLDAP variable in Makefile to point to the OpenLDAP source root.
  4. Run 'make' to produce slapd-sha2.so
    $ make
    cc -I/home/jturner/openldap/openldap2.3-2.3.30/include -Wall -g -c slapd-sha2.c
    cc -I/home/jturner/openldap/openldap2.3-2.3.30/include -Wall -g -c sha2.c
    cc -I/home/jturner/openldap/openldap2.3-2.3.30/include -shared -Wall -g slapd-sha2.o sha2.o -o slapd-sha2.so
    
  5. Copy slapd-sha2.so somewhere permanent, eg. /usr/local/lib/openldap/slapd-sha2.so

Usage

  1. Edit your slapd.conf (/etc/ldap/slapd.conf on Ubuntu, /etc/openldap/slapd.conf on Redhat), and add:
    moduleload /usr/local/lib/openldap/slapd-sha2.so
    

    (specifying the path you saved slapd-sha2.so to)

  2. Restart slapd.

The {SHA512}, (SHA384} AND {SHA256} schemes should now be recognised by OpenLDAP.

Testing

A quick way to test whether it's working is to customize the rootdn and rootpw in slapd.conf, eg:

rootdn          "cn=admin,dc=example,dc=com"
# This encrypts the string 'secret'

rootpw  {SHA256}K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=

Then to test, run something like:

ldapsearch -b "dc=example,dc=com" -D "cn=admin,dc=example,dc=com" -x -w secret

Test hashes

Test hashes can be generated with openssl:

$ echo -n "secret" | openssl dgst -sha256 -binary | openssl enc -base64
K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=
$ echo -n "secret" | openssl dgst -sha384 -binary | openssl enc -base64
WKd1ukESvjAFrkQHznV9iP2nHUBJe7gCbsrFTU4//HIyzo3jq1rLMK45dg/ufFPt
$ echo -n "secret" | openssl dgst -sha512 -binary | openssl enc -base64
vSsar3708Jvp9Szi2NWZZ02Bqp1qRCFpbcTZPdBhnWgs5WtNZKnvCXdhztmeD2cm
W192CF5bDufKRpayrW/isg==

(join those lines up to form the full hash)

Alternatively we could modify an existing user's password with ldapmodify, and then test binding as that user:

$ ldapmodify -D "cn=admin,dc=example,dc=com" -x -W
Enter LDAP Password:
dn: uid=jturner,ou=People,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {SHA512}vSsar3708Jvp9Szi2NWZZ02Bqp1qRCFpbcTZPdBhnWgs5WtNZKnvCXdhztmeD2cmW192CF5bDufKRpayrW/isg==

modifying entry "uid=jturner,ou=People,dc=example,dc=com"
$ ldapsearch -b "dc=example,dc=com" -D "uid=jturner,ou=People,dc=example,dc=com" -x -w secret

Debugging

To see what's going on, recompile with SLAPD_SHA2_DEBUG (use the commented-out CCFLAGS in Makefile), and then run slapd from the console to see stderr:

$ sudo /etc/init.d/slapd stop
Stopping OpenLDAP: slapd.
$ sudo /usr/sbin/slapd -f /etc/ldap/slapd.conf -h ldap://localhost:389 -d 256
@(#) $OpenLDAP: slapd 2.4.9 (Jun 16 2008 08:09:52) $
        buildd@palmer:/build/buildd/openldap2.3-2.4.9/debian/build/servers/slapd
/etc/ldap/slapd.conf: line 123: rootdn is always granted unlimited privileges.
/etc/ldap/slapd.conf: line 140: rootdn is always granted unlimited privileges.
slapd starting
...
Validating password
  Password to validate: secret
  Hashes to: K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=
  Stored password scheme: {SHA256}
  Stored password value: K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=
  -> Passwords match
conn=0 op=0 BIND dn="cn=admin,dc=example,dc=com" mech=SIMPLE ssf=0
conn=0 op=0 RESULT tag=97 err=0 text=
conn=0 op=1 SRCH base="dc=example,dc=com" scope=2 deref=0 filter="(objectClass=*)"
conn=0 fd=12 closed (connection lost)
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Sep 23

    Jeff Turner says:

    Patch submitted to OpenLDAP here.

    Patch submitted to OpenLDAP here.