Hello,

I'm using curl version 7.37.1 to connect to a remote site through a proxy that 
requires 'negotiate' authentication. Curl fails to authenticate to the proxy 
because it performs the initial handshake but then does not complete it, thus 
failing the request.

This is the exact version of curl I'm using:
curl 7.37.1 (i386-pc-win32) libcurl/7.37.1 WinSSL
Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtsp 
smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IPv6 Largefile NTLM SPNEGO SSL SSPI

The file interrupted-trace.txt contains the verbose output of the following 
curl command:
curl.exe -vvv --proxy 10.2.0.254:8080 --proxy-negotiate --proxy-user : 
http://www.example.com

It shows just two interactions with the server, thus failing to answer to the 
challenge sent back by the server.

Looking at curl code for the SSPI negotiation, it appears that curl cleans-up 
the context when sending the authentication headers to the server: 
Curl_output_negotiate calls Curl_cleanup_negotiate that completely deletes the 
context.
While this clean-up is needed at the end of an handshake (to avoid a memory 
leak) it should be avoided while the handshake is till in progress, to prevent 
a premature clean-up of the handshake context.

I implemented the fix contained in the attached patch to solve the issue. It 
applies two changes:
1) avoid to clean-up the context if the return value from the 
InitializeSecurityContext function (neg_ctx->status) indicates that it is 
necessary to continue the handshake
2) exit from the negotiation if the status of the negotiation indicates that we 
already sent the authentication and the negotiation status is ok, meaning that 
we completed our part of the handshake. If we reach this point:
2.1) the server is again challenging us
2.2) but we already sent out all the authentication data and the 
InitializeSecurityContext function returned OK, meaning that we completed our 
part of  the process
2.3) the context is null, because it has been cleaned-up during the last call 
to Curl_output_negotiate and Curl_cleanup_negotiate, that must perform the 
clean-up to avoid a memory leak in the success scenario (in this scenario after 
sending out the last headers, the negotiation code gets never called again).

So I changed the check at 2) because the context would be always null at that 
point (it was always null also before my change to the clean-up function), thus 
generating a failure loop. Hopes this explains my attempt for fixing the issue.

The resulting code is able to successfully authenticate to the proxy (see 
success-trace.txt).

Is this change ok? Does it have any side effect?

Regards,
Bernardo

                                          
curl.exe -vvv --proxy 10.2.0.254:8080 --proxy-negotiate --proxy-user : 
http://www.example.com

