I spent a while trying to make an ISAPI filter that would
perform the NTLM challenge/response handshake with Internet
Explorer. Why? Well, apart from wanting to find out more about how
the authentication process works, this would allow the
authentication to occur without IIS then impersonating that user.
In addition, you could add control with the filter without needing
to worry about setting NTFS permissions on files and folders.

I ran into a problem though, and I'm sure it is my ISAPI code
rather than my NTLM code causing the problem.

Here's what happens:

The first request comes in and I check for an Authorization:
header. Since there isn't one, I send back a 401 with a
WWW-Authenticate: header asking for NTLM and close the
connection.

The second request comes in on a new connection as planned with
an Authorization: header with NTLM and the base 64 encoded token. I
hook up AcceptSecurityContext and receive SEC_I_CONTINUE_NEEDED as
expected so I create a new WWW-Authenticate: header with the base
64 encoded token for the challenge. I send this back with a 401 and
ask for the connection to be kept open
(SF_STATUS_REQ_FINISHED_KEEP_CONN). I think this is where it goes
wrong.

The next request comes in on the same connection with the NTLM
response in the Authorization: header, but my filter never sees it.
I can see the response from Internet Explorer by monitoring the TCP
port with tcpTrace, but I think something has gone wrong with the
connection by then.

What should happen is that I will get the NTLM response, again
call AcceptSecurityContext and this time I should get SEC_E_OK
whereupon I know that I am authenticated, I can set my custom HTTP
header, and also set a flag so that I know any subsequent requests
on the same connection are preauthenticated.

I've made the source code
available 
here
in case somebody can spot what I've done wrong (it's a
VS.NET project but that's only really important in so far as I used
an ATL Server include for the base 64 coding).

If you spot what is wrong or have any clues, please get in
touch.