Discussion:
HttpSendRequest err 12015 with NTLM + INTERNET_FLAG_KEEP_CONNECTION
(too old to reply)
hash1baby
2005-04-18 07:02:15 UTC
Permalink
Not making any progress solving our WININET problem, despite reading
other threads in this ng - any help appreciated.

We're using WININET to POST data to https on IIS. (Actually using
the gsoap_Wininet.cpp unit, which bridges gSOAP to WININET. The
source code is clear, purports to work with NTLM when
INTERNET_FLAG_KEEP_CONNECTION is set, and employs standard WININET
authentication patterns apparantly taken from MSDN sample code.)
We use ethereal to monitor traffic, and we're using the debug build
of wininet for logging.

The basic problem is that the HttpSendRequest fails with
GetLastError() = 12015, even though we use
INTERNET_FLAG_KEEP_CONNECTION in HttpOpenRequest.

Interaction as follows:
gSoap Wininet (tcp) Proxy
----- ------- -----
| | |
| InternetOpenA ----------> | |
| ("gSOAP", | |
| INTERNET_OPEN_TYPE_PRECONFIG, |
| NULL, NULL, 0) | |
|<-h1--------------------------+ |
| | |
| InternetSetStatusCallback-> |
| // (only for logging) | |
|<-----------------------------+ |
| | |
| InternetCrackUrl -------->| |
| (...) | |
|<-----------------------------+ |
| | |
| InternetConnect ---------->| |
| (hI, ...) | |
|<-hC--------------------------+ |
| | |
| HttpOpenRequestA --------->| |
| (hC, "POST", url, | |
| "HTTP/1.1", NULL, NULL, | |
| INTERNET_FLAG_SECURE | | |
| INTERNET_FLAG_KEEP_CONNECTION, |
| ...) | |
|<-hR--------------------------+ |
| | |
| HttpAddRequestHeadersA--> | |
| (hR,..) | |
|<-----------------------------+ |
| | |
|----HttpSendRequestA -------> | |
| (hR, NULL, 0, buffer, len) |
| | |
| | |
| | <-> { interaction to } <-> |
| | { download proxy.pac } |
| | |
| { open a CONNECT request } |
| | |
| HttpSendRequestA ------+ |
| | |-> |
| | CONNECT x.x.x.x:443 HTTP/1.0 |
| | User-Agent: gSOAP |
| | Host: x.x.x.x |
| | Content-Length: 0 |
| | Proxy-Connection: Keep-Alive |
| | Pragma: No-Cache |
| | | |
| | | |
| | |<- |
| | HTTP/1.1 407 Proxy |
| | Authentication Required ( The |
| | ISA Server requires |
| | authorization to fullfill the |
| | request. Access to the Web |
| | Proxy service is denied. ) |
| | Via: 1.1 machinename |
| | Proxy-Authenticate: NTLM |
| | ... |
| | Connection: Keep-Alive |
| | Proxy-Connection: Keep-Alive |
| | ... | |
| | | |
| |<---err = 12015-+ |
|<---err = 12015---------------+ |

The only notification I get on the StatusCallback is
INTERNET_STATUS_DETECTING_PROXY

I can see that internally WININET is failing to negotiation NTLM
through the proxy. I traced what happens when I use iexplore.exe
to GET the same resource, and saw exactly the same connect request
and 407 response status, except that WININET continued interaction
involved NTLM challenge-response before successfully connecting.
(Another maybe irrelavent difference was that WININET
created internal CONNECT request was opened using openned
INTERNET_FLAG_ASYNC. I don't know how to control that...)

btw, using WinXP (wininet.dll v6.0.2800.1400)

Any ideas appreciated.
Michael.
Stephen Sulzer
2005-04-21 00:04:40 UTC
Permalink
The INTERNET_FLAG_ASYNC flag would have no effect on proxy authentication.

When you run your SOAP client, is it running in the context of a logged-on
user? Or is it running in some other context, such as in a Windows NT
service?

One trick to try is to first send a HEAD or GET request for a static
resource located in the same virtual directory path where the POST request
is being sent to. Then send the SOAP POST request. You do not need to use
the same WinInet handles (including the InternetOpen handle) to send the
HEAD/GET request; just be sure to use the same OPEN_TYPE_PRECONFIG, SECURE
and KEEP_CONNECTION flags.

- Stephen
hash1baby
2005-04-27 01:16:12 UTC
Permalink
Post by Stephen Sulzer
When you run your SOAP client, is it running in the context of a logged-on
user? Or is it running in some other context, such as in a Windows NT
service?
logged-on user
Post by Stephen Sulzer
One trick to try is to first send a HEAD or GET request for a static
resource located in the same virtual directory path where the POST request
is being sent to. Then send the SOAP POST request. You do not need to use
the same WinInet handles (including the InternetOpen handle) to send the
HEAD/GET request; just be sure to use the same OPEN_TYPE_PRECONFIG, SECURE
and KEEP_CONNECTION flags.
The theory being that WININET has an initialization problem
with POST but not HEAD or GET?

I tried it but it didn't work.

any other ideas?

The MSDN article "Handling Authenticatation" ->
http://msdn.microsoft.com/library/en-us/wininet/wininet/handling_authentication.asp
mentions how to set registry to enable authentication.
It mentions setting DLLFile=winsspi.dll for NTLM - but this file isn't
on
my XP-SP1 system. Perhaps this advice is obsolete - iexplore.exe does
just
fine.
Stephen Sulzer
2005-04-27 09:06:51 UTC
Permalink
The idea behind the trick of sending a HEAD or GET request before a POST is
to avoid a problem with misbehaving, "impatient" servers that, after sending
back a 401/407 authentication-required response, then abruptly close the
connection before WinInet has finished sending the body of the POST request.
It can also be used as a minor performance trick to establish a persistent
socket connection (having authentication handled during the HEAD/GET
request) before sending a large POST request--this avoids sending a large
POST body multiple times.

The DLLFile=winsspi.dll is not an issue; the documentation is out-of-date,
as you suspect.

The only other thing I can think of has to do with the version of wininet
that you are using. 6.0.2800.1400 is a post-IE6SP1/pre-XPSP2 version of
WinInet.dll. That version of wininet.dll has been known to cause some
problems related to HTTPS/SSL POST requests--see KB article 831167, for
example.

If you can, upgrade your Windows XP & IE6 to XP SP2, or apply a more recent
IE6 post-SP1 update, to upgrade your wininet.dll to at least version
6.0.2800.1480:
http://support.microsoft.com/kb/889669
or
http://www.microsoft.com/technet/security/Bulletin/MS05-020.mspx


- Stephen
hash1baby
2005-04-28 09:31:11 UTC
Permalink
Post by Stephen Sulzer
The idea behind the trick of sending a HEAD or GET request before a POST is
to avoid a problem with misbehaving, "impatient" servers that, after sending
back a 401/407 authentication-required response, then abruptly close the
connection before WinInet has finished sending the body of the POST request.
I see. In my case it does not appear to be an impatient proxy.
(Rather it appears as if wininet closes the connection early,
picking up the HTTP response status in the first tcp segment,
not waiting for the html formatted error message to received
in the entity body over multiple subsequent tcp segments.)

I find it hard to implicate the proxy, because when I changed
my client's POST with a body to GET without a body, and compared
to iexplore, I saw I identical HTTP request go to the proxy
server, and identical response emitted from it. The only
difference was in wininet's handling of the response.
Post by Stephen Sulzer
If you can, upgrade your Windows XP & IE6 to XP SP2, or apply a more recent
IE6 post-SP1 update, to upgrade your wininet.dll to at least version
http://support.microsoft.com/kb/889669
or
http://www.microsoft.com/technet/security/Bulletin/MS05-020.mspx
Ok I tried SP2 - didn't change anything. (Although, surely
6.0.2800.1400 and 6.0.2800.1480 only differ in the build number??
Would MS really fix a bug without incrmenting the minor version?
Note that debug version is wininetdebug.6.0.2800.1106)

I'm still working on this Stephen. Thanks your advice and time.
hash1baby
2005-05-06 12:16:12 UTC
Permalink
Post by hash1baby
Not making any progress solving our WININET problem, despite reading
other threads in this ng - any help appreciated.
I gave up on this one.
In the end we were able to assume that there would
be a direct route from client to server, so
we configured the client to bypass the proxy, which
avoids the need to meet its authentication challenge.

Loading...