5

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?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Tobias Bambullis
  • 736
  • 5
  • 17
  • 45
  • Could you provide the cURL command that is being run? Also the output of the request from one of the hosts that work? – EternalHour Oct 10 '19 at 16:54

2 Answers2

3

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

tevemadar
  • 12,389
  • 3
  • 21
  • 49
  • thanks for your answer. You are right, the comparison is not equal. So you couldn't figure out that the problem was in header section of the Soap Client (see thaiers answer). – Tobias Bambullis Oct 11 '19 at 09:31
1

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

Thaier Alkhateeb
  • 585
  • 5
  • 8
  • 18