cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: NTLM proxy nightmare - POST problem?

From: Jonathan Arnold <jarnold_at_insors.com>
Date: Fri, 09 Mar 2007 17:20:53 -0500

Jonathan Arnold wrote:
> Daniel Stenberg wrote:
>> On Thu, 8 Mar 2007, Jonathan Arnold wrote:
>>
>>> I've attached the '--trace-ascii' log for the hang. It doesn't show
>>> much. A POST by curl, followed by a receive of the proxy auth error.
>>> Then nothing. It's not surprising there's no auth info in the first
>>> POST, as the key is that I'm doing an 'anyauth', so it first starts
>>> with nothing and tries to figure it out from there. If it does a GET,
>>> it works correctly, as you can see from the second log.
>>
>> Any chance you can run this with a debugger and see what libcurl is
>> waiting for at that moment?
>>
>> It seems like it doesn't consider itself done with either recving or
>> sending so it doesn't "act" on the auth stuff and thus just waits for
>> the recv/send to complete...
>
> It is looping in the Transfer routine, waiting for done to be true. The
> 'keepon' member variable is set to KEEP_WRITE, but it never gets cleared.
> But for some reason, conn->writesockfd is -1, which doesn't look right at
> all.
>
> I'll keep digging.

More info:

In the Curl_http_auth_act routine, 'perhapsrewind' is called if the request
isn't either a POST or a HEAD and if pickhost or pickproxy is true (in this case,
pickproxy is true). 'perhapsrewind' sets the conn's rewindaftersend to be true,
even though there is nothing to be sent and thus curl just loops, sending nothing
and receiving nothing.

rewindwaftersend gets set to true because of this peculiar if:

http.c(258):
     if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
        (data->state.authhost.picked == CURLAUTH_NTLM)) {
       if(((expectsend - bytessent) < 2000) ||
          (conn->ntlm.state != NTLMSTATE_NONE)) {
         /* The NTLM-negotiation has started *OR* there is just a little (<2K)
            data left to send, keep on sending. */

         /* rewind data when completely done sending! */
         if(!conn->bits.authneg)
           conn->bits.rewindaftersend = TRUE;

         return CURLE_OK;
       }

And yes, authproxy.picked == CURLAUTH_NTLM. And expectsend == -1, because it never
gets changed from its initial setting (not sure if the HTTPREQ_POST should be picking
up a postfieldsize or not).

I changed the if inside the CURLAUTH_NTLM if to check for a -1 expectsend, and it gets
a little further. But now it is looping because after it resends with the correct NTLM
proxy info, it gets a 401, but still thinks it is still negotiating the proxy, and not
now negotiating the http, so it keeps re-authing the proxy. I changed the if to be:

       if(((expectsend != -1) && (expectsend - bytessent) < 2000) ||
          (conn->ntlm.state != NTLMSTATE_NONE)) {

-- 
Jonathan Arnold           Software Engineer
inSORS Integrated Communications, Inc
jarnold_at_insors.com Office/fax: 781.391.2818
Received on 2007-03-09