Monday, May 7, 2012

HOWTO : OpenLDAP 2.4 Users & Groups Management and PAM Authentication on CentOS 6.2

Today we will create and manage users and groups in our OpenLDAP 2.4 daemon running on a CentOS 6.2 machine. Recall our goals :
  1. Install OpenLDAP 2.4.
  2. Configure Transport Layer Security (TLS).
  3. Manage users and groups in OpenLDAP.
  4. Configure pam_ldap to authenticate users via OpenLDAP.
  5. Use OpenLDAP as sudo's configuration repository.
  6. Use OpenLDAP as automount map repository for autofs.
  7. Use OpenLDAP as NFS netgroup repository again for autofs.
  8. Use OpenLDAP as the Kerberos principal repository.
  9. Setup OpenLDAP backup and recovery.
  10. Setup OpenLDAP replication.

Manage users and groups in OpenLDAP


We now have an empty OpenLDAP directory. We can prove this simply by trying to extract information from it.

ldapsearch -LLLxWD cn=admin,dc=company,dc=com -b dc=company,dc=com

Enter LDAP Password:
No such object (32)

If you're interested, the LDAP error codes can be found in section 4.1.10. « Result Message » of RFC 2251. In this case, error 32 means noSuchObject. But you can also have this error if an ACL prevents you from seeing the data.

In order to use our OpenLDAP directory, we need to create the base suffix and two Organizational Units (OU) to store our users and groups. So create an LDIF file with the following data.

vi ~/ldap/users+groups.ldif

Add this new data into our directory.

ldapmodify -a -xWD cn=admin,dc=company,dc=com -f ~/ldap/users+groups.ldif 

Verify that we now have the new data.

ldapsearch -LLLxWD cn=admin,dc=company,dc=com

Did you notice I didn't specify any -b dc=company,dc=com suffix with the previous ldapsearch command? That's because the suffix is already configured in the /etc/openldap/ldap.conf file.

Let's now add a few groups. We will create the following groups :
  • sysadmin to group the Linux systems administrators together.
  • oinstall, sysoper, asmdba, asmadmin and asmoper which are all Oracle related groups.
  • test.group to test verious parts of our PAM and LDAP architecture. It's always good to test!
  • panic which will be used by in case LDAP and/or NFS has a problem.
  • nssproxy which will be used to query this LDAP server instead of an anonymous user.
Of course, I encourage you to change this group list to fit your organization's needs. Create another LDIF file with the following data.


Add those new groups to our LDAP directory.

ldapmodify -a -xWD cn=admin,dc=company,dc=com -f ~/ldap/groups.ldif

Now it's time to create a few users. In this document, we will create the following users. Again, you should change this user list and the user's details (such as UID) to fit your corporation's needs.
  • drobilla. That's me :)
  • nssproxy. This user will be used to query our LDAP server instead of using an anonymous user.
  • panic. This user will be used when LDAP and/or NFS is broken. It is a local user, but we list it here in order to have a central place where we can get all of our UID. This prevents UID clash!
  • test.user. Again, this user will be used to test our setup as we build on this OpenLDAP server.
Let's write yet another LDIF file. Don't bother with the passwords for now, we will address those in a few minutes.


Add these users to the LDAP directory.

ldapmodify -a -xWD cn=admin,dc=company,dc=com -f ~/ldap/users.ldif

Let's now assign a proper password to the users. Repeat this procedure for each of the users. Note that this command will prompt twice for the new user's password and a third time for the cn=admin,dc=company,dc=com user's password.

ldappasswd -xZWD cn=admin,dc=company,dc=com -S cn=nssproxy,ou=users,dc=company,dc=com

New password: 
Re-enter new password: 
Enter LDAP Password: 

If you take a look in the /var/log/slapd.log file, you should see these lines which indicates the password has been modified :

slapd[5319]: conn=1022 op=1 PASSMOD id="cn=nssproxy,ou=users,dc=company,dc=com" new
slapd[5319]: conn=1022 op=1 RESULT oid= err=0 text=

We need to modify an OpenLDAP ACL to enable the nssproxy user access to our data. Let's first check which ACLs are in place. But first we need to know what is our database's DN?

sudo ldapsearch -LLLY EXTERNAL -H ldapi:/// -b cn=config dn | grep -i database

dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}bdb,cn=config
dn: olcDatabase={2}monitor,cn=config

Ok, so now we know that we need to edit the « olcDatabase={1}bdb,cn=config » DN. Let's see what ACLs are configured on this DN?

ldapsearch -xZLLLWD cn=admin,dc=company,dc=com -b olcDatabase={1}bdb,cn=config olcAccess

dn: olcDatabase={1}bdb,cn=config
olcAccess: {0}to *  by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=externa
 l,cn=auth" manage
olcAccess: {1}to attrs=userPassword  by self write  by * auth
olcAccess: {2}to dn.base="dc=company,dc=com"  by * search  by * none

We can see that we have ACLs on three configuration DN. We must then change these to allow the nssproxy user to read our data. Edit another LDIF file.

Apply the modifications to the OpenLDAP server.

ldapmodify -xZWD cn=admin,dc=company,dc=com -f ~/ldap/nssproxy.acl.ldif

Test to see if we can see our data with the nssproxy user? This command should return the entire Directory Information Tree (DIT)

ldapsearch -xZWD cn=nssproxy,ou=users,dc=company,dc=com "(objectClass=*)"

Test that you cannot get anything using another user.

