Giter Club home page Giter Club logo

Comments (24)

jay avatar jay commented on May 17, 2024

bisect in Windows VS2010 build shows request body behavior changed in 5dc68dd, 'HTTP: don't abort connections with pending Negotiate authentication'. @tvbuehler

from curl.

tvbuehler avatar tvbuehler commented on May 17, 2024

My guess is that the same problem existed before my change with NTLM instead of Negotiate (because the point of my patch was to make NTLM and Negotiate behave the same).

Maybe forcing "auth_start" to false when the response code is not 401/407 could fix this at least partially.

The main problem is that there is no separate request for "make sure authentication is ok for the following PUT/POST/...", instead we have to authenticate in the same connection with NTLM/Negotiate. So we send a request with a large body and get a 401/407 - now we can't abort the request, because we have to continue the authentication in the same connection.

(chunked uploading would help too, because then you could just stop sending data and still keep the connection in a valid state. but some servers won't like chunked uploading / no content-length..)

from curl.

bagder avatar bagder commented on May 17, 2024

We have code that makes NTLM authentication work connection-oriented but we lack all that for Negotiate. The current situation is not working, the previous situation was not working.

So, the questions are A) what we do short-term for the pending release and B) what we do long-term to get this fixed properly. Ideas?

from curl.

michael-o avatar michael-o commented on May 17, 2024

I have to make a stab here. I personally do not use and wouldn't use NTLM, I use either Kerberos or SPNEGO with Kerberos. In this case one can have request-level authentication because it always requires two tokens only. All is well after one request.

The main point is, a client cannot make any assumptions about the server whether it will persist the authentication or not.

@bagder, we have used the previous situation with SPNEGO against multiple servers with MIT Kerberos, JGSS and SSPI with various requests (GET, POST, PUT). We did not notice any problem before. Probably, I missed that discussion.

If someone has some valueable patch, please let me know, I'll test.

from curl.

bagder avatar bagder commented on May 17, 2024

@michael-o, I appreciate your input on this and your use case that no longer works is a pretty strong argument for reverting the offending patch as a first remedy.

The fact remains though that Negotiate is an authentication method that in my view is even worse than NTLM (and that is a pretty hard blow) and the fact that it may use NTLM in disguise makes it terribly annoying and hard to get right. I imagine that in your use cases it doesn't however and you end up with the kerberos version.

Did you try simply reverting the 5dc68dd commit and see if that works for you?

from curl.

michael-o avatar michael-o commented on May 17, 2024

@bagder, I checked out the 7.40.0 tag from Git, did a git revert on that commit and ran the stuff again on FreeBSD:

*   Trying <server_ip>...
* Connected to <hostname> (<server_ip>) port 8081 (#0)
> PUT /webapp/rest/files/2316975_A5E55802418A_2.pdf HTTP/1.1
> User-Agent: curl/7.40.0-DEV
> Host: <hostname>:8081
> Accept: application/json
> Content-Length: 7
> Expect: 100-continue
> 
< HTTP/1.1 401 Unauthorized
< Server: Apache-Coyote/1.1
< WWW-Authenticate: Negotiate
< Content-Type: text/html;charset=utf-8
< Content-Length: 974
< Date: Fri, 17 Apr 2015 16:52:45 GMT
< 
* Excess found in a non pipelined read: excess = 974 url = /webapp/rest/files/2316975_A5E55802418A_2.pdf (zero-length body)
* Closing connection 0
* Issue another request to this URL: 'http://<hostname>:8081/webapp/rest/files/2316975_A5E55802418A_2.pdf'
* Hostname <hostname> was found in DNS cache
*   Trying <server_ip>...
* Connected to <hostname> (<server_ip>) port 8081 (#1)
* Server auth using Negotiate with user ''
> PUT /webapp/rest/files/2316975_A5E55802418A_2.pdf HTTP/1.1
> Authorization: Negotiate YIIP7w...YOIrHaV3ZFuk8hD
> User-Agent: curl/7.40.0-DEV
> Host: <hostname>:8081
> Accept: application/json
> Content-Length: 7
> Expect: 100-continue
> 
< HTTP/1.1 100 Continue
[7 bytes data]
* We are completely uploaded and fine
< HTTP/1.1 201 Created
< Server: Apache-Coyote/1.1
< WWW-Authenticate: Negotiate oYHtMIHqo...9iFqt
< Connection: close
< Content-Type: application/json
< Content-Length: 24
< Date: Fri, 17 Apr 2015 16:52:46 GMT
< 
{ [24 bytes data]
* Closing connection 1
{"uid":"x0VVIyjbBv4vwA"}

It does work! Though, I do not understand why curl is throwing away the connection when it receives 401?! I see no reason for.

from curl.

bagder avatar bagder commented on May 17, 2024

It closes the connection because of the "Excess found in a non pipelined read" condition. I can't quite understand it either right now, but libcurl does not typically close a connection just because of a 401.

I reverted that commit just now. Thanks @jay for the bisect!

Sorry @tvbuehler, I realize this then removes a fix you wanted but I figure keeping the prior functionality takes precedence here. I believe @Frenche (?) is also currently working on fixing how Negotiate is (not) re-using connections properly.

from curl.

bagder avatar bagder commented on May 17, 2024

It would perhaps be suitable to deal with that in a separate issue. I consider this particular issue fixed now, even if it left us with some open wounds to heal...

from curl.

michael-o avatar michael-o commented on May 17, 2024

@bagder, thanks for the quick solution. Very much appreciated. Just to be clear, do you want to open another issue on the read excess with connection close?

@tvbuehler, if you have another patch. Ping me in the new ticket. I'll test.

from curl.

bagder avatar bagder commented on May 17, 2024

@michael-o: sure, but I can't promise I'll be able to work on it anytime soon...

from curl.

tvbuehler avatar tvbuehler commented on May 17, 2024

Well. My first thought was "Are you crazy? The fix actually fixed not working uploads". And tried to produce a test case with squid3.

And now the result is: If squid3 responds with 407 and curl continues to upload the large body, and then (after the post body is finished) starts a new request in the same connection with the valid authentication, squid3 just ignores all data it receives and times out after 2 minutes...

So I have no idea what curl actually should do :(

from curl.

bagder avatar bagder commented on May 17, 2024

@tvbuehler I realize your fix solved a problem, there's no denying of that but we're facing a release in less than 48 hours and it made a previously working use-case no longer work. Reverting a commit is never something we want to do, but in this case I simply favored to have the previous functionality there and re-work the new fix than the opposite. I'm sorry we're in this situation.

The Negotiate authentication in libcurl will also get a security patch just before 7.42.0 is released that will cripple it further since the current implementation leaves it open to a security problem (we will announce that on Wednesday when the release goes out).

All taken together: Negotiate support in libcurl needs (much) more work to get really good.

from curl.

iboukris avatar iboukris commented on May 17, 2024

Hi,

On Mon, Apr 20, 2015 at 2:32 PM, Daniel Stenberg [email protected]
wrote:

@tvbuehler https://github.com/tvbuehler I realize your fix solved a
problem, there's no denying of that but we're facing a release in less than
48 hours and it made a previously working use-case no longer work.
Reverting a commit is never something we want to do, but in this case I
simply favored to have the previous functionality there and re-work the new
fix than the opposite. I'm sorry we're in this situation.

The Negotiate authentication in libcurl will also get a security patch
just before 7.42.0 is released that will cripple it further since the
current implementation leaves it open to a security problem (we will
announce that on Wednesday when the release goes out).

All taken together: Negotiate support in libcurl needs (much) more work to
get really good.

And with Proxy it gets even more complicated, RFC 4559 initially states "This
mechanism is not used for HTTP authentication to HTTP proxies." however it
seem to be implemented by MS and others.
It is quite blurry to me what should be the behavior in regard to
persistent-auth and what's the expected behavior when regular server
authentication is also needed.

I found some interesting material to investigate and I'd like to test how
squid behaves but it's currently at the end of my priority list.
See this blog for example:
http://blogs.technet.com/b/isablog/archive/2009/07/30/excessive-authentication-traffic-accessing-an-iis-site-when-using-isa-server-2006-as-forward-proxy.aspx

from curl.

michael-o avatar michael-o commented on May 17, 2024

@tvbuehler, I don't understand that behavior in Squid. Furthermore, as a client implementor, You would not make any assumptions whether the server will persist that auth or not. You cannot know and you won't. You should have a look at libserf. Lieven Govaerts invested quite a lot of time to make both auth stateful and stateless. I did the testing at work against various servers.

@Frenche, I can confirm that this is used and is standard in Active Directory environment. We a farm of proxy servers with a cname for all of them. Microsoft TMG is running on that. I do authenticate against them with SPNEGO with libserf (for Subversion) and libcurl (for Git). This was actually my first initiative last year to get decent support in curl, in order to use external Git repos.

from curl.

tvbuehler avatar tvbuehler commented on May 17, 2024

@michael-o I have absolutely no idea what you are trying to tell me. But just for the record: both NTLM and Negotiate are supposed to authenticate the connection (not a single request), and the authentication steps should be done in a single connection - at least that is how I read some specs some months ago.

from curl.

iboukris avatar iboukris commented on May 17, 2024

On Mon, Apr 20, 2015 at 5:34 PM, Stefan Bühler [email protected]
wrote:

@michael-o https://github.com/michael-o I have absolutely no idea what
you are trying to tell me. But just for the record: both NTLM and Negotiate
are supposed to authenticate the connection (not a single request), and the
authentication steps should be done in a single connection - at least that
is how I read some specs some months ago.

No, in IIS when Kerberos is used underneath it is usually request-based
unless you enable 'authPersistNonNTLM' (maybe the default settings have
changed in recent windows versions).
While when NTLM is used (either in Negotiate or in raw NTLM) it
authenticate the connction by default (unless you
set AuthPersistSingleRequest to true - I've written about it here:
http://curl.haxx.se/mail/lib-2015-02/0174.html).

From security perspectives I agree with Michael that the best way is to
always consider Negotiate as connection based and never re-use unless we
run with the same credentials.

From connectivity perspectives however we can investigate how to guess best
if we are connection or request based in order to decide the best upload
scheme (only NTLM related?) and if we initially add the 'Authorization'
header (which will reset auth with most server side implementations).

For a good guess we need to understand if NTLM was used and try to read
relevant HTTP headers hints (Persistent-Auth).

I am aware that Negotiate is used with Proxies in practice but it doesn't
make the behavior more clear or consistent.

One more note, when authenticating to a server with Negotiate and thru a
proxy we also need to verify a non-standard header for security reasons -
see below from RFC 4559:

If an HTTP proxy is used between the client and server, it must take
care to not share authenticated connections between different
authenticated clients to the same server. If this is not honored,
then the server can easily lose track of security context
associations. A proxy that correctly honors client to server
authentication integrity will supply the "Proxy-support: Session-
Based-Authentication" HTTP header to the client in HTTP responses
from the proxy. The client MUST NOT utilize the SPNEGO HTTP
authentication mechanism through a proxy unless the proxy supplies
this header with the "401 Unauthorized" response from the server.

from curl.

michael-o avatar michael-o commented on May 17, 2024

@Frenche

From security perspectives I agree with Michael that the best way is to
always consider Negotiate as connection based and never re-use unless we
run with the same credentials.

Actually, I did not say that in such a way. All I said was that a client should not make any assumptions about the auth level (request or connection). Expect both behaviors. The behavior with IIS is a very good example. For instance, mod_spnego (michael-o/mod_spnego) authenticates on the connection while in Apache Tomcat it is always authenticated on the quest.

From connectivity perspectives however we can investigate how to guess best
if we are connection or request based in order to decide the best upload
scheme (only NTLM related?) and if we initially add the 'Authorization'
header (which will reset auth with most server side implementations).
For a good guess we need to understand if NTLM was used and try to read
relevant HTTP headers hints (Persistent-Auth).

Keep in mind that those headers are non-standard and are send by Microsoft products only. I would rather maintain an information on the connection whether auth is complete and reset when the server nags you again. This would ultimately mean that the auth was not persistent.

The client MUST NOT utilize the SPNEGO HTTP
authentication mechanism through a proxy unless the proxy supplies
this header with the "401 Unauthorized" response from the server.

This is a quite interesting case I have thought about several months ago but how likely is this? Any Kerberos-protected host is supposed to be inside the company and not outside. For us, we have a PAC-enabled proxy server which has a lot of domains which are within the corporate network as well as in the local intranet zone.

from curl.

iboukris avatar iboukris commented on May 17, 2024

On Mon, Apr 20, 2015 at 8:31 PM, Michael Osipov [email protected]
wrote:

@Frenche https://github.com/frenche

From security perspectives I agree with Michael that the best way is to
always consider Negotiate as connection based and never re-use unless we
run with the same credentials.

Actually, I did not say that in such a way. All I said was that a client
should not make any assumptions about the auth level (request or
connection). Expect both behaviors. The behavior with IIS is a very good
example. For instance, mod_spnego (michael-o/mod_spnego) authenticates on
the connection while in Apache Tomcat it is always authenticated on the
quest.

I agree that we can make no assumptions, and conclude the above.

From connectivity perspectives however we can investigate how to guess
best
if we are connection or request based in order to decide the best upload
scheme (only NTLM related?) and if we initially add the 'Authorization'
header (which will reset auth with most server side implementations).
For a good guess we need to understand if NTLM was used and try to read
relevant HTTP headers hints (Persistent-Auth).

Keep in mind that those headers are non-standard and are send by Microsoft
products only. I would rather maintain an information on the connection
whether auth is complete and reset when the server nags you again. This
would ultimately mean that the auth was not persistent.

These headers are non-standard but if they are there and we can use the to
improve connectivity then why not.

Leaving security aside, if we guess it is likely to be a request-based (non
NTLM and no Persistent-Auth or Persistent-Auth eq false) then we should
re-issue an authorization header and save a round-trip with Kerberos.

The client MUST NOT utilize the SPNEGO HTTP
authentication mechanism through a proxy unless the proxy supplies
this header with the "401 Unauthorized" response from the server.

This is a quite interesting case I have thought about several months ago
but how likely is this? Any Kerberos-protected host is supposed to be
inside the company and not outside. For us, we have a PAC-enabled proxy
server which has a lot of domains which are within the corporate network as
well as in the local intranet zone.

IMHO for best security we should check this header although non-standard.

from curl.

michael-o avatar michael-o commented on May 17, 2024

@Frenche, I agree on the rest if and only if it will be well documented.

Though, I do not agree on this for several reasons:

Leaving security aside, if we guess it is likely to be a request-based (non
NTLM and no Persistent-Auth or Persistent-Auth eq false) then we should
re-issue an authorization header and save a round-trip with Kerberos.

  1. HTTP does not encourage preemptive authentication
  2. You should not assume that the next request is going to be protected. Maybe it is just a unprotected resource. Consider that a token from a client could be several thousand bytes long. Outperforming the entire size of the request.
  3. Requests in corporate environments are extremely cheap. We have in most cases less than 20 ms for a roundtrip here.

from curl.

iboukris avatar iboukris commented on May 17, 2024

On Mon, Apr 20, 2015 at 11:02 PM, Michael Osipov [email protected]
wrote:

Though, I do not agree on this for several reasons:

Leaving security aside, if we guess it is likely to be a request-based (non
NTLM and no Persistent-Auth or Persistent-Auth eq false) then we should
re-issue an authorization header and save a round-trip with Kerberos.

  1. HTTP does not encourage preemptive authentication

Any reference? RFC 4559 allows it:

A client may initiate a connection to the server with an
"Authorization" header containing the initial token for the server.
This form will bypass the initial 401 error from the server when the
client knows that the server will accept the Negotiate HTTP
authentication type.

  1. You should not assume that the next request is going to be
    protected. Maybe it is just a unprotected resource. Consider that a token
    from a client could be several thousand bytes long. Outperforming the
    entire size of the request.

If it may be unprotected then OR CURLOPT_HTTPAUTH
with CURLAUTH_GSSNEGOTIATE and CURLAUTH_ONLY.
That's how other authentication protocols behave while your reasons are
valid for them as well.

  1. Requests in corporate environments are extremely cheap. We have in
    most cases less than 20 ms for a roundtrip here.

So they should not have problem with big auth headers :)
Round trips seem to complicate the flow...

from curl.

bagder avatar bagder commented on May 17, 2024

Guys, what about starting over with a fresh issue/pull request and try to work on getting some code done to improve this?

from curl.

innokenty avatar innokenty commented on May 17, 2024

Guys, so what's the solution if I'm getting exactly the same problem? It's hard to figure this out from your conversation and I believe I'm not the only one stuck with this.

from curl.

bagder avatar bagder commented on May 17, 2024

If you have a problem, the same as this or another one, using a modern curl version (say 7.50.x) then please file a new issue. Adding comments to an old issue thread is very hard to do anything sensible with.

from curl.

innokenty avatar innokenty commented on May 17, 2024

No, I have 7.43.0, I'll try to upgrade, thanks.

from curl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.