Does anyone use nscd?

Lawrence Stewart lstewart at freebsd.org
Thu Oct 6 13:11:39 UTC 2011


On 10/05/11 19:43, Dag-Erling Smørgrav wrote:
[snip]
>
> While we're at it, I'd be very grateful if someone could email me a
> quick and dirty guide to setting up an LDAP server for testing.  I have
> too much on my plate right now to start reading documentation...

A bit dated, but this build guide is reasonably complete and should 
pretty much all still be relevant. It has some bits you won't need if 
you're just setting something up for quick and dirty testing - I think 
they'll be obvious as you're working through it.

Cheers,
Lawrence
-------------- next part --------------

- Based mostly on information from these places (among many others!):
- http://www.freebsd.org/doc/en/articles/ldap-auth/index.html
- http://www.openldap.org/doc/admin24/


## USEFUL RANDOM TIDBITS ##

- These pearls of wisdom are useful during set up and debugging


- Use the "slapcat" tool on the server command line to show you the contents
- of the ldap database in ldif format. This is useful for rolling backups.
- Have a cron job call slapcat every 30 mins and write the output over the top
- of a file which is incrementally backed up

- Example of updating the "test" user's password as the DB admin
ldappasswd -x -S -H ldap://127.0.0.1 -D 'cn=root,dc=example,dc=com' -W 'uid=test,ou=people,dc=example,dc=com'


- LDAP data is often stored base64 encoded (e.g. userPassword field). Use this to decode:
echo "e0NSWVBUfSQxJEt5T3FxYmdlJDQec3VTLnZUY21rTzRGWENBVVBTMjE=" | perl -MMIME::Base64 -ne 'print decode_base64($_) . "\n";'

-To manually update an existing entry's attribute
ldapmodify -x -H ldap://127.0.0.1 -D 'cn=root,dc=example,dc=com' -W -f testuser.ldif
- With testuser.ldif contents:
dn: uid=test,ou=people,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {crypt}$1$pUXysTUZ$97r27L6FE21NDtZdNUYRc1


-To delete an existing entry
ldapmodify -x -H ldap://127.0.0.1 -D 'cn=root,dc=example,dc=com' -W -f testuser.ldif
- With testuser.ldif contents:
dn: uid=test,ou=people,dc=example,dc=com
changetype: delete

- Enable the monitor backend in slapd.conf and run the following query to get operational info about slapd
ldapsearch -x -H ldap://127.0.0.1 -b 'cn=Monitor' +

- Change the "loglevel" directive in slapd.conf to "conns filter stats" to get useful debugging info in /var/log/debug.log

- Setting "debug 1" in pam_ldap.conf and/or nss_ldap.conf will give you some useful debugging info on the client side in /var/log/debug.log

- 
## END USEFUL RANDOM TIDBITS ##








## SERVER CONFIG ##

- Add the following lines to /etc/make.conf to make the FreeBSD ports system
- use LDAP 2.4.x for ports that require LDAP (default uses 2.3.x)

# Use OpenLDAP 2.4.x
WANT_OPENLDAP_VER=24



- Install openldap server
cd /usr/ports/net/openldap24-server

make install clean

- Select options: SASL, PASSWD, PERL, ODBC, TCP_WRAPPERS, BDB, SEQMOD, SYNCPROV, DYNAMIC_BACKENDS


- Create a certificate/key for encrypted comms with the LDAP server

mkdir /usr/local/certs

openssl req -new -x509 -days 1825 -nodes -out /usr/local/certs/ldapserver.pem -keyout /usr/local/certs/ldapserver.pem

- The dialog with openssl should go something like this:

Country Name (2 letter code) [AU]:AU
State or Province Name (full name) [Some-State]:Victoria
Locality Name (eg, city) []:Melbourne
Organization Name (eg, company) [Internet Widgits Pty Ltd]: Org
Organizational Unit Name (eg, section) []: Org Unit
Common Name (eg, YOUR name) []:ldapserver.blah.com.au
Email Address []:youruser at blah.com.au

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:


#- Check that the basic details are all good
openssl x509 -subject -dates -fingerprint -noout -in /usr/local/certs/ldapserver.pem

#- Set perms on sensitive files
#create 'certs' group and add ldap and www users:

pw groupadd certs
pw groupmod certs -M www ldap

chmod 0440 /usr/local/certs/ldapserver.pem
chgrp certs /usr/local/certs/ldapserver.pem

#- Configure slapd, the ldap server

mkdir /var/db/slapd
chown ldap:ldap /var/db/slapd

cp /usr/local/etc/openldap/DB_CONFIG.example /var/db/slapd/DB_CONFIG

cd /usr/local/etc/openldap



edit slapd.conf

- Make the file look like this

#######################################################
include         /usr/local/etc/openldap/schema/core.schema
include         /usr/local/etc/openldap/schema/cosine.schema
include         /usr/local/etc/openldap/schema/inetorgperson.schema
include         /usr/local/etc/openldap/schema/nis.schema          
include         /usr/local/share/examples/samba/LDAP/samba.schema  

loglevel        conns filter stats
#loglevel       none
pidfile         /var/run/openldap/slapd.pid
argsfile        /var/run/openldap/slapd.args
modulepath      /usr/local/libexec/openldap
moduleload      back_bdb
defaultsearchbase "dc=blah,dc=com,dc=au"
password-hash   {CRYPT}
password-crypt-salt-format "$1$%.8s"
security ssf=128
TLSCertificateFile /usr/local/certs/ldapserver.pem
TLSCertificateKeyFile /usr/local/certs/ldapserver.pem
TLSCACertificateFile /usr/local/certs/ldapserver.pem

database        bdb
directory       /var/db/slapd
suffix          "dc=blah,dc=com,dc=au"
rootdn          "cn=root,dc=blah,dc=com,dc=au"
rootpw          <password from next step>
checkpoint      0 5
index           objectClass     eq
index           uid             eq
index           uidNumber       eq
index           gidNumber       eq

access to dn.base="sambaDomainName=LDAPSERVER,ou=samba,dc=blah,dc=com,dc=au"
 by dn.base="uid=samba,ou=admins,dc=blah,dc=com,dc=au" write

access to attrs=userPassword,sambaNTPassword,sambaLMPassword,sambaPasswordHistory,sambaPwdLastSet,sambaAcctFlags
 by self =xw
 by dn.base="uid=samba,ou=admins,dc=blah,dc=com,dc=au" write
 by * auth

access to *
 by self write
 by * read


#######################################################

#- Create a slapd root password, replacing "test" with real password
slappasswd -s "test"

- This will spit a string out to the console that looks like "{SSHA}L4kq3C1TWCpVnWKq8oeHtZV883ljiViM"
- Copy the entire string and paste it into the slapd config file at the "rootpw" line




# - edit /usr/local/etc/openldap/ldap.conf - add folowing line:

echo "TLS_REQCERT allow" >> /usr/local/etc/openldap/ldap.conf

#- Make ldap server start on boot
#edit /etc/rc.conf
#- Add the following line

echo 'slapd_enable=\"YES\"' >> /etc/rc.conf

- Start the server now
/usr/local/etc/rc.d/slapd start




## BEGIN OPTIONAL SERVER CONFIG ##

- Install PHP LDAP admin (phpldapadmin-1.1.0.5_2,1)

cd /usr/ports/www/apache22
make install clean

- select default options

cd /usr/ports/net/phpldapadmin
make install clean

- select options: CLI, CGI, APACHE, SUHOSIN, MULTIBYTE, IPV6, FASTCGI, PATHINFO for php5-5.2.6

- Make apache handle .php files via the php interpreter

edit /usr/local/etc/apache22/httpd.conf

