Soup To Nuts Sun DSEE

From Brandonhutchinson.com

Revision as of 15:38, 10 December 2007 by Hutch (Talk | contribs)
Jump to: navigation, search

In the following instructions, Sun Directory Server Enterprise Edition (DSEE) 6.1 is installed on two Solaris 10 Sparc servers. The LDAP servers are configured for multi-master replication over SSL. The LDAP passwd and group databases are populated from an existing NIS environment, and Solaris 8 Sparc LDAP clients are bound to the LDAP servers.

Contents

Download DSEE

From the DSEE download page, select the following options:

  • Under Step 1: Select Component, select Directory Server Enterprise Edition 6.x
  • Under Step 2: Select Version, select 6.1
  • Under Step 3: Select Delivery Type, select Compressed Archive (ZIP)
  • Under Step 4: Select Platform, select Solaris 10 SPARC

Install DSEE

Perform the following steps on both LDAP servers.

  • Extract the DSEE tarball.
$ gzip -cd DSEE.6.1.Solaris-Sparc-full.tar.gz | tar xvf -
  • Install DSEE. In this example, DSEE is installed in /opt/SUNWdsee.
$ cd DSEE_ZIP_Distribution
# ./dsee_deploy install --no-inter --install-path /opt/SUNWdsee

Directory Server instance creation

Perform the following steps on both LDAP servers.

  • Create a Directory Server instance. In this example, the Directory Instance is created in /var/ds. When prompted to choose the Directory Manager password, use the same Directory Manager password on both LDAP servers.
# dsadm create /var/ds
Choose the Directory Manager password:
Confirm the Directory Manager password:
Use 'dsadm start /var/ds' to start the instance
  • Start the Directory Server instance.
# dsadm start /var/ds

Directory Information Tree (DIT) creation

Perform the following steps on both LDAP servers.

  • Create the root suffix of the Directory Information Tree (DIT). In this example, the root suffix is dc=example,dc=com. Accept the self-signed certificate that was automatically created during #Directory Server instance creation.
# dsconf create-suffix dc=example,dc=com
  • Create the sub-suffix. In this example, the sub-suffix is dc=subdomain,dc=example,dc=com.
# dsconf create-suffix dc=subdomain,dc=example,dc=com
  • Attach the sub-suffix to the root suffix.
# dsconf set-suffix-prop dc=subdomain,dc=example,dc=com parent-suffix-dn:dc=example,dc=com

Configure SSL

Please see the excellent instructions at Native Solaris LDAP client over SSL from which much of this information was obtained.

Create the Certificate Authority (CA)

The following instructions assume OpenSSL is installed in /usr/local on hostname1, and that hostname1 will be the CA. These steps only need to be performed on hostname1.

  • Create the CA directory.
# mkdir /CA
# cd /CA
  • Create the CA private key.
# /usr/local/ssl/bin/openssl genrsa -out ca.key 1024
Generating RSA private key, 1024 bit long modulus
....++++++
..++++++
e is 65537 (0x10001)

  • Create a self-signed x509 CA certificate. The CA certificate will be valid for 20 years (-days 7300).
# /usr/local/ssl/bin/openssl req -out ca.cert -key ca.key -new -x509 -days 7300 -subj "/CN=Example Certificate Authority"
  • Create a configuration file for the CA (e.g., /CA/ca.conf). CA-signed certificates will be valid for 5 years (default_days = 1825).
[ ca ]
default_ca      = ExampleCA     # Default CA

[ ExampleCA ]
private_key     = ca.key        # CA key
certificate     = ca.cert       # CA certificate
database        = ca.db         # Keep track of certs issued
serial          = ca.serial     # Serial number for next cert
default_days    = 1825          # Validity for certs issued
default_md      = md5           # Default message digest
policy          = policy_cn     # What should be in subject
new_certs_dir   = .             # Dir for newly created certs

[ policy_cn ]
commonName      = supplied      # CN must be supplied
  • Create a database to track certificates.
# touch ca.db
  • Create a file containing the serial number for the next signed certificate.
# echo 01 > ca.serial

Create Certificate Signing Requests (CSRs)

Make sure to use the fully-qualified domain name of the LDAP server in the CSR subject (i.e., --name ...).

(hostname1) # dsadm request-cert --name hostname1.example.com --org organization --city city --state state --country country \ 
-o /CA/hostname1.cert.req -F ascii /var/ds
(hostname2) # dsadm request-cert --name hostname2.example.com --org organization --city city --state state --country country \
-o /tmp/hostname2.cert.req -F ascii /var/ds

Sign the CSRs

  • Copy hostname2:/tmp/hostname2.cert.req to hostname1:/CA.
  • Sign the CSRs on the CA server hostname1.
# cd /CA
# /usr/local/ssl/bin/openssl ca -config ca.conf -in hostname1.cert.req -out hostname1.cert
# /usr/local/ssl/bin/openssl ca -config ca.conf -in hostname2.cert.req -out hostname2.cert

