cURL / Mailing Lists / curl-library / Single Mail

curl-library

RE: about https proxy queston

From: Joe Mason <jmason_at_blackberry.com>
Date: Wed, 11 Feb 2015 23:43:12 +0000

> From: curl-library [curl-library-bounces_at_cool.haxx.se] on behalf of Daniel
> Stenberg [daniel_at_haxx.se]
> Subject: Re: about https proxy queston
>
> Still, based on your suggested change I think I understand the problem. It
> seems to be that the code uses some happy eyeballs logic even _after_ CONNECT
> has been sent to a proxy, while the happy eyeball phase is already (should be)
> over by then.
>
> So, to make the fix nicer I split waitconnect_getsock in two, and there's now
> a waitproxyconnect_getsock as well.

I'm running into a similar issue, but this patch doesn't fix it. I have a proxy that uses NTLM authentication, and I'm trying to tunnel an HTTPS connection through it. I'm using CURLMOPT_SOCKETFUNCTION to hook into my event loop.

! Connected to 10.90.48.25 (10.90.48.25) port 8080 (#4)
! Establish HTTP proxy tunnel to wd3.myworkday.com:443
! Proxy auth using NTLM with user 'dummy'
>>> CONNECT wd3.myworkday.com:443 HTTP/1.1
>>> Host: wd3.myworkday.com:443
>>> Proxy-Authorization: NTLM TlRMTVNTUAABAAAAAZIIQAUABQAYAAAAAAAAAB0AAABDT1JFMg==
>>> Proxy-Connection: Keep-Alive
>>> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10
>>>
<<< HTTP/1.1 407 Proxy Authentication Required ( Access is denied. )
<<< Via: 1.1 BBSPROXY3
<<< Proxy-Authenticate: NTLM TlRMTVNTUAACAAAABgAGADgAAAAFgolCEghn6Bz3o8cAAAAAAAAAAMIAwgA+AAAABgByFwAAAA9CAEIAUwACAAYAQgBCAFMAAQASAEIAQgBTAFAAUgBPAFgAWQAzAAQAJgBiAGIAcwAuAHQAZQBzAHQAbgBlAHQALgByAGkAbQAuAG4AZQB0AAMAOgBCAEIAUwBQAFIATwBYAFkAMwAuAGIAYgBzAC4AdABlAHMAdABuAGUAdAAuAHIAaQBtAC4AbgBlAHQABQAmAGIAYgBzAC4AdABlAHMAdABuAGUAdAAuAHIAaQBtAC4AbgBlAHQABwAIABpWy+5RRtABAAAAAA==
<<< Connection: Keep-Alive
<<< Proxy-Connection: Keep-Alive
<<< Pragma: no-cache
<<< Cache-Control: no-cache
<<< Content-Type: text/html
<<< Content-Length: 0
<<<
! TUNNEL_STATE switched to: 0
! Establish HTTP proxy tunnel to wd3.myworkday.com:443
! Proxy auth using NTLM with user 'dummy'
>>> CONNECT wd3.myworkday.com:443 HTTP/1.1
>>> Host: wd3.myworkday.com:443
>>> Proxy-Authorization: NTLM TlRMTVNTUAADAAAAAAAAAHAAAADyAPIAcAAAAAoACgBAAAAAEAAQAEoAAAAWABYAWgAAABAAEABiAQAABYKJQkMATwBSAEUAMgBkAG0AZQBqAGkAYQAwADEAdwBvAHIAawBzAHQAYQB0AGkAbwBuAKMv0AfO/E9CTaIxie3hqiYBAQAAAAAAAIAjA+9RRtABBl9JNSCBMaMAAAAAAgAGAEIAQgBTAAEAEgBCAEIAUwBQAFIATwBYAFkAMwAEACYAYgBiAHMALgB0AGUAcwB0AG4AZQB0AC4AcgBpAG0ALgBuAGUAdAADADoAQgBCAFMAUABSAE8AWABZADMALgBiAGIAcwAuAHQAZQBzAHQAbgBlAHQALgByAGkAbQAuAG4AZQB0AAUAJgBiAGIAcwAuAHQAZQBzAHQAbgBlAHQALgByAGkAbQAuAG4AZQB0AAc
>>> Proxy-Connection: Keep-Alive
>>> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10
>>>
<<< HTTP/1.1 200 Connection established
<<< Via: 1.1 BBSPROXY3
<<< Connection: Keep-Alive
<<< Proxy-Connection: Keep-Alive
<<<
! Proxy replied OK to CONNECT request
! successfully set certificate verify locations:
! CAfile: none
! CApath: /etc/openssl/certs

After this point, older versions of curl would continue to finish the TLS setup, but 7.39 just hangs.

I've traced it into ossl_connect_step2:

  err = SSL_connect(connssl->handle);

  /* 1 is fine
     0 is "not successful but was shut down controlled"
     <0 is "handshake was not successful, because a fatal error occurred" */
  if(1 != err) {
    int detail = SSL_get_error(connssl->handle, err);

    if(SSL_ERROR_WANT_READ == detail) {
      connssl->connecting_state = ssl_connect_2_reading;
      return CURLE_OK;
    }

I always get SSL_ERROR_WANT_READ, which returns up the stack to multi_runsingle, which is in CURLM_STATE_WAITPROXYCONNECT:

    case CURLM_STATE_WAITPROXYCONNECT:
      /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
      result = Curl_http_connect(data->easy_conn, &protocol_connect);

      if(data->easy_conn->bits.proxy_connect_closed) {
        /* connect back to proxy again */
        result = CURLE_OK;
        rc = CURLM_CALL_MULTI_PERFORM;
        multistate(data, CURLM_STATE_CONNECT);
      }
      else if(!result) {
        if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
          multistate(data, CURLM_STATE_WAITCONNECT);
      }
      break;

CURLE_OK gets returned from Curl_http_connect. proxy_connect_closed is not set,and tunnel_state is TUNNEL_COMPLETE, so it sets the state to CURLM_STATE_WAITCONNECT.

Then the next time through the loop, singlesocket runs and calls multi_getsock, which calls waitconnect_getsock. In older versions, waitconnect_getsock always returned with GETSOCK_WRITESOCK turned on, so the socket callback was called again with CURL_POLL_OUT. So my event loop would service the socket again, and it would reenter ossl_connect_step2, and this time SSL_connect would return 1, and the SSL handshake would complete.

In 7.39 multi_getsock returns 0, so nothing gets added to the action in singlesocket, and the socket callback never gets called.

Your patch doesn't fix this because in my case the problems in state CURLM_STATE_WAITCONNECT, not CURLM_STATE_WAITPROXYCONNECT, so waitconnect_getsock still gets called.

Joe

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2015-02-12