Solaris 10 Authentication with LDAP

1. Before Starting on the Solaris 10 Box

2. Account Creation on the Solaris 10 Box

This How-To describes only authentication, not authorisation. In order to login, a user must actually have an account created on the Solaris 10 box, with:

or equivalents in YP/NIS, etc., else login will fail!

3. Downloads

  nss_ldap-255
  openldap-2.3.32
  pam_ldap-184

  nss_ldap.tgz
  openldap-stable-20070110.tgz
  pam_ldap.tgz
Compile openldap, then the others, which link to it.

4. Misc Required Libs

You will need suitable versions of libssl, libcrypto, libgcc, etc, so get binary pkgs from sunfreeware.sun.com, e.g.,:

        /usr/sfw/lib/libssl.so.0.9.7
        /usr/sfw/lib/libcrypto.so.0.9.7
        /usr/local/lib/libgcc_s.so.1

5. Compilers, Make

Do yourself a favour and get GCC and Gnu Make from sunfreeware.sun.com.

6. PATH

Ensure that gcc, g++ and Gnu make are in your PATH before /usr/ccs/bin, else weirdness may happen.

7. OpenLDAP: configure, compile and install

    ./configure --disable-slapd --disable-slurpd
    make
    make install

    ls -l /usr/local/lib:

        liblber-2.3.so.0
        liblber-2.3.so.0.2.20
        liblber.a
        liblber.la
        liblber.so
        libldap-2.3.so.0
        libldap-2.3.so.0.2.20
        libldap.a
        libldap.la
        libldap.so
        libldap_r-2.3.so.0
        libldap_r-2.3.so.0.2.20
        libldap_r.a
        libldap_r.la
        libldap_r.so

8. SASL Header Files

The configure and/or make steps for one of pam_ldap or nss_ldap got its knickers in a twist over the SASL header files.

     ...some compilation fail related to <some_sasl_related_function> undefined...
The solution:
  cd /usr/include
  ln -s sasl/sasl.h sasl.h

9. pam_ldap configure, compile and install

    ./configure  --prefix=/usr/local --with-ldap-dir=/usr/local


    make
    make install


    ls -l /usr/local/lib/security/                 

        pam_ldap.so -> pam_ldap.so.1
        pam_ldap.so.1


    ldd /usr/local/lib/security/pam_ldap.so.1 

        .
        .
        libldap-2.3.so.0 =>      /usr/local/lib/libldap-2.3.so.0
        liblber-2.3.so.0 =>      /usr/local/lib/liblber-2.3.so.0
        .
        .