- Add the following lines under the existing line "AddType application/x-gzip .gz .tgz"

#######################################################
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
#######################################################

- Uncomment the following line

#Include etc/apache22/extra/httpd-ssl.conf




- Configure SSL/TLS

edit /usr/local/etc/apache22/extra/httpd-ssl.conf

- Comment out the following lines
#ServerName www.example.com:443
#ServerAdmin you at example.com

- Change the following lines appropriately

SSLCertificateFile "/usr/local/certs/ldapserver.pem"
SSLCertificateKeyFile "/usr/local/certs/ldapserver.pem"





- Make apache serve phpldapadmin via HTTPS

edit /usr/local/etc/apache22/Includes/phpldapadmin.conf

- Add the following lines:

#######################################################
RewriteEngine on
RewriteCond   %{SERVER_PORT}  !443$
RewriteRule ^/?(phpldapadmin/.*) https://%{SERVER_NAME}/$1 [R=301,L]

Alias /phpldapadmin /usr/local/www/phpldapadmin/htdocs

<Directory /usr/local/www/phpldapadmin>
    Order allow,deny
    Allow from all
    DirectoryIndex index.php
</Directory>
#######################################################


- Configure phpldapadmin

edit /usr/local/www/phpldapadmin/config/config.php

- Make the file look like this:

#######################################################
<?php
$i=0;
$ldapservers = new LDAPServers;
$ldapservers->SetValue($i,'server','name','LDAP Server');
$ldapservers->SetValue($i,'server','host','127.0.0.1');
$ldapservers->SetValue($i,'server','auth_type','session');
$ldapservers->SetValue($i,'server','tls',true);
$ldapservers->SetValue($i,'server','sasl_auth',false);

$friendly_attrs = array();
$friendly_attrs['facsimileTelephoneNumber'] = 'Fax';
$friendly_attrs['telephoneNumber']          = 'Phone';
$friendly_attrs['uid']                      = 'User Name';

$q=0;
$queries = array();
$queries[$q]['name'] = 'User List';
$queries[$q]['base'] = 'dc=blah,dc=com,dc=au';
$queries[$q]['scope'] = 'sub';
$queries[$q]['filter'] = '(&(objectClass=posixAccount)(uid=*))';
$queries[$q]['attributes'] = 'cn, uid, homeDirectory, telephonenumber, jpegphoto';
?>
#######################################################


- Make apache start on boot

edit /etc/rc.conf

- Add the following line

apache22_enable="YES"


- Start apache

apachectl start


- You should now be able to access http://<hostname>/phpldapadmin and login with your
- LDAP server's rootdn credentials
- e.g. username "cn=root,dc=blah,dc=com,dc=au" and password is the clear text version
- you typed into the slappasswd command previously to generate the rootpw option

- "Import" action in phpldapadmin can be used to run an ldif file against the server


## END OPTIONAL SERVER CONFIG ##






- Create an ldif file to seed the LDAP db with our required structure
- We'll use "people" as the OU for user accounts and "groups" as the OU for groups

edit /usr/local/etc/openldap/initldap.ldif

- seed ldif file contents:

#######################################################
#org
dn: dc=blah,dc=com,dc=au
objectClass: dcObject
objectClass: organization
dc: org
o: ORG NAME
description: Blah

# Create an OU for people
dn: ou=people,dc=blah,dc=com,dc=au
ou: people
objectClass: top
objectClass: organizationalUnit

# Create an OU for groups
dn: ou=groups,dc=blah,dc=com,dc=au
objectClass: top
objectClass: organizationalUnit
ou: groups
#######################################################


- Apply the contents of the ldif file against the DB (or use web interface)

ldapadd -c -x -f /usr/local/etc/openldap/initldap.ldif -H ldap://127.0.0.1 -D 'cn=root,dc=blah,dc=com,dc=au' -W -ZZ


## END SERVER CONFIG ##
















