This document outlines how to fully authenticate a Solaris 10 server against a Windows 2003 based Active Directory such as is used by CSCF for the School of Computer Science.
For the unindoctrinated, this exercise involves configuring client-server communications for to separated and different protocols.
To perform the outlined schema extension you will require the following.
elisa
within the CSCF
domain.
/etc/passwd
and /etc/shadow
files on the local Solaris host.
Most documentation on this subject speaks of upgrading all Active Directory domain controllers to Windows 2003 R2 (the second release of Windows 2003). However, we discovered that it is not necessary to fully upgrade our Windows 2003 domain controllers to version R2. One can separately 'prep' the existing schema to include the needed RFC 2307 attribute classes ( posixAccount
and posixGroup
). These classes carry the desired schema attributes for UNIX integration:
uidNumber gidNumber unixHomeDirectory loginShell
'Preping' the schema is done on the schema master server by running the command adprep
. This command can be found on on the second disk of the Windows 2003 R2 server installation disk set CDDRIVE:\CMPNENTS\R2\ADPREP\adprep.exe
. To prepare the AD run
adprep /forestprep
Domain controllers must then be systematically rebooted in order from this update to be in full effect. All domain controllers in our forest reboot themselves automatically once per week.
To perform the required Active Directory security changes you will require the following.
In Windows 2003 anonymous LDAP access of the Active Directory is disabled by default and must be enabled. This is done using the ADSI Editor
snap-in for the mmc.exe
console tool on the schema master server. Right-click on ADSI Edit
and make two connections:
cscf.uwaterloo.ca
)
CN=Directory Service,CN=Windows NT,CN=Services
. Right-click on the Directory Service
container and select 'Properties'. Find the dsHeuristics
attribute and edit it such that the last numeral in the seven digit number is a '2'. If the entry is not set at all then set it to read 0000002
.
Once this change has been made on the schema master it will take 10 to 20 minutes for it to propagate to every domain controller in the forest. But then all the domain controllers will permit an anonymous bind to LDAP. Although, at this point, you will still not be able to read any object attributes.
To read user attributes such as uidNumber
, permissions for the ANONYMOUS LOGON
must be set upon Active Directory containers or organizational units where anonymous lookup is to be permitted. In our case these locations are the Users
and Unassigned
OUs in the CS-GENERAL
domain ( ou=Users,ou=CS,dc=cs,dc=uwaterloo,dc=ca
and ou=Unassigned,dc=cs,dc=uwaterloo,dc=ca
respectively). We took care to ensure that special accounts like domain admins and kiosk accounts are not located within these OUs and so cannot be accessed using an anonymous LDAP bind.
In the case of the Users
and Unassigned
OUs, we added an ANONYMOUS LOGON
entry to their Security properties. This entry is first granted Read permissions, then under Advanced one checks to see that ANONYMOUS LOGON
has 'List Contents' permissions in addition to what Read provides. These permissions must be applied to 'This object and all child objects' - that does not get set by default.
Due to legacy issues, kerberos communicates using UDP by default. However, the size and complexity of information supplied by a Windows 2003 domain controller is often too large for UDP packets to handle. UDP is also connectionless, so packets can be lost and never recovered - very bad. For these reasons, it is recommended and, in our case, essential to force relevant domain controllers (KDC servers) in our domain (kerberos realm) to only use TCP for kerberos.
Initially, this need only be done in the AD domain in which you are joining the Solaris host. But over the longer term, all domain controllers in the forest should be converted in this way.
The procedure for configuring a domain controller to use TCP for kerberos is outlined in the following Microsoft web document.
http://support.microsoft.com/?id=244474
Simply, it requires creating/editing a DWORD
registry value called MaxPacketSize and setting it to the value one (1) in the following registry key for each domain controller in the domain.
HKLM\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters
The domain controllers must all be rebooted (not all at once, of course) for this change to take effect.
Solaris will not login a user unless it can determine his uid
, gid
, homedirectry
and loginshell
values. Since we will be configuring the Solaris host to look for these values in a user's Active Directory account and not locally, it would be a good idea to manually enter these values for a few users so that login may later be tested.
On a domain controller, use the ADSI Editor
snap-in of the Microsoft Management Console ( mmc.exe
) to manually populate the new attributes for each test use. Remember, the new attributes you wish to add info to are as follows:
uidNumber gidNumber unixHomeDirectory loginShell
To create such a user account you will require the following.
Unlike a Windows or a Macintosh system, a Solaris machine account must be manually created within an Active Directory domain. This account will be used by the Solaris host's kerberos client for the purpose of user authentication. Account creation for a Solaris host may be done using the Active Directory Users and Computers
tool from an Active Directory management system such as a domain controller.
It is recommended that this host account be a user account and not a computer account (or object) which is commonly created for Windows, Macintosh and SAMBA systems. For our purposes, this account will be named computername-host, enter this name into the User logon name
and Full name
fields when you create the new user. Creating the account, you will be called upon to set an account password. Set this password sufficiently complex and take note of it since it will be required for the creation of the Solaris system's keytab
file in the next section of this document.
Now enter into the account properties and select the Account
tab. In account characteristics, enable 'Do not require kerberos pre-auth'
, especially if time synchronization between the Active Directory and the Solaris host is not as yet established. Also ensure that the account is enabled, does not expire and that its password does not expire or require a change upon next logon.
Under the General
tab, it is a good idea to fill in the Description
field. For example:
Kerberos host principal for Solaris host _FQDN_for_computername_
keytab
File For The Solaris Host
To complete keytab
creation and installation you will require the following.
root
) access rights to the new Solaris host.
ktpass -ptype KRB5_NT_PRINCIPAL -crypto DES-CBC-MD5 -princ host/FQDN@Kerberos_Realm -mapuser Domain_Name\hostname-host -pass complexpasswd -out c:\temp\krb5.keytab
where Domain_Name
is the NetBIOS name for the Active Directory domain,=Kerberos_Realm= is the uppercase of the Domain_Name
, FQDN is the fully qualified domain name
of the computer, hostname
is the fqdn with truncated at the first dot, and complexpasswd
is to be substituted with the password that was set when the account was created in the previous section.
Recall that the domain cs.uwaterloo.ca
has the NetBIOS name of CS-GENERAL
with the requisite CS.UWATERLOO.CA
Kerberos realm.
Now return to the account properties for computername-host and select the Account
tab. The User logon name
entry should now have changed to be that of the account's SPN as specified in the ktpass
command above. The ktpass
command will also generate a keytab
file for the Solaris host in the location specified by the -out
option. This keytab
file must then be securely transferred to the Solaris host and placed at the following location in the UNIX file system.
/etc/krb5/krb5.keytab
To properly configure the Solaris host's Kerberos client you will require the following:
keytab
file created in the previous section of this document.
root
) access rights to the new Solaris host.
We start by placing the Windows generated keytab
file from the previous section into its proper location: /etc/krb5/krb5.keytab
. Security on this file should be set such that read rights are limited to its owner which must be root
.
Next, prepare the Kerberos client configuration file ( /etc/krb5/krb5.conf
) on the Solaris host. Below is a sample of the krb5.conf
file used for authenticating Solaris hosts in CSCF's CS-GENERAL
domain (the CS.UWATERLOO.CA
Kerberos realm). The Kerberos configuration is very similar to that used for a SAMBA server (ADAddSamba) but there are some additional components.
CS-GENERAL
domain ( CS.UWATERLOO.CA
kerberos realm). verify_ap_req_nofail = false
in [libdefaults]
udp_preference_limit = 1
in [libdefaults]
# #pragma ident "@(#)krb5.conf 1.2 99/07/20 SMI" # Copyright (c) 1999, by Sun Microsystems, Inc. # All rights reserved. [libdefaults] default_realm = CS.UWATERLOO.CA dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h forwardable = yes # default_tkt_enctypes = des-cbc-md5 ; or des-cbc-crc # default_tgs_enctypes = des-cbc-md5 ; or des-cbc-crc verify_ap_req_nofail = false udp_preference_limit = 1 [realms] CSCF.UWATERLOO.CA = { kdc = elisa.cscf.uwaterloo.ca:88 kdc = aeshena.cscf.uwaterloo.ca:88 kdc = glaciais.cscf.uwaterloo.ca:88 admin_server = elisa.cscf.uwaterloo.ca:464 kpasswd_server = elisa.cscf.uwaterloo.ca:464 kpasswd_protocol = SET_CHANGE } CS.UWATERLOO.CA = { kdc = intacta.cs.uwaterloo.ca:88 kdc = serverus.cs.uwaterloo.ca:88 kdc = viridis.cs.uwaterloo.ca:88 admin_server = intacta.cs.uwaterloo.ca:464 kpasswd_server = intacta.cs.uwaterloo.ca:464 kpasswd_protocol = SET_CHANGE } STUDENT.CS.UWATERLOO.CA = { kdc = eponina.student.cs.uwaterloo.ca:88 kdc = candenis.student.cs.uwaterloo.ca:88 kdc = cyanea.student.cs.uwaterloo.ca:88 admin_server = eponina.student.cs.uwaterloo.ca:464 kpasswd_server = eponina.student.cs.uwaterloo.ca:464 kpasswd_protocol = SET_CHANGE } [domain_realm] .cscf.uwaterloo.ca = CSCF.UWATERLOO.CA cscf.uwaterloo.ca = CSCF.UWATERLOO.CA .cs.uwaterloo.ca = CS.UWATERLOO.CA cs.uwaterloo.ca = CS.UWATERLOO.CA .student.cs.uwaterloo.ca = STUDENT.CS.UWATERLOO.CA student.cs.uwaterloo.ca = STUDENT.CS.UWATERLOO.CA [kdc] profile = /etc/krb5/kdc.conf [logging] default = FILE:/var/log/krb5/kdc.log kdc = FILE:/var/log/krb5/kdc.log admin_server = FILE:/var/log/krb5/kadmind.log [appdefaults] pam = { debug = true ticket_lifetime = 36000 renew_lifetime = 36000 forwardable = true krb4_convert = false } kinit = { renewable = true forwardable= true }
NOTE: As laid out in ADDnsConfiguration, our SCS (School of Computer Science) DNS space includes SRV records generated through the dynamic DNS registration of our forest domain controllers. In that case one may edit out direct references to specific KDC servers in krb5.conf
and enable dns_lookup_kdc
in [libdefaults]
. This causes the local kerberos client to use DNS to identify available KDC servers instead of maintaining them in the client's configuration file. However, if user password change is to be available, realm entries for admin_server
, kpasswd_server
and kpasswd_protocol
still need to be specified as DNS cannot convey the requisite SRV data. Use of dns_lookup_kdc = yes
should be implemented only after your Kerberos client is successfully configured.
With krb5.conf
and krb5.keytab
files in place in the /etc/krb5
directory on the Solaris host, one now initializes the kerberos client to the CS.UWATERLOO.CA
kerberos realm with the following command.
kinit -k -t /etc/krb5/krb5.keytab host/computername.cs.uwaterloo.ca@CS.UWATERLOO.CA
If you were successful kinit
will actually supply no output. However, executing a simple klist
command with no options should reveal new a kerberos ticket in the ticket cache. For example:
# klist Ticket cache: FILE:/tmp/krb5cc_0 Default principal: host/computername.cs.uwaterloo.ca@CS.UWATERLOO.CA Valid starting Expires Service principal 12/12/07 13:56:53 12/12/07 23:57:04 krbtgt/CS.UWATERLOO.CA@CS.UWATERLOO.CA renew until 12/19/07 13:56:53
But most importantly, there should be successful kerberos logon events appearing in the AD domain Security
logs for the computername-host account.
kinit
Errors
Password Incorrect While Getting Initial Credentials
This is the most difficult kinit
error to resolve. Most documentation is vague and talks of the keytab
file being corrupted or having the wrong key. The recommended course of action is to recreate the keytab
file on the domain controller and rerun the kinit
process on the Solaris host. It's worth trying at least once.
Other documentation suggests that Microsoft's ktpass
command cannot create properly encrypted keytab
files for Solaris hosts on certain types of hardware. In which case one can use the Solaris host's native ktutil
command as an alternate method for creating a keytab
file for the Solaris host.
KVNO
number for the host's SPN from the existing keytab
file with the command klist -k -t /etc/krb5/krb5.keytab
keytab
file by renaming it
ktutil
command to enter into the ktutil
interface
ktutil
interface, create a new key entry and write it back to /etc/krb5/krb5.keytab
addent -password -p host/computername.cs.uwaterloo.ca@CS.UWATERLOO.CA -k KVNO_number -e des-cbc-md5
wkt /etc/krb5/krb5.keytab
q
(quit command)
kinit
process again. Should kinit
fail again with the same error try a simple reset the password for the computername-host account in the Active Directory and attempt kinit
again.
Key Table Entry Not Found While Getting Initial Credentials
Client Not Found In Kerberos Database While Getting Initial Credentials
Both these errors can point to a mistake in the SPN naming either in the keytab
file, the executed kinit
command or perhaps the SPN for the Solaris host was not correctly mapped to the computername-host account in the Active Directory. You should check each item for a mistake.
You can check the SPN entered in the keytab
file by entering the command klist -k -t /etc/krb5/krb5.keytab
. Should there be an error then you will have to create a new keytab
file. Either re-run the Microsoft ktpass
command in the Active Directory with a correct SPN or utilize the Solaris ktutil
interface outlined in the above section to write a new keytab
file directly on the Solaris host.
You can check the SPN name mapping for the computername-host account using the Active Directory Users and Computers
tool. Open the account properties, the proper SPN name should be substituted for the User logon name
on the Account
tab. If it is incorrect then you should re-run the ktpass
command on the domain controller using the correct SPN. This will remap the account. This will generate another keytab
file but you will probably not require it.
Then attempt the kinit
process again.
If kinit
fails again with the Key Table Entry Not Found
error, then it is possible that the des-cbc-md5
encryption mode is not acceptable to the Solaris host's hardware or environment. The kerberos client may not be able to read the relevant SPN entry in the keytab
file. This has been known to occur for Solaris 10 hosts running on some forms of VMWare as opposed to being the base system OS. In this case create a keytab
file (or file entry) using rc4-hmac
encryption mode instead. This involves using the ktutil
command on the Solaris host.
KVNO
number for the host's SPN from the existing keytab
file with the command klist -k -t /etc/krb5/krb5.keytab
keytab
file by renaming it
ktutil
command to enter into the ktutil
interface
ktutil
interface, create a new key entry and write it back to /etc/krb5/krb5.keytab
addent -password -p host/computername.cs.uwaterloo.ca@CS.UWATERLOO.CA -k KVNO_number -e rc4-hmac
wkt /etc/krb5/krb5.keytab
q
(quit command)
msDS-KeyVersionNumber
Attributes
The KVNO
number for your Solaris host's SPN in the krb5.keytab
file must match the value of the msDS-KeyVersionNumber
attribute for the corresponding host account in the Active Directory. Be advised that each time the password for the host account is changed, the value of the msDS-KeyVersionNumber
attribute is incremented by one. Further, the value cannot be directly edited by either a domain or enterprise administrator.
One can view the value of the msDS-KeyVersionNumber
attribute for the host account using the previously mentioned ADSI
Editor. View the host account properties and all account attributes including msDS-KeyVersionNumber
are listed.
The KVNO
numbers in the Solaris host's krb5.keytab
file can be displayed using the klist -k
command at a Solaris command prompt.
At this point it would be a good idea to make a copy of the /etc/nsswitch.conf
file on the Solaris host and retain it in a safe place such as /tmp
. When configuring the LDAP client in the next section, the Solaris system often attempts to radically modify the /etc/nsswitch.conf
file. We've found this automatic modification to do more harm than good. Thus we create a stripped down, LDAP enabled nsswitch.conf
file which we can copy into place after configuring the Solaris LDAP client.
For most cases the default nsswitch.conf
file will have entries set only to the files
lookup mode. The exceptions being hosts
and ipnodes
which will also use dns
for lookups. In your copy of nsswitch.conf
add ldap
after the files
entry for both the passwd
and group
lines. Your version of nsswitch.conf
will now look rather a lot like the following. Keep this in safe location until you have configured the Solaris LDAP client to your satisfaction.
# DNS service expects that an instance of svc:/network/dns/client be # enabled and online. passwd: files ldap group: files ldap # You must also set up the /etc/resolv.conf file for DNS name # server lookup. See resolv.conf(4). hosts: files dns # Note that IPv4 addresses are searched for in all of the ipnodes databases # before searching the hosts databases. ipnodes: files dns networks: files protocols: files rpc: files ethers: files netmasks: files bootparams: files publickey: files # At present there isn't a 'files' backend for netgroup; the system will # figure it out pretty quickly, and won't use netgroups at all. netgroup: files automount: files aliases: files services: files printers: user files auth_attr: files prof_attr: files project: files tnrhtp: files tnrhdb: files
To properly configure the Solaris host's LDAP client you will require the following.
root
) access rights to the new Solaris host.
ldapclient
command at a Solaris host prompt. To simplify this process it is better to keep the command text in a text file for easy editing and then cat
the contents into a csh
shell in the following manner when you want to execute.
cat ldapconfig.txt | /bin/csh
Where the contents of ldapconfig.txt
are as follows.
ldapclient manual \ -a credentialLevel=anonymous \ -a authenticationMethod=none \ -a defaultSearchBase=dc=cs,dc=uwaterloo,dc=ca \ -a defaultSearchScope=sub \ -a followReferrals=false \ -a domainName=cs.uwaterloo.ca \ -a preferredServerList=129.97.152.249 \ -a defaultServerList=129.97.152.159 \ -a attributeMap=group:cn=displayName \ -a attributeMap=group:userpassword=userPassword \ -a attributeMap=group:memberuid=memberUid \ -a attributeMap=group:gidnumber=gidNumber \ -a attributeMap=passwd:uid=cn \ -a attributeMap=passwd:gidnumber=gidNumber \ -a attributeMap=passwd:uidnumber=uidNumber \ -a attributeMap=passwd:homedirectory=unixHomeDirectory \ -a attributeMap=passwd:loginshell=loginShell \ -a attributeMap=shadow:uid=cn \ -a attributeMap=shadow:shadowflag=shadowFlag \ -a attributeMap=shadow:userpassword=userPassword \ -a objectClassMap=group:posixGroup=group \ -a objectClassMap=passwd:posixAccount=user \ -a objectClassMap=shadow:shadowAccount=user \ -a serviceSearchDescriptor=passwd:"dc=cs,dc=uwaterloo,dc=ca?sub" \ -a serviceSearchDescriptor=group:"dc=cs,dc=uwaterloo,dc=ca?sub"
Once this command runs successfully, replace /etc/nsswitch.conf
with your edited copy of nsswitch.conf
from above. It would also be a good idea to restart the LDAP client service on the Solaris host with the following command.
svcadm restart svc:/network/ldap/client:default
NOTE: At the present time we have only successfully configured the LDAP client using a single IP address for the preferredServerList
entry. In order for the Solaris host to not be completely dependent upon one domain controller for LDAP services, the given IP address ( 129.97.152.249
) represents a load balanced cluster of domain controllers. In the CS-GENERAL
domain TCP ports 389
and 636
(LDAP and LDAPS) are load balanced across all domain controllers using Microsoft Network Load Balancing
- a built-in feature of all Windows 2003 servers. The load balancing manages the distribution of client LDAP packets to available domain controllers in the cluster. Network Load Balancing
must be configured in Multicast
mode for all cluster members otherwise the domain controllers will not be able to communicate with each other and the domain will slowly desynchronize - very, very bad.
There is also a defaultServerList
entry in the above command line. This represents a single domain controller in the CS-GENERAL
domain which will provide LDAP services in the event the load balanced cluster becomes unavailable.
For the CS-TEACHING
domain, the LDAP cluster is 129.97.152.125
.
NOTE: We have a line in the ldapclient
command that reads, -a attributeMap=group:cn=displayName \
. This configuration maps the UNIX groupname attribute to the displayName
attribute of an Active Directory group object. As opposed to the default condition of simply mapping to a group object's cn
attribute. This mapping is a local adaptation in order to overcome some locally created technical issues and is probably not necessary for all set ups.
To configure the Solaris host's PAM Stack you will require the following:
root
) access rights to the new Solaris host.
/etc/pam.conf
file. For this document, we will be modifying the 'other' service module in the PAM stack but these modification may be applied to differing services specified in the pam.conf
file.
For LDAP account lookup, the /etc/pam.conf
is now modified by adding the pam_ldap.so
module into the account management stack. We place this module prior to a unix account ( /etc/passwd
) look up. If a user account is found through LDAP then that is sufficient for accepting the account.
other account requisite pam_roles.so.1 other account sufficient pam_ldap.so.1 other account sufficient pam_unix_account.so.1
For Kerberos authentication we add the pam_krb5.so
module to the authentication stack in pam.conf
. In this case, authentication through the Kerberos realm occurs first and if successful is considered sufficient for the user to be regarded as authenticated for the local Solaris host.
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
If you wish for users to be able to set their Kerberos (Active Directory) passwords, these additional modifications are necessary. One is to introduce the the pam_krb5.so
module into the password
management stack for the other
login service.
other password required pam_dhkeys.so.1 other password requisite pam_authtok_get.so.1 other password sufficient pam_krb5.so.1 other password requisite pam_authtok_check.so.1 other password required pam_authtok_store.so.1
The next is the (seemingly redundant) introduction of the pam_krb5.so
module into the auth
stack of the passwd
login service.
passwd auth requisite pam_authtok_get.so.1 passwd auth required pam_dhkeys.so.1 passwd auth sufficient pam_krb5.so.1 debug passwd auth required pam_unix_cred.so.1 passwd auth required pam_unix_auth.so.1
ChallengeResponseAuthentication
must be enabled in sshd_config
in order to force password changes upon users whose AD accounts have been set to demand a password change upon next logon.