Integrating *NIX client in Active Directory using LDAP Part - II

In our last post we discussed regarding the configuring Windows box to hold UNIX related attributes for LDAP authentication. We proceed to discuss the steps to join a Solaris 10 box into Active Directory.

The Solaris client must join an Active Directory domain to use Active Directory for security and directory services. The adjoin.sh script automates the domain join operation by executing the following steps from the Solaris client:

· Auto-detects the Active Directory domain controller

· Creates a machine account (also called a Computer object) for the Solaris host in Active Directory and generates a random password for this account

· Configures the Solaris host as a Kerberos client of the Active Directory domain controller by using the /etc/krb5/krb5.conf file

· Configures the /etc/krb5/krb5.keytab file on the Solaris host by using the keys for the machine account (also called host credentials)

The adjoin.sh script uses the ksetpw binary to set the password for the machine account and to configure the local keytab file. Run adjoin -h to see the options supported by the adjoin.sh script. This script requires proper DNS configuration on the client. Therefore, /etc/resolv.conf must point to the correct DNS domain and servers, and /etc/nsswitch.conf must use DNS for host resolution. Ensure that the ksetpw binary is in the same directory as adjoin.sh.

My testing around this shows that until I used the adjoin.sh script from adjoin-s10u5.tar.gz from <jp.opensolaris.org/os/project/winchester/files/> ; it was hitting an error like “cannot join the active directory”.

I have configured my /etc/resolv.conf file to have the Active Directory domain name and name server to my DNS server’s IP.

bash-3.00# cat /etc/resolv.conf

domain win2k3r2dc1.sfu

nameserver x.x.x.x

Also, to the /etc/nsswitch.conf file was configured to use dns to find the hosts.

bash-3.00# egrep "hosts|ipnodes" /etc/nsswitch.conf

hosts: dns ldap [NOTFOUND=return] files

ipnodes: dns ldap [NOTFOUND=return] files

The following adjoin.sh example output is for a Solaris host, sfusol101, that tries to join an Active Directory domain, win2k3r2dc1.sfu, that is served by the Active Directory domain controller, sfu2k3r2dc1.win2k3r2dc1.sfu. The -f option forces the creation of a machine account for sfusol101 even if one already exists. If a machine account already exists, the existing account is first removed before being recreated.

bash-3.00# ./adjoin -f

Joining domain: win2k3r2dc1.sfu

Looking for domain controllers and global catalogs (A RRs)

Looking for KDCs and DCs (SRV RRs)

        KDCs = sfu2k3r2dc1.win2k3r2dc1.sfu 88

        DCs = sfu2k3r2dc1.win2k3r2dc1.sfu 389

Password for Administrator@WIN2K3R2DC1.SFU:

Looking for forest name

  Forest name = win2k3r2dc1.sfu

Looking for Global Catalog servers

Looking for site name

        Looking for subnet object in the global catalog

Could not find site name for any local subnet

        Site name not found. Local DCs/GCs will not be discovered

Looking to see if there's an existing account...

Looking to see if the machine account contains other objects...

Deleting existing machine account...

Creating the machine account in AD via LDAP

adding new entry CN=SFUSOL101,CN=Computers,DC=win2k3r2dc1,DC=sfu

Setting the password/keys of the machine account

Result: success (0)

Getting kvno

KVNO: 2

Determining supported enctypes for machine account via LDAP

This must not be a Longhorn/Vista AD DC!

        So we assume 1DES and arcfour enctypes

ARCFOUR will be supported

Finishing machine account

modifying entry CN=SFUSOL101,CN=Computers,DC=win2k3r2dc1,DC=sfu

adjoin: Done

At this point we should be able to see a new computer object for the Solaris 10 box in the Active Directory and Computer snap-in.

csnapin_sol10

The contents of the krb5.conf file should be as follows:

bash-3.00# cat /etc/krb5/krb5.conf

[libdefaults]

        default_realm = WIN2K3R2DC1.SFU

[realms]

        WIN2K3R2DC1.SFU = {

                kdc = sfu2k3r2dc1.win2k3r2dc1.sfu

                kpasswd_server = sfu2k3r2dc1.win2k3r2dc1.sfu

                kpasswd_protocol = SET_CHANGE

                admin_server = sfu2k3r2dc1.win2k3r2dc1.sfu

        }

[domain_realm]

        .win2k3r2dc1.sfu = WIN2K3R2DC1.SFU

Use the ldapsearch command for a user to ensure the presence of POSIX attributes. In the following output, the attributes in bold were added by Identity Management for UNIX and those in italics are the SFU attributes. Actual output only shows one set of attributes. The example shows both sets to highlight the attribute names.

