ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


Kerberos: The Definitive Guide

Single Sign-on for Your Web Applications with Apache and Kerberos

by Jason Garman, author of Kerberos: The Definitive Guide
09/11/2003

So you now have a fully functioning Kerberos infrastructure. All of your machines, regardless of operating system or architecture, are able to utilize the single sign-on infrastructure that Kerberos provides for some typical services, such as local login and email. However, there are some web applications that you'd now like to provide to your users, and you'd like them to utilize all of the hard work you've put into establishing a Kerberos infrastructure. In short, you want to Kerberize your internal web applications. But how?

Well, unfortunately, the answer is a bit complicated. There have been many attempts to Kerberize web servers and browsers, starting with NCSA Mosaic browsers and NCSA httpd servers that supported Kerberos 4 in the mid '90s. Today, the most prevalent standard for performing Kerberos authentication is the HTTP Negotiate mechanism, which is integrated into Microsoft Internet Explorer and Internet Information Server. There's also a simpler mechanism, available in patches for Mozilla and Apache, but it is not enabled by default on either Mozilla or Apache, and it doesn't interoperate with IE and IIS.

To understand how we got into this position, we need to take a few steps back and look at the current state of both Kerberos and web authentication. First, we'll take a look at the current state of Kerberos 5 APIs. Most applications that use Kerberos 5 don't use the Kerberos 5 API directly; instead, they use an abstraction layer "above" Kerberos 5. Most people (well, at least people familiar with programming Kerberos applications) will say that this layer exists to reduce complexity in client and server code, but the real reason behind using this abstraction is that the raw Kerberos 5 APIs are not standardized across implementations; they are subject to change from revision to revision; and, in general, they are a pain to use. And of course, standards being what they are, there's two of these abstraction layers to choose from: GSSAPI and SSPI. GSSAPI, or the "Generic Security Services API," is the API provided by Unix-based Kerberos 5 implementations. SSPI, the "Security Support Provider Interface," is Microsoft's answer to GSSAPI and, of course, available only for Windows 2000 and above.

Related Reading

Kerberos: The Definitive Guide
By Jason Garman

Now, let's take a look at the state of web authentication today. Those who have worked with web authentication in the past are familiar with Basic, the most common authentication mechanism. Basic authentication is a simple exchange between client and server; the server sends the browser a "realm," to which the client must authenticate. The browser displays this realm string, and prompts the user for a username and password that is valid in the given realm. The browser then passes this username and password back to the server in clear text when it retries the original request. (OK, for the pedants in the audience, the username and password are obfuscated with Base-64.)

Kerberized Web Authentication Today

Of course, we can always jury-rig Basic authentication to work with our Kerberos realm; we can perform the user authentication on the web server, given a Kerberos username and password entered through Basic authentication. Of course, there are some security precautions that must be taken in order to make sure this method is secure. First, the connection between server and browser must be encrypted with SSL to protect the plain-text credentials. And second, the web server should take appropriate precautions, including verifying the user's TGT against a service principal to prevent possible man-in-the-middle attacks on the Kerberos protocol exchange. With the appropriate security measures in mind, this setup will work and, dare I say it, may even be appropriate, in some cases. However, to anyone who has taken the time and effort to establish a Kerberos infrastructure, this "solution" falls well short of what should be possible with a fully Kerberized authentication environment.

The immediate response that comes to mind is to use one of the abstraction layers we discussed above. A set of patches for both Apache and Mozilla implement Kerberos authentication in just this way; the patches use GSSAPI to provide authentication based on Kerberos to Apache and Mozilla. These patches are available at meta.cesnet.cz/software/heimdal/negotiate.en.html.

However, we want to interoperate with Internet Explorer, so let's continue on.

The Simple and Protected Negotiation Mechanism

Microsoft took a slightly more complex approach, for practical reasons. While the default authentication mechanism in Windows 2000 and above is Kerberos, support for NTLM is still required for backward compatibility with NT and earlier operating systems. GSSAPI abstracts out the details of interfacing with different authentication mechanisms, but it doesn't provide a way to negotiate which of the mechanisms to use. Therefore, Microsoft uses SPNEGO, the Simple and Protected Negotiation mechanism. SPNEGO provides a method where server and client can mutually negotiate the best authentication mechanism to use (in this case, NTLM and Kerberos). The use of SPNEGO for web-based authentication is referred to as the HTTP Negotiate protocol. Once the negotiation is finished, then the mutually agreed upon authentication mechanism can begin. In this case, we'll only be compatible with the Windows Kerberos authentication mechanism; it will fail if Windows attempts to use NTLM instead.

