Repository navigation
Payload dropped from POST when using proxy with NTLM authentication #2431
Copy link
Copy link
Closed
Description
I did this
Performed a POST request to an API that I am using (https://api.emarsys.net/api/v2/email/getlaunchesofemail, documentation here) using NTLM authentication for the corporate proxy that I am behind. The JSON payload is however dropped from the request as is evidenced by the Content-Length: 0 header.
(This issue is related to the downstream use of the R curl package, see jeroen/curl#146.)
$ curl --proxy http://<proxy_url>:<proxy_port> \
--proxy-ntlm \
--proxy-user : \
--verbose \
--include \
--header "Content-Type: application/json" \
--header 'X-WSSE: UsernameToken <token>' \
--data '{"emailId":"1234"}' \
https://api.emarsys.net/api/v2/email/getlaunchesofemail
* timeout on name lookup is not supported
* Trying <proxy_ip>...
* TCP_NODELAY set
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to <proxy_url> (<proxy_ip>) port <proxy_port> (#0)
* Establish HTTP proxy tunnel to api.emarsys.net:443
* Proxy auth using NTLM with user ''
> CONNECT api.emarsys.net:443 HTTP/1.1
> Host: api.emarsys.net:443
> Proxy-Authorization: NTLM <token>
> User-Agent: curl/7.53.0
> Proxy-Connection: Keep-Alive
>
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0< HTTP/1.1 200 Connection established
<
* Proxy replied OK to CONNECT request
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
} [5 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.2 (IN), TLS handshake, Server hello (2):
{ [109 bytes data]
* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [5413 bytes data]
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
{ [333 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [70 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
{ [1 bytes data]
* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: OU=Domain Control Validated; OU=EssentialSSL Wildcard; CN=*.emarsys.net
* start date: Nov 20 00:00:00 2015 GMT
* expire date: Dec 16 23:59:59 2018 GMT
* subjectAltName: host "api.emarsys.net" matched cert's "*.emarsys.net"
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
* SSL certificate verify ok.
} [5 bytes data]
> POST /api/v2/email/getlaunchesofemail HTTP/1.1
> Host: api.emarsys.net
> User-Agent: curl/7.53.0
> Accept: */*
> Content-Type: application/json
> X-WSSE: UsernameToken <token>
> Content-Length: 0
>
{ [5 bytes data]
< HTTP/1.1 400 Bad Request
< Server: openresty/1.11.2.2
< Date: Wed, 28 Mar 2018 11:33:56 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 59
< Connection: keep-alive
< X-Ratelimit-Limit: 1000
< X-Ratelimit-Reset: 1522236840
< X-Ratelimit-Remaining: 999
< Strict-Transport-Security: max-age=15552000; includeSubDomains; preload
< X-Suite-Response-Time: 19
< Vary: Accept-Encoding
< Cache-Control: max-age=0, no-cache, no-store, must-revalidate
< Pragma: no-cache
<
{ [59 bytes data]
100 59 100 59 0 0 34 0 0:00:01 0:00:01 --:--:-- 35HTTP/1.1 200 Connection established
HTTP/1.1 400 Bad Request
Server: openresty/1.11.2.2
Date: Wed, 28 Mar 2018 11:33:56 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 59
Connection: keep-alive
X-Ratelimit-Limit: 1000
X-Ratelimit-Reset: 1522236840
X-Ratelimit-Remaining: 999
Strict-Transport-Security: max-age=15552000; includeSubDomains; preload
X-Suite-Response-Time: 19
Vary: Accept-Encoding
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Pragma: no-cache
{"replyCode":6004,"replyText":"Invalid email ID","data":""}
* Connection #0 to host <proxy_url> left intactI expected the following
A POST request to https://api.emarsys.net/api/v2/email/getlaunchesofemail with a non-zero Content-Length header and the following JSON object as the payload:
{
"emailId":"1234"
}curl/libcurl #version
curl 7.53.0 (x86_64-w64-mingw32) libcurl/7.53.0 OpenSSL/1.0.2k zlib/1.2.11 libssh2/1.8.0 nghttp2/1.19.0 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smtp smtps telnet tftp
Features: IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz TLS-SRP HTTP2 HTTPS-proxy Metalinkoperating system
Microsoft Windows 7 Professional
6.1.7601 Service Pack 1, build 7601
Reactions are currently unavailable
Activity
gvanem commentedon Mar 28, 2018
Where did the
"inX-WSSE: UsernameToken <token>"come from?Probably some shell SNAFU in action. In such cases, it's handy to use the
--libcurl -option to see whatCURLOPT_xcurl is using. With thispost-test.bat:curl seems to send what was intended (except for the proxy stuff):
I see no
Content-length: 0with the above.bagder commentedon Mar 28, 2018
Here's what I believe happens:
This asks for NTLM auth with the proxy, but as can be seen in the verbose output there's no NTLM negotiation happening so I suspect that curl doesn't correctly note the "auth phase done" there and when it is time to send the POST request, it thinks it is still in a "multi-pass authentication phase" during which it skips sending the request body for data-saving purposes.
Work-around: try
--proxy-anyauthinstead of--proxy-ntlm, it should make it work for NTLM-proxies but even for this case without auth.matthijsvanderloos commentedon Mar 28, 2018
@gvanem The quote in
X-WSSE: UsernameToken <token>"was part of the token, which I forgot to remove...The generated libcurl code using the
--libcurloption is:So interestingly the
CURLOPT_POSTFIELDSoption does contain the correct payload, but curl still drops it from the actual request.@bagder yes,
--proxy-anyauthworks, but I think in my case it is resorting to Negotiate authentication, so I cannot confirm this completely.gvanem commentedon Mar 28, 2018
That wasn't clear from your 1st post. So maybe
curl --verboseisn't verbose enough?stale commentedon Mar 12, 2019
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
MarcelRaad commentedon Mar 12, 2019
There's an active PR for this now.