bash-3.00# ldapsearch -h sfu2k3r2dc1.win2k3r2dc1.sfu -b "cn=users,dc=win2k3r2dc1,dc=sfu" -o mech=gssapi -o authzid='' "cn=user1"

version: 1

dn: CN=user1,CN=Users,DC=win2k3r2dc1,DC=sfu

objectClass: top

objectClass: person

objectClass: organizationalPerson

objectClass: user

cn: user1

givenName: user1

distinguishedName: CN=user1,CN=Users,DC=win2k3r2dc1,DC=sfu

instanceType: 4

whenCreated: 20090410193520.0Z

whenChanged: 20090410081004.0Z

displayName: user1

uSNCreated: 20496

uSNChanged: 20556

name: user1

objectGUID:: 6PoklKVrN0+YBxKg5WPgiA==

userAccountControl: 66048

badPwdCount: 0

codePage: 0

countryCode: 0

badPasswordTime: 0

lastLogoff: 0

lastLogon: 128843237708750000

pwdLastSet: 128838246047656250

primaryGroupID: 513

objectSid:: AQUAAAAAAAUVAAAAOdXTkrp7Y/6sP9sfVQQAAA==

accountExpires: 9223372036854775807

logonCount: 2

sAMAccountName: user1

sAMAccountType: 805306368

userPrincipalName: user1@win2k3r2dc1.sfu

objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=win2k3r2dc1,DC=sfu

uid: user1

msSFU30Name: user1

msSFU30NisDomain: win2k3r2dc1

uidNumber: 10000

gidNumber: 10000

unixHomeDirectory: /home/user1

loginShell: /bin/sh

The next step is to initializing the Solaris LDAP Client

Now we configure the Solaris host as an LDAP client of Active Directory, which allows the Solaris host to access naming service information from Active Directory. As prerequisites, the DNS client and nscd should be enabled, and the /etc/resolv.conf file should be properly configured. Verify that both forward and reverse DNS lookup of the Active Directory server succeeds from the Solaris host, as shown in the following example. If reverse DNS lookup fails, then add a PTR record for the Active Directory server to the DNS server, if it does not exist. Modify /etc/nsswitch.ldap to use DNS for hosts and ipnodes. Unlike earlier versions, nscd in the Solaris 10 08/07 release supports enhanced LDAP connection management and improved caching. We must enable nscd to use the per-user authentication functionality as follows:

bash-3.00# svcadm enable svc:/network/dns/client:default

bash-3.00# svcadm enable name-service-cache

bash-3.00# dig sfu2k3r2dc1.win2k3r2dc1.sfu +short

<output should be IP address of the domain controller>

bash-3.00# dig -x <IP address of the domain controller +short

sfu2k3r2dc1.win2k3r2dc1.sfu.

bash-3.00# grep dns /etc/nsswitch.ldap

hosts: dns ldap [NOTFOUND=return] files

ipnodes: dns ldap [NOTFOUND=return] files

In the following example, Microsoft Windows Server 2003 Enterprise Edition R2 has UNIX related attributes enabled.

bash-3.00# ldapclient -v manual \

-a credentialLevel=self \

-a authenticationMethod=sasl/gssapi \

-a defaultSearchBase=dc=win2k3r2dc1,dc=sfu \

-a domainName=win2k3r2dc1,dc=sfu\

-a defaultServerList=<ip adress of the domain controller> \

-a attributeMap=passwd:gecos=cn \

-a attributeMap=passwd:homedirectory=unixHomeDirectory \

-a objectClassMap=group:posixGroup=group \

-a objectClassMap=passwd:posixAccount=user \

-a objectClassMap=shadow:shadowAccount=user \

-a serviceSearchDescriptor=passwd:cn=users,dc=win2k3r2dc1,dc=sfu?one \

-a serviceSearchDescriptor=group:cn=users,dc=win2k3r2dc1,dc=sfu?one

Let’s restart the LDAP client.

bash-3.00# svcadm restart svc:/network/ldap/client:default

And verify the contents of the LDAP client cache.

bash-3.00# ldapclient list

NS_LDAP_FILE_VERSION= 2.0

NS_LDAP_SERVERS= <IP address of the domain controller>

NS_LDAP_SEARCH_BASEDN= dc=win2k3r2dc1,dc=sfu

NS_LDAP_AUTH= sasl/GSSAPI

NS_LDAP_CACHETTL= 0

NS_LDAP_CREDENTIAL_LEVEL= self

NS_LDAP_SERVICE_SEARCH_DESC= passwd:cn=users,dc=win2k3r2dc1,dc=sfu?one

NS_LDAP_SERVICE_SEARCH_DESC= group:cn=users,dc=win2k3r2dc1,dc=sfu?one

NS_LDAP_ATTRIBUTEMAP= passwd:gecos=cn

