Installing OpenLDAP on Solaris9

OpenLDAP requires certain other software to compile and install. For TLS/SSL capability I chose to install OpenSSL. This may not be acceptable to some people due to license issues. I chose to use BerkeleyDB as the back-end to OpenLDAP, we are already using the Sleepycat software on other servers so it seemed a natural choice. There are other alternatives to this backend. I also installed cyrus-sasl as SASL is now required by the LDAPv3 standard. So far I haven't experimented with SASL authentication.

OpenSSL:

(version 0.9.7b)

requires a working bc which was not available on initial 'NERC' Solaris. Downloaded gnu bc and then:

setup gcc

NOTE: this sets the environment variable LD_LIBRARY_PATH to point to gcc libraries /nerc/packages/gcc/<version>/lib and /nerc/packages/gcc/<version>/lib/sparcv9

./configure
make timetest

this threw up some warnings about implicit declarations

make
make install (as root and csh)

installing OpenSSL

setup gcc
./Configure solaris-sparcv9-gcc shared
make
make test
make install (as root)

testing the linking as suggested in the documentation:

LD_LIBRARY_PATH=/usr/lib ldd /usr/local/ssl/lib/libssl.so

does not work in this case unless:

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/ssl/lib ldd /usr/local/ssl/lib/libssl.so

Sleepycat db4

(version 4.1.25)

