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.
- Sources are in my Mercurial repository.
- Download mod_auth_sspi_1.0.5b-vc9-2.2.11.zip (beta, updated 2009/2/17)
More binaries are available in my downloads directory.
Important
- this binary was built for Apache 2.2.11 (other downloads for for Apache 2.2.8 and 2.2.9 are available too)
- requires Windows XP, Server 2003, 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 the VC2005 SP1 redist installed.
- update – zip files has renamed
mod_auth_sspi.so.manifesttohttpd.exe.manifest– this file needs to be in yourApache2\bindirectory 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
I check incoming POST requests, on existing connections only, for whether they have a Content-Length of zero.
Only IE (I think…) does this when it wants to re-authenticate. SSPI restarts the auth process and IE eventually sends its correct POST and data.
No need for per_auth_request to be always ON; we 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#defineinmod_auth_sspi.h–DEFAULT_SSPI_PACKAGEis nowNEGOTIATEinstead ofNTLM. (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 toNTLM– whileNegotiateseemed 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.soto yourApache2\modulesdirectory - if using the apache.org MSI binary: copy
httpd.exe.manifesttoApache2\bin - edit your
httpd.conffile 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, Server 2003, 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 renameafxres.htowindows.hand 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.
- download Visual C++ Express 2005
On the download site, click on “Previous Versions” to get the 2005 edition. - the Windows 2003 R2 Platform SDK
If doing a web or custom install, be sure to include the IE SDK to get all of the headers you’ll need. - the Visual C++ 2005 SP1 redist package
- minGW (optional, see above)
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.x\srclib\apr-util\aprutil.dsw- go to
Tools > Options > Projects and Solutions > VC++ Directories- add your
SDK\Includedirectory toInclude files - add your
SDK\Libdirectory toLibrary Files
- add your
- go to
- set your build type to
ReleaseorReleaseNT(I usedReleaseNT) - build
apr - build
aprutil - build
libapr(need to addadvapi32.libto the project’sProperties > Configuration > Linker > Input) - build
libaprutil(need to addlibexpat.libfrom expat. Again, add it to your Linker Input list and add the directory of the.libfile to your Library Files include paths - do
File > Close Solution
Build local libhttpd
- open
Apache.dswin yourhttpd-2.2.8source directory. - build
libapr- (need to add
Shell32.libto theProperties > Config Properties > Linker > Inputlist)
- (need to add
- 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.- the fix:
/d "LONG_NAME="Apache HTTP Server Core""should really be/d "LONG_NAME=Apache HTTP Server Core"
- the fix:
- need to add
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”,
cdto your Mercurial repository, and- type
nmake.- you may need to adjust the
AP_LIBPATHline so that\srclib\apr\Releasebecomes\srclib\apr\NT\Releaseif you built usingReleaseNTinstead ofReleasein your build settings, above
- you may need to adjust the
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.
Great! At last!
Thanks!
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.
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.
Hi there,
Good to see you having a go with this problem. I too was stumped by it. I have tried your patch and it works well for all POSTS except seemingly those submitted by way of javascript, eg, AJAX, REST, JSON etc. IE does something weird and closes the connection after the first 401 response. It does not attempt to try a NTLM_AUTH. This is something I don’t think can be fixed server-side and its a real pain as it prevents technologies such as AJAX from working with NTLM auth.
Out of interest, would it not be more correct to detect IE sending a NTLM_NEGOTIATE message instead of the zero-length POST? Although I cannot imagine too many times a web app would need to send a zero-length POST it could happen. However a NTLM_NEGOTIATE should only be sent when the browser wishes to re-auth.
Some random thoughts. Would love to see your code in the official repo – keep up the good work.
Regards,
Lee