10. nss_ldap: configure, compile and install

    ./configure  --prefix=/usr/local --with-ldap-dir=/usr/local
 
    make
    make install


    ls -l /usr/local/lib/*nss*

        /usr/local/lib/nss_ldap.so -> nss_ldap.so.1
        /usr/local/lib/nss_ldap.so.1


    ldd /usr/local/lib/nss_ldap.so.1 

        .
        .
        libldap-2.3.so.0 =>      /usr/local/lib/libldap-2.3.so.0
        liblber-2.3.so.0 =>      /usr/local/lib/liblber-2.3.so.0
        .
        .

11. nss_ldap s-link

trussing sshd at some point suggested

    cd /usr/lib
    mv nss_ldap.so.1 nss_ldap.so.1_______simonh
    ln -s /usr/local/lib/nss_ldap.so.1 nss_ldap.so.1 
though I may have had the Solaris native LDAP libs installed at that point, so this step may not be necessary.

12. /etc/pam.conf

  other   auth requisite          pam_authtok_get.so.1
  other   auth required           pam_dhkeys.so.1
  other   auth required           pam_unix_cred.so.1
  #
  #other      auth required           pam_unix_auth.so.1 
  #
  #     ...original, as installed...
  #
  #
  #other      auth binding            pam_unix_auth.so.1 server_policy
  #other      auth required           /usr/local/lib/security/pam_ldap.so.1
  #
  #     ...as from http://docs.lucidinteractive.ca/index.php/Solaris_LDAP_client_with_OpenLDAP_server
  #        for Solaris native ldap client...
  #
  #
  other   auth sufficient         pam_unix_auth.so.1
  other   auth required           /usr/local/lib/security/pam_ldap.so.1 use_first_pass
  #
  #     ...for OpenLDAP client, inspired by Simon's notes on Solaris 7 (Cosmos
  #        and Eric, RIP), from many years ago ("use_first_pass" optional)...
and perhaps
  login   auth requisite          pam_authtok_get.so.1
  login   auth required           pam_dhkeys.so.1
  login   auth required           pam_unix_cred.so.1
  #
  #login      auth required       pam_unix_auth.so.1
  #
  #login      auth binding            pam_unix_auth.so.1 server_policy
  #login      auth required           /usr/local/lib/security/pam_ldap.so.1
  #
  login   auth sufficient       pam_unix_auth.so.1
  login   auth required         /usr/local/lib/security/pam_ldap.so.1
  login   auth required         pam_dial_auth.so.1

13. nsswitch.conf

  passwd:     files ldap [TRYAGAIN=5]

14. ldap.conf

  /etc/ldap.conf -> /usr/local/etc/ldap.conf
  /usr/local/etc/openldap/ldap.conf -> /usr/local/etc/ldap.conf
      #
      # ...I suspect the latter is not needed...

Development version, /usr/local/etc/ldap.conf:

  host brunei.its.manchester.ac.uk:389
  base ou=people,o=University of Manchester,c=GB
  scope sub
  pam_filter objectclass=posixAccount
  pam_login_attribute uid
  ssl no

Production version, /usr/local/etc/ldap.conf:

  host ldap.man.ac.uk:389
  base ou=uman,o=ac,c=uk
  scope sub
  pam_filter objectclass=posixAccount
  pam_login_attribute uid
  pam_password nds
  ssl no

15. LDAP Server Config — Required Attributes

This is rough and needs to be checked:

 -- google shows:

     -- pam_filter objectclass=posixAccount
     -- pam_login_attribute uid

     and
      -- ldap posixAccount object class contains
          -- uidNumber
             gidNumber
             gecos
             homeDirectory
             loginShell 

         so the ldap server must contain these attrs for authentication,
         _even_ if they are not to be used (e.g., nss specs another 
         name-service for home-dir)

          -- even ldap-bind success (i.e., correct cn/dn and password,
             as seen in ethereal) are not enough for pam_ldap to consider 
             auth to be successful

          -- confirmation from openldap _server_ logs:
 
             attr=uid userPassword uidNumber gidNumber cn homeDirectory loginShell gecos

16. ldapsearch

Anonumous:

    /usr/local/bin/ldapsearch -x -W -H ldap://ldap.man.ac.uk -s sub \
                                                        -b "c=uk" "cn=mpciish2"
        # ...empty password...

Development:

    /usr/local/bin/ldapsearch -x -W -H ldap://brunei.its.manchester.ac.uk \
        -D "cn=Simon Hood+umanroleid=43549,ou=Enterprise Systems,\
            ou=IT Services,ou=Administration & Central Services,ou=People,\
            o=University of Manchester,c=GB"  -s sub "cn=Simon Hood"

        # ...mpciish2's password...

Production:

    /usr/local/bin/ldapsearch -x -W -H ldap://ldap.man.ac.uk \
                            -D "cn=mpciish2,ou=mc,ou=admin,ou=uman,o=ac,c=uk" \
                            -s sub -b "c=uk" "cn=mpciish2"

        # ...mpciish2's password...

17. SSL/TSL vs Diagnostics

Don't be a smartarse: do the whole thing plain-text first, so you can use tcpdump, tethereal and/or ethereal to diagnose problems easily.

18. Diagnostics/Troubleshooting

18.1. Steps

Ok, so it does not work! Suggested steps, in order:

  1. ensure an anonymous ldapsearch works — and that all posixAccount attributes are found (uidNumber, gidNumber, homeDirectory);

  2. check that ldapsearch will bind as a potentially LDAP-authenticated user works;

  3. check the bind/search sequence by using Ethereal (see below);

  4. check the PAM config (/etc/pam.conf).

  5. check the logs on the LDAP client;

  6. check the logs on the LDAP server;

  7. check the correct shared-object libraries are being loaded/found and that configuration files are being found, using truss (see below).

18.2. Ethereal/Tethereal

tethereal show shown a sequence of bind, search, bind as <username>:

  11.509128 130.88.202.79 -> 130.88.211.28 TCP 35797 > ldap [SYN] Seq=0 Ack=0 Win=49640 Len=0 MSS=1460 WS=0
  11.509566 130.88.211.28 -> 130.88.202.79 TCP ldap > 35797 [SYN, ACK] Seq=0 Ack=1 Win=6144 Len=0 MSS=1460 WS=2
  11.509594 130.88.202.79 -> 130.88.211.28 TCP 35797 > ldap [ACK] Seq=1 Ack=1 Win=49640 Len=0
  11.510550 130.88.202.79 -> 130.88.211.28 LDAP MsgId=1 Bind Request, DN=(null)
  11.511360 130.88.211.28 -> 130.88.202.79 LDAP MsgId=1 Bind Result
  11.511386 130.88.202.79 -> 130.88.211.28 TCP 35797 > ldap [ACK] Seq=15 Ack=15 Win=49640 Len=0
  11.513010 130.88.202.79 -> 130.88.211.28 LDAP MsgId=2 Search Request, Base DN=ou=uman,o=ac,c=uk
  11.530484 130.88.211.28 -> 130.88.202.79 LDAP MsgId=2 Search Entry, 1 result
  11.530505 130.88.202.79 -> 130.88.211.28 TCP 35797 > ldap [ACK] Seq=135 Ack=1453 Win=49640 Len=0
  11.532352 130.88.202.79 -> 130.88.211.28 LDAP MsgId=3 Bind Request, DN=cn=mpciish2,ou=mc,ou=admin,ou=uman,o=ac,c=uk
  11.534650 130.88.211.28 -> 130.88.202.79 LDAP MsgId=3 Bind Result
  11.534886 130.88.202.79 -> 130.88.211.28 LDAP MsgId=4 Bind Request, DN=(null)
  11.537365 130.88.211.28 -> 130.88.202.79 LDAP MsgId=4 Bind Result
  11.641551 130.88.202.79 -> 130.88.211.28 TCP 35797 > ldap [ACK] Seq=222 Ack=1481 Win=49640 Len=0
For more detail on each step, try tethereal -V, or ethereal.

18.3. Server Logs

Server logs are your friend...

18.4. sshd -d and truss

Have a look at

    /usr/lib/ssh/sshd -d -p 222
and
    truss /usr/lib/ssh/sshd -d -p 222
to check that the correct shared-object libraries are being picked up (e.g., not Solaris native libs) and appropriate configuration files (e.g.ldap.conf) are found ok.