## CLIENT CONFIG ##

- Add the following lines to /etc/make.conf to make the FreeBSD ports system
- use LDAP 2.4.x for ports that require LDAP (default uses 2.3.x)

# Use OpenLDAP 2.4.x
WANT_OPENLDAP_VER=24


- Install required ports


Paste the following patch into the file shown below:
/usr/ports/security/pam_ldap/files/patch-groupdnfix
################################################################

--- pam_ldap.c.orig     2008-06-27 17:51:37.000000000 +1000
+++ pam_ldap.c  2008-06-27 17:45:11.000000000 +1000
@@ -4020,7 +4020,7 @@
     {
       rc = ldap_compare_s (session->ld,
                           session->conf->groupdn,
-                          session->conf->groupattr, session->info->userdn);
+                          session->conf->groupattr, session->info->username);
       if (rc != LDAP_COMPARE_TRUE)
        {
          snprintf (buf, sizeof buf, "You must be a %s of %s to login.",

################################################################

cd /usr/ports/security/pam_ldap
make install clean

cd /usr/ports/net/nss_ldap
make install clean

cd /usr/ports/security/pam_mkhomedir
make WITH_PROFILE=yes install clean


- Configure pam to attempt ldap auth before falling back on local file auth

edit /etc/pam.d/sshd

- Add the following line before "auth required pam_unix.so no_warn try_first_pass"

auth            sufficient      /usr/local/lib/pam_ldap.so      no_warn config=/usr/local/etc/pam_ldap.conf try_first_pass


- Add the following line before "account required pam_unix.so"
account         sufficient        /usr/local/lib/pam_ldap.so      no_warn ignore_authinfo_unavail ignore_unknown_user


- Add the following line before "session required pam_permit.so"

session         required        /usr/local/lib/pam_mkhomedir.so



- Make sure /home exists either as a symlink to a directory or an actual directory

edit /usr/local/etc/pam_ldap.conf

- Make the file contents this:

#######################################################
uri ldap://ldapserver.blah.com.au
base dc=blah,dc=com,dc=au
ssl start_tls
tls_checkpeer no
#debug 1
#######################################################


- Configure nss to use ldap to resolve uid/gid info

edit /etc/nsswitch.conf

- Change the following lines accordingly

group: files ldap
passwd: files ldap

- nss_ldap is written by the authors of pam_ldap and they can share config files
ln -s /usr/local/etc/pam_ldap.conf /usr/local/etc/nss_ldap.conf

- If nss is working, "touch test.file ; chown ldapuid:ldapgid test.file" where "ldapuid" is a uid of a user in ldap that isn't
- in the local system's /etc/passwd file and "ldapgid" is a gid of a group in ldap that isn't
- in the local system's /etc/group file
- Then run "ls -l test.file" and you should see the user name and group name details from ldap next to the file




### Local logins
The original config only sets up ldap auth for SSH logins
Add support for local LDAP logins if required:
edit /etc/pam.d/login with the same options as you did for /etc/pam.d/sshd to allow local ldap logins




### Adding nsswitch caching with nscd
Without caching, an offline LDAP server renders the workstation almost useless, as each time a username is required, eg "ls -al" the system will try and connect o the LDAP server to resolve the name.

The solution is the Name Service Caching Daemon. This basic configuration will mean that once logged into a machine (auth is done) uid/username pairs will be cached locally. 


confirm /etc/nscd.conf contains the following

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
enable-cache passwd yes
enable-cache group yes
enable-cache hosts yes
enable-cache services yes
enable-cache protocols yes
enable-cache rpc yes
enable-cache networks yes

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This will configure nscd to cache everything it can.
By default, caches are kept for 1 hour.
This can be changed by adding an entry as below.
A line is needed for each chache type you would like to alter.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
positive-time-to-live passwd 7200

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


edit /etc/rc.conf
add:

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
nscd_enable="YES"


^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
edit /etc/nssswitch.conf
add 'cache' as the first source for group, hosts, passwd, services, protocaols, rpc and networks.

This will enable caching of users and passwords from ldap as well as DNS host lookups





### LDAP Password changes with 'passwd'
edit /usr/local/etc/pam_ldap.conf

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
add "pam_passwd exop"

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: With the 'exop' option, the password is sent in clear text (BUT it is over TLS so will still be secure) and upon receiving the password, the server encrypts it into the proper format. 'crypt' also works, and sends an encrypted password to ldap, but it is ideal to keep passwords in exactly the same format in ldap as is kept in a locat master.passwd file.

The system password command is very old and isn't aware that passwords can be changed for LDAP users.
We therefore have to add a hack to bypass this limitation. (There is no feasable alternate solution at this stage).

edit /usr/src/usr.bin/passwd/passwd.c
Replace:
    errx(1, "Sorry, `passwd' can only change passwords for local or NIS users.");
With:
                fprintf(stderr, "Now you can change LDAP password via PAM\n");

make install in that directory.


edit /etc/pam.d/passwd
add the following line before the pam_unix.so entry

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
password        sufficient      /usr/local/lib/pam_ldap.so      no_warn try_first_pass config=/usr/local/etc/pam_ldap.conf

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^




### Restricting Logins to a particular group

http://lists.freebsd.org/pipermail/freebsd-questions/2005-October/100816.html

edit /usr/local/etc/pam_ldap.conf
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pam_groupdn cn=login_group,ou=groups,dc=blah,dc=com,dc=au
pam_member_attribute memberUid

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
WARNING: For this to work the FULL DN of the user must be listed in the memberUid attribute of the posix group specified in pam_groupdn config.

Suggestion, use a separate OU for hosts, which contain groups with machine names -> full dn of allowed users on those machines should be stored in memberUid
OR
add a separate attribute 'loginDN' to relavant groups that will be used for login restrictions. change pam_member_atrribute from memberUid to loginDN

### Preventing long delays during Auth when LDAP server isn't available

By default, when the LDAP server isn't available, the client will not give up trying to connect to the LDAP server.
Changing the bind policy to 'soft' will cause the client to give up immediately if the server is not available.

# Reconnect policy:
#  hard_open: reconnect to DSA with exponential backoff if
#             opening connection failed
#  hard_init: reconnect to DSA with exponential backoff if
#             initializing connection failed
#  hard:      alias for hard_open
#  soft:      return immediately on server failure

edit /usr/local/etc/pam_ldap.conf


^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bind_policy soft 

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

### Allowing machine logins to be restricted by groups

Paste the following patch into the file shown below:
/usr/ports/security/pam_ldap/files/patch-groupdnfix

--- pam_ldap.c.orig     2008-06-27 17:51:37.000000000 +1000
+++ pam_ldap.c  2008-06-27 17:45:11.000000000 +1000
@@ -4020,7 +4020,7 @@
     {
       rc = ldap_compare_s (session->ld,
                           session->conf->groupdn,
-                          session->conf->groupattr, session->info->userdn);
+                          session->conf->groupattr, session->info->username);
       if (rc != LDAP_COMPARE_TRUE)
        {
          snprintf (buf, sizeof buf, "You must be a %s of %s to login.",
cd /usr/ports/
make clean


## END CLIENT CONFIG ##



## BEGIN SAMBA SERVER CONFIG ##

   passdb backend = ldapsam:ldap://ldapserver.blah.com.au
   ldap admin dn = uid=samba,ou=admins,dc=blah,dc=com,dc=au
   ldap ssl = no
   ldap delete dn = no
   ldap user suffix = ou=people
   ldap group suffix = ou=groups
   ldap machine suffix = ou=computers
   ldap suffix = dc=blah,dc=com,dc=au

## END SAMBA SERVER CONFIG ##


More information about the freebsd-hackers mailing list