ldapsearch -xLLLZWD cn=drobilla,ou=users,dc=company,dc=com "(objectClass=*)"

result: 50 Insufficient access

Excellent! We can now continue.

LDAP Browser


Now that we're starting to have a few objects in the LDAP directory, you should think about installing an LDAP Browser. It's a GUI which helps you visualize your LDAP data. My own personal favorite is Apache Directory Studio. It's a free, cross-platform and full featured LDAP Browser. It can be installed stand-alone or inside Eclipse. That's how I use it on my PC-BSD 9.0 desktop.

Ok, we achieved another of our goals...
  1. Install OpenLDAP 2.4.
  2. Configure Transport Layer Security (TLS).
  3. Manage users and groups in OpenLDAP.
  4. Configure pam_ldap to authenticate users via OpenLDAP.
  5. Use OpenLDAP as sudo's configuration repository.
  6. Use OpenLDAP as automount map repository for autofs.
  7. Use OpenLDAP as NFS netgroup repository again for autofs.
  8. Use OpenLDAP as the Kerberos principal repository.
  9. Setup OpenLDAP backup and recovery.
  10. Setup OpenLDAP replication.
The next section will discuss how to configure PAM with LDAP.

Configure pam_ldap to authenticate users via OpenLDAP


Login to another machine running CentOS 6.2 (or install a new one :) Install the required packages on this client.

sudo yum -y install openldap openldap-clients nss-pam-ldapd pam_ldap

Before we start changing this client's configuration file, we should test again just to make sure our nssproxy user is ok and that we can connect to the OpenLDAP machine.

ldapsearch -xZLLLWD cn=nssproxy,ou=users,dc=company,dc=com -b dc=company,dc=com -H ldap://alice.company.com:389

Edit the system-wide LDAP client configuration file.

sudo vi /etc/openldap/ldap.conf

Edit another system-wide LDAP client configuration file.

sudo vi /etc/nslcd.conf

Fix permissions on the /etc/nslcd.conf file because there is the password for our nssproxy user.

sudo chmod 600 /etc/nslcd.conf
sudo chown root:root /etc/nslcd.conf

Edit the network service switch configuration file.

sudo vi /etc/nsswitch.conf

Make sure the nslcd daemon starts at boot.

sudo chkconfig nslcd on

Start it.

sudo /etc/init.d/nslcd start

Make sure you do NOT have the nssproxy user in the system's local passwd file. This should return nothing.

grep nssproxy /etc/passwd

Then test the new LDAP query.


getent passwd test.user
test.user:x:1101:1101:Test User:/home/test.user:/bin/bash


getent group test.group
test.group:*:1101:

Good! That means the system can now find users and groups from the LDAP directory.

We can thus configure the PAM LDAP module. Note that we could use the authconfig(8) and authconfig-tui(8) tools to configure PAM LDAP, but I prefer to edit the files manually. Keep note that if you edit the files manually and then user either of those tools, the configurations in /etc/nslcd.conf and pam.d will be removed! So edit the /etc/pam_ldap.conf file.


Then edit several files in the /etc/pam.d directory. First the system authentication PAM in which we list the new pam_ldap module.


Next we also want to use pam_ldap to authenticate users coming in via sshd(8), so let's tell PAM about it.


Of course, we also need to configure sshd(8) so it knows we want to use pam_ldap


In this file we also restricted who could login via the AllowGroups directive. Now restart sshd so that it knows about the new configuration.

sudo /etc/init.d/sshd restart

We also like to let our users know that this machine is restricted via a simple /etc/issue file:

cat /etc/issue
Restricted Access.

Create a home directory for the user.

sudo mkdir /home/test.user
sudo chown test.user:test.group /home/test.user

Ok, from the client machine, issue a tail on the secure log file to see if things work?

sudo tail -F /var/log/secure

While from another machine, try to ssh into this new LDAP configured client.

ssh -v test.user@client.company.com

You should now have access to the client :)

But wait! If you take a look at the /var/log/slapd.log file on the OpenLDAP server, you will find quite a lot of lines like these :

slapd[6152]: <= bdb_equality_candidates: (objectClass) not indexed
slapd[6152]: <= bdb_equality_candidates: (uid) not indexed

If we take a look to our server, we notice that we don't have any indexes at the moment.

sudo ldapsearch -LLLY EXTERNAL -H ldapi:/// -b olcDatabase={1}bdb,cn=config olcDbIndex

That means we must modify the backend database to create indexes for these attributes. So edit another LDIF file.


Add those changes to the LDAP server.

sudo ldapmodify -a -H ldapi:/// -f ~/ldap/posixAccount.indexes.ldif

Then check if the changes have been properly installed?

sudo ldapsearch -LLLY EXTERNAL -H ldapi:/// -b olcDatabase={1}bdb,cn=config olcDbIndex

dn: olcDatabase={1}bdb,cn=config
olcDbIndex: default pres,eq
olcDbIndex: uid
olcDbIndex: cn,sn pres,eq,sub
olcDbIndex: objectClass eq

olcDbIndex: memberUid eq
olcDbIndex: uniqueMember eq
olcDbIndex: uidNumber
olcDbIndex: gidNumber eq

Excellent! We should not have any more errors in our slapd.log file.

We now have finished another of our goals!
  1. Install OpenLDAP 2.4.
  2. Configure Transport Layer Security (TLS).
  3. Manage users and groups in OpenLDAP.
  4. Configure pam_ldap to authenticate users via OpenLDAP.
  5. Use OpenLDAP as sudo's configuration repository.
  6. Use OpenLDAP as automount map repository for autofs.
  7. Use OpenLDAP as NFS netgroup repository again for autofs.
  8. Use OpenLDAP as the Kerberos principal repository.
  9. Setup OpenLDAP backup and recovery.
  10. Setup OpenLDAP replication.