Add signed server certificate and CA certificate to database

  • Copy hostname1:/CA/hostname2.cert and hostname1:/CA/ca.cert to hostname2:/tmp
  • Add the CA-signed server certificate.
(hostname1) # dsadm add-cert --ca /var/ds hostname1 /CA/hostname1.cert
(hostname2) # dsadm add-cert --ca /var/ds hostname2 /tmp/hostname2.cert
  • Add the CA certificate.
(hostname1) # dsadm add-cert --ca -C /var/ds ExampleCA /CA/ca.cert
(hostname2) # dsadm add-cert --ca -C /var/ds ExampleCA /tmp/ca.cert

Modify dse.ldif

dse.ldif on each LDAP server must be changed to use the new server certificates instead of the defaultCert self-signed certificate for secure LDAP. Although dsconf set-server-prop ssl-rsa-cert-name should be used to make this change, I was unable to get it to work.

  • On hostname1, change nsSSLPersonalitySSL: defaultCert to nsSSLPersonalitySSL: hostname1 in /var/ds/config/dse.ldif.
  • On hostname2, change nsSSLPersonalitySSL: defaultCert to nsSSLPersonalitySSL: hostname2 in /var/ds/config/dse.ldif.

Restart Directory Server on both LDAP servers to begin using the new server certificates for secure LDAP.

# dsadm restart /var/ds

Create the LDAP client certificate database files (if applicable)

