Description
For all the stumble upon this issue.
CURL 8.20.0 has been integrated into PHP with a breaking change. (For 8.5.5 we had 8.19.0).
I think it is a PHP related issue, because on curl side, this is intended new build behaviour.
Is there anything we can do about it?
It breaks all libraries that rely on curl for NTLM based auth (Which for example Exchange API uses a lot)
There is no mention for this upgrade in the changelog or this breaking change.
Details:
curl/curl#20698
https://curl.se/ch/8.20.0.html -> build: make NTLM disabled by default
PHP Version
PHP 8.5.6 (cli) (built: May 18 2026 17:15:53) (ZTS Visual C++ 2022 x64)
Copyright (c) The PHP Group
Zend Engine v4.5.6, Copyright (c) Zend Technologies
with Zend OPcache v8.5.6, Copyright (c), by Zend Technologies
Operating System
Windows
The exact issue in our use case
MS Exchange EWS API uses SOAP to communicate. On-Premise solution still need NTLM based auth for this API to work.
With PHP 8.5.5 everything works fine, starting with 8.5.6 it doesnt work anymore.
Here are all required working parts for the curl request that is made.
<?php
$location = "xxx";
$headers = [
'Method: POST',
'Connection: Keep-Alive',
'User-Agent: PHP-SOAP-CURL',
'Content-Type: text/xml; charset=utf-8',
"SOAPAction: xxx",
'Expect: 100-continue',
];
$request = '<?xml...';
$options = [
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_HTTPAUTH => CURLAUTH_NTLM,
CURLOPT_USERPWD => "user:pw"
];
$options[CURLOPT_HEADER] = true;
$options[CURLOPT_POST] = true;
$options[CURLOPT_POSTFIELDS] = $request;
$streamVerboseHandle = fopen('php://temp', 'w+');
$ch = curl_init($location);
curl_setopt_array($ch, $options);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $streamVerboseHandle);
$response = curl_exec($ch);
rewind($streamVerboseHandle);
$verboseLog = stream_get_contents($streamVerboseHandle);
var_dump($verboseLog);
var_dump($response);
Response with 8.5.5
* Host xxx:443 was resolved.
* IPv6: (none)
* IPv4: xxx.64, xxx.63
* Trying xxx.64:443...
* ALPN: curl offers http/1.1
* SSL Trust: peer verification disabled
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 / secp384r1 / rsaEncryption
* ALPN: server accepted http/1.1
* Server certificate:
* xxx
* OpenSSL verify result: 14
* SSL certificate verification failed, continuing anyway!
* Established connection to xxx (xxx.64 port 443) from xxx.13 port 51422
* using HTTP/1.x
* Server auth using NTLM with user 'xxx'
> POST /EWS/Exchange.asmx HTTP/1.1
Host: xxx
Authorization: NTLM xxxx
Accept: */*
Method: POST
User-Agent: PHP-SOAP-CURL
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://schemas.microsoft.com/exchange/services/2006/messages/CreateItem"
Expect: 100-continue
Content-Length: 0
Connection: Keep-Alive
* Request completely sent off
< HTTP/1.1 401 Unauthorized
< Server: Microsoft-IIS/10.0
< request-id: b910309c-74dc-4e1b-8f5b-d73fb77b7ddd
< WWW-Authenticate: NTLM TlRMTVNTUAACAAAACAAIADgAAAAFgomi0...
< X-OWA-Version: 15.2.1544.11
< WWW-Authenticate: Negotiate
< X-Powered-By: ASP.NET
< X-FEServer: xxx04
< Date: Wed, 27 May 2026 10:28:05 GMT
< Content-Length: 0
* Ignoring the response-body
* setting size while ignoring
<
* Connection #0 to host xxx:443 left intact
* Issue another request to this URL: 'https://xxx/EWS/Exchange.asmx'
* Reusing existing https: connection with host xxx
* Server auth using NTLM with user 'xxx'
> POST /EWS/Exchange.asmx HTTP/1.1
Host: xxx
Authorization: NTLM xxx
Accept: */*
Method: POST
User-Agent: PHP-SOAP-CURL
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://schemas.microsoft.com/exchange/services/2006/messages/CreateItem"
Expect: 100-continue
content-length: 1165
Connection: Keep-Alive
< HTTP/1.1 100 Continue
<
* upload completely sent off: 1165 bytes
< HTTP/1.1 200 OK
< Cache-Control: private
< Transfer-Encoding: chunked
< Content-Type: text/xml; charset=utf-8
< Server: Microsoft-IIS/10.0
< request-id: 4ef2eca0-87cb-4e46-9292-6b6247b322b4
< X-CalculatedBETarget: xxx
< X-DiagInfo: xxx04
< X-BEServer: xxx04
< X-AspNet-Version: 4.0.30319path=/EWS; secure; HttpOnly
< Persistent-Auth: true
< X-Powered-By: ASP.NET
< X-FEServer: xxx04
< Date: Wed, 27 May 2026 10:28:05 GMT
<
* Connection #0 to host xxx:443 left intact
Response with 8.5.6
* Host xxx was resolved.
* IPv6: (none)
* IPv4: 1xxx
* Trying xxx
* ALPN: curl offers http/1.1
* SSL Trust: peer verification disabled
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 / secp384r1 / rsaEncryption
* ALPN: server accepted http/1.1
* Server certificate:
* xxx
* OpenSSL verify result: 14
* SSL certificate verification failed, continuing anyway!
* Established connection to xxx
* using HTTP/1.x
> POST /EWS/Exchange.asmx HTTP/1.1
Host: xxx
Accept: */*
User-Agent: PHP-SOAP-CURL
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://schemas.microsoft.com/exchange/services/2006/messages/CreateItem"
Expect: 100-continue
content-length: 1165
Connection: Keep-Alive
* Request completely sent off
< HTTP/1.1 401 Unauthorized
< Server: Microsoft-IIS/10.0
< request-id: 7fa0326f-98db-4a66-a4d1-da4fa301b206
< X-OWA-Version: 15.2.1544.11
< WWW-Authenticate: Negotiate
< WWW-Authenticate: NTLM
< X-Powered-By: ASP.NET
< Date: Wed, 27 May 2026 09:58:45 GMT
< Content-Length: 0
<
* Connection #0 to host xxx left intact
It stops here, no further data
Description
For all the stumble upon this issue.
CURL 8.20.0 has been integrated into PHP with a breaking change. (For 8.5.5 we had 8.19.0).
I think it is a PHP related issue, because on curl side, this is intended new build behaviour.
Is there anything we can do about it?
It breaks all libraries that rely on curl for NTLM based auth (Which for example Exchange API uses a lot)
There is no mention for this upgrade in the changelog or this breaking change.
Details:
curl/curl#20698
https://curl.se/ch/8.20.0.html -> build: make NTLM disabled by default
PHP Version
Operating System
Windows
The exact issue in our use case
MS Exchange EWS API uses SOAP to communicate. On-Premise solution still need NTLM based auth for this API to work.
With PHP 8.5.5 everything works fine, starting with 8.5.6 it doesnt work anymore.
Here are all required working parts for the curl request that is made.
Response with 8.5.5
Response with 8.5.6