See you later,

DA+

52 comments:

  1. Due to AllowGroups in /etc/ssh/sshd_config, the test.user can't really login because test.group is not included. Also, this set up means that even root can't login because root group is not included. It is best to allow local accounts to be able to login, in addition to the ldap accounts.

    ReplyDelete
  2. @Anonymous : I've changed the sshd_config file to add the test.group group into AllowGroups.

    But allowing root over ssh is a very bad idea. The default sshd_config file also doesn't allow root over ssh. In fact, most -if not all- the Linux security guides specify not to allow root over ssh (or worse, over rsh!).

    And for the other local or LDAP accounts, it depends on your organisation. But in most places I've worked for (~12 differents corporations) most users never need a shell access to the UNIX or Linux machines. They mostly need access to the server's services (i.e. HTTP, Wiki, SMTP, NTP, SQL, etc).

    But again, YMMV ;)

    David

    ReplyDelete
  3. You sshd_config actually allows for root access via ssh keys:

    PermitRootLogin without-password

    This is very secure if you have good control on your ssh keys.

    ReplyDelete
  4. Yes, it does seem like it. But root still doesn't have remote access on the servers because the root group is not in AllowGroups. I use the « PermitRootLogin without-passwords » to allow remote backup using rsnapshot.

    The trick here is that there is another user with UID zero on my servers : the user backup.

    This user can login without-password (and thus using it's ssh key), but it doesn't have an interactive shell on the servers. It has the rssh shell. rssh is a restricted shell for use with OpenSSH (see http://www.pizzashack.org/rssh/ for more info). I further restrict rssh to the rsync command only.

    Also, the ~backup/.ssh/authorized_keys file on each server is modified to include a « from="backupserver.domain.com" » keyword further restricting the use of this key.

    See http://itdavid.blogspot.ca/search/label/rsnapshot for more info on how to setup this particular backup configuration.

    Regards,

    David

    ReplyDelete
    Replies
    1. It does work in your setup where you have backup account already set up. However, in a newly setup server, with your version of sshd_config, no one can even sudo to root any more. I got bitten by this and I had to get into single user mode to change sshd_config so that I can control the server again. My point is that to the unwary user, this kind of set up can make him locked out of the server, if local accounts are not allowed and sudo via ldap has not been set up yet.

      Delete
  5. You do have a very interesting point. Thank you for bringing it forward. I should modify a blog post to include a safe no-matter-how-you-change-your-server's-authentication setup, you'll always be able to login.

    Or at least warn the unwary user.

    Once you understand how the authentication works, it's easier to play with it. As always, RTFM and test, test, test.

    > I got bitten by this and I had to get into single user mode to change sshd_config so that I can control the server again.

    Sorry mate :(

    As you can imagine, these blog posts are not a trap. I don't work on these posts during the week-end to fool people I don't know into breaking their Linux machines. What would be the point?

    Thanks for your input,

    DA+

    ReplyDelete
  6. @Anonymous : I've modified the sshd_config files to include a warning about the AllowGroups configuration. The warning in the file's header is...

    # WARNING : This configuration restricts ssh access to the
    # WARNING : groups listed in AllowGroups. Make sure your
    # WARNING : user is part of at least one of those groups.
    # WARNING : If not, YOU MAY BE LOCKED OUT OF YOUR SERVER.
    # WARNING : If that happens, use the system's console.

    If that warning was present in the files, do you think you would have avoided the problem when you first used the instructions in this blog post?

    David

    ReplyDelete
  7. David,

    THANK you so much for taking your time to author these awesome blog posts on a topic that easily spans three ten pound tech manuals! This makes it so much easier for those of us who prefer learning by doing; combing through configs, tailing logs, and just getting down to the nitty gritty on a very complex topic.

    Oh, and the "WARNING" comments for sshd_config are absolutely PRICELESS!! LOL!

    -ACE

    ReplyDelete
  8. @ACE : Great! Glad you enjoy these posts. And thanks for the good words, I appreciate them :)

    DA+

    ReplyDelete
  9. I'm having an existing Samba PDC with LDAP (using samba.schema) able to authenticate Windows users but mislead/astonish in authenticating to Linux as the clients. Do you have any ideas, comments or solutions? I believe it is same concepts on authenticating users and groups you have presented. Hope you can give me insights with it..

    ReplyDelete
    Replies
    1. @Ewann : I've never configured OpenLDAP with the samba.schema to authenticate Windows users. So be wary of my comments here ;)

      I would start by making sure I log my OpenLDAP activities properly. That's done by setting « olcLogLevel » to « stats » in your cn=config. Then start a shell and issue a « sudo tail -F /var/log/slapd.log » (or whatever your slapd(8C) log file is). Keep that tail open and fire up another shell in which you try to authenticate a Linux user.

      Of course, you have to configure your Linux machine to query the appropriate OpenLDAP distinguished name in order to fetch your OpenLDAP user's data (i.e. passwd, group and shadow). Instructions on how to configure your Linux machine are found in this blog post. Edit your /etc/nsswitch.conf file to use LDAP as the second source of information (after file) for group, shadow and password. This is important so as not to lock yourself out of your own Linux machine! Then make sure you can get the entire list of users and groups with the getent command. For exmaple, this command...

      getent passwd

      ...should display the entire local /etc/passwd file AND your OpenLDAP users.

      While this one...

      getent group

      ...should output the entire /etc/group groups AND your OpenLDAP groups.

      Don't forget to check if you can get the shadow data from your OpenLDAP server again using getent. Keep in mind that when you query shadow, you have to be root (or use sudo) and specify a user. You can't get the entire shadow data and getent will not complain if you try. For example, let's say the test.user is not found in your local /etc/shadow file and he's only in your OpenLDAP server, then this command...

      sudo getent shadow test.user

      ...should display this OpenLDAP user's shadow information.

      If any of those three getent command fail, you will not be able to authenticate users via your OpenLDAP server.

      Each and every time you hit getent, check the logs on your OpenLDAP server. If you have more than one OpenLDAP server, then configure your test Linux machine to query only one them (or better : send all your OpenLDAP servers logs to a central syslog machine and check that machine's logs).

      With this you should catch LDAP query errors and be able to rectify them.

      Let me know how it goes?

      HTH,

      DA+

      Delete
    2. Thanks a lot David, you give me enough insights with it.

      What I did, used to copy the samba server configuration to the client (testing only 1) but change the security = domain instead of user (in the server).

      I can't see my logs, what do you mean by "setting « olcLogLevel » to « stats » in your cn=config. Then start a shell and issue a « sudo tail -F /var/log/slapd.log » (or whatever your slapd(8C) log file is)"?

      If issue the command getent passwd --> I saw the users from the local and from the OpenLDAP same with the command getend group.

      But for the getend shadow , no display for any user in the LDAP but for local it will display. I can't see logs except on the logs of my client.
      #tail -F /var/log/samba/log.smbd

      [2012/07/20 17:26:20.249671, 0] lib/smbldap.c:1180(smbldap_connect_system)
      ldap_connect_system: Failed to retrieve password from secrets.tdb
      2012/07/20 17:26:21.250435, 0] passdb/secrets.c:350(fetch_ldap_pw)
      fetch_ldap_pw: neither ldap secret retrieved!

      My question now is it automatically be retrieved the userPassword from a particular uid, in ou=users? A bit mislead.

      Btw what I did, i used the join the member to my existing PDC
      net rpc join -S -u then restart the smbd and the nmbd.

      But if I issue this command,
      #net ads info
      ads_connect: No logon servers
      ads_connect: No logon servers
      Didn't find the ldap server!

      Another command, it will display like this one
      #net ads status -U Administrator
      Enter Administrator's password:
      ads_connect: No logon servers
      ads_connect: No logon servers

      Lastly on the server, i check it
      #netstat -alxA unix | grep ldapi
      no result(s).

      Any idea?

      Delete
    3. @Ewann : Hello again and sorry for the late reply. I don't have much experience with Samba. In fact, I try to stay away from Samba as much as possible. But I understand it's a requirement at many sites (like where I just started! Note to self : read a good Samba book :)

      For this...

      #netstat -alxA unix | grep ldapi
      no result(s).

      ...I would check the /etc/sysconfig/ldap file to make sure the slapd daemon listens to a UNIX socket. Then restart slapd. This should be easy to fix.

      Also check your /etc/nslcd.conf file. If you retrive userPassword from your OpenLDAP server, you may have to play with the schema settings for nslcd.

      Finally, about this...

      I can't see my logs, what do you mean by "setting « olcLogLevel » to « stats » in your cn=config. Then start a shell and issue a « sudo tail -F /var/log/slapd.log » (or whatever your slapd(8C) log file is)"?

      ...well I mean you need to make sure slapd has the appropriate log setting before you can debug.

      Of course, if your LDAP repository is a Microsoft Active Directory machine, I won't be able to help you much! Just checking to make sure that is not the case :)

      HTH,

      DA+

      Delete
  10. This comment has been removed by the author.

    ReplyDelete
  11. Hi,
    I keep getting these 2 errors on my client pc's
    ldap_sasl_bind(SIMPLE): Can't contact LDAP server(-1)

    and ldap_sasl_interactive_bind_s: Can't contact LDAP server(-1)

    ReplyDelete
    Replies
    1. @Hubert : Hi, I'm going to need a lot more information in order to help you. What commands return which error would be a good start. Cheers!

      Delete
    2. When I run
      ldapsearch -xZLLLWD cn=nssproxy,ou=users,dc=company,dc=com -b dc=company,dc=com -H ldap://alice.company.com:389

      the error i get is ldap_sasl_bind(SIMPLE): Can't contact LDAP server(-1)

      Delete
    3. When I run
      ldapsearch -xZLLLWD cn=nssproxy,ou=users,dc=company,dc=com -b dc=company,dc=com -H ldap://alice.company.com:389

      the error i get is ldap_start_tls: Can't contact LDAP server(-1)

      Delete
    4. @Hubert : Sorry for the very late post. I was away in vacation!

      It's strange, because both your queries are identical, but yet you have two different errors?!

      I'd first check if your daemon has SSL enabled. Check the /etc/sysconfig/ldap file, make sure it has this enabled :

      # Enable various slapd interfaces.
      SLAPD_LDAP=yes
      SLAPD_LDAPI=yes
      SLAPD_LDAPS=no

      Also be sure you're TLS configuration is ok? Check the configuration with this command (make sure you run this from the local OpenLDAP server and that you issue it as root via sudo)

      sudo ldapsearch -LLLY EXTERNAL -b cn=config -H ldapi:/// -s base | grep -i olctls

      olcTLSCACertificateFile: /etc/pki/tls/certs/companyCA.crt
      olcTLSCertificateFile: /etc/pki/tls/certs/alice.company.com.pem
      olcTLSCertificateKeyFile: /etc/pki/tls/certs/alice.company.com.key
      olcTLSVerifyClient: never

      Then make sure all the files listed there exist and have the following permissions :

      -rw-r--r--. 1 root root 1326 Apr 24 14:08 /etc/pki/tls/certs/companyCA.crt

      -rw-r--r--. 1 ldap ldap 1952 May 23 14:08 /etc/pki/tls/certs/alice.company.com.pem

      -rw-------. 1 ldap ldap 1708 May 23 13:53 /etc/pki/tls/certs/alice.company.com.key

      Then restart slapd(8) with this...

      sudo /etc/init.d/slapd restart

      Check your log file /var/log/slapd.log and test again. What do you have?

      HTH,

      DA+

      Delete
  12. Hi, great blog..this has been such a relief. Just a little question though
    When i run getent passwd test.user nothing happens. I have made all the changes to the nsswitch.conf.

    ReplyDelete
    Replies
    1. > Hi, great blog..this has been such a relief

      Thanks! Glad I could help.

      > When i run getent passwd test.user nothing happens.

      Well, let's start by the basic : do you have a test.user in your OpenLDAP server? If so, is it in the same ou=users,dc=company,dc=com as the others? And is your /etc/openldap/ldap.conf correctly configured? Can you getent passwd other OpenLDAP users?

      DA+

      Delete
  13. Yes, there's test.user in my OpenLDAP server, I can see it in my phpldapadmin page. My ldap.conf is configured exactly like you said, but I can't getent passwd on any user.

    ReplyDelete
    Replies
    1. Ok, next step is to check if the OpenLDAP user cn=test.user has the proper LDAP attributes. But which attributes do we need exaclty? Well, that's easy to find out. We start by making sure our olcLogLevel is properly set. To find out, connect to your OpenLDAP server and issue this query :

      sudo ldapsearch -LLLY EXTERNAL -H ldapi:/// -s base -b cn=config olcLogLevel

      This will print your current log level settings. Mine is this...

      olcLogLevel: stats sync

      Now I like to keep « stats » in there. I also keep « sync » because I want to see the OpenLDAP replication service logs. If you don't have a replicated OpenLDAP server, you don't need sync. Ok, so now that we know that olcLogLevel has « stats » in it, we can start a shell to monitor our logs. While connected to your OpenLDAP server, issue this :

      sudo tail -F /var/log/slapd.log

      In another shell, query your shadow database. Don't forget that is you type this...

      getent shadow test.user

      ...you will *never* have a result. Why? Simple : one needs to be root to be able to see the local /etc/shadow file right? It's the same for the OpenLDAP shadow data. So hit this...

      sudo getent shadow test.user

      ...and you should get the intended result.

      When you type the above command, the logs in your other shell should display the OpenLDAP stats. In there you will see the query that getent sent to slapd. This is it :

      Jul 26 11:09:04 alice slapd[923]: conn=8491 op=3 SRCH base="ou=users,dc=company,dc=com" scope=2 deref=0 filter="(&(objectClass=shadowAccount)(uid=test.user))"

      Jul 26 11:09:04 king slapd[923]: conn=8491 op=3 SRCH attr=shadowFlag shadowMin shadowMax userPassword shadowWarning shadowInactive uid shadowExpire shadowLastChange

      The first line tells us the we need the « shadowAccount » objectClass. The second line shows us the required LDAP attributes (i.e. shadowFlag shadowMin shadowMax userPassword shadowWarning shadowInactive uid shadowExpire shadowLastChange).

      We can now double-check if our OpenLDAP cn=test.user has the appropriate objectClass and attributes. Still on your OpenLDAP machine, issue this query...

      sudo ldapsearch -LLLY EXTERNAL -H ldapi:/// -b cn=test.user,ou=users,dc=company,dc=com

      ...and you should see something like this :

      dn: cn=test.user,ou=users,dc=caprion,dc=com
      uid: test.user
      gecos: Test User
      objectClass: top
      objectClass: account
      objectClass: posixAccount
      objectClass: shadowAccount
      shadowMin: 0
      shadowMax: 99999
      shadowWarning: 7
      homeDirectory: /nfs/home/test.user
      cn: test.user
      userPassword:: TTN0NGwxbmsh
      shadowLastChange: 15474
      loginShell: /bin/bash
      gidNumber: 5007
      uidNumber: 5007

      As you can see, we have the « objectClass: shadowAccount » which is required by getent. We also have the various « shadow » attributes listed above.

      If you don't have all this, then it won't work.

      HTH,

      DA+

      Delete
  14. When I run sudo ldapmodify -a -H ldapi:/// -f ~/ldap/posixAccount.indexes.ldif, it requires a password, and every password I type returns :
    ldap_sasl_interactive_bind_s: Invalid credentials (49)
    additional info: SASL(-13): user not found: no secret in database

    ReplyDelete
    Replies
    1. Same with me Kwesi with different errors
      SASL/GSSAPI authentication started
      ldap_sasl_interactive_bind_s: Local error (-2)
      additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Credentials cache file '/tmp/krb5cc_0' not found)

      what I did was to modify the command
      ldapmodify -xZWD cn=admin,dc=company,dc=com -f posixAccount.indexes.ldif

      I found that it can also added on the slapd.conf (before coming up to this, what I did create a script that will do from scratch).

      David I now solve my problems before with solving it in reverse, meaning your tutorial #3 then back to tutorial #2, because by default the client (which is also the host) not yet configured to use the OpenLDAP which generates errors. Thank you for this most useful tutorials.

      (I'm back from busy work... hope it helps).

      Delete
    2. Hello Ambot Lang,

      Good to know your OpenLDAP setup now works. I'm curious to know what you did to fix it exactly. As other people seem to have the same error you had on your first post. And what is the content of the script you created?

      Thanks for the good words :)

      Cheers,

      DA+

      Delete
  15. Hi, David

    Sorry for the long response, too busy at work coz of the new project. Then at home, we've been cut off our net (just flatting dunno how they manage it,at least this day reanimation jutsu release back to normal). For the script just follow your nice tutorials but I have to emphasize creating the certificates (which mostly including me got an error on the TLS/SSL connections and your tutorial uses MS Certreq command which not familiar with, not much fan of MS, in relation have you heard the story why the Peso Bill's wife is not happy, because of two reasons micro and soft, jk only)

    this is optional you can modify /etc/pki/tls/openssl.cnf so you can make your life easier, by just pressing enter key. Just modify with _default see
    https://www.dropbox.com/s/m68t5x0mzyxyupc/openssl.cnf


    then you will see similar to this
    Country Name (2 letter code) [PH]:
    State or Province Name (full name) [Mindanao]:
    Locality Name (eg, city) [Aurora]:
    Organization Name (eg, company) [Ambot Lang Bisdak]:
    Organizational Unit Name (eg, section) [Mga Lumad]:
    Common Name (eg, your name or your server's hostname) [aurora.zamboanga.del.sur]:
    Email Address [ambotlang@rocketmail.com]:


    Here is the script:
    rm -Rf CA
    rm -f *.pem
    ./xCA.pl -newca
    openssl req -new -nodes -keyout newreq.pem -out newreq.pem
    ./xCA.pl -sign
    cp -f newcert.pem /etc/openldap/certs
    cp -f newreq.pem /etc/openldap/certs
    cp -f CA/cacert.pem /etc/openldap/certs
    #testing where aurora.x.x.x:636 is your ldap
    openssl s_client -connect aurora.zamboanga.del.sur:636 -showcerts -state -CAfile /etc/openldap/certs/cacert.pem


    on the first 2 line of script it does
    Delete the folder CA (check the xCA.pl see the next) if exist and all pem extensions


    modify the following in the xCA.pl (an old script but very useful, courtesy of the authors)
    here is the script
    https://www.dropbox.com/s/ct99sahhtfjq0hy/xCA.pl

    $CATOP="CA";
    $CAKEY="cakey.pem";
    $CAREQ="careq.pem";
    $CACERT="cacert.pem";

    note $CATOP you can specify a specific folder on it (absolute addressing),
    for more info
    http://www.openssl.org/docs/apps/CA.pl.html

    on the slapd.conf add these files
    TLSCertificateFile /etc/openldap/certs/newcert.pem
    TLSCertificateKeyFile /etc/openldap/certs/newreq.pem
    TLSCACertificateFile /etc/openldap/certs/cacert.pem

    or if you don't want to start from scratch (it assumed ldap is running)
    root@xxx#ldapmodify -Y EXTERNAL -H ldapi:///
    SASL/EXTERNAL authentication started
    SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
    SASL SSF: 0
    # input like follows

    dn: cn=config
    add: olcTLSCertificateFile
    olcTLSCertificateFile: /etc/openldap/certs/newcert.pem
    -
    add: olcTLSCertificateKeyFile
    olcTLSCertificateKeyFile: /etc/openldap/certs/newreq.pem
    -
    add: olcTLSCACertificateFile
    olcTLSCACertificateFile: /etc/openldap/certs/cacert.pem
    # Press "Ctrl+D" to quit/save

    Just change the names to fit to your configurations. Hope it really helps to others.

    Cheers!

    ReplyDelete
  16. Hi David,
    I have previously configured LDAP with TLS and it worked on CentOS 6.2. Then I update the system using yum update, and it is now 6.3. My LDAP no longer works. I found that the 'nslcd' was removed and replaced with 'sssd'. What should I do to make LDAP/TLS work again?

    Thanks in advance,

    ReplyDelete
    Replies
    1. Hello Anonymous,

      I find quite brutal to remove pam_ldap and nslcd in order to install sssd during the 6.2 > 6.3 upgrade. Sorry, it sure wasn't my call.

      You now have two choices : a) setup sssd or b) remove sssd and reinstall pam_ldap + nslcd and reconfigure.

      If you go with b) hopefully the configuration files should still be there with a .rpmnew or something. If you used RCS, then it should be easy to revert to the old setup.

      I haven't done it yet. So I can't give you more precise information.

      And I'm on vacation, so I'm not even supposed to check my computer :)

      Good luck!

      DA+

      Delete
    2. Hi David,

      I found your guide to be most helpful in setting up a working LDAP setup. I am using RHEL 6.3 so had to use sssd for client authentication. Everything worked for me flawlessly until I tried to change the password from the client side with 'passwd' and found that it threw an authentication token manipulation error. After spending enough time digging through logs and google search results, I found out that the problem was acl ordering. According to the example the {0} acl is access to * and {1} is access to attrs=userPassword. The password change from client side succeeded when I put the userPassword acl first and * as second. Just thought you would like to know.

      P.S. How about another wonderful guide to extend the LDAP database through a samba PDC frontend ?

      Delete
    3. Hi /\niNdya,

      Great info! Thanks for the debug and for sharing this. I'm a little rusty on my own blog post, so in which file should I change this?

      Thanks!

      DA+

      P.S. I must admit I don't use Samba at all. Not anymore anyway. But isn't sssd supposed to handle that? I've never played with sssd so far, only read about it. Seems great though.

      Delete
  17. Hi David,
    Great set of blog postings! I'm happily ldaping across my enterprise now. I haven't had much time to research it just yet but when I implement the indexes my authentication breaks. When looking into it with ldapsearch I did notice that approximate queries worked but equals queries didn't. Also, when I added an & to the search it fell apart again (&(uid~=myuid)(objectClass~=posixAccount)). I almost complete guess is that this is because the indexes aren't defined for them (I haven't had time to tweak and experiment with this). Looking at the slapd.log this is the query that is run to find a user's account. I'm on CentOS 6.3 + Errata. If I come across the answer first I'll post it back but for now I wanted to let you and the other followers of this posting that there can potentially be an issue with the indexing.

    ReplyDelete
    Replies
    1. Hey Adam,

      Thanks for sharing the info. If you have an indexing issue, it should be reported in the server logs. But don't forget that logging is configured in OpenLDAP. Depending on your « olcLogLevel » configuration, you may or may not view the issues affecting your system.

      See « Table 5.1: Debugging Levels » at http://www.openldap.org/doc/admin24/slapdconf2.html for all the possible « olcLogLevel » values and what they mean.

      HTH,

      DA+

      Delete
    2. Hi David,
      First of all,great thanks to you for such nice tutorial.I found it best.
      I have done all as here.Created certificates with openssl way (1st method). I got this error: sudo ldapmodify -a -H ldapi:/// -f ~/ldap/posixAccount.indexes.ldif
      SASL/GSSAPI authentication started
      ldap_sasl_interactive_bind_s: Local error (-2)
      additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Credentials cache file '/tmp/krb5cc_0' not found)

      And I can not login with ldap users with ssh.when I do getent passwd test.user it is OK.But when connect with ssh test.user@host1 I can not login and in /var/log/secure I see
      Jul 24 15:02:39 host1 sshd[21092]: Failed password for test.user from
      server1 port 38593 ssh2
      Jul 24 15:02:39 host1 sshd[21093]: fatal: Access denied for user test.user by PAM account configuration.

      I am using centos 6.4. Can you help me to solve this ? Thanks in advance..

      Delete
    3. Hi Kamil,

      The log says that your « cache file '/tmp/krb5cc_0' not found ». This usually happens when the Kerberos setup is not done. Have you tried to issue a « kinit » before you tried to contact the LDAP server?

      The next error seems to come from you PAM setup. Well, that's what the SSH daemon says. Which probably points to your SSH configuration that points to PAM. Try changing UsePAM from « yes » to « no » and restart the SSH daemon and see what happens?

      HTH,

      DA+

      Delete
  18. This comment has been removed by a blog administrator.

    ReplyDelete
  19. Hey David!! Before to start, i really want to thank you for all your help during my ldap nightmare, it have been really complicated to me. Well i hope you can help this time too. See i used this command:

    [root@localhost ~]# ldapsearch -x -D AdminMD
    ldap_bind: Invalid DN syntax (34)
    additional info: invalid DN

    Where AdminMD it is an user from my ldap Server.

    I think i'm doing something stupid, but now this is driving me crazy. Thanks a lot for your time.

    Tony

    ReplyDelete
    Replies
    1. Hello Tony,

      The -D switch requires a Distinguished Name (DN) attribute. But you're not feeding it a DN, only a name. The ldapsearch man page is clear :

      -D binddn
      Use the Distinguished Name binddn to bind to the LDAP directory.

      Try using something like so...

      ldapsearch -x -D dc=AdminMD

      ...because your only problem is a syntax error.

      HTH,

      DA+

      Delete
    2. Hi Tony,

      Ok, my example wasn't good. Try something like this instead :

      ldapsearch -D 'cn=admin,dc=company,dc=com'

      Of course, you'll need the other arguments as well in there for this to work.

      HTH,

      DA+

      Delete
    3. Hey David, thanks again for your time, i tried with this:

      [root@localhost ~]# ldapsearch -D 'cn=AdminMD,dc=company,dc=com'
      ldap_bind: Server is unwilling to perform (53)
      additional info: unauthenticated bind (DN with no password) disallowed

      AdminMD actually has a password, so i'm a little lost. Hopping you can help me again.

      Cheers

      Tony

      Delete
    4. Hello Tony,

      This one is easy to fix. It's simply that you haven't told the ldapsearch command that you want to use a password. The man page will tell you that you have two choices for password :

      -W
      Prompt for simple authentication. This is used instead of specifying the password on the command line.

      -w passwd
      Use passwd as the password for simple authentication.

      So choose one of them. I suggest using -W instead of -w simply because the password won't have to be in clear text on the command line and then saved in your bash history file.

      HTH,

      DA+

      Delete
  20. Hi David, I had to drink a lot of coffee before thinking of the unthinkable... I had credentials refused between LDAP and nslcd, and it turned that I did what I should have done thinking normally, storing bindpw encrypted in nslcd.conf. It turned to be a big mistake :) Perhaps it might make sense if you could amend your post to explicitely mention this. At least it would have saved me 2 days of work :)

    Nevertheless, going to more important remarks, is there REALLY no way to have bindpw stored encrypted?

    Have a nice day, Greetings from Greece :)
    Stelios

    ReplyDelete
    Replies
    1. Hello Stelios,

      I know, I hate that clear text password too. But the nslcd.conf(5) man page is clear about this :

      bindpw PASSWORD
      Specifies the clear text credentials with which to bind. This option is only applicable
      when used with binddn above. If you set this option you should consider changing
      the permissions of the nslcd.conf file to only grant access to the root user.

      Well, changing the file permission is just a band aid right? A better solution would be to be able to list an encrypted password just like autofs_ldap_auth.conf(5) can do with the encoded_secret configuration keyword. Once simply has to issue something like this to create the base64 encoded password :

      echo -n "mySecretPassword" | openssl enc -base64

      NOTE : make sure you add the -n switch to echo(1) otherwise the base64 portion of the string has a carriage return and it won't work.

      BUT, coming back to nslcd.conf(5), there is hope! This is also listed in the man page :

      KERBEROS AUTHENTICATION OPTIONS
      krb5_ccname NAME
      Set the name for the GSS-API Kerberos credentials cache.

      Which means that if you have a Kerberos realm, you can simply create a new Kerberos principal for the nslcd(8) daemon. Extract it's keys into a special nslcd keytab and then make sure your OpenLDAP ACLs allow this principal read access to the values we need. Easy! I just never took the time to do it (shame on me!)

      On the other side, the nssproxy LDAP user is just that, a read-only Name Service Switch Proxy user. It prevents anonymous binds to the OpenLDAP servers.

      HTH,

      DA+

      Delete
  21. Hi David, I should had RTFM but I prefered your blog which is better than the FM :)

    Kerberos is a good idea, I might try it, for now I am trying to setup a stable machine, once this is done, I will try Kerberos and hopefully share the result.

    Stelios

    ReplyDelete
  22. Hello David,

    It's Fredouille, we speaks on your Backup Recovery post...

    One question please :
    when you say : "Before we start changing this client's configuration file, we should test again just to make sure our nssproxy user is ok and that we can connect to the OpenLDAP machine." by using command below :
    ldapsearch -xZLLLWD cn=nssproxy,ou=users,dc=company,dc=com -b dc=company,dc=com -H ldap://alice.company.com:389

    Do I verify on server machine or on client's one ?

    Because this command is running on server but doesn't work on client and give this :
    ldap_start_tls: connect error (-11)
    additional info: TLS error -8172:Peer's certificate issuer has benn marked as not trusted by the user.
    Enter LDAP Password :
    ldap_result: can't contact LDAP server (-1)

    I understand that my certificate is not trusted but I don't understand why I can't contact server because used password is good...

    Is it simply because client is not configured ?

    Thanks for your help...

    Fredouille

    Bye

    ReplyDelete
  23. David,

    I believe there is a mistake in https://dl.dropboxusercontent.com/u/72609528/blog/openldap/etc.nslcd.conf

    uid nslcd
    gid ldap

    "gid" should not be "ldap", because it will produce error :
    nslcd: /etc/nslcd.conf:9: gid: not a valid gid: 'ldap'

    Miralem

    ReplyDelete
    Replies
    1. Hi Miralem,

      You're right! I'll correct the file.

      Thanks! :)

      David

      Delete
    2. Actually, I've been thinking about the error you had. It's simply that nslcd can't find the ldap GID on your server. That's not an error per se, it just means that your network doesn't have the ldap GID configured. So either remove ldap from the nslcd.conf file or create the ldap group.

      HTH,

      DA+

      Delete
  24. Hi Dave. Thanks a lot for your business. I've faced quite a strange problem and would appreciate your assistance, if you don't mind of course.

    The problem is: When I set shadowMax 90;shadowMin 1 and shadowWarning 7 for user in LDAP
    1 - user is still being urged to change password even if it has just been changed
    2 - user is still able to do this despite shadowMin 1
    To avoid the first problem I have to switch shadowMax to -1, but I have no idea how to solve the second problem.

    I use libnss-ldap and libpam-ldap. I also cache passwords with pam-ccreds. Slapd has 2.4.31 version.

    All the other aspects of LDAP seem to work fine.

    Do you have any ideas?

    ReplyDelete
    Replies
    1. Hi there,

      I haven't played a lot with these parameters unfortunately. Do you also run the nslcd(8) daemon? It might be caching things (not sure here, just throwing ideas).

      Do you also use Kerberos? If so, this also has a password aging policy.

      Sorry I can't give you a more precise answer.

      HTH,

      David

      Delete
    2. Hi David,

      I followed your tutorial and came this far. :)

      I'm stuck with the ssh -v test.user@client.company.com part. I tried doing this on the ldapserver, ldapclient, and another machine. However, in all cases, the test.user can't login. Do you have any idea where it went wrong?

      Delete
  25. Hi Dave. Thanks a lot for your business. I've faced quite a strange problem and would appreciate your assistance, if you don't mind of course.

    The problem is: When I set shadowMax 90;shadowMin 1 and shadowWarning 7 for user in LDAP
    1 - user is still being urged to change password even if it has just been changed
    2 - user is still able to do this despite shadowMin 1
    To avoid the first problem I have to switch shadowMax to -1, but I have no idea how to solve the second problem.

    I use libnss-ldap and libpam-ldap. I also cache passwords with pam-ccreds. Slapd has 2.4.31 version.

    All the other aspects of LDAP seem to work fine.

    Do you have any ideas?

    ReplyDelete