New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inifinite loop during NTLM authentication #435

Closed
phlipsi opened this Issue Sep 15, 2015 · 12 comments

Comments

Projects
None yet
3 participants
@phlipsi

phlipsi commented Sep 15, 2015

Our client connects to a proxy which uses NTLM authentication. The destination is a server whose server certificate does not match to the actual hostname. The proxy authentication type is set to CURLAUTH_ANY. The following steps are necessary in order to reproduce the problem:

curl_easy_setopt(curl, CURLOPT_PROXY, proxy_ip);
curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxy_port);
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_userpwd);
curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);

curl_easy_setopt(curl, CURLOPT_CAINFO, ca_cert);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, stderr);

curl_easy_setopt(curl, CURLOPT_URL, "https://<destination-ip>:443");
assert(curl_easy_perform(curl) == CURLE_PEER_FAILED_VERIFICATION);

This call fails since the server certificate doesn't match to the actual hostname. Now we go on:

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_perform(curl);

Problem: The last call to curl_easy_perform() never returns. libcurl sends over and over CONNECT request, of course receives always an HTTP status code 407 but does not carry on to authenticate itself.

Using

printf("libcurl: %s\n", curl_version_info(CURLVERSION_NOW)->version);

we get libcurl: 7.45.0-DEV. The used proxy is the latest Squid 2 using a simple fake authentication. The destination server is an Apache 2.4. If necessary I can provide their configuration files in order to reproduce the error.

@iboukris

This comment has been minimized.

Contributor

iboukris commented Sep 15, 2015

Does it behave differently when setting CURLAUTH_NTLM (no probing)?
Is it regular NTLM or via Negotiate?
What's the auth methods offered by the proxy (paste -v output)?
What platform is the client running on?

@iboukris

This comment has been minimized.

Contributor

iboukris commented Sep 15, 2015

FWIW, it doesn't reproduce by me.

@phlipsi

This comment has been minimized.

phlipsi commented Sep 15, 2015

Does it behave differently when setting CURLAUTH_NTLM (no probing)?

Yes, using CURLAUTH_ANY is essential to reproduce the error. I think the infinite loop occurs in the probing. libcurl sends the plain CONNECT request over and over although the proxy response always contains the header

Proxy-Authenticate: NTLM

in order to initiate the regular NTLM negotiation process.

Is it regular NTLM or via Negotiate?

The Squid configuration contains

auth_param ntlm program /usr/lib/squid/fakeauth

so I guess via NTLM and not via negotiate

What's the auth methods offered by the proxy (paste -v output)?

Whose debug output do you mean? The libcurl's one or the Squid's one? I activated only NTLM-authentication in Squid. The response from the proxy contains only the above mentioned header.

What platform is the client running on?

I'm using Ubuntu 15.04 x86_64.

FWIW, it doesn't reproduce by me.

In order to reproduce the error it is essential that libcurl succeeds to connect to the proxy once beforehand. This connection must be torn down due to some SSL validation issue or something else. The second connection attempt to the proxy then fails.

@iboukris

This comment has been minimized.

Contributor

iboukris commented Sep 15, 2015

On Sep 15, 2015 11:10 PM, "Philipp Wähnert" notifications@github.com
wrote:

Does it behave differently when setting CURLAUTH_NTLM (no probing)?

Yes, using CURLAUTH_ANY is essential to reproduce the error. I think the
infinite loop occurs in the probing. libcurl sends the plain CONNECT
request over and over although the proxy response always contains the header

Proxy-Authenticate: NTLM

in order to initiate the regular NTLM negotiation process.

Is it regular NTLM or via Negotiate?

The Squid configuration contains

auth_param ntlm program /usr/lib/squid/fakeauth

so I guess via NTLM and not via negotiate

What's the auth methods offered by the proxy (paste -v output)?

Whose debug output do you mean? The libcurl's one or the Squid's one? I
activated only NTLM-authentication in Squid. The response from the proxy
contains only the above mentioned header.

Curl debug output

What platform is the client running on?

I'm using Ubuntu 15.04 x86_64.

FWIW, it doesn't reproduce by me.

In order to reproduce the error it is essential that libcurl succeeds to
connect to the proxy once beforehand. This connection must be torn down due
to some SSL validation issue or something else. The second connection
attempt to the proxy then fails.


Reply to this email directly or view it on GitHub.

@phlipsi

This comment has been minimized.

phlipsi commented Sep 15, 2015

This is the libcurl log:

* Rebuilt URL to: https://<destination>:443/
* Hostname was NOT found in DNS cache
*   Trying <proxy>...
* Connected to <proxy> (<proxy>) port 8128 (#0)
* Establish HTTP proxy tunnel to <destination>:443
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Connection: Keep-Alive

< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Tue, 15 Sep 2015 21:16:58 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: close
< 
* Ignore 1062 bytes of response-body
* Connect me again please
* successfully set certificate verify locations:
*   CAfile: <ca-cert-file>
  CApath: /etc/ssl/certs
* Unknown SSL protocol error in connection to <destination>:443 
* Found bundle for host <destination>: 0x886a60
* Hostname was found in DNS cache
*   Trying <proxy>...
* Connected to <proxy> (<proxy>) port 8128 (#1)
* Establish HTTP proxy tunnel to <destination>:443
* Proxy auth using NTLM with user '<user>'
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Authorization: NTLM <ntlm>
Proxy-Connection: Keep-Alive

< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Tue, 15 Sep 2015 21:16:58 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM <ntlm>
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: keep-alive
< Proxy-Connection: keep-alive
< 
* Ignore 1062 bytes of response-body
* TUNNEL_STATE switched to: 0
* Establish HTTP proxy tunnel to <destination>:443
* Proxy auth using NTLM with user '<user>'
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Authorization: NTLM <ntlm>
Proxy-Connection: Keep-Alive

< HTTP/1.0 200 Connection established
< 
* Proxy replied OK to CONNECT request
* successfully set certificate verify locations:
*   CAfile: <ca-cert-file>
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*    subject: <subject>
*    start date: 2015-09-15 08:26:28 GMT
*    expire date: 2016-09-14 08:26:28 GMT
* SSL: certificate subject name 'test-server' does not match target host name '<destination>'
* Closing connection 1
* Found bundle for host <destination>: 0x886a60
* NTLM-proxy picked AND auth done set, clear picked!
* Hostname was found in DNS cache
*   Trying <proxy>...
* Connected to <proxy> (<proxy>) port 8128 (#2)
* Establish HTTP proxy tunnel to <destination>:443
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Connection: Keep-Alive

< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Tue, 15 Sep 2015 21:16:58 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: close
< 
* Ignore 1062 bytes of response-body
* Connect me again please
* successfully set certificate verify locations:
*   CAfile: <ca-cert-file>
  CApath: /etc/ssl/certs
* Unknown SSL protocol error in connection to <destination>:443 
* Found bundle for host <destination>: 0x886a60
* NTLM-proxy picked AND auth done set, clear picked!
* Hostname was found in DNS cache
*   Trying <proxy>...
* Connected to <proxy> (<proxy>) port 8128 (#3)
* Establish HTTP proxy tunnel to <destination>:443
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Connection: Keep-Alive

< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Tue, 15 Sep 2015 21:16:58 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: close
< 
* Ignore 1062 bytes of response-body
* Connect me again please

and so on. I think the essential line here is

* NTLM-proxy picked AND auth done set, clear picked!

which indicates to me that libcurl didn't properly recover from the last successful authentication and following unsuccessful certificate verification.

@iboukris

This comment has been minimized.

Contributor

iboukris commented Sep 15, 2015

On Wed, Sep 16, 2015 at 12:28 AM, Philipp Wähnert notifications@github.com
wrote:

This is the libcurl log:

  • Rebuilt URL to: https://:443/
  • Hostname was NOT found in DNS cache
  • Trying ...
  • Connected to () port 8128 (#0)
  • Establish HTTP proxy tunnel to :443

    CONNECT :443 HTTP/1.1
    Host: :443
    Proxy-Connection: Keep-Alive

< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Tue, 15 Sep 2015 21:16:58 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: close

Your proxy close the connection each time it sends the initial 407 with
Proxy-Authenticate header.
Not that this is wrong to do so as far as I can tell, but that's why it
didn't happen to me (mod_proxy).

I tweaked my apache server to do the same and I think I've reproduced it
now.
I'll try to investigate further.

  • Ignore 1062 bytes of response-body
  • Connect me again please
  • successfully set certificate verify locations:
  • CAfile:
    CApath: /etc/ssl/certs
  • Unknown SSL protocol error in connection to :443
  • Found bundle for host : 0x886a60
  • Hostname was found in DNS cache
  • Trying ...
  • Connected to () port 8128 (#1)
  • Establish HTTP proxy tunnel to :443
  • Proxy auth using NTLM with user ''

    CONNECT :443 HTTP/1.1
    Host: :443
    Proxy-Authorization: NTLM
    Proxy-Connection: Keep-Alive

< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Tue, 15 Sep 2015 21:16:58 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: keep-alive
< Proxy-Connection: keep-alive
<

  • Ignore 1062 bytes of response-body
  • TUNNEL_STATE switched to: 0
  • Establish HTTP proxy tunnel to :443
  • Proxy auth using NTLM with user ''

    CONNECT :443 HTTP/1.1
    Host: :443
    Proxy-Authorization: NTLM
    Proxy-Connection: Keep-Alive

< HTTP/1.0 200 Connection established
<

  • Proxy replied OK to CONNECT request
  • successfully set certificate verify locations:
  • CAfile:
    CApath: /etc/ssl/certs
  • SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
  • Server certificate:
  • subject:
  • start date: 2015-09-15 08:26:28 GMT
  • expire date: 2016-09-14 08:26:28 GMT
  • SSL: certificate subject name 'test-server' does not match target host name ''
  • Closing connection 1
  • Found bundle for host : 0x886a60
  • NTLM-proxy picked AND auth done set, clear picked!
  • Hostname was found in DNS cache
  • Trying ...
  • Connected to () port 8128 (#2)
  • Establish HTTP proxy tunnel to :443

    CONNECT :443 HTTP/1.1
    Host: :443
    Proxy-Connection: Keep-Alive

< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Tue, 15 Sep 2015 21:16:58 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: close

Again, same pattern as mentioned above.

  • Ignore 1062 bytes of response-body
  • Connect me again please
  • successfully set certificate verify locations:
  • CAfile:
    CApath: /etc/ssl/certs
  • Unknown SSL protocol error in connection to :443

What's the above line? it is already set to not verify.. I think this is
the culprit !

  • Found bundle for host : 0x886a60
  • NTLM-proxy picked AND auth done set, clear picked!
  • Hostname was found in DNS cache
  • Trying ...
  • Connected to () port 8128 (#3)
  • Establish HTTP proxy tunnel to :443

    CONNECT :443 HTTP/1.1
    Host: :443
    Proxy-Connection: Keep-Alive

< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Tue, 15 Sep 2015 21:16:58 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: close
<

  • Ignore 1062 bytes of response-body
  • Connect me again please

and so on. I think the essential line here is

  • NTLM-proxy picked AND auth done set, clear picked!

which indicates to me that libcurl didn't properly recover from the last
successful authentication and following unsuccessful certificate
verification.

This log is issued when libcurl creates a new connection to clear NTLM
authentication state.
I'm not sure it's the best thing to do (restart probing) but technically it
should work anyway.

iboukris added a commit to iboukris/curl that referenced this issue Sep 16, 2015

NTLM: Reset auth-done when using a fresh connection
With NTLM a new connection will always require authentication.
Fixes curl#435
@iboukris

This comment has been minimized.

Contributor

iboukris commented Sep 16, 2015

Ok, doesn't seem related to the SSL error I mentioned.

I think I see what's happening though (vaguely), since we don't reset authhost->done when we start a fresh connection we might think we are already authenticated and not send authz header.

This might be related to the changes from:
898808f

The commit below solves the problem by me:
iboukris@8af13d9

@DarovskikhAndrei

This comment has been minimized.

DarovskikhAndrei commented Sep 16, 2015

Why are you change NTLM auth only? Negotiate auth also can have this bug.

@phlipsi

This comment has been minimized.

phlipsi commented Sep 16, 2015

Your proxy close the connection each time it sends the initial 407 with
Proxy-Authenticate header.
Not that this is wrong to do so as far as I can tell, but that's why it
didn't happen to me (mod_proxy).

According to this specification it's an behavior which has to be expected by the client.

  • Unknown SSL protocol error in connection to :443

What's the above line? it is already set to not verify.. I think this is the culprit !

It's necessary that the destination server tears down the connection. I observed the same error with libcurl if the server hangs up for some other reason.

The commit below solves the problem by me:
iboukris/curl@8af13d9

I'll take a look at the commit. Thank you!

@phlipsi

This comment has been minimized.

phlipsi commented Sep 16, 2015

iboukris/curl@8af13d9

This solves the issue. The Log looks now like expected - Sorry for the verbose post but for the sake of completeness:

* STATE: INIT => CONNECT handle 0x74f7c8; line 1090 (connection #-5000) 
* Rebuilt URL to: https://<destination>:443/
* Added connection 0. The cache now contains 1 members
*   Trying <proxy>...
* STATE: CONNECT => WAITCONNECT handle 0x74f7c8; line 1143 (connection #0) 
* Connected to <proxy> (<proxy>) port 8128 (#0)
* STATE: WAITCONNECT => WAITPROXYCONNECT handle 0x74f7c8; line 1240 (connection #0) 
* Marked for [keep alive]: HTTP default
* Establish HTTP proxy tunnel to <destination>:443
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Connection: Keep-Alive

* Read response immediately from proxy CONNECT
< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Wed, 16 Sep 2015 07:54:02 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: close
< 
* Ignore 1062 bytes of response-body
* Connect me again please
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: <ca-cert-file>
  CApath: none
* Unknown SSL protocol error in connection to <destination>:443 
* Marked for [closure]: Failed HTTPS connection
* Curl_done
* Closing connection 0
* The cache now contains 0 members
* STATE: WAITPROXYCONNECT => CONNECT handle 0x74f7c8; line 1223 (connection #-5000) 
* Added connection 1. The cache now contains 1 members
* Hostname <proxy> was found in DNS cache
*   Trying <proxy>...
* STATE: CONNECT => WAITCONNECT handle 0x74f7c8; line 1143 (connection #1) 
* Connected to <proxy> (<proxy>) port 8128 (#1)
* STATE: WAITCONNECT => WAITPROXYCONNECT handle 0x74f7c8; line 1240 (connection #1) 
* Marked for [keep alive]: HTTP default
* Establish HTTP proxy tunnel to <destination>:443
* Proxy auth using NTLM with user '<user>'
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Authorization: NTLM <ntlm>
Proxy-Connection: Keep-Alive

* Read response immediately from proxy CONNECT
< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Wed, 16 Sep 2015 07:54:02 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM <ntlm>
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: keep-alive
< Proxy-Connection: keep-alive
< 
* Ignore 1062 bytes of response-body
* TUNNEL_STATE switched to: 0
* Establish HTTP proxy tunnel to <destination>:443
* Proxy auth using NTLM with user '<user>'
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Authorization: NTLM <ntlm>
Proxy-Connection: Keep-Alive

* Read response immediately from proxy CONNECT
< HTTP/1.0 200 Connection established
< 
* Proxy replied OK to CONNECT request
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: <ca-cert-file>
  CApath: none
* STATE: WAITPROXYCONNECT => SENDPROTOCONNECT handle 0x74f7c8; line 1228 (connection #1) 
* STATE: SENDPROTOCONNECT => PROTOCONNECT handle 0x74f7c8; line 1254 (connection #1) 
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*    subject: <subject>
*    start date: 2015-09-15 08:26:28 GMT
*    expire date: 2016-09-14 08:26:28 GMT
* SSL: certificate subject name 'test-server' does not match target host name '<destination>'
* Marked for [closure]: Failed HTTPS connection
* Curl_done
* Closing connection 1
* The cache now contains 0 members
* Expire cleared
* STATE: INIT => CONNECT handle 0x74f7c8; line 1090 (connection #-5000) 
* Added connection 2. The cache now contains 1 members
* NTLM-proxy picked AND auth done set, clear picked!
* Hostname <proxy> was found in DNS cache
*   Trying <proxy>...
* STATE: CONNECT => WAITCONNECT handle 0x74f7c8; line 1143 (connection #2) 
* Connected to <proxy> (<proxy>) port 8128 (#2)
* STATE: WAITCONNECT => WAITPROXYCONNECT handle 0x74f7c8; line 1240 (connection #2) 
* Marked for [keep alive]: HTTP default
* Establish HTTP proxy tunnel to <destination>:443
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Connection: Keep-Alive

* Read response immediately from proxy CONNECT
< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Wed, 16 Sep 2015 07:54:02 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: close
< 
* Ignore 1062 bytes of response-body
* Connect me again please
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: <ca-cert-file>
  CApath: none
* Unknown SSL protocol error in connection to <destination>:443 
* Marked for [closure]: Failed HTTPS connection
* Curl_done
* Closing connection 2
* The cache now contains 0 members
* STATE: WAITPROXYCONNECT => CONNECT handle 0x74f7c8; line 1223 (connection #-5000) 
* Added connection 3. The cache now contains 1 members
* Hostname <proxy> was found in DNS cache
*   Trying <proxy>...
* STATE: CONNECT => WAITCONNECT handle 0x74f7c8; line 1143 (connection #3) 
* Connected to <proxy> (<proxy>) port 8128 (#3)
* STATE: WAITCONNECT => WAITPROXYCONNECT handle 0x74f7c8; line 1240 (connection #3) 
* Marked for [keep alive]: HTTP default
* Establish HTTP proxy tunnel to <destination>:443
* Proxy auth using NTLM with user '<user>'
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Authorization: NTLM <ntlm>
Proxy-Connection: Keep-Alive

* Read response immediately from proxy CONNECT
< HTTP/1.0 407 Proxy Authentication Required
< Server: squid/2.HEAD-CVS
< Date: Wed, 16 Sep 2015 07:54:02 GMT
< Content-Type: text/html
< Content-Length: 1062
< X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
< Proxy-Authenticate: NTLM <ntlm>
< X-Cache: MISS from proxy
< Via: 1.0 proxy:8128 (squid/2.HEAD-CVS)
< Connection: keep-alive
< Proxy-Connection: keep-alive
< 
* Ignore 1062 bytes of response-body
* TUNNEL_STATE switched to: 0
* Establish HTTP proxy tunnel to <destination>:443
* Proxy auth using NTLM with user '<user>'
> CONNECT <destination>:443 HTTP/1.1
Host: <destination>:443
Proxy-Authorization: NTLM <ntlm>
Proxy-Connection: Keep-Alive

* Read response immediately from proxy CONNECT
< HTTP/1.0 200 Connection established
< 
* Proxy replied OK to CONNECT request
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: <ca-cert-file>
  CApath: none
* STATE: WAITPROXYCONNECT => SENDPROTOCONNECT handle 0x74f7c8; line 1228 (connection #3) 
* STATE: SENDPROTOCONNECT => PROTOCONNECT handle 0x74f7c8; line 1254 (connection #3) 
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*    subject: <subject>
*    start date: 2015-09-15 08:26:28 GMT
*    expire date: 2016-09-14 08:26:28 GMT
*    issuer: <issuer>
*    SSL certificate verify ok.
* STATE: PROTOCONNECT => DO handle 0x74f7c8; line 1275 (connection #3) 
> GET / HTTP/1.1
Host: <destination>
Accept: */*

* STATE: DO => DO_DONE handle 0x74f7c8; line 1337 (connection #3) 
* STATE: DO_DONE => WAITPERFORM handle 0x74f7c8; line 1464 (connection #3) 
* STATE: WAITPERFORM => PERFORM handle 0x74f7c8; line 1474 (connection #3) 
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Date: Wed, 16 Sep 2015 07:54:03 GMT
* Server Apache/2.4.10 (Ubuntu) is not blacklisted
< Server: Apache/2.4.10 (Ubuntu)
< Last-Modified: Tue, 15 Sep 2015 08:41:53 GMT
< ETag: "27-51fc52767c975"
< Accept-Ranges: bytes
< Content-Length: 39
< Content-Type: text/html
< 
<htlm><body>Hello World!</body></html>
* STATE: PERFORM => DONE handle 0x74f7c8; line 1632 (connection #3) 
* Curl_done
* Connection #3
@iboukris

This comment has been minimized.

Contributor

iboukris commented Sep 16, 2015

@DarovskikhAndrei Negotiate has several variants so its hard to tell.
Anyway, Negotiate code first needs some refactoring to be more connection bound, then I think we should go over all USE_NTLM occurrences and consider the Negotiate cases.

@phlipsi I didn't mean to say the proxy was wrong, just tried to explain the difference in behavior.
Thanks for testing!

@iboukris

This comment has been minimized.

Contributor

iboukris commented Sep 16, 2015

Ok, here is a better description of what seem to be going on (after playing a little with gdb).

You first need a successful authentication to set 'done' to true.
Then if the connection gets closed, we re-create one and we cleanup 'picked' since 'done' is set.
Then we send an empty request because 'picked' is cleared.
Then we receive initial 407 and we collected all the available auth-methods.
Then iff the proxy asked to close the connection we close and recreate - once again clearing 'picked' since 'done' is still set!

I still think the patch is correct, and it seem similar to what the code used to do.

@bagder bagder closed this in f65e07c Sep 19, 2015

jgsogo added a commit to jgsogo/curl that referenced this issue Oct 19, 2015

NTLM: Reset auth-done when using a fresh connection
With NTLM a new connection will always require authentication.
Fixes curl#435

@lock lock bot locked as resolved and limited conversation to collaborators May 7, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.