NTLM с cURL возвращает 401
Цель: подключение к серверу Exchange (EWS)
Метод: cURL
Проблема: не удается пройти проверку подлинности (NTLM), запрос возвращает 401. 1
Кажется, существует старая, хорошо документированная проблема, которая началась с перехода cURL с OpenSSL на NSS. Я читал, что реализация NTLM зависит от OpenSSL, и поэтому этот шаг нарушил аутентификацию NTLM.
Проблема показана ниже, но важными частями, кажется, возвращаются 401
и gss_init_sec_context()
ниже этого.
Я не понимаю, что моя текущая версия:
- Имеет вариант OpenSSL в соответствии с https://launchpad.net/ubuntu/+source/curl/7.22.0-3ubuntu4
- поддерживает NTLM по той же ссылке
- На самом деле использует этот вариант (а не NSS) в соответствии с журналом ниже (он говорит
libcurl/7.22.0 OpenSSL
) - Не должно беспокоить связанная ошибка согласно пунктам выше.
- но это влияет, как показывает тот факт, что я получаю 401
Я не уверен, как это можно исправить. Я мог найти много старых (в основном 2010) ссылок на эту проблему, но ничего нового и, конечно же, ничего с решением. Я знаю, что предоставленные ссылки (см. 2) показывают, что это может работать с более старой версией (7.19), но я не могу (или не желаю) перейти на эту версию.
Несколько реализаций Exchange-Communication (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 например:
- https://bugs.launchpad.net/ubuntu/+source/curl/+bug/675974
- https://bugzilla.redhat.com/show_bug.cgi?id=603783
- https://stackoverflow.com/questions/4341368/curl-always-returns-401-with-ntlm
- Это та же проблема, но не учитывает тот факт, что
NSS
вопрос не должен присутствовать в моемOpenSSL
Libcurl.
- Это та же проблема, но не учитывает тот факт, что
скручиваемая информация:
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
2 ответа
Я не совсем уверен, почему, но хотя моя версия 7.22 не должна быть затронута всей проблемой NTLM, похоже, что это так.
Похоже, единственное решение - использовать старую (<7.19, я пробовал с 7.15) версию или использовать новую версию (я пробовал 7.26). Как я уже сказал, я не могу понизить или обновить сам libcurl только для этой функции. Это означает, что нам нужно найти обходной путь....
Обходной путь используется (предупреждение: взломать)
Скачайте и скомпилируйте локон, который вы хотите использовать. Я НЕ делал это как root //
sudo
это потому что я не хочу заменять текущий libcurl и т.д!wget http://curl.haxx.se/download/curl-7.26.0.zip ./configure --prefix=/local_path/ make make install
Протестировать новый
curl
Команда, которую мы только что скомпилировали: она дает 401, но затем вместоgss_init_sec_context()
Вы должны увидеть, как оно достигает (в конце) 302. Это выигрыш.Взломать часть: используйте это
libcurl
при вызове вашего скрипта. Мы работаем с сторонним PHP-приложением (одна из причин, по которой меня не устраивает изменение всех curl-библиотек), и вместо прямого вызова этого мы создаем уродливую, но работающую оболочку, которая вызывает что-то вроде этого:$se = shell_exec("LD_LIBRARY_PATH=/local_path/lib php /path/3rdparty.php");
Да, у этого есть недостатки, и да, это немного скелетный пример (имеется в виду, что вы, вероятно, захотите добавить некоторые вещи, например, может быть, оригинальный путь, например), но основы вроде бы есть.
Не очень горжусь этим, но я думаю, что все больше людей ограничены тем, что они не могут просто пойти и обновить свои libcurl
к случайной версии и используют какой-то плагин, который использует, например, php-ews
или что-нибудь построить на NTLMSoapClient
,
Я надеюсь, что есть еще один вариант в будущем, но так как в настоящее время это единственный способ заставить его работать, я решил поделиться.
Для всех пользователей Centos /RHEL 6.X обратите внимание на: