Kerberos Principals for Unix-based Services in Active Directory

A service principal is needed whenever you want to provide Single Sign-on for users that have already authenticated against an Active Directory domain. They are also handy for verifying the TGT issued by a domain controller on user login. The process of creating a principal can be summarized in a few basic steps:

  • Create a user in AD representing the service
  • Map the Windows user name to a service principal name
  • Set the password on the account
  • Generate a keytab file and install (or merge) it on the Unix host providing the service

CSCF Conventions

In AD, the Windows user name for the principal account is of the form hostname-servicename. So, the user name representing the host service principal for cpu02 would be cpu02-host.

Another thing to keep in mind is that Unix-based service principals are located in a specific place in the directory tree of the domain. (actually this does not matter, as the principal will be searched for in the AD tree albeit from an administrative point of view you should put them in a human findable location).

Creating Principals from the Unix side using mkADprincipals.pl

With a standalone Ubuntu Linux box and domain credentials with sufficient privileges, you can do all you need to without access to a Windows host. All you need to do, is run the mkADprincipals.pl script.

Pre-Requisites for mkADprincipals.pl

  • Set-up LDAPS on your Linux client
  • Install PERL modules: libio-socket-ssl-perl liblocale-gettext-perl    libnet-ldap-perl libterm-readkey-perl libunicode-map8-perl    libunicode-string-perl libstring-random-perl

Example usage

Suppose you wish to create an nfs service principal for the hosts krbtux and krbsol in the STUDENT.CS.UWATERLOO.CA domain. First, create a file named myhosts that contains the FQDN of each host, one per line. Then run the script:

mkADprincipals.pl -h canadenis.student.cs.uwaterloo.ca -D Administrator@STUDENT.CS.UWATERLOO.CA 
-b 'OU=Unix machine accounts,OU=Special Accounts,OU=CS,DC=student,DC=cs,DC=uwaterloo,DC=ca' 
-f myhosts -R STUDENT.CS.UWATERLOO.CA -s nfs

After running the perl script, for each host, you need to do the following:

  • Run ktutil.
  • At the ktutil: prompt, type addent -password -p PRINCIPAL_NAME -k KVNO -e des-cbc-crc, where PRINCIPAL_NAME and KVNO are given by the perl script.
    • The principal generated may have the shortened form (for host principal) host/hostname without mention of the realm. You must change it to host/hostname@STUDENT.CS.UWATERLOO.CA.
  • When prompted, enter the password output by the perl script.
  • Type wkt hostname.keytab.
  • Exit ktutil by typing q.
  • Securely copy the keytab file(s) that you generated to the krb5.keytab file on each host. Note that the host(s) might already have a keytab file, so you may have to merge them using ktutil.

Possible Improvements to mkADprincipals.pl

  • Better error handling.
  • Just plain better coding.
  • Have it generate keytab files itself.

Creating Principals on the Windows Side

This method is clearly not as convenient as the above Unix side approach but it might be more reliable as both the account and keytab are being created by Windows tools and are therefore likely to be consistent but this is merely a speculative comment and cannot be justified formally smile

Create a User based account for the host such that the User login name is host\FQDN@DOMAIN_NAME where FQDN is to be substituted with the _fully qualified domain name_ of the host and DOMAIN_NAME is the Windows domain the principal is being added to. As a result of this you will see the field =User login user (pre-windows 2000)= field filled out automatically. Instead edit it to read hostname-host, where hostname has no dots (I suspect this isn't really too important but you will need to remember it when using the ktpass command to generate a keytab file). Set a password and set to not expire and set 'Do not require kerberos pre-auth'.

Create keytab file to transferred to Linux system.

ktpass -ptype KRB5_NT_PRINCIPAL -crypto DES-CBC-MD5 -princ host/fqdn@KERBERO_REALM
          -mapuser Domain_Name\hostname-host -pass ComplexPasswd -out c:\temp\krb5.keytab
where DOMAIN_NAME is either cscf.uwaterloo.ca, cs.uwaterloo.ca, student.cs.uwaterloo.ca, =sysadmins.cscf.uwaterloo.ca which correspond, to the NetBios names CSCF, CS-GENERAL, CS-TEACHING, CSCF-SYSADMINS, respectively (Aside: The notion of a NetBios name seems to correspond to something called pre-windows 2000 Domain name). The KERBEROS name is simply the uppercase of the domain name (see http://support.microsoft.com/kb/248807 for confirmation).

As an example suppose we have a host called mathdude.cscf and that we want to add it to the CSCF domain. We would then have User login name of host/mathdude.cscf.uwaterloo.ca@cscf.uwaterloo.ca and the older pre-windows 2000 name of CSCF\mathdude-host. The corresponding ktpass command to generate a keytab for this host is

ktpass -ptype KRB5_NT_PRINCIPAL -crypto DES-CBC-MD5 -princ host/mathdude.cscf.uwaterloo.ca@CSCF.UWATERLOO.CA
         -mapuser CSCF\hostname-host -pass ComplexPasswd -out c:\temp\krb5.keytab.mathdude
where ComplexPasswd is the same one you used to create the principal for the hostname. Next transfer (via ssh, for example) the file c:\temp\krb5.keytab.mathdude to mathdude.cscf and copy it to /etc/krb5.keytab which will have the following permissions and ownership
-rw------- 1 root root 82 2007-11-19 13:47 /etc/krb5.keytab

Change passwd of a User in the Active Directory from Ubuntu

We have created a user, walter, in the Active Directory using Windows tools. We now install the krb5-user package which contains kpasswd command which changes the password of a Kerberos principal. We can then change =walter='s password
kpasswd walter
Password for walter@CS.UWATERLOO.CA:
NOTE. That klist as root gives no cached credentials.

The above works without any changes to the system other than creating a kerberos credentials for the host, setting up, /etc/krb5.keytab and /etc/krb5.conf. No pam configuration of any kind and no editing of /etc/nsswitch.conf.

Package libnss_ldap installed on Ubuntu client

The package libnss-ldap possesses the dynamic library /lib/libnss_ldap-2.6.1.so and is configured by /etc/ldap.conf. The library has the following shared object dependencies:
# ldd /lib/libnss_ldap-2.6.1.so
        linux-gate.so.1 =>  (0xffffe000)
        libldap_r.so.2 => /usr/lib/libldap_r.so.2 (0xb7f00000)
        liblber.so.2 => /usr/lib/liblber.so.2 (0xb7ef4000)
        libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0xb7eca000)
        libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7ec6000)
        libnsl.so.1 => /lib/tls/i686/cmov/libnsl.so.1 (0xb7eae000)
        libresolv.so.2 => /lib/tls/i686/cmov/libresolv.so.2 (0xb7e9b000)
        libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7e83000)
        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7d39000)
        libcrypt.so.1 => /lib/tls/i686/cmov/libcrypt.so.1 (0xb7d0a000)
        libsasl2.so.2 => /usr/lib/libsasl2.so.2 (0xb7cf3000)
        libgnutls.so.13 => /usr/lib/libgnutls.so.13 (0xb7c83000)
        libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0xb7bfb000)
        libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0xb7bd6000)
        libcom_err.so.2 => /lib/libcom_err.so.2 (0xb7bd2000)
        libkrb5support.so.0 => /usr/lib/libkrb5support.so.0 (0xb7bca000)
        libkeyutils.so.1 => /lib/libkeyutils.so.1 (0xb7bc8000)
        /lib/ld-linux.so.2 (0x80000000)
        libtasn1.so.3 => /usr/lib/libtasn1.so.3 (0xb7bb8000)
        libgpg-error.so.0 => /usr/lib/libgpg-error.so.0 (0xb7bb4000)
        libz.so.1 => /usr/lib/libz.so.1 (0xb7b9e000)
        libgcrypt.so.11 => /usr/lib/libgcrypt.so.11 (0xb7b4d000)
