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
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
