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+

91 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
    4. Hi Anindya, You saved my life today. Your observation is wonderful. David, wonderful guide. I learned all my openldap tweaks from here.

      Delete
    5. Hey, that's a cool blog comment! Glad I could help my friend :)

      Delete
    6. And thanks to Anindya ;-D

      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
  26. Hello, for some reason the links to the config files are not working.

    ReplyDelete
    Replies
    1. Hello Brian,

      Strange, I just tried all of the config and LDIF links and they're all good. I'm using Dropbox as the repository for the files. Maybe it had an issue when you tried?

      Can you please try again and let me know if you still have an issue?

      Thanks,

      David

      Delete
    2. Hi David,
      Thanks for the quick response, as i am enjoying your articles. I am having issues getting to the config files, the error reported back from my different browsers are:

      The webpage at https://dl.dropbox.com/u/72609528/blog/openldap/users%2Bgroups.ldif might be temporarily down or it may have moved permanently to a new web address.
      Error code: ERR_SSL_VERSION_OR_CIPHER_MISMATCH

      Delete
  27. Links to the config files are not working.

    ReplyDelete
    Replies
    1. Hey Brian,

      Sorry for the (very) late reply. If my memory is good, there was indeed an issue with DropBox. I belive it's fixed now. Let me know if that's not the case?

      Cheers,

      David

      Delete
  28. Hello David.
    Excellent Blog. Helped quite a bit with this new form of ldap without the slapd.conf.
    One place I'm stuck at is I've got everything working, ssl, ldapsearches, modifies passwds etc.
    However getent passwd and getent group fails to get anything from ldap. I see that the objectClass=shadowAccount in /var/log/slapd corresponds to the ldap.entry as you'd explained to Ewann Kho, however it fails after that.
    conn=1007 op=0 BIND dn="" method=128
    conn=1007 op=0 RESULT tag=97 err=0 text=
    conn=1007 op=1 SRCH base="dc=test,dc=com" scope=2 deref=0 filter="(&(objectClass=posixAccount)(uid=root))"
    conn=1007 op=1 SRCH attr=uid
    I hope this is sufficient. If not please let me know what info you may need.
    Once again. Thankyou very much

    ReplyDelete
    Replies
    1. Hey Anonymous,

      Glad I could help.

      For the problem at hand, did you update the /etc/nsswitch.conf file with these entries?

      passwd: files ldap
      shadow: files ldap
      group: files ldap

      If not, then getent(1) won't know to query the OpenLDAP servers for passwd and group. Note that for the shadow entry, you need to use sudo with getent. If you don't use sudo, then the getent shadow user will silently fail.

      HTH,

      David

      Delete
  29. It appears to me that the query is looking under People rather than Users. This from the slapd.log:
    conn=1090 op=3 SRCH base="ou=People,dc=test,dc=com" scope=2 deref=0 filter="(&(objectClass=posixAccount)(uid=test.user))"

    While this is part of the output of an ldapsearch for test.user
    > cn=test.user,ou=Users,dc=test,dc=com

    So I suppose I can find out how to change how nssproxy looks for users, or edit the whole ldif changeing Users, to People.
    Thankyou.

    ReplyDelete
    Replies
    1. Indeed, the OU is People. If you configured the OpenLDAP servers to use ou=users instead of ou=people, then you must update the /etc/nslcd.conf file and /etc/pam_ldap.conf files with the correct entries.

      Example for /etc/nslcd.conf (don't forget to change the bind password) :

      # /etc/nslcd.conf
      #
      # Configuration file for nslcd(8).
      # See nslcd.conf(5), nslcd(8) and nsswitch.conf(5) for more info.
      #
      # David Robillard, April 25th, 2012.

      uid nslcd
      gid ldap
      uri ldap://ldap1.example.com ldap://ldap2.example.com
      base dc=example,dc=com
      binddn cn=nssproxy,ou=users,dc=example,dc=com
      bindpw changeMe
      rootpwmoddn cn=admin,dc=example,dc=com
      base group ou=groups,dc=example,dc=com
      base passwd ou=users,dc=example,dc=com
      base shadow ou=users,dc=example,dc=com
      bind_timelimit 5
      timelimit 10
      idle_timelimit 60
      ssl start_tls
      tls_reqcert never
      tls_cacertfile /etc/pki/tls/certs/rootca.crt
      nss_initgroups_ignoreusers adm,bin,daemon,dbus,ftp
      nss_initgroups_ignoreusers games,gopher,halt,lp,mail,mailnull
      nss_initgroups_ignoreusers nfsnobody,nobody,nscd,nslcd,ntp,operator
      nss_initgroups_ignoreusers panic,root,rpc,rpcuser,saslauth
      nss_initgroups_ignoreusers shutdown,smmsp,sshd,sync,uucp,vcsa

      # EOF

      And example for /etc/pam_ldap.conf (again, update the password) :

      # /etc/pam_ldap.conf
      #
      # Configuration for PAM LDAP module. See pam_ldap(5).
      #
      # David Robillard, April 26th, 2012.

      base ou=users,dc=example,dc=com
      uri ldap://ldap1.example.com ldap://ldap2.example.com
      binddn cn=nssproxy,ou=users,dc=example,dc=com
      bindpw changeMe
      timelimit 15
      bind_timelimit 15
      pam_member_attribute gidNumber
      nss_base_passwd ou=users,dc=example,dc=com?one
      nss_base_shadow ou=users,dc=example,dc=com?one
      nss_base_group ou=groups,dc=example,dc=com?one
      nss_base_netgroup ou=netgroup,dc=example,dc=com?one
      ssl start_tls
      tls_cacertfile /etc/pki/tls/certs/rootca.crt

      # EOF

      HTH,

      David

      Delete
  30. Hello. Yes, I'd updated /etc/nsswitch like this;
    passwd: files ldap
    shadow: files ldap
    group: files ldap

    pam.d/system-auth has these from the yum installation as well:
    auth sufficient pam_ldap.so use_first_pass
    account [default=bad success=ok user_unknown=ignore] pam_ldap.so
    password sufficient pam_ldap.so use_authtok
    session optional pam_ldap.so


    ReplyDelete
  31. And Yes Sir. Changing the /etc/nslcd.conf to this did the trick
    Thankyou for your time on this.

    base passwd ou=Users,dc=test,dc=com
    base shadow ou=Users,dc=test,dc=com

    ReplyDelete
    Replies
    1. As a side note, keep in mind that LDAP is case-insensitive. So in your config files and queries, using this...

      ou=Users,dc=test,dc=com

      ...is the exact same thing as this...

      ou=users,dc=test,dc=com

      ...and this :

      OU=users,DC=test,DC=com

      The case is mainly for us humans to help split the DIT objects. Use what you prefer really.

      HTH,

      David

      Delete
  32. I spoke too soon I suppose. The errors just keep on coming
    This running nslcd -d so as to get more data and I see this error:

    nslcd: [3c9869] DEBUG: ldap_simple_bind_s("cn=nssproxy,ou=Users,dc=test,dc=com","***") (uri="ldap://chomp.test.com")
    nslcd: [3c9869] failed to bind to LDAP server ldap://chomp.test.com: Can't contact LDAP server: Transport endpoint is not connected
    nslcd: [3c9869] no available LDAP server found, sleeping 1 seconds
    nslcd: [7b23c6] DEBUG: ldap_initialize(ldap://chomp.test.com
    nslcd: [7b23c6] DEBUG: ldap_simple_bind_s("cn=nssproxy,ou=Users,dc=test,dc=com","***") (uri="ldap://chomp.test.com")
    nslcd: [7b23c6] failed to bind to LDAP server ldap://chomp.test.com: Can't contact LDAP server: Transport endpoint is not connected
    nslcd: [7b23c6] no available LDAP server found
    nslcd: [3c9869] DEBUG: not retrying server ldap://chomp.test.com which failed just 0 second(s) ago and has been failing for 11 seconds
    nslcd: [3c9869] no available LDAP server found

    I see no discrepancy between /etc/nslcd.conf and /etc/pam_ldap.conf and /etc/openldap/ldap.conf

    however I did run authconfig earlier, it did edit these files but I got them back. Is there anything else needs done to remove authconfigs settings, or anywhere else I should look for this error.
    Once again, thanks for your help here.

    ReplyDelete
    Replies
    1. Hey there,

      Well, let's start with the basics :

      a) Is there a firewall between the client and your OpenLDAP server?
      b) Can you telnet to TCP port 389 from the client to chomp.test.com?
      c) If so, then do you have the proper OpenLDAP ACLs in place to allow nssproxy to connect?
      d) Not only connect, but also read the data you need it to read?

      HTH,

      DA+

      Delete
    2. Obviously, is the OpenLDAP service running on chomp.test.com? :)

      Delete
  33. Thanks for replying.
    Actually, I'm trying to ssh in to the server here. Not using localhost, but the eth0 address. So no firewall.
    BTW, ldapsearches, *modifies .. etc work on clients, just not ssh.
    I'd first noticed this issue when I was watching the nscd logs and restarting slapd, nscd would complain about Can't contact LDAP server: Transport endpoint is not connected.
    telnet to the port's been working fine
    ~]# telnet 10.10.0.45 389
    Trying 10.10.0.45...
    Connected to 10.10.0.45.
    Escape character is '^]'.

    By the proper ldap ACL I suppose you mean the NIS one.
    I'd tried using rfc2307bis so I could try it with sssd yesterday, but I didn't want to update the entire set of ldifs I'd created so far, but the slapd I recreated, is not using it now. I don't see rfc2307bis in /etc/openldap/slapd.d/cn=config/cn=schema, which shows this:
    cn=schema]# ls
    cn={0}core.ldif cn={11}ppolicy.ldif cn={13}schema.ldif cn={2}inetorgperson.ldif cn={4}corba.ldif cn={6}openldap.ldif cn={8}java.ldif
    cn={10}nis.ldif cn={12}kerberos.ldif cn={1}cosine.ldif cn={3}collective.ldif cn={5}duaconf.ldif cn={7}dyngroup.ldif cn={9}misc.ldif

    So I think nslcd is having problems connecting to the ldap server.

    ReplyDelete
  34. Doh!! Looks like it was pam.d
    Fixed now.
    Thanks for getting me past those blocks earlier.
    Also, I'm taking you up on the case insensitivity of the config files. Much easier knowing that.

    ReplyDelete
    Replies
    1. Ah good. I mentioned the case thing because I realized that a lot of people didn't seem to know. Good thing I did then :)

      Delete
  35. Hello. I've got one more question. This one to do with users being able to use the 'passwd' command to change their passwds.
    I created an ldif like this:
    add: olcAccess
    olcAccess: {0}to attrs=userPassword
    by self write
    by anonymous auth
    by * none

    add: olcAccess
    olcAccess: {0}to * by * read

    then ran the cmd:
    ldapmodify -a -xD cn=admin,dc=test,dc=com -f anybody.passwd.ldif -w somepass

    it ran, but I couldn't see any resulting change in the ldifs in /etc/openldap/slapd.d/cn\=config

    I'd assumed I'd see it where the nssproxy entry was. However It's not there.
    Also, the 'passwd' cmd fails with:
    LDAP password information update failed: Insufficient access
    passwd: Permission denied

    At first I thought it was pam issues, but I wonder if there is any kind of conflict with the nssproxy users entry
    add: olcAccess
    olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
    by dn.base="cn=nssproxy,ou=Users,dc=whatcounts,dc=com" read
    by * auth
    by * none

    Thanks again for your help here.

    ReplyDelete
    Replies
    1. Hey there,

      OpenLDAP ACLs are quite hard to nail when you first start playing with them. One thing of importance is that their order number changes when you add or delete them. So, in the example you listed, you're adding two ACLs with the number zero (as in {0}). This will surely fail. I'd suggest you make a copy or backup of your /etc/openldap directory before and after you change any ACLs. Screwing yourself is easy here, so better make sure you're save.

      Next, query your OpenLDAP directory before and after each changes. That will allow you to see which number which ACL has and, if you add or remove an ACL, that number will change. That is often confusing.

      Note that the ACLs are evaluated from top to bottom, so make sure you place them in the right order.

      Finally, a good old RTFM is in order :
      http://www.openldap.org/doc/admin24/access-control.html

      Good luck,

      David

      Delete
  36. Hello David,
    thanks for your great tutorial. I am stuck on connecting over ssh using the test.user account:

    The /var/log/secure on the server I am trying to connect to shows:
    Dec 14 15:49:54 dummy sshd[2327]: pam_ldap(sshd:auth): Authentication failure; user=test.user
    Dec 14 15:49:54 dummy unix_chkpwd[2329]: password check failed for user (test.user)

    On the ldap server /var/log/slapd shows:
    ...
    Dec 14 15:49:54 ldap slapd[6643]: conn=1010 op=5 SRCH base="ou=users,dc=example,dc=com" scope=2 deref=0 filter="(&(objectClass=shadowAccount)(uid=test.user))"
    Dec 14 15:49:54 ldap slapd[6643]: conn=1010 op=5 SRCH attr=shadowExpire shadowInactive shadowFlag shadowWarning shadowLastChange uid shadowMin shadowMax
    Dec 14 15:49:54 ldap slapd[6643]: conn=1010 op=5 SEARCH RESULT tag=101 err=0 nentries=1 text=
    Dec 14 15:49:54 ldap slapd[6643]: conn=1011 op=5 SRCH base="ou=users,dc=example,dc=com" scope=2 deref=0 filter="(&(objectClass=posixAccount)(uid=test.user))"
    Dec 14 15:49:54 ldap slapd[6643]: conn=1011 op=5 SRCH attr=loginShell cn gidNumber uidNumber objectClass homeDirectory gecos uid
    Dec 14 15:49:54 ldap slapd[6643]: conn=1011 op=5 SEARCH RESULT tag=101 err=0 nentries=1 text=

    What I noticed is there never is a query for the userPassword attribute. Could that be the problem? I saw your reply to someone else where you said "userPassword" should be among the shadowAccount search.

    Some other things I did / noticed:
    - the tutorial says to edit "/etc/pam.d/system-auth-ac" while the comment within that file claims to be "/etc/pam.d/system-auth" - as both exist I am not sure which one to edit
    - in both files my distribution (CentOS 7) uses "password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=" instead of "password requisite pam_cracklib.so try_first_pass retry=3 type=" used in your tutorial - could that be a problem?
    - "sudo getent shadow test.user" result is "test.user:*:15140:0:99999:7:::0"
    - ldapsearch -H ldap://ldap.example.com -D cn=test.user,ou=users,dc=example,dc=com -b cn=test.user,ou=users,dc=example,dc=com -W accepts the password I try to use for ssh

    ReplyDelete
    Replies
    1. After trying various configuration settings unsuccessfully I simply switched over to use sssd instead which worked right away.
      On to the next part!

      Delete
    2. Hey, glad to hear you're now operational. And yes, sssd is the future. I'd love to switch over to it and write a new blog series. One day, one day :)

      Delete
  37. In case somebody else runs into the issue that I just had:

    In order to get TLS to work, I had to copy my root CA certificate from my LDAP server to the client at /etc/pki/tls/certs/rootca.crt. That let my ldapsearch work properly, but after setting up my client with nslcd, I was getting TLS failures when trying to getent passwd test.user. Here's the log on my LDAP server:

    Feb 20 15:22:48 ldap1 slapd[3475]: conn=1169 fd=21 ACCEPT from IP=10.0.0.195:41244 (IP=0.0.0.0:389)
    Feb 20 15:22:48 ldap1 slapd[3475]: conn=1169 op=0 EXT oid=1.3.6.1.4.1.1466.20037
    Feb 20 15:22:48 ldap1 slapd[3475]: conn=1169 op=0 STARTTLS
    Feb 20 15:22:48 ldap1 slapd[3475]: conn=1169 op=0 RESULT oid= err=0 text=
    Feb 20 15:22:48 ldap1 slapd[3475]: conn=1169 fd=21 closed (TLS negotiation failure)

    And here's the log on my client:

    Feb 20 15:17:34 ldap2 nslcd[2543]: [8b4567] ldap_start_tls_s() failed (uri=ldap://ldap1.example.com): Connect error: Permission denied
    Feb 20 15:17:34 ldap2 nslcd[2543]: [8b4567] failed to bind to LDAP server ldap://ldap1.example.com: Connect error: Permission denied
    Feb 20 15:17:34 ldap2 nslcd[2543]: [8b4567] no available LDAP server found, sleeping 1 seconds

    It turned out to be a pretty simple issue. The nslcd user couldn't read the rootca.crt certificate. I did:
    chown nslcd:ldap /etc/pki/tls/certs/rootca.crt

    When I restarted nslcd, all was well.

    ReplyDelete
  38. Hello David,

    Very good tutorial. Need suggestion, I want the LDAP user should be able to change their own password using 'passwd' command. What changes should I make in your sample "/root/nssproxy.acl.ldif" file to make that happen.
    I have tried the following but it still doesnt help. Please guide me through this.
    --
    access to attrs=userPassword
    by self write
    by anonymous auth
    by dn.base="cn=Manager,dc=example,dc=org" write
    by * none

    access to *
    by self write
    by dn.base="cn=Manager,dc=example,dc=org" write
    by * read

    --

    ReplyDelete
    Replies
    1. Hey Unknown,

      Here's what the ACLs look like on my host :

      olcAccess: {0}to attrs=userPassword,userPKCS12 by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage by dn.base="cn=admin,dc=example,dc=com" manage by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manage by dn.base="cn=nssproxy,ou=users,dc=example,dc=com" read by self write by dn.regex="replication,ou=users,dc=example,dc=com" read by anonymous auth by * none

      olcAccess: {1}to attrs=shadowLastChange by self write by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage by dn.base="cn=admin,dc=example,dc=com" manage by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manage by dn.base="cn=nssproxy,ou=users,dc=example,dc=com" read by dn.regex="replication,ou=users,dc=example,dc=com" read by self write by * auth by * none

      olcAccess: {2}to dn.subtree="ou=kerberos,ou=services,dc=example,dc=com" by dn.exact="cn=krbadmin,ou=users,dc=example,dc=com" write by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" read by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read by dn.base="cn=admin,dc=example,dc=com" read by dn.regex="replication,ou=users,dc=example,dc=com" read by * none

      olcAccess: {3}to dn.subtree="dc=example,dc=com" by dn.base="cn=admin,dc=example,dc=com" manage by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manage by dn.exact="cn=krbadmin,ou=users,dc=example,dc=com" write by dn.exact="cn=nssproxy,ou=users,dc=example,dc=com" read by dn.regex="uid=autofsclient/.*,cn=example.com,cn=gssapi,cn=auth" read by dn.regex="replication,ou=users,dc=example,dc=com" read by * none

      Delete
    2. That setup allows users to use the passwd(1) command. You will have to change the numbers in curly braces of course to fit your environment.

      HTH

      David

      Delete
    3. Hello David,

      I have tried the ACL {0} and {1} but the client side no longer to able to communicate using nssproxy user. As I am using nssproxy user to fetch information. Are there any changes need to be done on client side or I am missing something.

      Delete
    4. Hey Gaurav,

      Playing with OpenLDAP ACL was one of the hardest part of creating this blog series. So don't despair if you also find it difficult!

      Can you post what your ACL look like at the moment? It would help to debug.

      Keep in mind that ACLs are evaluated from top to bottom. So passwords and such should be done at the top.

      HTH,

      DA+

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

      Delete
    6. Hello David,

      Please find the output of the file: "/etc/openldap/slapd.d/cn=config/olcDatabase={1}bdb.ldif"

      # AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
      # CRC32 d77a0ad6
      dn: olcDatabase={1}bdb
      objectClass: olcDatabaseConfig
      objectClass: olcBdbConfig
      olcDatabase: {1}bdb
      olcSuffix: dc=example,dc=com
      olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=extern
      al,cn=auth" manage by dn.base="cn=nssproxy,ou=users,dc=example,dc
      =com" read by * auth by * none
      olcAccess: {1}to attrs=userPassword by self write by * auth
      olcAccess: {2}to dn.base="dc=example,dc=com" by * search by * no
      ne
      olcAddContentAcl: FALSE
      olcLastMod: TRUE
      olcMaxDerefDepth: 15
      olcReadOnly: FALSE
      olcRootDN: cn=admin,dc=example,dc=com
      olcRootPW:: e1NTSEF9WkhtdTRQVU9VSHBleFNvQUs4dHBmQnhiRjdBSDFGOW0=
      olcSyncUseSubentry: FALSE
      olcMonitoring: TRUE
      olcDbDirectory: /var/lib/ldap
      olcDbCacheSize: 1000
      olcDbNoSync: FALSE
      olcDbDirtyRead: FALSE
      olcDbIDLcacheSize: 0
      olcDbLinearIndex: FALSE
      olcDbMode: 0600
      olcDbSearchStack: 16
      olcDbShmKey: 0
      olcDbCacheFree: 1
      olcDbDNcacheSize: 0
      structuralObjectClass: olcBdbConfig
      entryUUID: 25a9235c-4a1e-1035-944a-6da87ebb0f2a
      creatorsName: cn=config
      createTimestamp: 20160108063818Z
      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
      entryCSN: 20160110154223.597363Z#000000#000#000000
      modifiersName: cn=admin,dc=example,dc=com
      modifyTimestamp: 20160110154223Z


      --------------
      I tried to use the acl provided by you earlier:

      "/root/acl.ldif"

      dn: olcDatabase={1}bdb,cn=config
      changetype: modify
      delete: olcAccess
      olcAccess: {0}
      -
      # Then add a new ACL at position {0}.
      add: olcAccess
      olcAccess: {0}to attrs=userPassword,userPKCS12 by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage by dn.base="cn=admin,dc=example,dc=com" manage by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manage by dn.base="cn=nssproxy,ou=users,dc=example,dc=com" read by self write by dn.regex="replication,ou=users,dc=example,dc=com" read by anonymous auth by * none

      # EOF


      Let me know if I missed something. Thank you for the help really appropriate.

      Delete
    7. Hello David,

      Let me know your suggestions for above post.

      Delete
    8. Hello Gaurav,

      Sorry for the late reply, I am in vacation traveling. Will get back on April 18th.

      David

      Delete
  39. Hi David,
    Excellent detailed work.
    My getent passwd and getent group failed to return anything from ldap.
    I was sure my configuration was correct.
    After some time, I finally got it to work after I restarted slapd.
    Hope this helps someone.

    ReplyDelete
    Replies
    1. Nice! Happy I could help :)

      Thanks,

      DA+

      Delete

Note: Only a member of this blog may post a comment.