HOWTO secure OpenLDAP network
From Gentoo Linux Wiki
| Installation • Kernel & Hardware • Networks • Portage • Software • System • X Server • Gaming • Non-x86 • Emulators • Misc |
Contents |
[edit] Introduction
LDAP stands for Lightweight Directory Access Protocol. All information inside a directory is structured hierarchically. Even more, if you want to enter data inside a directory, the directory must know how to store this data inside a tree. Lets take a look at a fictional company and an Internet-like tree:
dc=org
|
dc=mydomain
|
o=myserver
__________/ \_________
/ \
ou=UsersGroups ou=Services
____/ \_____ / \
/ \ DHCP BIND
ou=Users ou=Groups
/ \
___/ \___
/ \
cn=root cn=tux
Dc means directory component, o means organization, ou means organizational unit.
For this guide, there will be some assumptions and conventions.
You have one server and one client. Your server is named 'myserver'. Your client is called 'myclient'. You have a domain, called 'mydomain.org'. You want to use your server to authenticate your client logins.
This Guide is divided into two parts: Server and Client.
[edit] Server setup
[edit] Security
We don't want anyone eavesdropping the LDAP server, so let's make sure that the connection inside the domain is secure. There are many references online, here we'll just produce the basic steps to bring SASL functional. If you want to go ahead and skip this dull part, go ahead, but remember that you will have to get back here later. The later instructions rely that all this has been commenced.
First, generate an SSL certificate to secure your directory. Answer the question you receive as good as possible. When asked for your Common Name, enter the name the clients will use when contacting the server. This is usually the full domainname.
Servers also often support the non-standard "LDAPS" ("Secure LDAP", commonly known as "LDAP over SSL") protocol. The LDAPS differs from LDAP in that it connects to a special port, ldaps (tcp/636). OpenLDAP has the ability to enable SSLv3 capabilities. Similar to SSL is Transport Layer Security (TLSv1). While SSL operates on a secure connection (ldaps://:636) and is a Netscape-defined protocol, TLS offers the same encryption on regular LDAP connections (ldap://:389) and is an industry standard (RFC 2830). Both types of secure connections are set up identically. It is only the URL that is different.
For more information, see
- PLAIN / LOGIN
- Insecure - strongly discouraged
- DIGEST-MD5
- DIGEST-MD5 relies on the client and the server sharing a "secret", usually a password. Good for relatively secure networks.
- GSSAPI
- utilizes Kerberos V to provide secure authentication services. Kerberos is viewed as a secure, distributed authentication system suitable for both small and large enterprises.
- EXTERNAL
- When used in conjunction with TLS X.509-based public key technology, EXTERNAL offers strong authentication.
[edit] SSL Certs
Since we are using SSL/TLS, we need to generate a certificate to allow incoming and outgoing transactions. Generating a self-signed certificate is pretty easy, and it needs to be done any time a server's domain name is changed. You can put additional hostnames in the subjectAltName extension field of the certificate, but how to do this is beyond the scope of this document.
For now, just do the following. Make sure to answer the questions as best you can.
# openssl req -config /etc/ssl/openssl.cnf -new -x509 -nodes \
-out /etc/ssl/ldap.pem -keyout /etc/openldap/ldap-key.pem -days 999999
This will generate the SSL/TLS certificate to /etc/ssl/ldap.pem and private key to /etc/openldap/ldap-key.pem. Keep these files on the server, and copy both of them onto the clients.
On Gentoo, edit /etc/conf.d/slapd and add the following, commenting out the existing line:
| File: /etc/conf.d/slapd |
OPTS="-h 'ldaps:// ldapi://%2fvar%2frun%2fopenldap%2fslapd.sock'" |
The above is only for ldap over ssl. If you do not desire it, or are troubleshooting it might help to change that to the following (ldap:// is the only thing that is added):
| File: /etc/conf.d/slapd (if you want to add support for ldap without ssl) |
OPTS="-h 'ldaps:// ldap:// ldapi://%2fvar%2frun%2fopenldap%2fslapd.sock'" |
For help with intermediate/chained SSL certificates (e.g. Go Daddy's Turbo SSL certs), see OpenLDAP with a Go Daddy “Turbo SSL Secure Certificate” in Disruptive Library Technology Jester.
[edit] Installing OpenLDAP
On your server, you need to install the following software, and alter the file permissions for security reasons. Something may be missing, and you see this document also mentions apt-get. Use this if you're working in Debian-derived environments.
- OpenLDAP is the ldap we will be using.
- pam_ldap allows pam to authenticate via ldap,
- nss_ldap allows you to get name services like dns from ldap
| Code: installing openldap and friends |
# On Gentoo:
# emerge openldap pam_ldap nss_ldap
# chown ldap:ldap -R /var/lib/openldap-{ldbm,data,slurp}
# On Debian/Ubuntu: # on the server: apt-get install ldap-server # on both server and clients: # apt-get install ldap-client libsasl2-gssapi-mit php4-kadm5 ldapscripts libsasl2 php4-snmp libpam-mkhomedir libpam-ldap libpam-mount # apt-get install krb5-kdc libpam-krb5 krb5-config |
[edit] Sudo schema
To let ldap users use sudo, add the following schema. It was found from sudo.schema
| File: /etc/openldap/schema/sudo.schema |
attributetype ( 1.3.6.1.4.1.15953.9.1.1
NAME 'sudoUser'
DESC 'User(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.2
NAME 'sudoHost'
DESC 'Host(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.3
NAME 'sudoCommand'
DESC 'Command(s) to be executed by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.4
NAME 'sudoRunAs'
DESC 'User(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.5
NAME 'sudoOption'
DESC 'Options(s) followed by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
DESC 'Sudoer Entries'
MUST ( cn )
MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoOption $description ) )
|
[edit] Kerberos 5 schema
Here is the krb5-kdc.schema file that is referenced in the /etc/openldap/slapd.conf file below. It was found from krb5-kdc.schema
| File: /etc/openldap/schema/krb5-kdc.schema |
# $Id: krb5-kdc.schema,v 1.1 2004/03/22 17:25:05 quanah Exp $
# Definitions for a Kerberos V KDC schema
# OID Base is iso(1) org(3) dod(6) internet(1) private(4) enterprise(1) padl(5322) kdcSchema(10)
#
# Syntaxes are under 1.3.6.1.4.1.5322.10.0
# Attributes types are under 1.3.6.1.4.1.5322.10.1
# Object classes are under 1.3.6.1.4.1.5322.10.2
# Syntax definitions
#krb5KDCFlagsSyntax SYNTAX ::= {
# WITH SYNTAX INTEGER
#-- initial(0), -- require as-req
#-- forwardable(1), -- may issue forwardable
#-- proxiable(2), -- may issue proxiable
#-- renewable(3), -- may issue renewable
#-- postdate(4), -- may issue postdatable
#-- server(5), -- may be server
#-- client(6), -- may be client
#-- invalid(7), -- entry is invalid
#-- require-preauth(8), -- must use preauth
#-- change-pw(9), -- change password service
#-- require-hwauth(10), -- must use hwauth
#-- ok-as-delegate(11), -- as in TicketFlags
#-- user-to-user(12), -- may use user-to-user auth
#-- immutable(13) -- may not be deleted
# ID { 1.3.6.1.4.1.5322.10.0.1 }
#}
#krb5PrincipalNameSyntax SYNTAX ::= {
# WITH SYNTAX OCTET STRING
#-- String representations of distinguished names as per RFC1510
# ID { 1.3.6.1.4.1.5322.10.0.2 }
#}
# Attribute type definitions
attributetype ( 1.3.6.1.4.1.5322.10.1.1
NAME 'krb5PrincipalName'
DESC 'The unparsed Kerberos principal name'
EQUALITY caseExactIA5Match
SINGLE-VALUE
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.5322.10.1.2
NAME 'krb5KeyVersionNumber'
EQUALITY integerMatch
SINGLE-VALUE
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
attributetype ( 1.3.6.1.4.1.5322.10.1.3
NAME 'krb5MaxLife'
EQUALITY integerMatch
SINGLE-VALUE
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
attributetype ( 1.3.6.1.4.1.5322.10.1.4
NAME 'krb5MaxRenew'
EQUALITY integerMatch
SINGLE-VALUE
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
attributetype ( 1.3.6.1.4.1.5322.10.1.5
NAME 'krb5KDCFlags'
EQUALITY integerMatch
SINGLE-VALUE
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
attributetype ( 1.3.6.1.4.1.5322.10.1.6
NAME 'krb5EncryptionType'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
attributetype ( 1.3.6.1.4.1.5322.10.1.7
NAME 'krb5ValidStart'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.5322.10.1.8
NAME 'krb5ValidEnd'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.5322.10.1.9
NAME 'krb5PasswordEnd'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE )
# this is temporary; keys will eventually
# be child entries or compound attributes.
attributetype ( 1.3.6.1.4.1.5322.10.1.10
NAME 'krb5Key'
DESC 'Encoded ASN1 Key as an octet string'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
attributetype ( 1.3.6.1.4.1.5322.10.1.11
NAME 'krb5PrincipalRealm'
DESC 'Distinguished name of krb5Realm entry'
SUP distinguishedName )
attributetype ( 1.3.6.1.4.1.5322.10.1.12
NAME 'krb5RealmName'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
# Object class definitions
objectclass ( 1.3.6.1.4.1.5322.10.2.1
NAME 'krb5Principal'
SUP top
AUXILIARY
MUST ( krb5PrincipalName )
MAY ( cn $ krb5PrincipalRealm ) )
objectclass ( 1.3.6.1.4.1.5322.10.2.2
NAME 'krb5KDCEntry'
SUP krb5Principal
AUXILIARY
MUST ( krb5KeyVersionNumber )
MAY ( krb5ValidStart $ krb5ValidEnd $ krb5PasswordEnd $
krb5MaxLife $ krb5MaxRenew $ krb5KDCFlags $
krb5EncryptionType $ krb5Key ) )
objectclass ( 1.3.6.1.4.1.5322.10.2.3
NAME 'krb5Realm'
SUP top
AUXILIARY
MUST ( krb5RealmName ) )
|
[edit] Slapd configuration
You should now have a file called /etc/openldap/slapd.conf. This is the file that controls all the ldap access and tree layout for OpenLDAP. We will make a few changes to it.
We want to make sure that it accepts "INetOrgPerson" and "NIS" schemas, because we want to authenticate net users, and nis stuff. The cosine schema adds support for COSINE and X.500 directory pilots (RFC 1274). This simply fills a dependency for the other schemas. Also, if we want kerberos and/or samba, we need to stick that in here (TODO: will update tutorial for that later).
Start editing right after "core.schema"
| File: /etc/openldap/slapd.conf |
# Include the needed data schemes
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/sudo.schema
include /etc/openldap/schema/misc.schema
include /etc/openldap/schema/krb5-kdc.schema # google for this schema
# you may use one of "md5" "smd5" "sha" "ssha" "crypt" or "cleartext" as password hash
# or put something like {SASL}myuser@mydomain.com in the userPassword attribute
# to use another authentication backend through sasl.
# Use crypt to hash the passwords
password-hash {crypt}
# Define SSL and TLS properties (optional)
TLSCertificateFile /etc/ssl/ldap.pem
TLSCertificateKeyFile /etc/openldap/ldap-key.pem
#TLSCACertificateFile /etc/ssl/ldap.pem
# you should set the loglevel to 256 initially, this will give you
# some good hints when debugging problems. Read man slapd.conf what the loglevel
# directive will give you
loglevel 256
# Further down...
# slapd gentoo init script doesn't make pid correctly
# so we define it here too
pidfile /var/run/openldap/slapd.pid
access to * by self write by * read
# for databases you can either use "bdb" or "ldbm". bdb is generally favoured by
# the openldap project as it is faster and more stable, it is somewhat difficult
# to setup when your server is under high load. Hint: create a DB_CONFIG file in
# your data directory (/var/lib/openldap-data/) and read the berkeley db documentation
# at sleepycat.com
database ldbm
suffix "dc=mydomain,dc=org"
checkpoint 32 30
rootdn "cn=admin,dc=mydomain,dc=org"
directory /var/lib/openldap-data/
index objectClass eq
#disallow bind_anon
|
Now add a root password by issuing the command:
# echo rootpw `slappasswd -h {Md5}` >> /etc/openldap/slapd.conf
The password (and rootdn) is database-specific, so it must be introduced in the proper section inside the config file. rootpw can only be set when rootdn is under suffix.
[edit] Importing base
You can use this file as the base:
| File: base.ldif |
dn: dc=mydomain,dc=org objectclass: organization objectclass: dcObject o: My Domain Name dc: mydomain description: My new LDAP domain dn: ou=Hosts,dc=mydomain,dc=org ou: Hosts objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: ou=Rpc,dc=mydomain,dc=org ou: Rpc objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: ou=Services,dc=mydomain,dc=org ou: Services objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: nisMapName=netgroup.byuser,dc=mydomain,dc=org nismapname: netgroup.byuser objectClass: top objectClass: nisMap objectClass: domainRelatedObject associatedDomain: mydomain dn: ou=Mounts,dc=mydomain,dc=org ou: Mounts objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: ou=Networks,dc=mydomain,dc=org ou: Networks objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: ou=People,dc=mydomain,dc=org ou: People objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: ou=Group,dc=mydomain,dc=org ou: Group objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: ou=Netgroup,dc=mydomain,dc=org ou: Netgroup objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: ou=Protocols,dc=mydomain,dc=org ou: Protocols objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: ou=Aliases,dc=mydomain,dc=org ou: Aliases objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: mydomain dn: nisMapName=netgroup.byhost,dc=mydomain,dc=org nismapname: netgroup.byhost objectClass: top objectClass: nisMap objectClass: domainRelatedObject associatedDomain: mydomain |
ldapadd -x -D "cn=admin,dc=mydomain,dc=org" -W -f base.ldif
[edit] Startup and testing
First do a simple syntax check of your slapd.conf file by running slaptest as root. If there are any errors and you need more detail try increasing slaptest's debug level: slaptest -d 10.
Start the slapd service:
# /etc/init.d/slapd start
Add it into default runlevel:
# rc-update add slapd default
Configure a client for testing, so that use can use ldapsearch to test and debug basic connectivity. Later you may want to test the TLS.
| File: /etc/openldap/ldap.conf |
URI ldap://myserver.mydomain.org BASE dc=myserver,dc=mydomain,dc=org #TLS_CERT /etc/ssl/ldap.pem #TLS_KEY /etc/openldap/ldap-key.pem #TLS_REQCERT never |
The TLS_CERT variable should point to the certificate you have created and transferred to the client. TLS_REQCERT tells the client not to request the certificate since we have already installed it on the local client.
Your friends here are ldapsearch and openssl s_client. You may test different things if the communication works, whether you can establish a secure tunnel and your certificate is ok.
You may first try to search rootDSE, for which the anonymous operation should be permitted.
$ ldapsearch -x -s base -b ""
The following should produce a list of all the entries in your ldap:
$ ldapsearch -x -D "cn=admin,dc=mydomain,dc=org" -W
With a user account you should first try that the queries are working without SASL or TSL. Use the -W switch, or put your password into /etc/ldap.secret for a while (remember to remove it).
$ ldapsearch -Hldap://myserver.mydomain.org -b "" -s base -D "cn=admin,dc=myserver,dc=mydomain,dc=org" -y /etc/ldap.secret
If successful, you should receive an output describing the Active Directory LDAP description. If you cannot perform simple top level searches on your Active Directory, then you should locate and fix any problems.
Once that works try with SASL but without TSL:
$ ldapsearch -Hldap://myserver.mydomain.org -b "" -s base -Omaxssf=0
Notice the '-Omaxssf=0' which should disable SASL security layers.
If you use SSL, you can use the openssl s_client:
$ openssl s_client -connect openad.local:636 -CAfile /etc/ssl/ldap.pem
Finally, try with both SASL and TSL:
$ ldapsearch -Hldap://myserver.mydomain.org -b "" -s base -Omaxssf=0 -ZZ
If you get:
- certificate verify failed. check your certificate status requirements.
Also don't forget to append the following line to your /etc/hosts.allow
| File: /etc/hosts.allow |
slapd: all |
| FIXME: Discuss possible problems at this point. |
[edit] Home directories on the server
Later in this document the pam module pam_mount will be introduced, that mounts the user home directories. See the NFS page on how to setup the NFS server for shared home directories.
[edit] Administration
[edit] GUIs
Now it's time to step out from the command line and text-based editors for a while, and install a nice administration GUI for the LDAP.
[edit] Fedora directory server
[edit] Luma
Luma is a nice-and-simple LDAP browser that can delete nodes and change attributes, but can't create new entries. Very easy to setup and looks quite attractive.
[edit] Jxplorer
JXplorer is an LDAP-Browser written in Java. It is available for a lot of operating systems, including Linux, Windows and MacOS.
- Ldap operations: add/delete/copy/modify
- Complex operations: tree copy and tree delete
- Optional GUI based search filter construction
- SSL and SASL authentication
- Schema-Browsing
It is a pity, that it does not support {crypt} encryption, so you have to use another LDAP-Tool if you have to reset a Userpassword, but apart from this fact it is one of the best browsers.
[edit] Phpldapadmin
A good choice is phpldapadmin. The Apache configuration is beyond the scope of this document. The default configuration is just OK so go to the http://localhost/phpldapadmin/ and login using the admin account.
If you started phpldapadmin before adding the sudo schema, delete all php sessions (phpldapadmin stores all schema in session and is not smart enough to reload it) and import following ldif:
| Code: SUDO ldif |
dn: ou=sudoers,dc=.... ou: sudoers objectClass: organizationalUnit objectClass: top |
[edit] Migration
You can either use the existing structure by migrating it to the proper format with migrationtools, or create a blank template by hand. Either way, you'll end up with an LDIF template.
Open migrate_common.ph and edit the following:
$DEFAULT_BASE = "dc=mydomain,dc=org"; $EXTENDED_SCHEMA = 1; # Comment these lines out unless you have a mail schema loaded #$DEFAULT_MAIL_DOMAIN = "mydomain.org"; #$DEFAULT_MAIL_HOST = "mail.mydomain.org";
Now run the migration scripts:
# export ETC_SHADOW=/etc/shadow # cd /usr/share/migrationtools # ./migrate_base.pl > /tmp/base.ldif # ./migrate_group.pl /etc/group /tmp/group.ldif # ./migrate_hosts.pl /etc/hosts /tmp/hosts.ldif # ./migrate_passwd.pl /etc/passwd /tmp/passwd.ldif
You probably do not want (local) root or non-person users to your LDAP, so edit the passwd.ldif file and remove the entries you do not like.
posixAccount does not accept UTF-8 gecos fields. This is a huge problem is some countries, and should be fixed by editing nis.schema:
| File: nis.schema.diff |
--- nis.schema~ 2007-05-03 16:45:29.000000000 +0600
+++ nis.schema 2007-05-03 16:45:51.000000000 +0600
@@ -48,9 +48,9 @@
attributetype ( 1.3.6.1.1.1.1.2 NAME 'gecos'
DESC 'The GECOS field; the common name'
- EQUALITY caseIgnoreIA5Match
- SUBSTR caseIgnoreIA5SubstringsMatch
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+ EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
attributetype ( 1.3.6.1.1.1.1.3 NAME 'homeDirectory'
DESC 'The absolute path to the home directory'
|
| Note: This disagree with RFC 2307, and some programs may not work properly, but who cares :)? |
You can import the template from the web interface or from the command line:
# ldapadd -D "cn=admin,dc=mydomain,dc=org" -W -f <template_file>
Note: If you didn't install the SSL sertificates, you may disable security check and use the -x switch.
[edit] Creating new users
Next step is to create users. The following attributes need to be set for the NSS module to work.
- uid
- uidNumber
- gidNumber - the respective group also has to be set
There's a handy package called ldapscripts (in Debian - on Gentoo the package exists in the layman portage overlay sunrise) with which adding users to LDAP is similar to creating POSIX accounts.
Edit /etc/ldapscripts/ldapscripts.conf. On Gentoo, the package installation didn't initialize the LDAP database for you, thus you need to manually run (with slapd running):
# _ldapinit
Add a new user:
# ldapadduser newuser users
which will create the minimal structure for the ldapscripts in the database. The users can then change their password with the command:
$ ldappasswd -x -W -S -D "uid=$(whoami),ou=People,dn=...."
[edit] Example LDAP layout LDIF
Here is an example ldif, if you don't want to use migrationtools:
| Code: small but complete ldif for testing |
dn: dc=myserver,dc=mydomain,dc=org
dc: myLdapServer
objectClass: top
objectClass: domain
objectClass: domainRelatedObject
associatedDomain: mydomain.org
dn: ou=People,dc=myserver,dc=mydomain,dc=org
ou: People
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain.org
dn: ou=Group,dc=myserver,dc=mydomain,dc=org
ou: Group
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain.org
dn: cn=users,ou=Group,dc=myserver,dc=mydomain,dc=org
objectClass: posixGroup
objectClass: top
cn: users
userPassword: {crypt}x
gidNumber: 100
|
Add the schema:
ldapadd -x -D "cn=admin," -W -f test.ldif
Remove the test user:
ldapdelete "uid=myuser,ou=People," -x -D "cn=admin," -W
If you defined a BASE, you can leave off the base definition here, and use a plain comma instead.
Set desired username and uid (I'm using uid == 1000 + lastipoctet). You will be able to set initial password to the user using phpldapadmin. New users can be copied from the existing one via phpldapadmin. Pay attention at the host field - it specifies list of hosts where this user is allowed to login.
Now you can start adding sudo rules with almost the same format as /etc/sudoers:
| Code: SUDO entry |
dn: cn=iced,ou=sudoers,dc=iowg cn: iced sudoCommand: ALL sudoHost: ALL sudoUser: iced objectClass: sudoRole objectClass: top Note: You can add sudoOption: !authenticate if you wish to allow a user to use sudo without secondary authentication, however this is not recommended for any entry which grants root privileges. |
[edit] Clients
Some setup is necessary on client side (including server itself). Some packages for start:
# emerge pam_ldap nss_ldap openldap
[edit] Configuration
You should have a file called /etc/openldap/ldap.conf. This file tells the client programs from the openldap package (ldapsearch, ldapadd, ...) which server it should connect to. Don't confuse this one with /etc/ldap.conf (/etc/libnss-ldap.conf) which is for the pam_ldap and nss_ldap packages from padl.com.
Here we use TLS in a standard LDAP port. LDAP is a standard, and not less secure given that TLS is configured properly. The client and server establish TLS before any LDAP messages are transferred (without a Start TLS operation). The LDAPS connection must be closed upon TLS closure.
This file configures the NSS/PAM modules:
| File: /etc/ldap.conf or /etc/libnss-ldap.conf |
host myserver.mydomain.org uri ldap://myserver.mydomain.org base dc=mydomain,dc=org ldap_version 3 ssl on ssl start_tls rootbinddn cn=admin,dc=... scope sub bind_policy soft TODO: add definition for binduser pam_password exop pam_filter objectclass=posixAccount pam_login_attribute uid pam_member_attribute memberUid pam_check_host_attr yes nss_base_passwd ou=users,dc=... nss_base_shadow ou=users,dc=... nss_base_group ou=groups,dc=... |
Bind_policy is necessary to be set to 'soft' to prevent system boot failure due to udev looking for ldap server before network startup.
Modify your /etc/pamd.d/system-auth file to use ldap too so that all other files including it use ldap. This enables for example kdm,login and sshd to use ldap. With following construction you can avoid problems with duplicated accounts in ldap, and system files.
| File: /etc/pam.d/system-auth |
#%PAM-1.0 auth required pam_env.so auth [success=ignore default=1] pam_localuser.so auth [success=done new_authtok_reqd=done default=1] pam_unix.so likeauth nullok try_first_pass auth sufficient pam_ldap.so try_first_pass auth required pam_deny.so account sufficient pam_unix.so account sufficient pam_ldap.so password required pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 retry=3 password sufficient pam_unix.so nullok md5 shadow use_authtok password sufficient pam_ldap.so use_authtok password required pam_deny.so session required pam_limits.so session required pam_unix.so #Creates the home directories if they do not exist session required pam_mkhomedir.so skel=/etc/skel/ umask=0022 session optional pam_ldap.so |
Enable LDAP searches for the NSS module:
| File: /etc/nsswitch.conf |
passwd: compat db ldap shadow: compat db ldap group: compat db ldap |
For SUDO configuration, gentoo uses /etc/ldap.conf.sudo. Be sure to configure this file, otherwise you'll end up ripping out your hair for some time like i did....
Emerge package sudo with USE flag ldap, if you want file ldap.conf.sudo installed.
| File: /etc/ldap.conf.sudo |
# See ldap.conf(5) and README.LDAP for details
# This file should only be readable by root
# supported directives: host, port, ssl, ldap_version
# uri, binddn, bindpw, sudoers_base, sudoers_debug
# tls_{checkpeer,cacertfile,cacertdir,randfile,ciphers,cert,key}
suffix dc=mydomain,dc=org
sudoers_base ou=sudoers,dc=mydomain,dc=org
host 127.0.0.1
|
[edit] Using offline authentication
To use offline authentication for ldap users, in case if server is down, or if you are using laptop out of network, it is needed to install in your client station:
# emerge sys-libs/nss-db sys-auth/nss_updatedb sys-auth/pam_ccreds
Some of these packages you can find in swegener overlay.
Then change configuration files:
Set nsswitch.conf to use system files, then ldap, and then if cannot use ldap, local copy of ldap base in db.
| File: /etc/nsswitch.conf |
passwd: files ldap [NOTFOUND=return] db shadow: files ldap [NOTFOUND=return] db group: files ldap [NOTFOUND=return] db |
Set system auth to use pam_unix for local users, or ldap/copy of passwords for LDAP users.
There is a restriction for LDAP uids, all users with uid > 10000 are assumed as LDAP users.
| File: /etc/pam.d/system-auth |
#%PAM-1.0 auth required pam_env.so auth [success=ignore default=1] pam_localuser.so auth [success=done new_authtok_reqd=done default=die] pam_unix.so likeauth nullok shadow auth [authinfo_unavail=1 success=ignore default=2] pam_ldap.so auth [default=done] pam_ccreds.so action=store use_first_pass auth [success=done default=die] pam_ccreds.so action=validate use_first_pass auth [default=ignore] pam_echo.so Delete cached password auth [default=bad] pam_ccreds.so action=update auth required pam_deny.so account [authinfo_unavail=ignore user_unknown=ignore default=done] pam_unix.so account sufficient pam_localuser.so account [success=ignore default=1] pam_succeed_if.so uid > 10000 account [authinfo_unavail=ignore default=done] pam_ldap.so account sufficient pam_permit.so password required pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 try_first_pass retry=3 password sufficient pam_unix.so nullok use_authtok shadow md5 try_first_pass password sufficient pam_ldap.so use_authtok use_first_pass password required pam_deny.so session required pam_limits.so session required pam_unix.so session required pam_mkhomedir.so skel=/etc/skel/ umask=0066 session optional pam_ldap.so |
The last step is regular update of local copy of ldap base. It can be performed using cron job, for example using following file:
| File: /etc/cron.daily/nss_updatedb |
#!/bin/bash /usr/sbin/nss_updatedb ldap |