downloaded Berkeley DB4 from Sleepycat software (think I applied the patch for locking available here: http://www.sleepycat.com/update/4.1.25/patch.4.1.25.html)

Note that it does not install into /usr/local as expected but to /usr/local/BerkeleyDB-X therefore use the --prefix option to configure.

setup gcc
export CC=gcc
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/ssl/lib
cd db-4.1.25/build_unix
../dist/configure --prefix=/usr/local --enable-shared
make
make install (as root)

Cyrus SASL

(version 2.1.13, note that libs have version number 2.0.13 for some reason)

./configure --with-openssl=/usr/local/ssl --disable-krb4 --disable-gssapi
make
make install (as root)
cd /usr/lib
ln -s ../local/lib/sasl2 sasl2

This last step is important, don't forget it!

note: as yet I have not tested any SASL capabilities as I have been more interested in getting TLS encryption working with simple authentication. It may be useful to use SASL in future for extra security, for instance when authenticating against the directory as a directory administrator or for replication.

OpenLDAP

(version 2.1.21)

note: version 2.1.22 is reported to be faster when using a bdb backend.

This software should be compiled on a local disk if you want to run the tests before installation. BDB does not work over NFS and therefore OpenLDAP will not be able to start up the database. Also, "make install" changes stuff in the tree and so there could be permissions problems due to root being mapped to user nobody on a NFS mount.

apply this patch (I think it creates a workaround for a bug in solaris that makes a certain attribute [nismapname?] case sensitive which is contrary to the standard - patch based on version 2.1.20 but applies pretty cleanly to 2.1.21 and 2.1.22):

*** servers/slapd/result.c.orig Thu Feb 27 12:52:50 2003
--- servers/slapd/result.c      Thu Feb 27 12:55:07 2003
***************
*** 879,885 ****
                if ( attrs == NULL ) {
                        /* all attrs request, skip operational attributes */
                        if( is_at_operational( desc->ad_type ) ) {
!                               continue;
                        }
  
                } else {
--- 879,888 ----
                if ( attrs == NULL ) {
                        /* all attrs request, skip operational attributes */
                        if( is_at_operational( desc->ad_type ) ) {
!
!                               if (strcasecmp( e->e_dn, LDAP_ROOT_DSE )) {
!                                       continue;
!                               }
                        }
  
                } else {
***************
*** 1074,1080 ****
                if ( attrs == NULL ) {
                        /* all attrs request, skip operational attributes */
                        if( is_at_operational( desc->ad_type ) ) {
!                               continue;
                        }
  
                } else {
--- 1077,1087 ----
                if ( attrs == NULL ) {
                        /* all attrs request, skip operational attributes */
                        if( is_at_operational( desc->ad_type ) ) {
!
!                               /* Hack for Solaris */
!                               if (strcasecmp( e->e_dn, LDAP_ROOT_DSE )) {
!                                       continue;
!                               }
                        }
  
                } else {

ie
cd openldap-2.1.21; gpatch -p0 < patchfile

setup gcc
export CC=gcc
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/ssl/lib:/usr/local/lib
export LDFLAGS="-L/usr/local/ssl/lib -L/usr/local/lib -R/usr/local/ssl/lib:/usr/local/lib"
export CPPFLAGS="-I/usr/local/ssl/include -I/usr/local/include"

./configure --with-cyrus-sasl --with-tls --enable-crypt
make depend

make
make test
make install (as root)

Now you need to setup the server. With the configuration options above, the configuration file for slapd will be in /usr/local/openldap/etc.

Configuration

Schema:

I used the following to include the relevant schema files:

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/etc/openldap/schema/locking.schema
include /usr/local/etc/openldap/schema/solaris.schema
include /usr/local/etc/openldap/schema/DUAConfig.schema
include /usr/local/etc/openldap/schema/amd.schema
include /usr/local/etc/openldap/schema/automount.schema

(amd is the BSD automounter and is not used here therefore amd schema is not needed)

DUAConfig provides the schema for profiles

nis provides the nisObject type schema

solaris provides the schema needed for Solaris specific objects

automount is the newer(?) schema for autofs used by Sol9 and Debian(testing), RedHat searches using both schema so can be accommodated either way.

Access Control:

Whilst debugging the installation, disable all access control and allow read access to * by * Afterwards I configured access control like this:

# rule one
# Solaris need anon access to rootDSE
access to dn=""
 by peername=127.0.0.1 read
 by peername=192.168.99.* read
 by dn.exact="cn=proxyagent,ou=profile,dc=your,dc=base read"
 by * none

Solaris searches the rootDSE to find the capabilities of the server (e.g. supported sasl mechanisms) before it does anything else.

# rule two
# Solaris needs anon access to base
access to dn.base="dc=your,dc=base"
 by peername=127.0.0.1 read
 by peername=192.168.99.* read
 by dn.exact="cn=proxyagent,ou=profile,dc=your,dc=base" read
 by * none

Solaris searches for nisDomain which is the base of the directory

# rule three
# allow users to change own passwords
# allow authentication and proxyagent to read passwords
access to attr=userPassword
 by self write
 by anonymous auth
 by dn.exact="cn=proxyagent,ou=profile,dc=your,dc=base" read
 by * none

Restrict access to user passwords. This allows users to change their own passwords. Note users are anonymous until they are authenticated therefore need to allow anonymous users to authenticate against the password entry. The proxy agent needs access to the user password. Note that this may be too restrictive as PAM (and therefore the proxyagent) may need write access to the password, this needs to be investigated.

# rule four
# restrict access to solaris profiles
#access to dn.subtree="ou=profile,dc=your,dc=base"
# by peername=127.0.0.1 read
# by peername=192.168.99.* read
# by dn.exact="cn=proxyagent,ou=profile,dc=your,dc=base" read
# by * none

This is a bit paranoid as there is no password or other sensitive information stored in the profiles. Credentials are stored locally on the clients.

# rule 4.5
# restrict write access to sensitive rdns
access to attr=userid,cn,uidnumber,gidnumber,homedirectory
 by peername=127.0.0.1 read
 by peername=192.168.99.* read
 by dn.exact="cn=proxyagent,ou=profile,dc=your,dc=base" read
 by * none

users should not be allowed to alter the above attributes. Any changes to these attributes should be done by a directory administrator

# rule five
# allow authenticated users to add modify and delete in own subtree
access to dn.children="ou=people,dc=nerc-wallingford,dc=ac,dc=uk"
 by self write

 by dn.exact="cn=proxyagent,ou=profile,dc=your,dc=base" read
 by * none

This should allow users to add and/or modify information to their entry such as phone numbers, email addresses etc. however, it is not extensively tested.

# rule six
# allow unencrypted access to autofs info
access to dn.subtree="nisMapName=*,dc=nerc-wallingford,dc=ac,dc=uk"
 by ssf=1 read

This lowers the security strength to allow searching of nisMaps, needed for Linux autofs if you set a higher default security strength factor elsewhere.

access to * by * read

catchall... probably not needed but testing is ongoing

Database backend

I'm using the Sleepycat DB4 backend as mentioned in the software section. In this part of the configuration file you need to define the suffix of the directory and the administrator settings

suffix “dc=your,dc=suffix”

rootdn “cn=manager,dc=your,dc=suffix”

rootpw {SHA1}<passwordhash>

or whatever cipher you want to use. Also define where you want your db files to be stored:

database /var/openldap

This may not be an ideal place, the directory should be on a separate disk to the log files. Also in this section, the TLS configuration commands. See later in the doc for these.

Indexing

Indexing will greatly improve the performance of the server but too much indexing will start to diminish performance as indices have to be maintained. OpenLDAP requires that objectClass be indexed but it is also useful to include the following which have been grokked from watching the debug output running slapd with a -d64 debug level. This reports when a search is made that isn't indexed.

index uid eq
index uidnumber eq
index gidnumber eq
index memberuid eq
index ipnetworknumber eq
index cn pres,eq,sub
index sn pres,eq,sub
index objectClass eq
index nisdomain eq
index nismapname eq
index iphostnumber eq
index ipserviceprotocol eq
index ipserviceport eq
index ou eq

I occasionally see a message complaining about uniqueMember not being indexed but slapd does not tolerate an index for this attribute.

Populate directory:

I actually used the iPlanet database as a skeleton but it is simple to create the proper organisational units required and some example LDIF is given below. The iPlanet one is created when you initialise it using idsconfig. Essentially you need to create organisationalUnits for people, group, networks, etc. It is useful to create a profile ou for storing Solaris profiles generated by the ldapclient command:

dn: ou=profile,dc=your,dc=base
ou: profile
objectClass: top
objectClass: organizationalUnit

here is a proxyagent used for binding to the server during authentication:

dn: cn=proxyagent,ou=profile,dc=your,dc=base
cn: proxyagent
sn: proxyagent
objectClass: top
objectClass: person
userPassword: <hashed password>
Solaris profiles can be generated by using the ldapclient command:

ldapclient genprofile \
-a profilename=<profilename> \
-a defaultsearchbase=<basedn> \
-a authenticationmethod=<tls:simple,tls:sasl,simple etc> \
-a credentiallevel=proxy \
192.168.99.99

This is a different syntax Solaris 8. This will produce a basic profile, other arguments can be added to make a more specific profile or extra attributes can be added later directly to the directory. The resulting LDIF output can then be added to the directory.

Here is a sample solaris 9 profile (version 2) using simple authentication and some mapping so that it uses nisMap and nisObject type searches rather than automount and automountMap:

dn: cn=melvin-sol9,ou=profile,dc=your,dc=base
objectClass: top
objectClass: DUAConfigProfile
defaultServerList: 192.168.99.99
defaultSearchBase: dc=your,dc=base
cn: melvin-sol9
credentialLevel: proxy
followReferrals: true
serviceSearchDescriptor: auto_master:nismapname=auto_master,dc=your,dc=base
objectclassMap: automount:automountMap=nisMap
objectclassMap: automount:automount=nisObject
attributeMap: automount:automountMapName=nisMapName
attributeMap: automount:automountInformation=nismapentry
attributeMap: automount:automountKey=cn
authenticationMethod: simple

here is a sample Solaris 8 profile (version1), note the differences:

dn: cn=default-sol8,ou=profile,dc=your,dc=base
SolarisBindDN: cn=Proxyagent,ou=profile,dc=your,dc=base
SolarisBindPassword: password
SolarisLDAPServers: 192.168.99.99
SolarisSearchBaseDN: dc=your,dc=base
SolarisAuthMethod: NS_LDAP_AUTH_SIMPLE
SolarisTransportSecurity: NS_LDAP_SEC_NONE
SolarisSearchReferral: NS_LDAP_FOLLOWREF
SolarisSearchScope: NS_LDAP_SCOPE_ONELEVEL
SolarisSearchTimeLimit: 30
SolarisCacheTTL: 43200
cn: default-sol8
objectClass: top
objectClass: SolarisNamingProfile

version 1 profiles cannot map attributes and cannot define encryption methods.

Use the PADL migration tools that come with RedHat or can be downloaded from their website to migrate the flat files. The passwd migration has to be tweaked as Solaris requires the shadowAccount objectClass to be set. Simply add in

print $HANDLE "objectClass: shadowAccount\n";

along with the other objectClass definitions.
ypcat passwd > passwd
/usr/share/openldap/migration/migrate_passwd.pl passwd > passwd.ldif

etc

then, depending on whether you are using OpenLDAP or Solaris tools:

ldapadd -x -h host -b basedn -D managerdn -w password -f passwd.ldif

(-x turns off SASL)

or

ldapadd -h host -b basedn -D managerdn -w password -f passwd.ldif

Remember to use the -k option to ypcat(1) when converting automount maps in order to see the key.

Encrypted Sessions

It is good practice to reduce exposure of passwords as much as possible even if they are store encrypted (as is standard on UNIX-like systems). During a simple authentication to the slapd server, the user password is visible on the wire – just as it is when using NIS. This is to be avoided and so it would be preferable to take advantage of the encryption opportunities of TLS/SSL. This is of course a very big subject which won't be covered in full here.

TLS is the new name for SSLv3. It is exactly the same protocol but with a new name. You may not find this information on the web so I put it here. More accurately - TLSv1 is the standardised successor to SSLv3, SSL being a proprietry protocol from Netscape, TLS is the version standardised by the IETF. LDAP over TLS/SSL is usually on a seperate port from unencrypted LDAP and is known as ldaps://. This uses "out of band" encryption, in other words the LDAP session is run over a secure tunnel that has been negotiated out of band. OpenLDAP can use the "startTLS" extended operation to negotiate an encrypted tunnel in band. Therefore an existing LDAP connection can negotiate to switch to an encrypted session. This extended operation is not yet widely supported by other applications. A clear summary is available here.

Linux clients are based on PADL modules and as such rely on a configuration file usually stored under /etc but if you are compiling these yourself you can specify anywhere for these configuration files. On RedHat, the configuration file for these modules is somewhat confusingly called /etc/ldap.conf. This is a source of major confusion amongst people setting up clients for the first time. The OpenLDAP configuration file is /etc/openldap/ldap.conf and the PADL configuration file is /etc/ldap.conf. On Debian(sarge) it is slightly clearer, the PADL configuration files are /etc/pam_ldap.conf and /etc/libnss-ldap.conf and the OpenLDAP configuration file is /etc/ldap/ldap.conf. Debian has a much better man page for all the options possible for these files.

I will describe here how to set up a simple encryption scheme between client and server. I will not go into client authentication as I haven't implemented that.

In simple terms:

  1. The client requests a session with the server

  2. The server provides a copy of its own certificate

  3. The client uses that certificate to encrypt and decrypt traffic to and from the network

  4. The server uses its private key associated with the certificate to encrypt and decrypt traffic to and from the network

Additionally, the client may authenticate the server certificate. This is the case for clients based on OpenLDAP software. This means that the servers certificate has to be signed by a certificate authority (CA) and the client must have a copy of the CA's public certificate.

Set up a CA

OpenSSL can be used to setup a private CA. This is described at this site but I will also outline it here. OpenSSL comes with some tools including some scripts to make certificate generation easier, these are called /usr/local/ssl/misc/CA.sh and CA.pl

Make a directory for your CA

cd /var/myca

CA.sh -newca

create a new certificate and fill in the blanks as requested. It is important to fill these in with meaningful entries as this certificate will be publicly readable and installed on the client machines. It will also be visible as the server negotiates the encrypted session and is used when debugging problems.

TIP: to change certificate lifetime (or other options) set environment variable SSLEAY_CONFIG eg:

export SSLEAY_CONFIG="-days 730"

for a 2 year certificate. Tried changing this option directly in CA script but it didnt seem to have much effect. The above method does work.

Create a server certificate

now create a certificate request, this process is similar but the most important thing to remember is that the cn of the certificate must be the FQDN of the server. The certificate will be rejected if these do no match.

CA.sh -newreq

or

openssl req -new -nodes -keyout newreq.pem -out newreq.pem

the -nodes option remove the need for a passphrase but if you use the CA script you will have to remove the passphrase later. Do not put in a challenge password. Now sign the certificate request:

CA.sh -sign

If you need to remove the passphrase:

openssl rsa -in newreq.pem -out slapd-key.pem

to remove it and strip the certificate request then:
mv newcert.pem slapd-cert.pem

now you have a server certificate and its corresponding key. Note the key should be fully protected as with all private keys and should have permissions to reflect this. Next configure slapd to use the relevant certificates by using the following entries in slapd.conf:

TLSCACertificateFile /usr/local/etc/openldap/cacert.pem
TLSCertificateFile /usr/local/etc/openldap/slapd-cert.pem
TLSCertificateKeyFile /usr/local/etc/openldap/slapd-key.pem

where cacert.pem is the CA certificate, a copy of which should be installed on the clients that will use it.

Client Configuration

Files that are not directly affecting/affected by client configuration but which may also need examining and/or tweaking:

/etc/pam.conf or /etc/pam.d/*
/etc/auto_master or /etc/auto.master
/etc/hosts

Remeber to set up ldap.conf for the client applications (e.g. ldapsearch). This configuration file can be in various places depending on the compilation options, these include /etc/openldap/ldap.conf,/etc/ldap/ldap.confand/usr/local/etc/openldap/ldap.conf. Set HOST or URI to point to the server with the same name as is in the certificate so that -ZZ option will work. Don't confuse this file with the configuration file for the pam_ldap and nss_ldap modules which has the same name by default (RedHat ships like this) and is usually /etc/ldap.conf.

Solaris

(Tested on Solaris8 and Solaris9 - versions earlier than 8 will not work as clients)
Solaris clients are configured using the ldapclient(1M) command. If you have set up profiles as described above then the following command will download the profile and configure the client:

ldapclient init -a profilename=spiffy-profile \
-a domainname=foo.bar.com \
-a proxydn=cn=proxyagent,ou=profile,dc=your,dc=base \
-a proxypassword=eatmyshorts \
192.168.99.99

The proxypassword argument can be omitted in which case it is prompted for.

And... REBOOT. Yes I know it sucks but its the only reliable way I've found to get everything working properly, perhaps its possible to restart every affected daemon... As an example - after a ldapclient init command it is not possible to login on the console until after a reboot, perhaps restarting xdm (or whatever it is on Solaris) would solve this? Also worth noting is the possibilities of lock out especially if attempting this remotely. Make sure you can login as root over ssh before you reboot.

Beware of using this utility to modify the profile, it should only be used when the profile has been setup manually, also "ldapclient mod", tends to delete /etc/nsswitch.conf and occasionally /etc/defaultdomain. You have been warned.

With the application of patch 108993-xx (xx >= 14) to Solaris 8, the LDAP capabilities of the Solaris 9 client are backported. This means that a Solaris 8 client can use the same profile as a Solaris 9 client. Note however that ldapclient(1M) still uses the old syntax which has been changed considerably in Solaris 9.

Files changed by ldapclient:

/etc/nsswitch.conf
/etc/defaultdomain
/var/yp/binding/<nisdomain>
/var/ldap/ldap_client_file
/var/ldap/ldap_client_cred

At the moment, the /var/ldap/ldap_client_* files are in plaintext but Sun does not guarantee that this will remain the case so it is wise to get used to using ldapclient(1M) and/or profiles to maintain and examine these files.

Remember - if using encryption, will also need to change /etc/hosts to hold the exact name of the server(s) as given in by the cn in the server certificate.

Linux

(Tested on RedHat9 and Debian-sarge)
On RedHat, should be able to use authconfig(8) or authconfig-gtk to setup LDAP client authentication, however, I haven't tested this very well and I don't see an obvious way of telling the client where to find the CA certificate or how to use a proxyagent. Therefore you may have to do a bit of manual configuration afterwards. Here is a sample /etc/ldap.conf file for configuring pam_ldap:

host your.slapd.server
base dc=your,dc=base
rootbinddn cn=proxyagent,ou=profile,dc=your,dc=base
pam_password crypt

for encryption options see the later section. The password for the proxyagent is stored in /etc/ldap.secret in plain text so apply stringent permissions to it. Also configure /etc/openldap/ldap.conf for ldap comand line tools:

host your.server.com
base dc=your,dc=base

other files to check:

/etc/nsswitch.conf
/etc/pam.d/*
/etc/hosts

make sure the ip address of the server is resolvable and if using TLS, that it matches the cn in the certificate.

All of the above is also relevant to Debian. Make sure you have the following packages installed:

libldap2
libldap2-tls
libnss-ldap
libpam-ldap
ldap-utils
autofs
autofs-ldap
portmap (needed for autofs and nfs)
nfs

Note: Debian has superior man pages for ldap related topics. Also the configuration files are seperated more logically. The openldap configuration file is /etc/ldap/ldap.conf, the PADL pam module configuration file is /etc/pam_ldap.conf and the PADL nss module configuration file is /etc/libnss-ldap.conf. Make sure to adjust settings in each one to avoid authentication information travelling over the network in the clear.

Irix

(Tested on 6.5.14f)
Irix is pretty easy to set up although I had a niggling problem in the ldap.conf file which turned out to be non-printable characters in one of the lines. I think they were introduced when cutting and pasting from one editor to another.

The configuration for LDAP on Irix is in one file /var/ns/ldap.conf.  No encryption is possible at the time of writing (Aug 2003). Irix caches all name service information in /var/ns/cache and once configured the only file that matters is /etc/nsswitch.conf. Use nsadmin(1M) to control the name service daemon (nsd), flush and restart after every change:

nsadmin flush
nsadmin restart

also,

nsadmin cat passwd
nsadmin cat shadow

to check the cached files. Here is part of /var/ns/ldap.conf note comments can start with ';' or '#':

security        ssl     ; none, ssl
cipher          RSA_RC4_40_MD5

these options have no meaning and do not work. Presumably they are for future enhancements to the ldap client.

base    "dc=your,dc=base"
scope   subtree         ; subtree, onelevel, sbase
binddn  "cn=proxyagent,ou=profile,dc=your,dc=base"
bindpwd "<clear text password>
regsub USERPASSWORD{{crypt\}|{CRYPT\}}{}

Irix doesn't like having the {CRYPT} before the crypted password so this strips out both {CRYPT} and {crypt}. Note that the '}' has to be escaped. This option is only documented in later releases.

; SCHEMA DEFINITION
table           passwd.byname
filter_lookup   (&(OBJECTCLASS=POSIXACCOUNT)(UID=%s))
filter_list     (OBJECTCLASS=POSIXACCOUNT)
format          "UID:**:UIDNUMBER:GIDNUMBER:GECOS:HOMEDIRECTORY:LOGINSHELL"
                                                                               
table           passwd.byuid
filter_lookup   (&(OBJECTCLASS=POSIXACCOUNT)(UIDNUMBER=%s))
format          "UID:**:UIDNUMBER:GIDNUMBER:GECOS:HOMEDIRECTORY:LOGINSHELL"

The USERPASSWORD is replaced with * as we are using shadow passwords (HINT: use pwconv to enable shadow passwords).

table           shadow.byname
filter_lookup   (&(OBJECTCLASS=SHADOWACCOUNT)(UID=%s))
filter_list     (OBJECTCLASS=SHADOWACCOUNT)
require         USERPASSWORD
format          "UID:USERPASSWORD:SHADOWLASTCHANGE:SHADOWMIN:SHADOWMAX:SHADOWWARNING:SHADOWINACTIVE:SHADOWEXPIRE:SHADOWFLAG"

shadowPassword entry. Note the requirement for USERPASSWORD. Other entries that may need to be added/altered are the automount entries.

The configuration file is quite flexible and can generate ldapsearch type requests for any objects you wish as long as you can get the syntax right. Here is an example of automount maps using the nisObject objectclass:

table           auto.data
filter_lookup   (&(OBJECTCLASS=NISOBJECT)(NISMAPNAME=auto.data)(CN=%s))
filter_list     (&(OBJECTCLASS=NISOBJECT)(NISMAPNAME=auto.data))
format          "CN\tNISMAPENTRY"

I am using flat file /etc/auto_master or /etc/auto.master files on client hosts as these can have differences dependent on architecture, these master files can then point at a combination of maps available on the LDAP server or locally.

Note that from Irix 6.5.20, OpenLDAP 2.1.12 comes with it so that ldap client tools such as ldapsearch etc are installed as part of the system. For earlier versions it should be possible to install the package, if not then compile OpenLDAP client tools manually. I have heard that for versions earlier than about 6.5.7, ldap doesn't really work at all.

PAM:

At first I thought that Solaris (at least version 8) would need the PADL security modules in order to interoperate with OpenLDAP and use TLS so I tried using the PADL pam and nss modules but had little success with these and reverted to the native solaris modules. With the patch mentioned above, Solaris 8 and 9 are able to work with OpenLDAP server and use the native pam and nss modules making use of TLS/SSL. This configuration has not been extensively tested especially with regard to account management etc.

On Solaris the following /etc/pam.conf file is used to enable authentication over LDAP:
(NOTE: seems pam_ldap only really needed if using SASL, pam_unix is able to do tls:simple auth)

#
# Authentication management
#
# login service (explicit because of pam_dial_auth)
#
login auth required pam_authtok_get.so.1
login auth required pam_dhkeys.so.1
login auth required pam_dial_auth.so.1
login auth sufficient pam_unix_auth.so.1
login auth required pam_ldap.so.1 try_first_pass
#
# rlogin service (explicit because of pam_rhost_auth)
#
rlogin auth sufficient pam_rhosts_auth.so.1
rlogin auth required pam_authtok_get.so.1
rlogin auth required pam_dhkeys.so.1
rlogin auth sufficient pam_unix_auth.so.1
rlogin auth required pam_ldap.so.1 try_first_pass
#
# rsh service (explicit because of pam_rhost_auth)
#
rsh auth sufficient pam_rhosts_auth.so.1
rsh auth required pam_authtok_get.so.1
rsh auth required pam_dhkeys.so.1
rsh auth sufficient pam_unix_auth.so.1
rsh auth required pam_ldap.so.1 try_first_pass
#
# PPP service (explicit because of pam_dial_auth)
#
ppp auth required pam_authtok_get.so.1
ppp auth required pam_dhkeys.so.1
ppp auth required pam_dial_auth.so.1
ppp auth sufficient pam_unix_auth.so.1
ppp auth required pam_ldap.so.1 try_first_pass
#
# Default definitions for Authentication management
# Used when service name is not explicitly mentioned for authenctication

#
other auth required pam_authtok_get.so.1
other auth required pam_dhkeys.so.1
other auth sufficient pam_unix_auth.so.1
other auth required pam_ldap.so.1 try_first_pass
#
# passwd command (explicit because of a different authentication module)

#
passwd auth sufficient pam_passwd_auth.so.1
passwd auth required pam_ldap.so.1 try_first_pass
#
# cron service (explicit because of non-usage of pam_roles.so.1)
#
cron account required pam_projects.so.1
cron account required pam_unix_account.so.1
#
# Default definition for Account management
# Used when service name is not explicitly mentioned for account management
#
other account requisite pam_roles.so.1
other account required pam_projects.so.1
other account required pam_unix_account.so.1
#
# Default definition for Session management
# Used when service name is not explicitly mentioned for session management
#
other session required pam_unix_session.so.1
#
# Default definition for Password management
# Used when service name is not explicitly mentioned for password management
#
other password required pam_dhkeys.so.1
other password required pam_authtok_get.so.1
other password required pam_authtok_check.so.1
other password sufficient pam_authtok_store.so.1
other password required pam_ldap.so.1
#
# Support for Kerberos V5 authentication (uncomment to use Kerberos)
#
#rlogin auth optional pam_krb5.so.1 try_first_pass
#login auth optional pam_krb5.so.1 try_first_pass
#other auth optional pam_krb5.so.1 try_first_pass
#cron account optional pam_krb5.so.1
#other account optional pam_krb5.so.1
#other session optional pam_krb5.so.1
#other password optional pam_krb5.so.1 try_first_pass

Linux uses individual files in /etc/pam.d but the effect is the same.

NSS

Most of the client configuration is performed by altering /etc/nsswitch.conf. On Solaris there is a file /etc/nsswitch.ldap which can just be copied straight across. Most network services can be done via LDAP on Solaris, here is an example file:

#
# /etc/nsswitch.ldap:
#
# An example file that could be copied over to /etc/nsswitch.conf; it
# uses LDAP in conjunction with files.
#
# "hosts:" and "services:" in this file are used only if the
# /etc/netconfig file has a "-" for nametoaddr_libs of "inet" transports.

# the following two lines obviate the "+" entry in /etc/passwd and /etc/group.
passwd: files ldap
group: files ldap

# consult /etc "files" only if ldap is down.
hosts: ldap [NOTFOUND=return] files
ipnodes: files
# Uncomment the following line and comment out the above to resolve
# both IPv4 and IPv6 addresses from the ipnodes databases. Note that
# IPv4 addresses are searched in all of the ipnodes databases before
# searching the hosts databases. Before turning this option on, consult
# the Network Administration Guide for more details on using IPv6.
#ipnodes: ldap [NOTFOUND=return] files

networks: ldap [NOTFOUND=return] files
protocols: ldap [NOTFOUND=return] files
rpc: ldap [NOTFOUND=return] files
ethers: ldap [NOTFOUND=return] files
netmasks: ldap [NOTFOUND=return] files
bootparams: ldap [NOTFOUND=return] files
publickey: ldap [NOTFOUND=return] files

netgroup: ldap

automount: files ldap
aliases: files ldap

# for efficient getservbyname() avoid ldap
services: files ldap
sendmailvars: files

# role-based access control
auth_attr: files ldap
exec_attr: files ldap
prof_attr: files ldap
user_attr: files ldap

# audit
audit_user: files ldap
project: files ldap

This can obviously be tweaked to suit individual sites. I haven't done extensive testing on Linux to determine how many of the services can use LDAP as a name service.

TLS:

Once the CA certificate is installed somewhere on the Linux client it is a simple matter of configuring the PADL ldap.conf file to use TLS.

tls_cacert /etc/ssl/cacert.pem
ssl start_tls

OpenLDAP clients (Linux) can be tested by using the -ZZ flag to ldapsearch which forces TLS encryption.

ldapsearch -x -H ldap://server/ -b <basedn> -ZZ objectClass=*

Note that ldap://server/ must match the cn in the certificate.

Solaris clients behave in a slightly different way in that they don't do TLS over port 389. Instead they do encryption over the ldaps port 636. This means it is vital that the server is listening on this port, therefore, the command line for starting the server must look like this:

slapd -h “ldap:/// ldaps:///” -d9

Note the quotation marks – don't get caught out by this, without them, there will be no error message but only the first port will be opened. The -d9 option is a debugging option where:

1 trace function calls
2 debug packet handling
4 heavy trace debugging
8 connection management
16 print out packets sent and received
32 search filter processing
64 configuration file processing
128 access control list processing
256 stats log connections/operations/results
512 stats log entries sent
1024 print communication with shell backends
2048 entry parsing

(from slapd.conf(5))

The next big difference is that Solaris does not want to verify the server certificate by checking it against the CA certificate. Instead it keeps a copy of the server certificate in /var/ldap along with its other configuration files and checks against that. It stores this certificate in db format as used by Netscape and Mozilla which makes it difficult to handle. Here is a recipe that worked for me.

Create a new Netscape profile (save any bookmarks you may have in here first!):

rm -rf ~/.netscape

launch netscape (Sun say version 4 and that's the version I used but other versions may or may not work, and the same applies to Mozilla). This will recreate the .netscape directory with default files. Next, point the browser at https://<your.ldap.server>:636/ which will prompt the server to offer its certificate to the browser. Accept the certificate forever. This certificate is now stored in ~/.netscape/cert7.db. Copy cert7.db and key3.db to /var/ldap on the Solaris client. The client now has the necessary credentials for TLS encryption. Note that the key3.db file should not contain any private keys. This is not entirely satisfactory as the client is also trusting other certificates that come as defaults in netscape. I have been unsuccessful using certutil to extract just the certificate that I wanted so this will have to do for now. NOTE: I have managed to get a version of certutil that works... gurulabs have a Solaris9 package although the IPlanet libraries are needed for proper operation, this means that you can easily manipulate the certificates in the cert7.db file, change the permissions etc. Next you can initialise the client using ldapclient(1M):

ldapclient -v init \

-a domainname=your.domain.com \
-a profilename=profilename \
-a proxydn=cn=proxyagent,ou=profile,<basedn> \
-a proxypassword=password \
192.168.99.99

for a Solaris 9 client (-v flag for verbose, not actually needed) or:

ldapclient -v \

-P profilename \
-d your.domain.com \
-D cn=proxyagent,ou=profile,<base> \
-w password \
192.168.99.99

for a Solaris 8 client.

Make sure that the IP address supplied above for the slapd server corresponds to the exact cn in the server certificate (hint: use /etc/hosts)

The Automounter

The Solaris automounter is pretty well behaved and will carry out is duties with little tweaking. It is worth noting that Sun have adopted the schema which defines automountMap and automount objectclasses and the automountInformation attribute in Solaris 9 (note they also define automountKey but I haven't seen this anywhere else, this seems to correspond directly to cn) as opposed to nisMap and nisObject objectclasses and nisMapEntry and nisMapName attributes which have been used until recently by Solaris and Linux distributions. This is why the Solaris profile above has schema and attribute mapping so that the client will look for nis* information. If Solaris (>=8) and recent Linux distributions (tested Redhat9 and Debian(sarge)) are to be used exclusively then this mapping is not necessary. With patch 108993 Solaris 8 will happily use the new schema and will also be able to cope with mappings (previously not possible on Solaris 8).

The Linux automounter is a bit different. It requires anonymous access to the directory and it needs to bind to the server using the dn of the map, using ldap protocol version 2, and with no password. Therefore, the following configuration options need to be set in slapd.conf:

allow bind_v2 bind_anon_dn

note that these two options (and presumably any others) need to be entered in a single 'allow' entry otherwise only the last one parsed is recognised - there is no error or warning in the debug information. Also the Linux automounter does not honour encryption options setup on the client and therefore, the server must accept unencrypted access although this can be restricted (see ACLs above).

Redhat9 can be configured to take auto.master automount information from the server by putting the following line in /etc/nsswitch.conf

automount: ldap

however, this does not work on Debian(sarge) which must get its auto.master from a flat file but that file can then point at the ldap server using the following syntax:

/users ldap:<your.slapd.server:ou=auto.users,dc=your,dc=base

in this example the automountMap type schema is used.

Examples of the two formats for the LDIF entries are illustrated below:

dn: nisMapName=auto_master,dc=your,dc=base
nisMapName: auto_master
objectClass: top
objectClass: nisMap

dn: cn=/users,nisMapName=auto_master,dc=your,dc=base
objectClass: top
objectClass: nisObject
nisMapName: auto_master
cn: /users
nismapentry: auto_users

dn: nisMapName=auto_users,dc=your,dc=base
objectClass: top
objectClass: nisMap
nisMapName: auto_users

dn: cn=itss,nisMapName=auto_users,dc=your,dc=base
objectClass: top
objectClass: nisObject
nisMapName: auto_users
cn: itss
nismapentry: -rw,hard,timeo=10,quota,intr nfs-server:/path/to/nfs

and:

dn: ou=auto.master,dc=your,dc=base
objectClass: top
objectClass: automountMap
ou: auto.master

dn: cn=/users,ou=auto.master,dc=your,dc=base
objectClass: top
objectClass: automount
cn: /users
automountInformation: ou=auto.users,dc=your,dc=base

dn: ou=auto.users,dc=your,dc=base
objectClass: top
objectClass: automountMap
ou: auto.users

dn: cn=itss,ou=auto.users,dc=your,dc=base
objectClass: top
objectClass: automount
cn: itss
automountInformation: nfs-server:/path/to/nfs

I remain mystified as to which of these formats is the correct and future-proof way to go. Both appear in RFC2307.  The PADL migration tools use the nisObject objectclass. RedHat appear to have changed from automount to nisObject and released patches for autofs, on the other hand, Solaris appear to have changed from nisObject (in Solaris 8) to automount (in Solaris 9).

The problems encountered with automounting NFS filestores place a few restrictions on configuration. RedHat is fairly flexible in that it will search for automount maps using both schemas, Solaris can be made to search either by using mappings, Debian(sarge) only looks for automount schema definitions, Irix requires maps for everything so should be able to use either. So far untested on any other platforms. Older versions of Solaris are LDAP blind and so can be discounted, Linux comes in many flavours and may behave differently depending on implementation.

On the other hand, separate NIS maps are currently maintained for Linux and Solaris automounters as Linux does not support direct automount maps, so it may be feasible to maintain separate maps for each schema. The BSD amd automounter may be more flexible than the Linux one, it appears to have more ldap specific options and I think it supports direct maps but it requires a schema all of its own.

My own opinion is that we should adopt the automount schema as used by default on Solaris and recent Linux distributions, especially as Solaris 8 can be made to work with this schema. Other (older?) distributions can be accommodated by creating maps with the nis schema.

Problem encountered with Solaris /etc/auto_master file; I had problems using a period in automount map names, e.g. auto.users. To get around this I replace the period with an underscore and put ServiceSearchDescriptors in the ldap profile. My Solaris profile now looks (something) like this:

dn: cn=profilename,ou=profile,dc=my,dc=base
objectClass: top
objectClass: DUAConfigProfile
defaultSearchBase: dc=my,dc=base
cn: profilename
credentialLevel: proxy
followReferrals: true
objectclassMap: automount:automountMap=nisMap
objectclassMap: automount:automount=nisObject
attributeMap: automount:automountMapName=nisMapName
attributeMap: automount:automountInformation=nismapentry
attributeMap: automount:automountKey=cn
defaultServerList: 192.168.99.99
authenticationMethod: tls:simple
serviceSearchDescriptor: auto_packagessolaris:nismapname=auto.packagessolaris,
 dc=my,dc=base
serviceSearchDescriptor: auto_users:nismapname=auto.users,dc=my,dc=base
serviceSearchDescriptor: auto_data:nismapname=auto.data,dc=my,dc=base
serviceSearchDescriptor: auto_nerc:nismapname=auto.nerc,dc=my,dc=base
profileTTL: 43200

This way I can have one set of universal maps on the directory server.

Extra: I would expect it is possible to configure the server to do the relevant mapping/redirection so that only one schema and information set is needed, but I haven't yet discovered how to do this even when asking on the OpenLDAP mailing list.

Further Information

http://sapiens.wustl.edu/~sysmain/info/openldap/

http://research.imb.uq.edu.au/~l.rathbone/ldap/

http://www.openldap.org/pub/ksoper/OpenLDAP_TLS_howto.html#5.2

http://www.ypass.net/solaris8/openldap/introtoldap.html

http://ldap.akbkhome.com/?click=1055930909

http://www.openldap.org/lists/openldap-software/200208/msg00582.html

http://www.bolthole.com/solaris/LDAP.html

http://docs.sun.com/db/doc/806-5580/6jej518op?a=view

http://www.personal.psu.edu/faculty/r/b/rbf/ldap.bookmarks.html

http://ldapzone.com/

http://ldap.akbkhome.com/

http://www.cse.sc.edu/~jqu/work/systemadmin/LDAP.html

http://www.cse.sc.edu/~jqu/work/systemadmin/ldap/compile.html

http://www.netsys.com/openldap-software/2003/02/msg00202.html

http://www.linux-age.com/linux/tipps/openldap.txt