* Rebuilt URL to: http://www.example.com/
* Hostname was NOT found in DNS cache
*   Trying 10.2.0.254...
* Connected to 10.2.0.254 (10.2.0.254) port 8080 (#0)
> GET http://www.example.com/ HTTP/1.1
> User-Agent: curl/7.37.1
> Host: www.example.com
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 407 Proxy Authentication Required ( The ISA Server requires 
authorization to fulfill the request. Access to the Web Proxy filter is denied. 
 )
< Via: 1.1 ISA10
< Proxy-Authenticate: Negotiate
< Proxy-Authenticate: Kerberos
< Proxy-Authenticate: NTLM
< Connection: Keep-Alive
< Proxy-Connection: Keep-Alive
< Pragma: no-cache
< Cache-Control: no-cache
< Content-Type: text/html
< Content-Length: 4107
<
* Ignoring the response-body
* Connection #0 to host 10.2.0.254 left intact
* Issue another request to this URL: 'http://www.example.com/'
* Found bundle for host www.example.com: 0x39f990
* Re-using existing connection! (#0) with host 10.2.0.254
* Connected to 10.2.0.254 (10.2.0.254) port 8080 (#0)
* Proxy auth using GSS-Negotiate with user ''
> GET http://www.example.com/ HTTP/1.1
> Proxy-Authorization: Negotiate 
> TlRMTVNTUAABAAAAt7II4gMAAwAwAAAACAAIACgAAAAFAs4OAAAAD1RFTUlTQTEwSVNB
> User-Agent: curl/7.37.1
> Host: www.example.com
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 407 Proxy Authentication Required ( Access is denied.  )
< Via: 1.1 ISA10
< Proxy-Authenticate: Negotiate 
TlRMTVNTUAACAAAABgAGADgAAAA1wonioBTO6AT2AsJISWsAAAAAAGoAagA+AAAABQLODgAAAA9JAFMAQQACAAYASQBTAEEAAQAQAFQARQBNAEkAUwBBADEAMAAEAA4ASQBTAEEALgBUAEUATQADACAAdABlAG0AaQBzAGEAMQAwAC4ASQBTAEEALgBUAEUATQAFAA4ASQBTAEEALgBUAEUATQAAAAAA
< Connection: Keep-Alive
< Proxy-Connection: Keep-Alive
< Pragma: no-cache
< Cache-Control: no-cache
< Content-Type: text/html
< Content-Length: 0
<
* Connection #0 to host 10.2.0.254 left intact

Attachment: negotiate.patch
Description: Binary data

curl-fixed.exe -vvv --proxy 10.2.0.254:8080 --proxy-negotiate --proxy-user : 
http://www.example.com
* Rebuilt URL to: http://www.example.com/
* Hostname was NOT found in DNS cache
*   Trying 10.2.0.254...
* Connected to 10.2.0.254 (10.2.0.254) port 8080 (#0)
> GET http://www.example.com/ HTTP/1.1
> User-Agent: curl/7.37.1
> Host: www.example.com
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 407 Proxy Authentication Required ( The ISA Server requires 
authorization to fulfill the request. Access to the Web Proxy filter is denied. 
 )
< Via: 1.1 ISA10
< Proxy-Authenticate: Negotiate
< Proxy-Authenticate: Kerberos
< Proxy-Authenticate: NTLM
< Connection: Keep-Alive
< Proxy-Connection: Keep-Alive
< Pragma: no-cache
< Cache-Control: no-cache
< Content-Type: text/html
< Content-Length: 4107
<
* Ignoring the response-body
* Connection #0 to host 10.2.0.254 left intact
* Issue another request to this URL: 'http://www.example.com/'
* Found bundle for host www.example.com: 0x39f990
* Re-using existing connection! (#0) with host 10.2.0.254
* Connected to 10.2.0.254 (10.2.0.254) port 8080 (#0)
* Proxy auth using GSS-Negotiate with user ''
> GET http://www.example.com/ HTTP/1.1
> Proxy-Authorization: Negotiate 
> TlRMTVNTUAABAAAAt7II4gMAAwAwAAAACAAIACgAAAAFAs4OAAAAD1RFTUlTQTEwSVNB
> User-Agent: curl/7.37.1
> Host: www.example.com
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 407 Proxy Authentication Required ( Access is denied.  )
< Via: 1.1 ISA10
< Proxy-Authenticate: Negotiate 
TlRMTVNTUAACAAAABgAGADgAAAA1woniXSF2/075ZpPokKcAAAAAAGoAagA+AAAABQLODgAAAA9JAFMAQQACAAYASQBTAEEAAQAQAFQARQBNAEkAUwBBADEAMAAEAA4ASQBTAEEALgBUAEUATQADACAAdABlAG0AaQBzAGEAMQAwAC4ASQBTAEEALgBUAEUATQAFAA4ASQBTAEEALgBUAEUATQAAAAAA
< Connection: Keep-Alive
< Proxy-Connection: Keep-Alive
< Pragma: no-cache
< Cache-Control: no-cache
< Content-Type: text/html
< Content-Length: 0
<
* Connection #0 to host 10.2.0.254 left intact
* Issue another request to this URL: 'http://www.example.com/'
* Found bundle for host www.example.com: 0x39f990
* Re-using existing connection! (#0) with host 10.2.0.254
* Connected to 10.2.0.254 (10.2.0.254) port 8080 (#0)
* Proxy auth using GSS-Negotiate with user ''
> GET http://www.example.com/ HTTP/1.1
> Proxy-Authorization: Negotiate 
> TlRMTVNTUAADAAAAAAAAAEgAAAAAAAAASAAAAAAAAABIAAAAAAAAAEgAAAAAAAAASAAAAAAAAABIAAAANcKI4gUCzg4AAAAP
> User-Agent: curl/7.37.1
> Host: www.example.com
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 OK
< Via: 1.1 ISA10
< Connection: Keep-Alive
< Proxy-Connection: Keep-Alive
< Content-Length: 1270
< Age: 422305
< Expires: Thu, 14 Aug 2014 10:46:52 GMT
< Date: Thu, 07 Aug 2014 10:46:52 GMT
< Content-Type: text/html
< Etag: "359670651"
* Server ECS (iad/182A) is not blacklisted
< Server: ECS (iad/182A)
< Accept-Ranges: bytes
< Cache-Control: max-age=604800
< Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
< X-Cache: HIT
< x-ec-custom-error: 1
<
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif
;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 50px;
        background-color: #fff;
        border-radius: 1em;
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        body {
            background-color: #fff;
        }
        div {
            width: auto;
            margin: 0 auto;
            border-radius: 0;
            padding: 1em;
        }
    }
    </style>
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is established to be used for illustrative examples in docume
nts. You may use this
    domain in examples without prior coordination or asking for permission.</p>
    <p><a href="http://www.iana.org/domains/example";>More information...</a></p>

</div>
</body>
</html>
* Connection #0 to host 10.2.0.254 left intact
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to