使用 cURL 的 NTLM 返回 401

使用 cURL 的 NTLM 返回 401

目标:连接到 Exchange 服务器 (EWS)
方法:卷曲
问题:无法获得身份验证(NTLM),请求返回401。1

似乎有一个老问题,记录良好它始于 cURL 从 OpenSSL 移至 NSS。我了解到 NTLM 的实现依赖于 OpenSSL,因此此举破坏了 NTLM 身份验证。

问题如下所示,但重要的部分似乎是返回的部分401gss_init_sec_context()其下方的部分。

我不明白的是,我的当前版本:

  • 有一个 OpenSSL 变体https://launchpad.net/ubuntu/+source/curl/7.22.0-3ubuntu4
  • 根据同一链接,支持 NTLM
  • 根据下面的日志(它说libcurl/7.22.0 OpenSSL)实际上使用了这个变体(而不是 NSS)
  • 根据上述几点,不应该被链接的错误所困扰。
  • 但确实受到影响,因为我收到了 401

我不确定如何修复这个问题。我找到了很多关于这个问题的旧参考资料(大部分是 2010 年的),但没有新的,当然也没有解决方案。我知道提供的参考资料(见2)表明这可能适用于旧版本(7.19),但我无法(也不愿意)降级到该版本。

Exchange 通信 (EWS) 的几种实现都使用 cURL 来检索 EWS 文件 (wsdl 等),因此我确信一定存在一种可行的方法,但我找不到它。有人知道我该怎么办吗?我是否遇到了另一个错误,我是否误解了事实,这是否仍与链接中提供的情况相同,并且永远无法修复?


1错误如下:

curl https://*DOMAIN*/Exchange.asmx -w %{http_code} --ntlm -u *USERNAME* --verbose --show-error
Enter host password for user '*USERNAME':
* About to connect() to DOMAIN port 443 (#0)
*   Trying IP... connected
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using AES128-SHA
* Server certificate:
     *SNIP*
*        SSL certificate verify ok.
* Server auth using NTLM with user 'USERNAME'
> GET /EWS/Exchange.asmx HTTP/1.1
> Authorization: NTLM *snip*
> User-Agent: curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: DOMAIN
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Server: Microsoft-IIS/7.5
< Set-Cookie: exchangecookie=xxx; expires=Wed, 17-Jul-2013 07:45:30 GMT; path=/; HttpOnly
< WWW-Authenticate: NTLM  *SNIP*
* gss_init_sec_context() failed: : Credentials cache file '/tmp/krb5cc_1005' not foundWWW-Authenticate: Negotiate
< X-Powered-By: ASP.NET
< Date: Tue, 17 Jul 2012 07:45:30 GMT
< Content-Length: 0
<
* Connection #0 to host DOMAIN left intact
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):

例如2 :


卷曲信息:

user@server:~$ curl -V
curl 7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtmp rtsp smtp smtps telnet tftp
Features: GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP

答案1

我不太清楚为什么,但是虽然我的 7.22 版本不应该受到整个 NTLM 问题的影响,但看起来似乎确实如此。

唯一的解决方案似乎是使用旧版本(<7.19,我尝试使用 7.15)或使用新版本(我尝试使用 7.26)。如前所述,我无法仅为了此功能而降级或升级 libcurl 本身。这意味着我们需要找到一种解决方法……

已使用解决方法(警告:即将发生黑客攻击)

  1. 下载并编译您想要使用的 curl。我没有以 root 身份执行此操作 //sudo因为我不想替换当前的 libcurl 等!

    wget http://curl.haxx.se/download/curl-7.26.0.zip
    ./configure --prefix=/local_path/
    make
    make install
    
  2. 测试我们刚刚编译的新curl命令:它确实给出了 401,但是您应该gss_init_sec_context()看到它最终转到 302。这是胜利。

  3. 黑客部分:libcurl在调用脚本时使用它。我们正在使用第三方 PHP“应用程序”(我不愿意更改所有 curl 库的原因之一),而不是直接调用它,我们制作了一个丑陋但可以工作的包装器,它调用类似这样的内容:

    $se = shell_exec("LD_LIBRARY_PATH=/local_path/lib php /path/3rdparty.php");
    

是的,这有缺点,是的,这是一个骨架示例(意味着您可能想要添加一些内容,例如原始路径)但基础就在那里。

对此并不是很自豪,但我认为更多的人受到这样一个事实的限制:他们不能直接去更新他们的libcurl版本,而是使用某种使用例如的插件php-ews,或者任何建立在之上的东西NTLMSoapClient

我希望以后还有其他选择,但由于这是目前让它“发挥作用”的唯一方法,所以我想分享一下。

答案2

所有 Centos /RHEL 6.X 用户请查看:

https://bugzilla.redhat.com/show_bug.cgi?id=953864

相关内容