Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP + Curl: Connection closure while negotiation auth (HTTP 1.0?)

I have a problem between CURL and PHP. I tried to connect to an Exchange 2010 Server via EWS. The connection to the server works fine in command line using CURL but not with PHP Curl extension.

I attached an image with the debug information. On the left you see command line output, on the right PHP verbose output. When the PHP Curl Extension throws an error "Connection closure while negotiation auth (HTTP 1.0?)" the command line continues with a third HTTP request with results in an HTTP/1.1 302 Found:

log information

Some additional information:

  • I use this library for CURL-Requests: https://github.com/jamesiarmes/php-ntlm/blob/master/src/SoapClient.php
  • we have about 80 exchange servers where there is no problem. Only with this server there is a problem. Our customer told about a software called "Sophos" used as a proxy for the webserver
  • CURLOPT_HTTPAUTH is CURLAUTH_NTLM
  • PHP Version 7.3.1 / 7.3.9 also tested
  • cURL Information 7.63.0 / 7.52.1 also tested

Does anybody know why the PHP Curl Extension closes the connection before the third request? Is this a bug of the extension, can I use a constant of PHP Curl to avoid that or is there another solution?

like image 356
Tobias Bambullis Avatar asked Oct 08 '19 11:10

Tobias Bambullis


2 Answers

The connection is closed because the server says so. See your screenshot, one line above where the "What is the problem here?" points.

HTTP/1.1 401 Unauthorized
[...]
Connection: close
Content-Type: application/x-asmx

And probably the server closes the connection afterwards.

So that is not an action, but a result. The message is emitted in Curl_http_readwrite_headers:

#if defined(USE_NTLM)
      if(conn->bits.close &&
         (((data->req.httpcode == 401) &&
           (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
          ((data->req.httpcode == 407) &&
           (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
        data->state.authproblem = TRUE;
      }
#endif
#if defined(USE_SPNEGO)
      if(conn->bits.close &&
        (((data->req.httpcode == 401) &&
          (conn->http_negotiate_state == GSS_AUTHRECV)) ||
         ((data->req.httpcode == 407) &&
          (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
        data->state.authproblem = TRUE;
      }

Presumably from the first block (NTLM), but these are the two occurrences, and they are next to each other anyway.

Fun fact: the same function only a lot later checks for the presence of a Connection: close header, so having the mystical flag conn->bits.close set probably means that the server dropped the connection already and it was detected on socket-level.

Side remark: the two sides of the comparison show very dissimilar interactions. On the left there is a practically empty GET request (Host, Authorization, User-Agent and Accept headers are provided), while on the right side there is a lot more complicated POST request (same headers plus Method, SOAPAction, an empty content with Expect for continuation).

like image 70
tevemadar Avatar answered Oct 12 '22 23:10

tevemadar


I have faced such like this problem by using SoapClient and Microsoft Exchange 2010 Server, and the trick was by changing the header array option 'Expect: 100-continue' to 'Expect: 200-ok'

protected function buildHeaders($action)
{
    return array(
        'Method: POST',
        'Connection: Keep-Alive',
        'User-Agent: PHP-SOAP-CURL',
        'Content-Type: text/xml; charset=utf-8',
        "SOAPAction: \"$action\"",
        'Expect: 200-ok',
    );
}

The 100 (Continue) status code indicates that the initial part of a request has been received and has not yet been rejected by the server.

The 200 (OK) status code indicats that the request has succeeded. The meaning of a success varies depending on the HTTP method.

You can also check this out HTTP status codes

I wish this could help

like image 28
Thaier Alkhateeb Avatar answered Oct 13 '22 00:10

Thaier Alkhateeb