--------------------------------------------------------------------------------
readme.txt is the mod_spnego read-me file.

Author: Frank Balluffi and Markus Moeller

Copyright (C) 2002-2005 Frank Balluffi and Markus Moeller. All rights reserved.
--------------------------------------------------------------------------------

mod_spnego Read Me

Frank Balluffi and Markus Moeller
August 19, 2005

1 Introduction

mod_spnego is a reference implementation Apache module that supports
authentication via the RFC 2478 SPNEGO GSS-API mechanism. Currently, mod_spnego
supports Apache 1.3 and 2.0 on Linux, Solaris and Windows.

mod_spnego was originally written to handle RFC 2478 SPNEGO tokens sent by
Microsoft Internet Explorer. Later, support for RFC 1964 Kerberos tokens (as
sent by Mozilla Firefox on Linux) was added.

mod_spnego uses the following libraries:

- Apache
- MIT GSS-API or HEIMDAL GSS-API or IBM AIX NAS or Sun Solaris SEAM
- fbopenssl

fbopenssl contains extensions to OpenSSL, including APIs for GSS-API and SPNEGO.

mod_spnego has been built and tested on Apache 1.3.29* and 2.0.46 on the
following operating systems:

- Microsoft Windows 2000 Server Service Pack 4 with Visual C++ .NET
- Sun Solaris 2.8 (SunOS 5.8) with gcc 2.95
- SuSE Linux 8.2 with gcc 3.3

mod_spnego has been tested with the following clients:

Microsoft Internet Explorer on Windows XP Service Pack 1
Mozilla Firefox 1.0 on Windows XP Service Pack 1
Mozilla Firefox 1.0 on SuSE Linux 8

mod_spnego still lacks the following:

- group authorization files

For more information about open issues, see the Open Issues section (below).

* The authors were not able to install Apache 1.3.29 on Windows, so
  Apache 1.3.28 was used.

2 Building and Installation

2.1 Linux and UNIX

Build and install Apache. For example, Apache 1.3:

[Get apache_1.3.29.tar.gz.]
gunzip apache_1.3.29.tar.gz
tar xvf apache_1.3.29.tar
cd apache_1.3.29
./configure --prefix=/test/ballfra/apache --enable-module=most --enable-shared=max
make
make install

and for Apache 2.0:

[Get httpd-2.0.46.tar.gz.]
gzip -d httpd-2.0.46.tar.gz
tar xvf httpd-2.0.46.tar
cd httpd-2.0.46
./configure --prefix=/test/ballfra/apache2 --enable-so
make
make install

Build OpenSSL. For example:

[Get openssl-0.9.7b.tar.gz.]
gunzip openssl-0.9.7b.tar.gz
tar xvf openssl-0.9.7b.tar
cd openssl-0.9.7b
./config shared
make

Define the environment variable OPENSSLDIR to point to OpenSSL. For example:

echo $OPENSSLDIR
/home/ballfra/external/openssl-0.9.7b

If OpenSSL has been installed, change the following line in Makefile from:

SSLLIB = -Wl,-R$(OPENSSLDIR) -L$(OPENSSLDIR) -lcrypto

to:

SSLLIB = -Wl,-R$(OPENSSLDIR)/lib -L$(OPENSSLDIR)/lib -lcrypto

Build fbopenssl. For example:

cd fbopenssl
make CFG=release

Define the environment variable FBOPENSSLDIR to point to fbopenssl. For example:

echo $FBOPENSSLDIR
home/ballfra/src/fbopenssl

Build MIT GSS-API. For example:

[Get krb5-1.2.8.tar.gz.]
gunzip krb5-1.2.8.tar.gz
tar xvf krb5-1.2.8.tar
cd krb5-1.2.8/src
./configure --enable-shared --with-cc=gcc
make

To build version (MIT GSS-API) 1.3.1 with gcc, use "./configure --enable-shared CC=gcc".

Define the environment variable KRB5DIR to point to MIT KRB5. For example:

echo $KRB5DIR
home/ballfra/external/krb5-1.2.8

Build and install mod_spnego. For example, Apache 1.3:

MYCFLAGS="-I${KRB5DIR}/src/include -I${FBOPENSSLDIR}/include -I${OPENSSLDIR}/include"
MYLDFLAGS="-L${KRB5DIR}/src/lib/gssapi/krb5 -lgssapi_krb5 -L${FBOPENSSLDIR}/SunOS-debug -lfbopenssl -L${OPENSSLDIR} -lcrypto"
rm mod_spnego.o mod_spnego.so unix-env.o
rm -fr .libs
/test/ballfra/apache/bin/apxs -c -a -i -D APACHE13 -D HAVE_PUTENV $MYCFLAGS $MYLDFLAGS mod_spnego.c unix-env.c

or for HEIMDAL

MYCFLAGS="-I${KRB5DIR}/src/include -I${FBOPENSSLDIR}/include -I${OPENSSLDIR}/include"
MYLDFLAGS="-L${KRB5DIR}/src/lib/gssapi/krb5 -lgssapi -L${FBOPENSSLDIR}/SunOS-debug -lfbopenssl -L${OPENSSLDIR} -lcrypto"
rm mod_spnego.o mod_spnego.so unix-env.o
rm -fr .libs
/test/ballfra/apache/bin/apxs -c -a -i -D HEIMDAL -D APACHE13 -D HAVE_PUTENV $MYCFLAGS $MYLDFLAGS mod_spnego.c unix-env.c

and for Apache 2.0:

MYCFLAGS="-I${KRB5DIR}/src/include -I${FBOPENSSLDIR}/include -I${OPENSSLDIR}/include"
MYLDFLAGS="-L${KRB5DIR}/src/lib/gssapi/krb5 -lgssapi_krb5 -L${FBOPENSSLDIR}/SunOS-debug -lfbopenssl -L${OPENSSLDIR} -lcrypto"
rm mod_spnego.o
rm -fr .libs
/test/ballfra/apache2/bin/apxs -c -a -i $MYCFLAGS $MYLDFLAGS mod_spnego.c

Modify environment variable LD_LIBRARY_PATH to include directories containing
libcrypto.so and libgssapi_krb5.so.

or for HEIMDAL

MYCFLAGS="-I${KRB5DIR}/src/include -I${FBOPENSSLDIR}/include -I${OPENSSLDIR}/include"
MYLDFLAGS="-L${KRB5DIR}/src/lib/gssapi/krb5 -lgssapi -L${FBOPENSSLDIR}/SunOS-debug -lfbopenssl -L${OPENSSLDIR} -lcr
ypto"
rm mod_spnego.o
rm -fr .libs
/test/ballfra/apache2/bin/apxs -c -a -i -D HEIMDAL $MYCFLAGS $MYLDFLAGS mod_spnego.c

or for IBM AIX NAS with IBM HTTP Server 6.0.2.0)


MYCFLAGS="-I/opt/freeware/include"
MYLDFLAGS="-L/opt/freeware/lib -lgssapi_krb5 -lfbopenssl -lcrypto" 
rm mod_spnego.o
rm -fr .libs
/usr/IBMIHS/bin/apxs  -c -a -i -D HAVE_PUTENV $MYCFLAGS $MYLDFLAGS mod_spnego.c 

with libfbopenssl.a in /opt/freeware/lib, fbopenssl headers in /opt/freeware/include, openssl from the AIX Linux Toolkits and xlc compiler.

or for Sun Solaris SEAM 

MYCFLAGS="-I/usr/sfw/include -Wc,-g"
MYLDFLAGS="-lgss -L/usr/sfw/lib -Wl,-R/usr/sfw/lib -lfbopenssl -lcrypto"
rm mod_spnego.la mod_spnego.lo mod_spnego.o mod_spnego.slo
rm -fr .libs
/usr/apache2/bin/apxs -c -a -i -DSEAM -D HAVE_PUTENV $MYCFLAGS $MYLDFLAGS mod_spnego.c

with libfbopenssl.a in /usr/sfw/lib and fbopenssl headers in /usr/sfw/include 

2.2 Windows

Install Apache 1.3 or Apache 2.0.
For Apache 1.3, define the environment variable APACHE13DIR to point to
Apache 1.3. For example:

echo %APACHE13DIR%
C:\Program Files\Apache Group\Apache

For Apache 2.0, define the environment variable APACHE2DIR to point to
Apache 2.0. For example:

echo %APACHE2DIR%
C:\Program Files\Apache Group\Apache2

Build OpenSSL.
Define the environment variable OPENSSLDIR to point to OpenSSL. For example:

echo %OPENSSLDIR%
C:\external\openssl-0.9.7b

Build fbopenssl.
Define the environment variable FBOPENSSLDIR to point to fbopenssl. For example:

echo %FBOPENSSLDIR%
C:\frank\src\fbopenssl

Build MIT GSS-API.
Define the environment variable KRB5DIR to point to MIT KRB5. For example:

echo %KRB5DIR%
C:\external\kfw-2.1.2

Using Visual C++ .NET, build the following Win32 Debug and Win32 Release
configurations:

mod_spnego\mod_spnego.sln

Install mod_spnego. Note that mod_spnego is named mod_spnego.so on Windows, not
mod_spnego.dll.

3 Configuration

Obtain a keytab file for the service HTTP for your server.

Copy the keytab file to the default location or define the environment
variable KRB5_KTNAME to point to the keytab file. The default keytab files for
UNIX and Windows are /etc/krb5.keytab and \winnt\krb5kt. When defining
KRB5_KTNAME on Windows, use backslashes (not forward slashes) and do not specify
a drive letter (e.g., C:).

For each directory that you want to secure, specify the following directives
inside an httpd.conf Directory directive:

AllowOverride AuthConfig
[Krb5KeyTabFile key-tab-file]
Krb5ServiceName service-name

where service-name is a list of Kerberos version 5 service name to be used by
mod_spnego (e.g., HTTP http khttp) and key-tab-file points to a Kerberos version 5 keytab
file. The lowercase http has been seen from Mac Browsers and khttp was in some Mozilla 
versions used.


For example:

<Directory "/home/bob/apache2/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride AuthConfig
    Order allow,deny
    Allow from all
    Krb5KeyTabFile /home/alice/krb5kt
    Krb5ServiceName HTTP
</Directory>

The Krb5KeyTabFile directive causes the environment variable KRB5_KTNAME to be
set. Please note that the authors were not able to successfully place a keytab
file in a place other than \winnt\krb5kt on Windows 2000.

Inside each (file system) directory, create a file named .htaccess file
containing the following:

AuthType SPNEGO
Require {user user-list} | valid-user

where user-list is a list of Kerberos principal names separated by spaces that
are authorized to access the directory's files.

For example:

AuthType SPNEGO
Require user alice@FOO.COM bob@FOO.COM david@FOO.COM

or

AuthType SPNEGO
Require valid-user

Please note that the authors have experienced inconsistent behavior when the
AllowOverride directive is set to None and no .htaccess file is used (see Open
Issues).

By default, mod_spnego requires Kerberos authentication for each HTTP request.
To configure mod_spnego on Apache 2.0 or higher to only require Kerberos
authentication for the first request in each HTTP 1.1 Keep-Alive connection,
specify the following httpd.conf server directive:

Krb5AuthEachReq Off

By default, Krb5AuthEachReq is set to On. Krb5AuthEachReq is not supported on
Apache 1.3.

To create a http/hostname@REALM.COM service principal you have to copy the 
HTTP/hostname@REALM.COM entry in the keytab (As far as I know you cannot have a HTTP and 
http service principal in AD for the same server)

First do a list of the keytab file (I am assuming you use MIT Kerberos):

# klist -k -e -K -t /etc/httpd/HTTP.keytab
Keytab name: FILE:/etc/httpd/HTTP.keytab
KVNO Timestamp Principal
---- ----------------- --------------------------------------------------------
1 11/29/04 11:42:25 HTTP/moelma.test.com@TEST.COM (ArcFour with HMAC/md5) (0x0d41ede6808
2fc5b8611dc5da75b5d4f)

Then do a ktutil with the following commands:
#ktutil
ktutil: addent -key -p http/moelma.test.com@TEST.COM -k 1 -e rc4-hmac
Key for http/moelma.test.com@TEST.COM (hex): 0d41ede68082fc5b8611dc5da75b5d4f
ktutil: wkt /etc/httpd/HTTP.keytab
ktutil: quit

Use the same kvno and enc-type as the HTTP entry. This should create a second entry 
(with the service name http) to the keytab with the same key as for the HTTP service.

4 Architecture

 -------------------------
| Apache                  |
|-------------------------|
| mod_spnego              |
|-------------------------|
| fbopenssl | MIT GSS-API |
|-----------|-------------
| OpenSSL   |
 -----------

5 Debugging

5.1 Windows

The authors were not able to successfully attach a debugger on Windows by
calling DebugBreak (or __asm {int 3}), but were able to debug mod_spnego within
Visual Studio:

Open module in Visual Studio.
Build debug version of module.
Configure project's Debugging property to run "Apache.exe -X". For example:

Command:           C:\Program Files\Apache Group\Apache2\bin\Apache.exe
Command Arguments: -X
Working Directory: C:\Program Files\Apache Group\Apache2\bin

Configure httpd.conf to point to debug version of module.
From Visual Studio, set breakpoints and run debugger (F5).

Please note that the command-line option -X is documented for httpd on Linux and
UNIX, but not for Apache.exe on Windows. "apache.exe /?" does not list -X.

6 References

Baize, E. and Pinkas, D. RFC 2478: The Simple and Protected GSS-API Negotiation
Mechanism. December 1998.

Brezak, J. Internet Draft: HTTP Authentication: SPNEGO Access Authentication As
implemented in Microsoft Windows 2000 (draft-brezak-spnego-http-04.txt). October
2002.

Surati, Sanj and Muckin, Michael. HTTP-Based Cross-Platform Authentication via
the Negotiate Protocol Part I  Network Infrastructure
(http://msdn.microsoft.com/library/en-us/dnsecure/html/http-sso-1.asp). December
2002.

Surati, Sanj and Muckin, Michael. HTTP-Based Cross-Platform Authentication via
the Negotiate Protocol Part II  SPNEGO Tokens and the Negotiate Protocol
(http://msdn.microsoft.com/library/en-us/dnsecure/html/http-sso-2.asp). December
2002.

Surati, Sanj and Muckin, Michael. HTTP-Based Cross-Platform Authentication via
the Negotiate Protocol Part III  SPNEGO Token Handler API
(http://msdn.microsoft.com/library/en-us/dnsecure/html/http-sso-3.asp). December
2002.

Tschalar, Ronald. NTLM Authentication Scheme for HTTP
(http://www.innovation.ch/java/ntlm.html). June 17, 2003.

7 Bug Fixes and Enhancements

2003-11-14 mod_spnego.c:184 Fixed apr_pcalloc call to take length, not address
of value.

2004-01-19 Applied patch from Frank Taylor to handle SPNEGO tokens containing
Microsoft legacy object identifier 1.2.840.48018.1.2.2.

2005-01-24 Added support for server directive Krb5AuthEachReq on Apache 2.0.
Implementation is based on code from Horst Reiterer of Fabalabs.

2005-01-25 Added support for RFC 1964 Kerberos tokens as sent by Firefox on
Linux.

2005-04-14 Added detection and logging of NTLM tokens.

2005-08-08 Changed Krb5ServiceName to be a list of service names.
           Added the possibility of using Virtual Hosts

2005-08-19 Fix logging issues and empty require line

8 Open Issues

Modify makeSpnegoTargetToken and parseSpnegoInitialToken so that caller
allocates memory with apr_pcalloc?

Test log levels to control log output.

Make success log messages user friendly. For example:

mod_spnego: authentication hook handling request
mod_spnego: authentication hook sending "WWW-Authenticate: Negotiate"
mod_spnego: authentication hook returning 401
mod_spnego: authentication hook handling request for user %s
mod_spnego: authentication hook sending "WWW-Authenticate: Negotiate" and SPNEGO token
mod_spnego: authentication hook returning %d
mod_spnego: authorization hook handling request for user %s
mod_spnego: authorization hook returning %d

How expensive is calling gss_import_name and gss_acquire_cred per request? Is it
necessary to call these functions per request?

Add debug directives to write input and output SPNEGO tokens to files?

gss_accept_sec_context seems to return 851968 if there is too much time skew
between client and server. GSS-API? Is it possible to programmatically determine
that gss_accept_sec_context failed because of time skew? Also, mod_spnego does
not include KRB-ERROR message output by gss_accept_sec_context in SPNEGO
response token.

Test with no Require directive in .htaccess.

Should the Krb5ServiceName directive be mandatory? SPNEGO_CONFIG's
krb5ServiceName element could be initialized to "HTTP".

The authors were not able to successfully place a keytab file in a place other
than \winnt\krb5kt on Windows 2000.

Windows project and solution files were built with Visual C++ .NET 2003.

For Apache 1.3 on Solaris, make sure each Directory directive contains the
following directive:

    AllowOverride AuthConfig

On Apache 1.3 on Windows, apr_env_set (in win32-env.c) is forced to call
SetEnvironmentVariableA.

Test with "AllowOverride None" and the following directives in httpd.conf, not
in .htaccess:

AuthType SPNEGO
Require ...
