Fixing mod_auth_sspi and IE losing POST data

I think I’ve fixed this IE-loses-POST data bug; I’m seeking feedback, verification and testing from others that want to lend a hand.

Important

  • requires Apache 2.2.9 (build for Apache 2.2.8 is still available)
  • requires Windows XP or Vista w/ the Visual C++ redist installed
    • I posted a binary built with Visual Studio 2005; while I cannot get it to load, it may work on Windows 2000. (I don’t have access to any Windows 2000 machines.) You’ll need to VC2005 SP1 redist installed.
  • update - zip files has renamed mod_auth_sspi.so.manifest to httpd.exe.manifest - this file needs to be in your Apache2\bin directory if you’re using the Apache binary from apache.org

Unfortunately, since I used the latest Windows SDK, Windows 2000 cannot load this module. Once the changes are officially accepted, we can see about porting to other Windows platforms.

If you’d like me to build against other versions of Apache (on Vista or XP), use this site’s contact form to let me know.

I am interested in getting these changes back into SourceForge, but wanted to hack on my own (with revision control) first, which is why there’s a Mercurial repository. (I’m not trying to fork this project, or anything.)

This module does report itself as mod_auth_sspi 1.0.5 - that not meant to be an official 1.0.5; this is still a beta, and not officially accepted into the SourceForge project yet.

Development Details

I not an Apache or APR guru; I had to learn what was going on from scratch. I spent the first two days just getting familiar with the mod_auth_sspi source, and added a lot of comments along the way.

I eventually found the section where I should check for IE’s unique behavior; I detected its special case and coded a “reset” so that IE gets the re-authentication it is looking for.

Special thanks to all who contributed bits of info in the bug post - that’s what got me started int he right direction to code fix.

The Fix

Essentially, mod_auth_sppi now checks incoming POST requests (on existing connections only) to see if they have a Content-Length of zero.

IE (I think!) only does this when it want to re-authenticate. The module restarts the auth process and IE eventually sends its correct POST with all data. There is no longer a need to always run with per_auth_request ON, and we can save a bit of extra traffic to our web servers and Domain Controller.

Code Changes & Refactoring