from which we see that Kerberos, TLS, and SASL are builtin. In particular, the kerberos support seems to be via the GSSAPI interface.

At this point we are in position to edit /etc/nsswitch.conf and enable ldap. The vendor configuration is given by

# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.

passwd:         compat
group:          compat
shadow:         compat

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis
As noted in the comments of /etc/nsswitch.conf, much of the functionality of NSS is part of the C library. In particular, we have
dpkg -L libc6|grep nss
/lib/libnss_compat-2.6.1.so
/lib/libnss_dns-2.6.1.so
/lib/libnss_files-2.6.1.so
/lib/libnss_hesiod-2.6.1.so
/lib/libnss_nis-2.6.1.so
/lib/libnss_nisplus-2.6.1.so
/lib/libnss_compat.so.2
/lib/libnss_dns.so.2
/lib/libnss_files.so.2
/lib/libnss_hesiod.so.2
/lib/libnss_nis.so.2
/lib/libnss_nisplus.so.2
(by the way, the documention is in glibc-doc package not the glibc-doc-reference package).

Simply put, NSS, is a way of accessing system databases which various programs on a Linux may need to access. Examples include user data, name service data (presumably this is where the name came from). We would like to be able to consult and LDAP database via NSS. To enable this we install the libnss-ldap package which also pulls in the libpam-ldap package (it's not entirely clear what the exact dependency on pam is).

We make the following change to /etc/nsswitch.conf to enable LDAP database access

 rcsdiff ./nsswitch.conf 
===================================================================
RCS file: ./RCS/nsswitch.conf,v
retrieving revision 1.1
diff -r1.1 ./nsswitch.conf
7,9c7,9
< passwd:         compat
< group:          compat
< shadow:         compat
---
> passwd:         files ldap
> group:          files ldap
> shadow:         files ldap
Next we configure which LDAP database we wish to communicate with by editing /etc/ldap.conf appropriately. (At this point we need some way to access the Active Directory Anonymously which apparently is possible via Solaris NSS services but I haven't figured it out yet for Ubuntu/Linux.)

Authenticating existing users via Active Directory

By existing users I mean those that have an entry in /etc/passwd on the host they are attempting to login to albeit they may not have a Unix passwd in the shadow file but instead it exists in the AD.

Can we get this to work via /etc/nsswitch.conf setup? Can we get it work with the pam_krb5.so module? The answer to the first is unclear but the answer to the second is yes.

Automatic home directory creation if it does not exist

We want to use the account data stored in AD to create user's home directory along with the shell, UID, GID as stored in the AD rather than in the passwd file. In short the command getent passwd walter should give output (no luck yet as we need to be able bind anonymously which I haven't solved).

Topic attachments
I Attachment History Action Size Date Who Comment
Texttxt mkADprincipals.pl.txt r3 r2 r1 manage 5.6 K 2007-07-23 - 11:48 IlguizLatypov Show error messages.
Edit | Attach | Watch | Print version | History: r13 < r12 < r11 < r10 < r9 | Backlinks | Raw View | Raw edit | More topic actions...
Topic revision: r10 - 2007-12-04 - WalterTautz
 
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2025 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback