HOWTO setup ldap authentication
From Chaos
Contents |
Summary
This is an article designed to quickly and efficiently list what changes need to be made on a Linux server to allow pam_ldap, nss_ldap, Apache, Samba, and Sudo authentication via an OpenLDAP server, as well as enable password management (passwords are valid for 365 days, then they must be reset), and secure everything with SSL.
Caveats
This article assumes the following:
- You already have a working LDAP server with users and groups pre-populated.
- You have a good understanding of how Linux is laid out.
- Any software that you want to authenticate via LDAP is compiled with LDAP support. This includes, but is not limited to:
- Apache
- phpldapadmin
- Samba
- smbldap-tools
- nss_ldap
- pam_ldap
- sudo
- easy-rsa (for certificate management)
- All of the steps below are Gentoo-centric. They will work for just about any Linux distro (even BSD's), as long as you find the same files and make the same modifications. YMMV.
Easy RSA
You'll have to generate a SSL server certificate and key (ending in .crt and .key) for the OpenLDAP server, as well as the root CA authority file (ca.crt). This isn't an easy-rsa HOWTO, so you're on your own. The files I will be referencing are throughout this article are:
- /etc/openldap/ssl/ca.crt -- Certificate Authority File
- /etc/openldap/ssl/ldap.mycompany.net.crt -- Server Certificate File
- /etc/openldap/ssl/ldap.mycompany.net.key -- Server Private Key File
OpenLDAP
You will need to initially setup OpenLDAP with both port 389 (unencrypted) and 636 (encrypted). This will ensure you can do debugging on port 389, and see if there's anything wrong (when you do tcpdump, all LDAP traffic will be unencryted, making it much easier to debug). When the time comes though, you'll need to disable unencrypted communication on port 389 (it will still use TLS only), and use SSL on 636.
If you want to easily check and see if your LDAP server has the right certificate configured for SSL, run this command:
SSL on port 636: openssl s_client -connect ldap.mycompany.net:636
slapd.conf
Of course, you are going to store Samba and Sudoers in your LDAP directory, as well as standard PAM users. Ensure your config looks like this:
#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
# These includes are a part of the base OpenLDAP distribution.
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/nis.schema
include /etc/openldap/schema/ldapns.schema
include /etc/openldap/schema/samba.schema
include /etc/openldap/schema/sudo.schema
# Load dynamic backend modules:
modulepath /usr/lib/openldap/openldap
# moduleload back_shell.so
# moduleload back_relay.so
# moduleload back_perl.so
# moduleload back_passwd.so
# moduleload back_null.so
# moduleload back_monitor.so
# moduleload back_meta.so
moduleload back_hdb.so
# moduleload back_dnssrv.so
# Sample security restrictions -- Require port 389 to be TLS encrypted
# WARNING: DISABLE THIS INITIALLY FOR TESTING, THEN ENABLE
# Require integrity protection (prevent hijacking)
# Require 112-bit (3DES or better) encryption for updates
# Require 63-bit encryption for simple bind
security ssf=127 update_ssf=127 simple_bind=127
# Logging configuration. Enable this for debugging.
loglevel none
# SSL configuration. See the section on easy-rsa to generate the certificates and keys.
TLSCipherSuite HIGH:MEDIUM:-SSLv2
TLSCACertificateFile /etc/openldap/ssl/ca.crt
TLSCertificateFile /etc/openldap/ssl/ldap.mycompany.net.crt
TLSCertificateKeyFile /etc/openldap/ssl/ldap.mycompany.net.key
#######################################################################
# BDB database definitions
#######################################################################
database hdb
suffix "dc=mycompany,dc=net"
rootdn "cn=root,dc=mycompany,dc=net"
checkpoint 32 30 # <kbyte> <min>
ldap_version 3
# Cleartext passwords, especially for the rootdn, should
# be avoid. See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw {run slappasswd -s <password> to get this value}
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended, may be different for your Linux distribution.
directory /var/lib/openldap-data
# ACLs
defaultaccess none
# ACL For password changing on command-line via smbldap-passwd for non-root users
access to attrs=userPassword,sambaLMPassword,sambaNTPassword,sambaPwdLastSet,sambaPwdMustChange
by self write
by anonymous auth
by * none
# ACL for LDAP Manager Access
access to *
by self write
by users read
by anonymous auth
by * none
# Indices to maintain
index sambaSID eq
index sambaPrimaryGroupSID eq
index sambaDomainName eq
index objectClass,uid,uidNumber,gidNumber,memberUid eq
index cn,mail,surname,givenname eq,subinitial
ldap.conf
This is in reference to /etc/openldap/ldap.conf, the client-side LDAP library configuration. This file sets options for any client software that uses the OpenLDAP library to connect from this machine. The key settings are URI, BASE, and TLS_{CACERTDIR,CACERT,CACERTFILE,REQCERT}.
# # LDAP Defaults # # # See ldap.conf(5) for details # This file should be world readable but not world writable. # #BASE dc=example, dc=com #URI ldap://ldap.example.com ldap://ldap-master.example.com:666 #SIZELIMIT 12 #TIMELIMIT 15 #DEREF never URI ldaps://ldap.mycompany.net:636 BASE dc=mycompany,dc=net TLS_CACERTDIR /etc/openldap/ssl TLS_CACERT /etc/openldap/ssl/ca.crt TLS_CACERTFILE /etc/openldap/ssl/ca.crt TLS_REQCERT never
slapd Startup
In Gentoo, you have to tell slapd to use SSL when starting up. Modify the file /etc/conf.d/slapd, and add the following entries:
OPTS="-h 'ldap://ldap.mycompany.net ldaps://ldap.mycompany.net'"
System Authentication
ldap.conf
We need to modify /etc/ldap.conf. There are many options in ldap.conf, yours may vary. I have only included the ones I modified below.
# Your LDAP server. Must be resolvable without using LDAP.
# Multiple hosts may be specified, each separated by a
# space. How long nss_ldap takes to failover depends on
# whether your LDAP client library supports configurable
# network or connect timeouts (see bind_timelimit).
host ldap.mycompany.net
# The distinguished name of the search base.
base dc=mycompany,dc=net
# The distinguished name to bind to the server with.
# Optional: default is to bind anonymously.
binddn cn=root,dc=mycompany,dc=net
# The credentials to bind with.
# Optional: default is no credential.
bindpw s3cr3t
# The port.
# Optional: default is 389, 636 for SSL
port 636
# NOTE: Putting a short search/bind timelimit helps when OpenLDAP is restarted (or the system is rebooted).
# I've put mine as low as 1, with no ill affects.
# Search timelimit
timelimit 3
# Bind/connect timelimit
bind_timelimit 3
# Reconnect policy: hard (default) will retry connecting to
# the software with exponential backoff, soft will fail
# immediately.
bind_policy soft
# Check the 'host' attribute for access control
# Default is no; if set to yes, and user has no
# value for the host attribute, and pam_ldap is
# configured for account management (authorization)
# then the user will not be allowed to login.
# WARNING: IF YOU ENABLE THIS OPTION, NOBODY WILL BE ABLE
# TO LOG ON TO THIS SYSTEM UNTIL YOU ADD A NEW 'host'
# ENTRY (AND ASSOCIATED OBJECTCLASS) TO THEIR USER
# ACCOUNT. BE CAREFUL!
pam_check_host_attr yes
# Use paged rseults
nss_paged_results yes
# Pagesize: when paged results enable, used to set the
# pagesize to a custom value
pagesize 1000
# RFC2307bis naming contexts
# Syntax:
# nss_base_XXX base?scope?filter
# where scope is {base,one,sub}
# and filter is a filter to be &'d with the
# default filter.
# You can omit the suffix eg:
# nss_base_passwd ou=People,
# to append the default base DN but this
# may incur a small performance impact.
nss_base_passwd ou=Computers,dc=mycompany,dc=net?sub
nss_base_passwd ou=Users,dc=mycompany,dc=net?sub
nss_base_shadow ou=Users,dc=mycompany,dc=net?sub
nss_base_group ou=Groups,dc=mycompany,dc=net?one
# How passwords are stored in OpenLDAP
pam_password ssha
# Logging config. Note that debug 255 is commented out initially, this will create *A LOT* of log messages when enabled!!
logdir /var/log/nss_ldap
#debug 255
# Enable SSL communications.
ssl on
# OpenLDAP SSL options
# Require and verify server certificate (yes/no)
# Default is to use libldap's default behavior, which can be configured in
# /etc/openldap/ldap.conf using the TLS_REQCERT setting. The default for
# OpenLDAP 2.0 and earlier is "no", for 2.1 and later is "yes".
tls_checkpeer no
# For Gentoo's distribution of nss_ldap, as of 250-r1, we use these values
# (The hardwired constants in the code are changed to them as well):
nss_reconnect_tries 4 # number of times to double the sleep time
nss_reconnect_sleeptime 1 # initial sleep value
nss_reconnect_maxsleeptime 16 # max sleep value to cap at
nss_reconnect_maxconntries 2 # how many tries before sleeping
ldap.conf.sudo
On Gentoo, the sudo ldap.conf is located in a separate file, /etc/ldap.conf.sudo. Here's what it needs to contain:
# supported directives: host, port, ssl, ldap_version
# uri, binddn, bindpw, sudoers_base, sudoers_debug
# tls_{checkpeer,cacertfile,cacertdir,randfile,ciphers,cert,key}
host ldap.mycompany.net
port 636
ssl yes
base dc=lifepointfamily,dc=org
binddn cn=root,dc=mycompany,dc=net
bindpw s3cr3t
sudoers_base ou=Sudoers,dc=mycompany,dc=net
#sudoers_debug 2
pam_ldap
First things first, setup System and SSH authentication to use LDAP. Go in to the directory /etc/pam.d, and edit the file system-auth. Add in each line as it is below that has pam_ldap.so as an entry:
auth required pam_env.so auth sufficient pam_unix.so try_first_pass likeauth nullok auth required pam_ldap.so use_first_pass account required pam_ldap.so account required pam_unix.so password required pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 try_first_pass retry=3 password sufficient pam_unix.so try_first_pass use_authtok nullok md5 shadow password sufficient pam_ldap.so use_authtok use_first_pass session required pam_limits.so session required pam_env.so session required pam_unix.so session optional pam_ldap.so
Save the file and exit.
nsswitch.conf
Modify the file /etc/nsswitch.conf. This contains the settings for obtaining user and group information, and where it should be looked up. Mine looks something like this (all I do is modify the base nsswitch.conf to point to LDAP). Note the 'sudoers' entry, which is required:
passwd: files ldap shadow: files ldap group: files ldap sudoers: files ldap #passwd: files #shadow: files #group: files # passwd: db files nis # shadow: db files nis # group: db files nis hosts: files dns networks: files dns services: db files protocols: db files rpc: db files ethers: db files netmasks: files netgroup: files bootparams: files automount: files aliases: files
Test
Using one of your new LDAP user accounts, SSH to your system in a new session, and see if you can login. If you cannot, turn up logging and start debugging. Remember, do not log out of your current SSH session, especially if things are not working yet! You may lock yourself out!
You can also run 'getent passwd' which will show you a list of all users/computers in the LDAP directory, if everything is configured correctly.
Samba
On to Samba. Ensure Samba is compiled with LDAP support. Edit /etc/samba/smb.conf, and add settings for LDAP auth that look something like the following. Note that these are only LDAP-specific settings. There are many other options that go in to smb.conf, yours will vary. Note that these settings are for a Samba server that IS NOT a domain controller.
If you would like to use VASC, see the main VASC page for instructions. VASC is already SSL-ready.
passdb backend = ldapsam:ldaps://ldap.mycompany.net/ ldap delete dn = Yes ldap ssl = yes ldap suffix = dc=mycompany,dc=net ldap admin dn = uid=root,dc=mycompany,dc=net ldap group suffix = ou=Groups ldap user suffix = ou=Users ldap machine suffix = ou=Computers ldap idmap suffix = ou=Idmap
To set the password for the Admin DN in Samba, run 'smbpasswd -w mysecret'. It will save the encrypted password to secrets.tdb.
| root@localhost:/etc/samba# smbpasswd -w mysecret |
Restart Samba, you should be able to connect to the system using a user from LDAP.
Apache
httpd.conf
In Gentoo, the mod_ldap configuration is stored in /etc/apache2/modules.d/46_mod_ldap.conf. By default, you shouldn't need to modify anything, other than enabling the LDAP startup option in /etc/conf.d/apache2.
.htaccess
As long as your Apache is configured with LDAP support, enabling .htaccess files to auth against LDAP is easy. I have included the text below from one of mine that I use as a template (from Apache 2.2.11). This should be all the config you need to do.
AuthLDAPEnabled On AuthLDAPAuthoritative On AuthLDAPDereferenceAliases never AuthLDAPGroupAttributeIsDN On AuthLDAPGroupAttribute memberUid AuthLDAPBindDN uid=manager,ou=users,dc=mycompany,dc=net AuthLDAPBindPassword s3cr3t AuthName "Restricted Files" AuthType Basic AuthLDAPURL ldaps://ldap.mycompany.net/dc=mycompany,dc=net?uid?sub?(objectClass=posixAccount) # Let any valid user in require valid-user # Let only joe in #require user joe # Let anyone from group Administrators in #require group cn=Administrators,ou=groups,dc=mycompany,dc=net
PHPLDAPAdmin
PHPLDAPAdmin needs TLS in order to operate correctly with our LDAP server. Your config should have an entry like this:
$servers = new Datastore();
$servers->newServer('ldap_pla');
$servers->setValue('server','name','MyCompany LDAP');
$servers->setValue('server','host','ldap.mycompany.net');
$servers->setValue('server','port',389);
$servers->setValue('server','base',array('dc=mycompany,dc=net'));
$servers->setValue('login','auth_type','session');
$servers->setValue('login','bind_id','cn=root,dc=mycompany,dc=net');
$servers->setValue('login','bind_pass','');
$servers->setValue('server','tls',true);
Samba LDAP Tools
smbldap-tools is a set of utilities that's meant to help administer Samba and Unix accounts. After you have setup Samba, you can configure this tool to help you populate your users (and manage other things, passwords, group membership, etc.). Read the file closely for setting it up. There is one peculiar thing I wanted to mention, when setting up encrypted communication, you have to use TLS on port 389. I also simplified it by not requiring certificate verification, YMMV.
# Put your own SID. To obtain this number do: "net getlocalsid".
# If not defined, parameter is taking from "net getlocalsid" return
SID="{SID_VALUE}"
# Domain name the Samba server is in charged.
# If not defined, parameter is taking from smb.conf configuration file
# Ex: sambaDomain="IDEALX-NT"
sambaDomain="MYCOMPANY"
# Slave LDAP server
# Ex: slaveLDAP=127.0.0.1
# If not defined, parameter is set to "127.0.0.1"
slaveLDAP="ldap.mycompany.net"
# Slave LDAP port
# If not defined, parameter is set to "389"
slavePort="389"
# Master LDAP server: needed for write operations
# Ex: masterLDAP=127.0.0.1
# If not defined, parameter is set to "127.0.0.1"
masterLDAP="ldap.mycompany.net"
# Master LDAP port
# If not defined, parameter is set to "389"
masterPort="389"
# Use TLS for LDAP
# If set to 1, this option will use start_tls for connection
# (you should also used the port 389)
# If not defined, parameter is set to "1"
ldapTLS="1"
# How to verify the server's certificate (none, optional or require)
# see "man Net::LDAP" in start_tls section for more details
verify="none"
The rest of the settings should be pretty self explanatory.
Password Management
I found it very difficult at first to get password changes and expiration working with Samba and Windows clients, using OpenLDAP. Here's what I found:
- The "passwd chat" dialogue setting in smb.conf must be exact! This is easily achieved by running 'smbldap-passwd' for a random user, and then converting each line into something that looks like this (note how the text is wrapped in double-quotes):
- "*Changing UNIX and samba passwords for %u*""*New password*" %n"*Retype new password*" %n
- Remove all 'sambaPwd*' attributes on the individual accounts except for sambaPwdLastSet.
- On the main domain policy, set sambaMinPwdAge to 1 week (604800).
- On the main domain policy, set sambaMaxPwdAge to 1 year (31556926).
- In smbldap.conf, change defaultMaxPasswordAge to 365 (this is for Shadow Password expiration).
- If you have accounts that must have Shadow Passwords that do not expire, remove the attribute shadowMax from their LDAP entry.
- If you have accounts that must have Samba Passwords that do not expire, modify the attribute sambaAcctFlags to be [UX]. [1]