The following steps are only required when using TLS:Simple authentication. In this example, only "simple" authentication is used, because TLS:Simple authentication is impossible with Solaris 8 and Solaris 9 LDAP clients and the DSEE 6.1 LDAP server (see #Solaris 8 and Solaris 9 instructions).

The LDAP client database files are needed to "trust" the CA, and therefore trust all server certificates signed by the CA.

Solaris 10 instructions

  • On the CA (hostname1), create a new certificate and key database in /var/ldap. Do not enter a password when prompted.
# mkdir /var/ldap
# /usr/sfw/bin/certutil -N -d /var/ldap
Enter a password which will be used to encrypt your keys.
The password should be at least 8 characters long,
and should contain at least one non-alphabetic character.

Enter new password: 
Re-enter password:
  • Create the client database files.
# /usr/sfw/bin/certutil -A -d /var/ldap -n ExampleCA -t C,, -i /CA/ca.cert
  • Copy the following client databases files to /var/ldap on all Solaris 10 LDAP clients.
    • /var/ldap/cert8.db
    • /var/ldap/key3.db
    • /var/ldap/secmod.db
  • Change the permissions of these files to 444 on all Solaris 10 LDAP clients.

Solaris 8 and Solaris 9 instructions

The NSS security libraries in Solaris 8 and Solaris 9 only support cert7 server certificates. DSEE 5.2P4 and later create certificates in cert8 format. As far as I know, it is impossible to use TLS:Simple authentication on a Solaris 8 or Solaris 9 LDAP client with a DSEE 5.2P4 or later Directory Server. More information is available here and here.

The following notes show how to create LDAP client databases in cert7.db format. Using these instructions, I am able to get a Solaris 8 client to bind to a DSEE 6.1 server using TLS:Simple authentication. However, I receive the following error when trying to authenticate with a user in the LDAP passwd database:

[17/Sep/2007:14:17:30 -0500] conn=204 op=0 msgId=-1 - closing from Solaris_8_LDAP_client:38839 - B4 - Server failed to flush BER
data back to client -

In this example, hostname3 is a Solaris 8 LDAP client.

To create the LDAP client databases in cert7.db format:

Perform the following steps on hostname3:

  • Extract NSS 3.3.2.
# gzip -cd nss-3.3.2.tar.gz | tar xvf -
  • Extract Sun ONE Directory SDK for C 5.08.
# gzip -cd ldapcsdk5.08-SunOS5.8_OPT.OBJ.tar.gz
  • Copy the missing shared libraries to nss-3.3.2/lib.
# cp lib/libplc4.so lib/libplds4.so lib/libnspr4.so nss-3.3.2/lib
  • Create a new certificate and key database in /var/ldap. Do not enter a password when prompted.
# mkdir /var/ldap
# cd nss-3.3.2/bin
# LD_LIBRARY_PATH=../lib ./certutil -N -d /var/ldap
Enter a password which will be used to encrypt your keys.
The password should be at least 8 characters long,
and should contain at least one non-alphabetic character.

Enter new password: 
Re-enter password:
  • Create the client database files.
# LD_LIBRARY_PATH=../lib ./certutil -A -d /var/ldap -n ExampleCA -t C,, -i /tmp/ca.cert
  • Copy the following client databases files to /var/ldap on all Solaris 8 and Solaris 9 LDAP clients.
    • /var/ldap/cert7.db
    • /var/ldap/key3.db
    • /var/ldap/secmod.db
  • Change the permissions of these files to 444 on all Solaris 8 and Solaris 9 LDAP clients.

Create the schema and LDAP client profile

If you are using Solaris 10 Update 3 or earlier, the /usr/lib/ldap/idsconfig script will have to be modified to work with DSEE 6.x. A list of needed modifications is provided here.

Run the idsconfig script to prepare the schema and create an LDAP client profile. In this example, the proxy credential level is used with "simple" authentication. Since we are using multimaster replication, both LDAP servers--hostname1 with IP address 192.168.1.100 and hostname2 with IP address 192.168.1.101--are specified in the Default server list.

# /usr/lib/ldap/idsconfig

It is strongly recommended that you BACKUP the directory server
before running idsconfig.

Hit Ctrl-C at any time before the final confirmation to exit.

Do you wish to continue with server setup (y/n/h)? [n] y
Enter the iPlanet Directory Server's (iDS) hostname to setup: hostname1
Enter the port number for iDS (h=help): [389]
ERROR: idsconfig only works with iDS version 5.x, not 6.1.
Enter the directory manager DN: [cn=Directory Manager]
Enter passwd for cn=Directory Manager :
Enter the domainname to be served (h=help): [example.com] subdomain.example.com
Enter LDAP Base DN (h=help): [dc=subdomain,dc=example,dc=com]
  Checking LDAP Base DN ...
  Validating LDAP Base DN and Suffix ...
Enter the profile name (h=help): [default] simple
Default server list (h=help): [192.168.1.100] 192.168.1.100 192.168.1.101
Preferred server list (h=help):
Choose desired search scope (one, sub, h=help):  [one]
The following are the supported credential levels:
  1  anonymous
  2  proxy
  3  proxy anonymous
Choose Credential level [h=help]: [1] 2
The following are the supported Authentication Methods:
  1  none
  2  simple
  3  sasl/DIGEST-MD5
  4  tls:simple
  5  tls:sasl/DIGEST-MD5
Choose Authentication Method (h=help): [1] 2

Current authenticationMethod: simple

Do you want to add another Authentication Method? n
Do you want the clients to follow referrals (y/n/h)? [n]
Do you want to modify the server timelimit value (y/n/h)? [n]
Do you want to modify the server sizelimit value (y/n/h)? [n]
Do you want to store passwords in "crypt" format (y/n/h)? [n]
Do you want to setup a Service Authentication Methods (y/n/h)? [n] y
Do you want to setup a Service Auth. Method for "pam_ldap" (y/n/h)? [n] y
The following are the supported Authentication Methods:
  1  simple
  2  sasl/DIGEST-MD5
  3  tls:simple
  4  tls:sasl/DIGEST-MD5
Choose Service Authentication Method: [1]

Current authenticationMethod: pam_ldap:simple

Do you want to add another Authentication Method? n
Do you want to setup a Service Auth. Method for "keyserv" (y/n/h)? [n]
Do you want to setup a Service Auth. Method for "passwd-cmd" (y/n/h)? [n] y
The following are the supported Authentication Methods:
  1  simple
  2  sasl/DIGEST-MD5
  3  tls:simple
  4  tls:sasl/DIGEST-MD5
Choose Service Authentication Method: [1]

Current authenticationMethod: passwd-cmd:simple

Do you want to add another Authentication Method? n
Client search time limit in seconds (h=help): [30]
Profile Time To Live in seconds (h=help): [43200]
Bind time limit in seconds (h=help): [10]
Do you wish to setup Service Search Descriptors (y/n/h)? [n]

              Summary of Configuration

  1  Domain to serve               : subdomain.example.com
  2  Base DN to setup              : dc=subdomain,dc=example,dc=com
  3  Profile name to create        : simple
  4  Default Server List           : 192.168.1.100
  5  Preferred Server List         :
  6  Default Search Scope          : one
  7  Credential Level              : proxy
  8  Authentication Method         : simple
  9  Enable Follow Referrals       : FALSE
 10  iDS Time Limit                :
 11  iDS Size Limit                :
 12  Enable crypt password storage : FALSE
 13  Service Auth Method pam_ldap  : pam_ldap:simple
 14  Service Auth Method keyserv   :
 15  Service Auth Method passwd-cmd: passwd-cmd:simple
 16  Search Time Limit             : 30
 17  Profile Time to Live          : 43200
 18  Bind Limit                    : 10
 19  Service Search Descriptors Menu

Enter config value to change: (1-19 0=commit changes) [0]
Enter DN for proxy agent: [cn=proxyagent,ou=profile,dc=subdomain,dc=example,dc=com]
Enter passwd for proxyagent:
Re-enter passwd:

WARNING: About to start committing changes. (y=continue, n=EXIT) y

  1. Schema attributes have been updated.
  2. Schema objectclass definitions have been added.
  3. NisDomainObject added to dc=subdomain,dc=example,dc=com.
  4. Top level "ou" containers complete.
  5. automount maps: auto_home auto_direct auto_master auto_shared processed.
  6. ACI for dc=subdomain,dc=example,dc=com modified to disable self modify.
  7. Add of VLV Access Control Information (ACI).
  8. Proxy Agent cn=proxyagent,ou=profile,dc=subdomain,dc=example,dc=com added.
  9. Give cn=proxyagent,ou=profile,dc=subdomain,dc=example,dc=com read permission for password.
  10. Generated client profile and loaded on server.
  11. Processing eq,pres indexes:
      uidNumber (eq,pres)   Finished indexing.                 
      ipNetworkNumber (eq,pres)   Finished indexing.                 
      gidnumber (eq,pres)   Finished indexing.                 
      oncrpcnumber (eq,pres)   Finished indexing.                 
      automountKey (eq,pres)   Finished indexing.                 
  12. Processing eq,pres,sub indexes:
      ipHostNumber (eq,pres,sub)   Finished indexing.                 
      membernisnetgroup (eq,pres,sub)   Finished indexing.
      nisnetgrouptriple (eq,pres,sub)   Finished indexing.                 
  13. Processing VLV indexes:
      subdomain.example.com.getgrent vlv_index   Entry created
      subdomain.example.com.gethostent vlv_index   Entry created
      subdomain.example.com.getnetent vlv_index   Entry created
      subdomain.example.com.getpwent vlv_index   Entry created
      subdomain.example.com.getrpcent vlv_index   Entry created
      subdomain.example.com.getspent vlv_index   Entry created
      subdomain.example.com.getauhoent vlv_index   Entry created
      subdomain.example.com.getsoluent vlv_index   Entry created
      subdomain.example.com.getauduent vlv_index   Entry created
      subdomain.example.com.getauthent vlv_index   Entry created
      subdomain.example.com.getexecent vlv_index   Entry created
      subdomain.example.com.getprofent vlv_index   Entry created
      subdomain.example.com.getmailent vlv_index   Entry created
      subdomain.example.com.getbootent vlv_index   Entry created
      subdomain.example.com.getethent vlv_index   Entry created
      subdomain.example.com.getngrpent vlv_index   Entry created
      subdomain.example.com.getipnent vlv_index   Entry created
      subdomain.example.com.getmaskent vlv_index   Entry created
      subdomain.example.com.getprent vlv_index   Entry created
      subdomain.example.com.getip4ent vlv_index   Entry created
      subdomain.example.com.getip6ent vlv_index   Entry created

idsconfig: Setup of iDS server hostname1 is complete.


Note: idsconfig has created entries for VLV indexes.  Use the
      directoryserver(1m) script on hostname1 to stop
      the server and then enter the following vlvindex
      sub-commands to create the actual VLV indexes:

  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getgrent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.gethostent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getnetent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getpwent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getrpcent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getspent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getauhoent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getsoluent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getauduent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getauthent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getexecent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getprofent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getmailent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getbootent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getethent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getngrpent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getipnent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getmaskent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getprent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getip4ent
  directoryserver -s <server-instance> vlvindex -n dev -T subdomain.example.com.getip6ent

Modify Directory Access Control Instructions (ACIs)

  • Create an LDIF file with the following contents (e.g., /tmp/aci.ldif):
dn: dc=subdomain,dc=example,dc=com
changetype: modify
add: aci
aci: (target ="ldap:///dc=subdomain,dc=example,dc=com")(targetattr
 !="userPassword")(version 3.0;acl "Anonymous read-search access";allow (read
 , search, compare)(userdn = "ldap:///anyone");)
aci: (target="ldap:///dc=subdomain,dc=example,dc=com") (targetattr
 = "*")(version 3.0; acl "allow all Admin group"; allow(all) groupdn = "ldap:
 ///cn=Directory Administrators,ou=Groups,dc=subdomain,dc=example,dc=com";)
-
delete: aci
aci: aci: (target="ldap:///dc=subdomain,dc=example,dc=com")(targetattr="userPassword")(version 3.0; acl 
LDAP_Naming_Services_proxy_password_read; allow (compare,read,search) userdn =
"ldap:///cn=proxyagent,ou=profile,dc=subdomain,dc=example,dc=com";)
  • Apply the LDIF file.
# ldapmodify -D "cn=Directory Manager" -f /tmp/aci.ldif
Enter bind password:
modifying entry dc=subdomain,dc=example,dc=com

Explanation of ACI LDIF

When creating the schema using Directory Service Control Center (DSCC) and "Create Top Entry for the Suffix," the schema has the following ACIs:

aci: (target ="ldap:///dc=subdomain,dc=example,dc=com")(targetattr
 !="userPassword")(version 3.0;acl "Anonymous read-search access";allow (read
 , search, compare)(userdn = "ldap:///anyone");)
aci: (target="ldap:///dc=subdomain,dc=example,dc=com") (targetattr
 = "*")(version 3.0; acl "allow all Admin group"; allow(all) groupdn = "ldap:
 ///cn=Directory Administrators,ou=Groups,dc=subdomain,dc=example,dc=com";)
aci: (targetattr = "cn||uid||uidNumber||gidNumber||homeDirectory||shadowLastCh
 ange||shadowMin||shadowMax||shadowWarning||shadowInactive||shadowExpire||sha
 dowFlag||memberUid")(version 3.0; acl LDAP_Naming_Services_deny_write_access
 ; deny (write) userdn = "ldap:///self";)

A schema created using dsconf has only the following ACI:

aci: (targetattr = "cn||uid||uidNumber||gidNumber||homeDirectory||shadowLastCh
 ange||shadowMin||shadowMax||shadowWarning||shadowInactive||shadowExpire||sha
 dowFlag||memberUid")(version 3.0; acl LDAP_Naming_Services_deny_write_access
 ; deny (write) userdn = "ldap:///self";)

If the above ACI in bold is not present in the schema, you may receive errors

  • when binding to the client:
Failed to find defaultSearchBase for domain subdomain.example.com
  • during subsequent runs of idsconfig:
2. Schema objectclass definitions have been added.
  ERROR: update of NisDomainObject in dc=subdomain,dc=example,dc=com failed.
  • or when running ldaplist on an already-bound client:
ldaplist: Object not found
ldaplist: Object not found (Session error no available conn.
)

When creating an LDAP client profile using idsconfig with the proxy credential level, an ACI is added to allow the proxyagent user to read the userPassword attribute. This means that ldaplist -l passwd on an LDAP client will display the encrypted password hash of all LDAP users, something we definitely do not want. Since we are using pam_ldap for authentication, the proxyagent user does not need read access to the userPassword attribute, so we delete this ACI.

Directory Server password policy

Organizational requirements

Our organization requires adherence to the following password policy:

  • Maximum password age is 90 days.
  • Passwords must consist of both numeric and alphabetic characters.
  • New passwords cannot be the same as the 3 previously used passwords.
  • Accounts must be locked out after 4 invalid logon attempts.
  • Once locked out, user accounts remain locked until the System Administrator unlocks the account.

List the default password policy

The following is the default Directory Server password policy. Defaults that will have to be changed to meet our organization's password policy requirements are listed in bold.

# dsconf get-server-prop | grep ^pwd-
pwd-accept-hashed-pwd-enabled      :  N/A 
pwd-check-enabled                  :  off
pwd-compat-mode                    :  DS5-compatible-mode 
pwd-expire-no-warning-enabled      :  on 
pwd-expire-warning-delay           :  1d 
pwd-failure-count-interval         :  10m 
pwd-grace-login-limit              :  disabled 
pwd-keep-last-auth-time-enabled    :  off 
pwd-lockout-duration               :  1h
pwd-lockout-enabled                :  off
pwd-lockout-repl-priority-enabled  :  on 
pwd-max-age                        :  disabled
pwd-max-failure-count              :  3
pwd-max-history-count              :  disabled 
pwd-min-age                        :  disabled 
pwd-min-length                     :  6 
pwd-mod-gen-length                 :  6 
pwd-must-change-enabled            :  off 
pwd-root-dn-bypass-enabled         :  off 
pwd-safe-modify-enabled            :  off 
pwd-storage-scheme                 :  SSHA 
pwd-strong-check-dictionary-path   :  /opt/SUNWdsee/ds6/plugins/words-english-bi
g.txt 
pwd-strong-check-enabled           :  off
pwd-strong-check-require-charset   :  lower 
pwd-strong-check-require-charset   :  upper 
pwd-strong-check-require-charset   :  digit 
pwd-strong-check-require-charset   :  special 
pwd-supported-storage-scheme       :  CRYPT 
pwd-supported-storage-scheme       :  SHA 
pwd-supported-storage-scheme       :  SSHA 
pwd-supported-storage-scheme       :  NS-MTA-MD5 
pwd-supported-storage-scheme       :  CLEAR 
pwd-user-change-enabled            :  on

Modify the password policy

Perform the following steps on both LDAP servers.

  • Expire passwords after 90 days.
# dsconf set-server-prop pwd-max-age:90d
  • Require passwords to contain at least 1 of each pwd-strong-check-require-charset (by default, at least one uppercase, lowercase, number, and special character) and that passwords do not contain strings from pwd-strong-check-dictionary-path.
# dsconf set-server-prop pwd-check-enabled:on
Enabling "pwd-check-enabled" property automatically sets the value of "pwd-accept-hashed-pwd-enabled" property to  "off".
# dsconf set-server-prop pwd-strong-check-enabled:on
Directory Server must be restarted for changes to take effect.
  • Require passwords to contain any 3 (instead of all 4) of a (1) uppercase character, (2) lowercase character, (3) number, or (4) special character.
# dsconf set-server-prop pwd-strong-check-require-charset:any-three
Directory Server must be restarted for changes to take effect.
  • Prevent users from reusing their last 3 passwords.
# dsconf set-server-prop pwd-max-history-count:3
  • Lock user accounts indefinitely after 4 consecutive password failures.
# dsconf set-server-prop pwd-lockout-enabled:on
# dsconf set-server-prop pwd-max-failure-count:4

(The latter can be set while the former is "off" by default, although no account lockout would occur)

# dsconf set-server-prop pwd-lockout-duration:disabled

I make two other changes to the default password policy that are not part of our organization's password policy, but are listed in the Center for Information Security's Solaris Benchmark.

  • Warn users 4 weeks prior to password expiration.
# dsconf set-server-prop pwd-expire-warning-delay:28d
  • Require users to keep their passwords at least 7 days.
# dsconf set-server-prop pwd-min-age:7d

Finally, I configure the Directory Server to record the last authentication time for each user. This requires us to change pwd-compat-mode from DS5-compatible-mode to DS6-migration-mode or DS6-mode[1].

# dsconf set-server-prop pwd-keep-last-auth-time-enabled:on
Directory Server "localhost:389" raised an unexpected error:
"[LDAP: error code 53 - (Password Policy: modify policy entry) "pwdKeepLastAuthTime: true" is not supported in server mode   DS5-compatible-mode ("cn=config" pwdCompat: 0).]".
See the errors log for details.
The "set-server-prop" operation failed on "localhost:389".

# dsconf pwd-compat to-DS6-migration-mode
## Beginning password policy compatibility changes.
## Password policy compatibility changes finished.

Task completed (slapd exit code: 0).

# dsconf pwd-compat to-DS6-mode
## Beginning password policy compatibility changes.
## Password policy compatibility changes finished.

Task completed (slapd exit code: 0).
# dsconf set-server-prop pwd-keep-last-auth-time-enabled:on

Restart Directory Server

Restart the Directory Server for the password policy changes to take effect.

# dsadm restart /var/ds
Server stopped
Server started: pid=26834

Add LDAP entries

Bind an LDAP client

In order to use ldapaddent to populate the passwd and group databases below, you must first bind an LDAP client to an LDAP server. In this example, hostname3--a Solaris 8 Sparc LDAP client--should be bound to hostname1.

  • Solaris 8 instructions:
# ldapclient -w proxyagent_password -P simple -d subdomain.example.com \
-D cn=proxyagent,ou=profile,dc=subdomain,dc=example,dc=com hostname1
  • Solaris 10 instructions:
# ldapclient init -a profileName=simple -a domainName=subdomain.example.com \
-a proxyDN=cn=proxyagent,ou=profile,dc=subdomain,dc=example,dc=com -a proxyPassword=proxyagent_password hostname1

I recommend completing the remaining steps before binding the rest of the LDAP clients.

Populate the passwd database

We were asked to add all users with GID 2050 from an existing NIS environment into the LDAP passwd database. Instead of using the UIDs in the NIS passwd map, we want to reorder them, starting with UID 1000.

$ ypcat passwd | awk -F: '$4 == 2050 { print }' >  nis_passwd_map

e.g., reorder_nis_passwd_map.sh

#!/bin/sh

UID=1000

while read LINE ; do
   IFS=:
   set $LINE
   echo "$1:$2:$UID:$4:$5:$6:$7"
   UID=`expr $UID + 1`
done < nis_passwd_map > nis_passwd_map.new

mv nis_passwd_map.new nis_passwd_map

On an LDAP client, run ldapaddent command to populate the passwd database. Since the NIS passwd map contains the password hashes, use the -p flag with ldapaddent to process the password field. Note that the password you are prompted for is the cn=Directory Manager password.

Note: Since some of the imported passwords did not adhere to the Directory Server's password policy, pwd-check-enabled had to be temporarily disabled on the Directory Server.

(hostname3) # ldapaddent -a simple -p -D "cn=Directory Manager" -f nis_passwd_map passwd
Enter password:
19: Constraint violation
Error while adding line: ...

(hostname1) # dsconf set-server-prop pwd-check-enabled:off
Disabling "pwd-check-enabled" property automatically sets the value of "pwd-accept-hashed-pwd-enabled" property to  "N/A".

(hostname3) # ldapaddent -a simple -p -D "cn=Directory Manager" -f nis_passwd_map passwd
Enter password:
682 entries added

(hostname1) # dsconf set-server-prop pwd-check-enabled:on
Enabling "pwd-check-enabled" property automatically sets the value of "pwd-accept-hashed-pwd-enabled" property to  "off".

Populate the group database

The only group from the NIS group map that we want migrated to LDAP is the group with GID 2050.

$ ypcat group | awk -F: '$3 == 2050 { print }' > nis_group_map
 

Run the following command on an LDAP client to populate the group database.

# ldapaddent -a simple -D "cn=Directory Manager" -f nis_group_map group
Enter password:
19: Constraint violation
Error while adding line: ...
0 entries added

I'm not sure why, but I had to temporarily disable pwd-check-enabled on the Directory Server in order to populate the groups database with nis_group_map.

(hostname1) # dsconf set-server-prop pwd-check-enabled:off
Disabling "pwd-check-enabled" property automatically sets the value of "pwd-accept-hashed-pwd-enabled" property to "N/A".

(hostname3) # ldapaddent -a simple -D "cn=Directory Manager" -f nis_group_map group
Enter password:
1 entries added

(hostname1) # dsconf set-server-prop pwd-check-enabled:on
Enabling "pwd-check-enabled" property automatically sets the value of "pwd-accept-hashed-pwd-enabled" property to "off".

Populate the auto_home database

In our environment, user home directories are stored on a NetApp FAS system acting as an NFS server. The location of users' home directories is netapp_fas:/vol/home/user_id. To configure the /home AutoFS file system for this directory path, import the following LDIF file (e.g., /tmp/auto_home.ldif):

dn: automountKey=*,automountMapName=auto_home,dc=subdomain,dc=example,dc=com
automountInformation: -vers=3 netapp_fas:/vol/home/&
objectClass: automount
objectClass: top
automountKey: *
# ldapmodify -a -D "cn=Directory Manager" -f /tmp/auto_home.ldif
Enter bind password:
adding new entry automountKey=*,automountMapName=auto_home,dc=subdomain,dc=example,dc=com

Configure replication

The suffix dc=subdomain,dc=example,dc=com will be replicated over SSL in a multi-master configuration on LDAP servers hostname1 and hostname2.

  • Enable the master replicated suffix on both LDAP servers. The replication ID for all master replicas of the suffix must be unique; it will be "1" on hostname1 and "2" on hostname2.
(hostname1) # dsconf enable-repl -d 1 master dc=subdomain,dc=example,dc=com
Enter "cn=Directory Manager" password: 
Use "dsconf create-repl-agmt" to create replication agreements on "dc=subdomain,dc=example,dc=com".

(hostname2) # dsconf enable-repl -d 2 master dc=subdomain,dc=example,dc=com
Enter "cn=Directory Manager" password: 
Use "dsconf create-repl-agmt" to create replication agreements on "dc=subdomain,dc=example,dc=com".
  • Populate the multi-master password file on both servers. Although this password can be different on each server, I use the same password on both servers.
(hostname1) # echo multimaster_password > /var/ds/db/subdomain/multimaster_password_file
(hostname2) # echo multimaster_password > /var/ds/db/subdomain/multimaster_password_file
  • Create replication agreements and setup authentication between the two servers. In this multi-master replication configuration, hostname1 is the supplier for consumer hostname2, and hostname2 is the supplier for consumer hostname1. Accept the server certificates when prompted.
(hostname1) # dsconf create-repl-agmt --auth-protocol "ssl-simple" dc=subdomain,dc=example,dc=com hostname2:636
(hostname2) # dsconf create-repl-agmt --auth-protocol "ssl-simple" dc=subdomain,dc=example,dc=com hostname1:636
  • Configure the replication agreement authentication password file to be the multi-master password file.
# dsconf set-repl-agmt-prop -h hostname1 -p 389 dc=subdomain,dc=example,dc=com \
hostname2:636 auth-pwd-file:/var/ds/db/subdomain/multimaster_password_file
# dsconf set-repl-agmt-prop -h hostname2 -p 389 dc=subdomain,dc=example,dc=com \
hostname1:636 auth-pwd-file:/var/ds/db/subdomain/multimaster_password_file
  • Restart the Directory Server on both LDAP servers for the configuration changes to take effect.
(hostname1) # dsadm restart /var/ds
(hostname2) # dsadm restart /var/ds
  • Initialize the replica by copying the contents of dc=subdomain,dc=example,dc=com from hostname1 to hostname2.
(hostname1) # dsconf init-repl-dest dc=subdomain,dc=example,dc=com hostname2:636

Confirm replication is working

On hostname1:

# dsconf show-repl-agmt-status dc=subdomain,dc=example,dc=com hostname2:636
Enter "cn=Directory Manager" password:
Configuration Status   :  OK  
Authentication Status  :  OK  
Initialization Status  :  OK

Status                 :  Enabled  
Last Update Date       :  Sep 11, 2007 3:08:12 PM

On hostname2:

# dsconf show-repl-agmt-status dc=subdomain,dc=example,dc=com hostname1:636
Enter "cn=Directory Manager" password:
Configuration Status   :  OK  
Authentication Status  :  OK  
Initialization Status  :  OK

Status                 :  Enabled  
Last Update Date       :  Sep 11, 2007 3:13:54 PM

Final Steps

Prevent the proxyagent user's password from expiring

If you are using the proxy credential level on LDAP clients, the proxyagent user's password should never expire. If it does, LDAP clients will not be able to retrieve name service information from the LDAP server(s).

To prevent the proxyagent user's password from expiring:

$ /usr/bin/printf "dn: cn=proxyagent,ou=profile,dc=subdomain,dc=example,dc=com\nchangetype: \
modify\nreplace: PasswordExpirationTime\nPasswordExpirationTime: 20380119031407Z\n" | \
ldapmodify -h hostname1 -D "cn=Directory Manager"

Create user home directories

In our environment, the LDAP servers hostname1 and hostname2 have root-level access on the NetApp FAS system used for user home directories. On one of these systems, create user home directories using the above nis_passwd_map and the following script:

#!/bin/sh

[ ! -d /tmp/mnt ] && mkdir /tmp/mnt
mount netapp_fas:/vol/home /tmp/mnt

OLDIFS=$IFS

while read LINE ; do
   IFS=:
   set $LINE
   USER=$1
   UID=$3
   GID=$4
   mkdir /tmp/mnt/$USER
   IFS=$OLDIFS
   chown $UID:$GID /tmp/mnt/$USER
done < nis_passwd_map

Bind the remaining LDAP clients

Use the steps listed in #Bind an LDAP client to bind the remaining LDAP clients to the LDAP servers.

Configure the name service switch on LDAP clients

When running ldapclient to initialize the LDAP clients, /etc/nsswitch.conf is overwritten with /etc/nsswitch.ldap. It is likely that /etc/nsswitch.conf will have to be modified, as it does not use DNS when looking up hostnames, and generally only references local files when LDAP is not available.

Configure LDAP clients to use pam_ldap authentication

The default /etc/pam.conf file uses pam_unix authentication. pam_unix authentication has two drawbacks:

  • The user password must be stored in "crypt" format.
  • The userPassword attribute must be readable by the name service.

The latter drawback means that an ldaplist -l passwd command will reveal each user's password hash.

pam_ldap authentication does not have these drawbacks. With pam_ldap, users attempts to bind to the Directory Server using their identity and password. If the bind is successful, the user is authenticated. The userPassword attribute is not used by pam_ldap.

/etc/pam.conf must be modified to use pam_ldap. The following pam.conf files may be used for pam_ldap authentication:

Configure OpenSSH to use PAM for authentication

If you are using an OpenSSH server, you may have to configure it to use PAM for authentication. To enable PAM with OpenSSH, change UsePAM no to UsePAM yes in sshd_config. Solaris 8 and 9 users will likely have to perform this step.

The SSH server provided with Solaris 10 uses PAM for authentication by default via the PAMAuthenticationViaKBDInt yes configuration directive.

Upgrading to DS 6.2

I used this basic procedure to upgrade from DS 6.1 to DS 6.2 on our two LDAP servers.

  • Stop the Directory Server instance on hostname2.
  • Uncompress and install Directory Server 6.2, overwriting the previous installation.
  • Start the Directory Server on hostname2.
  • Confirm that any pending replication changes from hostname1 have transferred.
  • Repeat the process on hostname1.

On hostname2:

# /opt/SUNWdsee/ds6/bin/dsadm stop /var/ds
$ gzip -cd DSEE.6.2.Solaris-Sparc-full.tar.gz | tar xf -
$ cd DSEE_ZIP_Distribution
# ./dsee_deploy install --no-inter --install-path /opt/SUNWdsee
# /opt/SUNWdsee/ds6/bin/dsadm start /var/ds
(hostname1) # dsconf show-repl-agmt-status dc=subdomain,dc=example,dc=com hostname2:636

On hostname1:

# /opt/SUNWdsee/ds6/bin/dsadm stop /var/ds
$ gzip -cd DSEE.6.2.Solaris-Sparc-full.tar.gz | tar xf -
$ cd DSEE_ZIP_Distribution
# ./dsee_deploy install --no-inter --install-path /opt/SUNWdsee
# /opt/SUNWdsee/ds6/bin/dsadm start /var/ds
(hostname2) # dsconf show-repl-agmt-status dc=subdomain,dc=example,dc=com hostname1:636

Troubleshooting

Problems with SSL Replication in DSEE 6.2

I cannot get multimaster replication to work over SSL with DSEE 6.2.

(hostname1) # dsconf init-repl-dest dc=subdomain,dc=example,dc=com hostname2:636
Enter "cn=Directory Manager" password:
Initialization of "hostname2:636" failed
Server exit code: "900"
Server exit message: "Replication error initializing replica: Total update failed : Unable to bind consumer - Failed to bind to remote"
The "init-repl-dest" operation failed on "localhost:389".

However, my two DSEE 6.1 servers that were upgraded to DSEE 6.2 are still able to replicate over SSL, so the problem seems to be related to new DSEE 6.2 installations.

As a workaround, use non-SSL replication using TCP port 389.

ldaplist: Object not found (LDAP ERROR (1): Operations error.)

(LDAP_client) $ ldaplist -l passwd
ldaplist: Object not found (LDAP ERROR (1): Operations error.)
(LDAP_server) $ cat /var/ds/logs/errors
[11/Sep/2007:16:48:28 -0500] - ERROR<20753> - Backend Database - conn=-1 op=-1 msgId=-1 -  vlv_build_idl: can't follow db cursor (err -30989)

According to the DSEE Troubleshooting Guide, this error means the database is incoherent, and should be rebuilt using db2ldif, then ldif2db. However, these utilities are not provided with DSEE 6.1. I was able to restore normal functionality by restarting the directory server instance.

(LDAP_server) # dsadm restart
Personal tools