使用WinSSL、NTLM、HTTP2、SSH2和IPv6支持构建可工作的libcurl

50
在我们的PHP应用程序中,我们需要以以下方式构建PHP curl扩展,以支持以下功能:
  • WinSSL(访问Windows证书存储)
  • NTLM,Basic和Digest身份验证
  • HTTP/2支持
  • SSH2支持
  • IPv6支持
我尝试使用以下命令行构建curl以实现此目的:
  • 将其与WinSSL链接
  • 将其与nghttp2链接
  • 将其与libssh2链接
  • 启用IPv6
nmake /f Makefile.vc mode=dll VC=15 ENABLE_WINSSL=yes DEBUG=no MACHINE=x64 ENABLE_SSPI=no WITH_NGHTTP2=dll WITH_ZLIB=static WITH_SSH2=static WITH_DEVEL=C:\curl\deps-x64

winbuild/ 子文件夹中。然后我针对结果编译了 PHP 的 curl 扩展。

使用这个结果,当对提供基本身份验证、摘要身份验证、NTLM 和协商身份验证(Exchange Web服务)的 Web 服务进行 HTTP 请求时,我遇到了以下错误行为

  • 如果使用 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM); ,一切都正常。

  • 如果使用 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); ,一切也正常。

  • 如果使用 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM | CURLAUTH_BASIC);身份验证失败

失败的请求包含一个 NTLM 令牌,该令牌过于短小(似乎在某个点被截断)。一些谷歌搜索表明,这可能是由于 curl 编译时使用了 SSPI。但是,我无法禁用 SSPI,因为 WinSSL 需要它。

有人知道解决方法吗?如何获得一个满足所有上述要求的 PHP-curl 扩展?


2
是身份验证问题还是libcurl的错误?您能否发布一个CURLAUTH_NTLM | CURLAUTH_BASIC的CURLOPT_VERBOSE日志? - hanshenrik
2
TFM说你需要在Windows上使用SSPI来进行NTLM,所以我不认为那是它。继@Mason.Chase的评论之后,我会通过编写包装函数并执行doNTLM() || doBasicHTTP()来解决它,而不是将这两个选项传递给curl。 - ivanivan
1
我不确定CURL是否可以在同一连接中同时执行NTLM和Basic,因此忽略任何SSL,NTLM需要在发送到服务器之前进行加密和Base64编码,当您尝试连接时,服务器将提供Base64编码数据,这可能是您的问题。首先尝试打开连接并读取标题以查看它需要哪种方法,基本或NTLM。http://davenport.sourceforge.net/ntlm.html#ntlmHttpAuthentication - Barkermn01
1
@MartinBarker:服务器发送多个不同的WWW-Authenticate头,curl应该选择适当的头并进行身份验证。curl可以从问题选项中选择适当的头,因此在失败的情况下,curl应该选择NTLM或基本身份验证,并选择NTLM。但是,由于curl生成的Authorization头是错误的,因此身份验证失败。 - Jost
1
好的,我们需要看到你的代码,因为通常在构造请求之前使用CURL不会从服务器获取任何信息。 - Barkermn01
显示剩余5条评论
1个回答

1

我相信这里的LibCurl满足所有需求:

https://curl.haxx.se/windows

使用此文件:
#include <curl/curl.h>
#include <stdio.h>
int main() {
   curl_version_info_data *o = curl_version_info(CURLVERSION_NOW); 
   printf("SSL: %s\n", o->ssl_version);
   printf("NTLM: %d\n", o->features & CURL_VERSION_NTLM);
   printf("HTTP/2: %d\n", o->features & CURL_VERSION_HTTP2);
   printf("SSH2: %s\n", o->libssh_version);
   printf("IPv6: %d\n", o->features & CURL_VERSION_IPV6);
}

构建:

cc https.c `
'-Icurl-7.70.0-win64-mingw\include' `
'-Lcurl-7.70.0-win64-mingw\lib' `
-lcrypt32 `
-lcurl `
-lwldap32 `
-lws2_32

结果:

SSL: OpenSSL/1.1.1g (Schannel)
NTLM: 16
HTTP/2: 65536
SSH2: libssh2/1.9.0
IPv6: 1

我没有使用Visual Studio进行构建,而是使用了Clang:

https://github.com/mstorsjo/llvm-mingw

此外,我不确定OpenSSL/1.1.1g(Schannel)具体是什么意思,我猜它指的是OpenSSL和WinSSL两者都?如果不是这种情况,您可以使用CFG=-winssl自行构建LibCurl:

https://github.com/nu8/gulf/blob/master/c-https/1-curl.ps1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接