In my book, Kerberos: The Definitive Guide, I describe how to use Basic authentication to verify Kerberos passwords over the Web because of a lack of a freely available SPNEGO implementation. However, as the book was going to print, an Apache module that implements SPNEGO was released. While it is still in an early beta status, it does work quite well, and its only real drawback at this point is its cumbersome installation process. I will walk you thought the SPNEGO implementation process in the remainder of this article.

Implementing SPNEGO

What will this module allow you to do? It will enable Apache-based web servers to allow for transparent domain authentication through Active Directory. Windows-based clients who are logged into an Active Directory domain can now access Apache servers with this module through Internet Explorer, and be transparently authenticated to web applications on the Apache server. Internet Explorer will acquire Kerberos service tickets for the Apache server and use the Negotiate HTTP authentication mechanism to pass a Kerberos service ticket to the Apache server.

The prerequisites for implementing this solution are:

Setting Up the Web Server

First, you'll have to create a service principal for the Apache server. This service principal will be named HTTP/hostname@REALM. Our example will be for the host freebsd.wedgie.org, in the w2k.wedgie.org AD domain. The service principal in this case will be HTTP/freebsd.wedgie.org@W2K.WEDGIE.ORG (yes, HTTP needs to be capitalized, as this is the exact service principal that IE will request). This principal will be created in the Active Directory Users and Computers MMC snap-in and the keytab exported via the ktsetup program.

Because Windows usernames cannot contain slashes, you'll have to pick a username that will be mapped to the HTTP service principal. In this case, we will create a user named freebsdhttp. The password set for this account will become the service principal's key, so ensure that the password set for this account is a secure password.

Once the Windows user has been created, then you can map the user and export a keytab through the ktpass program. ktpass is not installed by default; it can be found inside of the support/tool subdirectory of the Windows 2000 Server installation CD. The ktpass command line we will use for our example is:

ktpass -out http.keytab -princ 
HTTP/freebsd.wedgie.org@W2K.WEDGIE.ORG -pass * -mapuser 
freebsdhttp

Successfully mapped HTTP/freebsd.wedgie.org to freebsdhttp.
Type the password for HTTP/freebsd.wedgie.org:
Key created.
Output keytab to http.keytab:

Keytab version: 0x502
keysize 65 HTTP/freebsd.wedgie.org@W2K.WEDGIE.ORG ptype 1 
(KRB5_NT_PRINCIPAL) vno 1 etype 0x1 (DES-CBC-CRC) keylength 
8 (0xf253024517c75f80)
Account has been set for DES-only encryption.

The keytab can now be copied from the Windows machine to the Apache server through some secure means, such as secure copy or using a floppy. We will place the keytab into the directory /usr/local/apache/etc, but it can be placed anywhere in the file system. Since the contents of this file are sensitive, it should be readable only by the user the web server runs as.

Compiling the Apache Module

Now we're ready to install mod_auth_gss_krb5. While the instructions on the SourceForge page show how to build the module statically inside of Apache at compile time, most administrators prefer the management flexibility of loadable Apache modules.

Let's step through how you can compile mod_auth_gss_krb5 as a shared module.

First, you'll need spnegohelp, which is the mini-SPNEGO library that Microsoft has released on its web site. This library is included with the module distribution in the spnegohelp directory. Note that there is a pre-processor define for __LITTLE_ENDIAN__ by default. Those running on processors with big- endian byte order, such as PowerPC or Sparc, will have to remove this pre- processor define from the makefile before building spnegohelp.

Now you're ready to compile the Apache module itself. Note that on the FreeBSD test machine, I had to remove all references to the log() function in mod_auth_gss_krb5.c. If these aren't removed, you will get unresolved references to _log in the server's error log when you load the module .

We'll use apxs, the Apache extension tool, to do the dirty work for us. Assuming that your Apache is installed into /usr/local/apache and MIT Kerberos has been installed into /usr/local, then the following command will compile and install the module into the appropriate location:

/usr/local/apache/bin/apxs -i -a -c -DEAPI_MM
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-I/usr/local/include -L/usr/local/lib 
../../../spnegohelp/spnegohelp.a -L/usr/local/lib
-lgssapi_krb5 -ldes425 -lkrb5 -lk5crypto -lcom_err 
mod_auth_gss_krb5.c

Now that apxs has compiled and installed the module, we can add the appropriate directives inside of our httpd.conf file to require authentication for certain directories. Inside of a <directory> section, insert the following directives:

 GssKrb5Keytab "/usr/local/apache/etc/httpd.keytab"
 Krb5Keytab "/usr/local/apache/etc/httpd.keytab"
 KrbAuthRealm W2K.WEDGIE.ORG
 Krb5SaveCredentials Off
 AuthType GSS
 GssAuth On
 AuthName "KRB5 Realm"
 require valid-user

The paths to the keytab and the realm name should be changed, of course. Now start the Apache server.

Configuring the Clients

Our next step is to configure the Windows client. Internet Explorer must be set up to recognize that our new Apache server is in the Intranet zone, and instructed to use domain authentication with it. Open up the Internet Options dialog inside of Internet Explorer. The Security tab contains the security zones that Internet Explorer recognizes. Click Intranet and click the Sites button. Click Advanced in the next dialog box, and a third dialog is presented where we can add sites that will be added to the Intranet zone. Click Add and type in the name of your Apache server, in this case "freebsd.wedgie.org." Return to the Internet Options dialog, Security tab. Click the "Custom Level" button for the Intranet security zone. Ensure that "User authentication - Automatic logon only in intranet zone" is selected (at the bottom of the list). Click OK.

If you're using Internet Explorer 6 or above, one more setting must be tweaked. Inside of the Internet Options dialog box, Advanced tab, there is a setting named "Enable Integrated Windows Authentication" inside of the Security group. If this box is not checked, check the box, and restart the machine. More information on these browser settings can be found in the Microsoft MSDN library.

Now that everything is set up, it's time to see if everything works. Open IE and go to the protected URL on the Apache server. If the page displays, then congratulations! The full Kerberos username of the client will be inserted into the REMOTE_USER environment variable on the Apache server side, for example Administrator@W2K.WEDGIE.ORG. A simple PHP script or server-side include page can be used to verify that the REMOTE_USER is now set.

Troubleshooting

What could go wrong?

First, let's take a look at what could happen on the client side. Ensure that you're logged in to the Windows domain and have a valid Kerberos TGT. You can also check to see if IE successfully acquired a service ticket for your Apache server through kerbtray, included with the Windows Resource Kit.

Next, make sure that you aren't using a proxy to contact your Apache server. Unfortunately, the Negotiate authentication method does not work through web proxies. Ensure that if a proxy is set, that an exclusion is made for the Apache sever (assuming, of course, that the server is reachable directly).

If instead you're getting internal server errors from Apache, you should make sure that the GssKrb5Keytab and Krb5Keytab directives give the correct path to the keytab and that it is readable by the web server's user ID. If problems persist, then there is probably something going wrong with your Kerberos configuration.

If you're getting an error message such as :

[Wed Aug 27 01:05:21 2003] [notice] [client 192.168.1.23] 
gss_acquire_cred() failed: No principal in keytab matches 
desired name:

the GSSAPI libraries either can't read or find your keytab, or your hostname or realm are misconfigured. Make sure that your hostname is set correctly; both forward and reverse DNS should map to the correct hostname. Test it out by doing nslookup queries on the Apache server itself. If your hostname is configured correctly, then ensure that the AD server is configured as your default_realm in the /etc/krb5.conf file.

Summary

After performing these steps, you now have an Apache web server that can interoperate with Internet Explorer clients in a Windows domain. Clients who access the protected area of your Apache web server will transparently pass their domain credentials to your web server through the use of Kerberos, with no separate username or password prompts.


O'Reilly & Associates recently released (August 2003) Kerberos: The Definitive Guide.

Copyright © 2009 O'Reilly Media, Inc.