I tried, as much as possible, to

  • preserve the existing coding style
    except I tried to wrap long lines before 80 characters. (Seems like the Apache source code does much the same.)
  • add comments (in the Doxygen format) liberally, to help out others new to Apache module hacking
  • not change any functionality other than what was required for this bug
    (one exception: I did change a #define in mod_auth_sspi.h - DEFAULT_SSPI_PACKAGE is now NEGOTIATE instead of NTLM. (Since both Firefox and IE support Kerberos, I was hoping the change would allow the stronger security method to be chosen. While it doesn’t seem to have broken anything, I have not yet confirmed that Kerberos is being used.)
    update - I changed the define back to NTLM - while Negotiate seemed to work fine on my XP dev machine, trying it on Firefox on W2k3 caused a bunch of 500 errors. (Oddly, IE7 worked fine with it.) Any Kerberos experts want to lend some information?

Install

This module will not work with versions of Apache prior to 2.2.8.

You will need to have the Visual C++ 2008 redist installed on your system or Apache won’t be able to load the module. (If you’re using the vc8 build, you must have the Visual C++ 2005 SP1 redist instead.)

  • unzip to contents of the file to a temporary directory of your choice
  • test to see if you installed the Visual C++ redist
    • open a command prompt in your temporary directory
    • run sspipkgs.exe
    • you should see a list of all installed SSPI packages on your server (I see 9 on mine)
  • copy mod_auth_sspi.so to your Apache2\modules directory
  • if using the apache.org MSI binary: copy httpd.exe.manifest to Apache2\bin
  • edit your httpd.conf file to load the module and turn on SSPI auth for a directory

httpd.conf example

LoadModule sspi_auth_module modules/mod_auth_sspi.so

<Directory "C:/webdata/htdocs">
    # Configure mod_auth_sspi - who can get stuff from this server.
    AuthName "Intranet SSPI"
    AuthType SSPI
    SSPIAuth On
    SSPIAuthoritative On

    SSPIOfferBasic On
    SSPIDomain MYDOMAIN
    SSPIOmitDomain On
    SSPIUsernameCase lower
    # PerRequestAuth can now be safely set to `off` in 1.0.5
    SSPIPerRequestAuth off

    require valid-user
</Directory>

How to Build

You can build a production-quality version of this module for yourself using freely available tools and compilers. Download and install the following:

Latest Editions (VC 2008)

These binaries will only load on Windows XP and Vista platforms. I’ll refer to this as VC9.

  • download Visual C++ Express 2008
  • the latest Windows SDK
  • the Visual C++ redist package
  • minGW (optional) - this gives you afxres.h, which is asked for in one of the resource files. You can save yourself a download and just rename afxres.h to windows.h and everything seems to work, but I haven’t tested this much.

Previous Version (VC 2005)

This versions produces binaries compatible with Windows 2000, XP, and Vista(?). I’ll refer to this as VC8.

Read this note about why using the latest-and-greatest software might not be so great. (I didn’t find that note until after I’d done all of my development work.)

Build local APR

Note the “need to add” steps all apply to VC8 only. VC9 seems to have them already set okay.

  • Start your Visual C++ IDE
  • open httpd-2.2.8\srclib\apr-util\aprutil.dsw
    • go to Tools > Options > Projects and Solutions > VC++ Directories
      • add your SDK\Include directory to Include files
      • add your SDK\Lib directory to Library Files
  • set your build type to Release or ReleaseNT (I used ReleaseNT)
  • build apr
  • build aprutil
  • build libapr (need to add advapi32.lib to the project’s Properties > Configuration > Linker > Input)
  • build libaprutil (need to add libexpat.lib from expat. Again, add it to your Linker Input list and add the directory of the .lib file to your Library Files include paths
  • do File > Close Solution

Build local libhttpd

  • open Apache.dsw in your httpd-2.2.8 source directory.
  • build libapr
    • (need to add Shell32.lib to the Properties > Config Properties > Linker > Input list)
  • build libaprutil
  • build libhttpd
    • need to add advapi32.lib (for security functions) to your Linker again
    • need to add user32.lib (for threading functions)
    • You’ll get a compiler error on httpd.rc - this is due to invalid quote nesting the build script. Look at the details build log (html file), drop into the VC command line build environment, and correct the quotes to compile the file yourself. Then use the VC IDE to resume building.
      • Example: /d "LONG_NAME="Apache HTTP Server Core"" should really be /d "LONG_NAME=Apache HTTP Server Core"

Close the VC IDE - you’re done with it for now. (And honestly, I’m not sure how many of these build steps are truly needed - this is just an account of what worked for me.)

Build mod_auth_sspi

Next I’d recommend using Mercurial to get the source from my repository.

hg clone http://dev.nosq.com/repos.hg/mod_auth_sspi/

You’ll need to edit the Makefile so that the first 5 define lines point to the right directories in your environment.

After that,

  • start the “Visual Studio 200x Command Prompt”,
  • cd to your Mercurial repository, and
  • type nmake.
    • you may need to adjust the AP_LIBPATH line so that \srclib\apr\Release becomes \srclib\apr\NT\Release if you built using ReleaseNT instead of Release in your build settings, above

If everything went well, you should have a .\bin directory with the newly built .so.

Updated using VC8

I went through and re-built using VC8 (Visual C++ 2005). It worked when I used the Apache binary from httpd.apache.org and included the httpd.exe.manifest file in the Apache2\bin directory.

Otherwise, when using the ApacheLounge binary, I got

httpd: Syntax error on line 127 of C:/dev/webservices/Apache2/conf/httpd.conf: Cannot  
load C:/dev/webservices/Apache2/modules/mod_auth_sspi.so into server: A dynamic  
link library (DLL) initialization routine failed.

when I ran httpd -t.

Development Changelog

  • rev7 - fixed bug where Negotiate causes Internal Server Errors (500 on w2k3 and Firefox
  • rev5 - tagged 1.0.5 beta as working

3 Comments on “Fixing mod_auth_sspi and IE losing POST data”

Keyd, July 14th, 2008 at 11:56 pm

Great! At last!
Thanks!

Mark, July 26th, 2008 at 6:58 am

I have been looking all over the place to solve this exact problem. Am running Apache 2.2.6 and cannot upgrade at this time. Do you know where a patched mod_auth_sspi.so can be found that will fix this IE prob w/ Apache 2.2.6? I’ve tried just about everything, would appreciate any suggestions or guidance. Thanks.

Jon, August 22nd, 2008 at 11:28 am

Good work and good instructions! This fixed my Windows auth problems with both IE7 and WebDAV.

Has anyone tried WebDAV on a Mac (OS X 10.5)? Safari properly authenticates, but not WebDAV. It pops up the login dialog (which includes a Domain field) but the login fails. In Apache access logs I see no user name, just as with the 1.0.4 IE7 bug.

Leave a Reply

Login Method

OpenID

Anonymous