NS_LDAP_ATTRIBUTEMAP= passwd:homedirectory=unixHomeDirectory

NS_LDAP_OBJECTCLASSMAP= group:posixGroup=group

NS_LDAP_OBJECTCLASSMAP= passwd:posixAccount=user

NS_LDAP_OBJECTCLASSMAP= shadow:shadowAccount=user

Using the Naming Service Switch and Pluggable Authentication Modules (PAM).

The following /etc/nsswitch.conf file configures the Solaris client to use Active Directory for users and groups, DNS for host resolution, and local files for other naming service lookups:

bash-3.00# cat /etc/nsswitch.conf

passwd: files ldap

group: files ldap

hosts: dns ldap [NOTFOUND=return] files

ipnodes: dns 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

services: files ldap

printers: user files ldap

auth_attr: files ldap

prof_attr: files ldap

project: files ldap

tnrhtp: files ldap

tnrhdb: files ldap

Use the pam_krb5.so.1 module in the /etc/pam.conf file to enable authentication, account management, and password management on the Solaris client by using Active Directory through Kerberos. Minimally, enable the module for login and other services. The following /etc/pam.conf file authenticates users by using Active Directory through Kerberos and authenticates through the UNIX login only if the Kerberos authentication fails (see the auth entries). This arrangement is helpful when a majority of the users are in Active Directory and when there are only a few non-Active Directory user accounts, such as root. The account entries check for password expiration when dealing with Active Directory and local UNIX password-aging policies. The password entries change the Active Directory password of the user and continue to change the local UNIX password only if the Active Directory password change fails.

login auth requisite pam_authtok_get.so.1

login auth required pam_dhkeys.so.1

login auth required pam_unix_cred.so.1

login auth sufficient pam_krb5.so.1

login auth required pam_unix_auth.so.1

login auth required pam_dial_auth.so.1

other auth requisite pam_authtok_get.so.1

other auth required pam_dhkeys.so.1

other auth required pam_unix_cred.so.1

other auth sufficient pam_krb5.so.1

other auth required pam_unix_auth.so.1

other account requisite pam_roles.so.1

other account required pam_unix_account.so.1

other account required pam_krb5.so.1

other password required pam_dhkeys.so.1

other password requisite pam_authtok_get.so.1

other password requisite pam_authtok_check.so.1

other password sufficient pam_krb5.so.1

other password required pam_authtok_store.so.1

Time to test the client

Let’s test the configuration by running the getent command for the passwd database for a particular user. If this command does not return the user, the client configuration failed. The /var/adm/messages file traps related errors.

bash-3.00# getent passwd user1

user1:x:10000:10000:user1:/home/user1:/bin/sh

We can use the ldaplist command to search for and list naming information. Note that running the ldaplist -l command returns a Critical Extension not found error, but if we specify an Active Directory user, you should get the correct output. The critical extension error occurs because Active Directory does not support some of the LDAP Version 3 extensions that are used by the Solaris LDAP client. In particular, Active Directory does not support the extension that is required for virtual list view (VLV) indexes.

bash-3.00# ldaplist -l passwd user1

dn: gecos=user1,gecos=Users,DC=win2k3r2dc1,DC=sfu

        objectClass: top

        objectClass: person

        objectClass: organizationalPerson

        objectClass: posixAccount

        cn: user1

        givenName: user1

        distinguishedName: CN=user1,CN=Users,DC=win2k3r2dc1,DC=sfu

        instanceType: 4

        whenCreated: 20090410193520.0Z

        whenChanged: 20090410081004.0Z

        displayName: user1

        uSNCreated: 20496

        uSNChanged: 20556

        name: user1

        objectGUID: #

        userAccountControl: 66048

        badPwdCount: 0

        codePage: 0

        countryCode: 0

        badPasswordTime: 0

        lastLogoff: 0

        lastLogon: 128843237708750000

        pwdLastSet: 128838246047656250

        primaryGroupID: 513

        objectSid: #

        accountExpires: 9223372036854775807

        logonCount: 2

        sAMAccountName: user1

        sAMAccountType: 805306368

        userPrincipalName: user1@win2k3r2dc1.sfu

        objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=win2k3r2dc1,DC=sfu

        uid: user1

        msSFU30Name: user1

        msSFU30NisDomain: win2k3r2dc1

        uidNumber: 10000

        gidNumber: 10000

        homedirectory: /home/user1

        loginShell: /bin/sh

        gecos: user1

Note: The objectGUID and objectSID attributes in the ldaplist output have binary values.

Verify that if we can log in successfully to the Solaris client as an Active Directory user by using ssh. Home directories that are shared by an NFS server can be automatically mounted at login time by configuring automount on the Solaris client.