0

I'd like libcurl to fallback to NTLM when kerberos is not available.

I'm using this setting,

// explicit
curl_easy_setopt(_curl, CURLOPT_HTTPAUTH, CURLAUTH_NTLM | CURLAUTH_GSSNEGOTIATE);
// or any
curl_easy_setopt(_curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); 

what actually happens, is that the server sends supported schemes

<= recv header: HTTP/1.1 401 Unauthorized
<= recv header: Content-Length: 0
text: Server Microsoft-HTTPAPI/2.0 is not blacklisted
<= recv header: Server: Microsoft-HTTPAPI/2.0
<= recv header: WWW-Authenticate: Negotiate
<= recv header: WWW-Authenticate: NTLM

but the client sends just a Negotiate token

text: Server auth using GSS-Negotiate with user ''
=> send header: POST /daas/services/hello HTTP/1.1
Authorization: Negotiate YHkGBisGAQUFAqBvMG2gMDAuBgorBgEEAYI3AgIKBgkqhkiC9xI...TC1NT0JMR0VS
User-Agent: libcurl-agent/1.0
Host: localhost:8008
Accept: */*
Content-Length: 328
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------19e8c490d70b39c1
....

Since I did not define an SPN yet, I expect the NTLM fallback to work but I get this

<= recv header: HTTP/1.1 401 Unauthorized
<= recv header: Content-Length: 0
text: Server Microsoft-HTTPAPI/2.0 is not blacklisted
<= recv header: Server: Microsoft-HTTPAPI/2.0
text: Authentication problem. Ignoring this.
<= recv header: WWW-Authenticate: Negotiate oYIBHDCCAAAAPRwBFAFIAAgAEA.....BvAG0ABQAcAGMAb
<= recv header: Date: Fri, 26 Sep 2014 16:16:24 GMT
text: HTTP error before end of send, stop sending
<= recv header:
text: Closing connection 2

I thought that the client is supposed to send several possible tokens and let the server choose which to answer on.

Any Ideas?

ren
  • 21
  • 1
  • 5

2 Answers2

0

No; the client is supposed to send the best mechanism, it is not supposed to send all mechanisms.

These mechanisms are not "fallbacks" in the sense that if one mechanism fails, it will try the second, then the third, etc. This would be a misoptimization for the case where the server advertises that it supports Negotiate, but in fact does not. This would devolve into something like:

Server: Hi, I suppose Negotiate, NTLM, Digest and Basic
Client: Okay, here's some Negotiate credentials
Server: Sorry! Either your credentials do not authenticate you, or whomever you authenticated as does not have authorization to view this page.
Client: Okay, well, what if I give you the same credentials, only in NTLM form
Server: What difference does that make?  You still can't come in.
Client: What about Digest?
Server: What do you mean, digest?  What makes you think that if I rejected your Negotiate and your NTLM credentials that suddenly your digest credentials will be any different?
Client: Well, here's the same credentials with Basic
Server: Okay, seriously, just go away.

Simply put, your server is not configured properly: if you advertise Negotiate, clients will provide negotiate credentials with the expectation that you can support them. Clients will not fall back to other schemes in the hope that those would be supported.

Edward Thomson
  • 74,857
  • 14
  • 158
  • 187
  • Agreed; that matches my experience as well, but any client that is not capable *should* simply move on to NTLM. I have seen a few clients that are mis configured in a way that they think that they can perform krb5 but cannot (time skew, for instance). – Edward Thomson Sep 27 '14 at 12:38
  • not the point, the server side supports both authentication methods, an SPN is available for the full hostname but using an IP or an alias without an SPN, causes a failure. though if i ask curl to use just NTLM it works fine. what's the point of bitmasking auth methods if they are not used as fallback? – ren Sep 27 '14 at 12:39
  • If you don't have an SPN then you don't have a trust relationship with the Kerberos server. This has nothing to do with IP addresses or name resolution. You lack a certificate and you cannot perform Kerberos. There is no fallback from "I said I could perform Negotiate, but I actually can't." – Edward Thomson Sep 27 '14 at 12:41
  • Hmm... the reality is that i have an SPN "HTTP/hostname.tree.domain.com" and the client sends a message in the same domain to "hostname", name resolution is successful and the connection is established, but the SPN the client has constructed does not match any SPN the serverside has. – ren Sep 27 '14 at 13:02
  • also, see this post - http://stackoverflow.com/questions/12260587/kerberos-fails-when-accessing-site-by-ip-address – ren Sep 27 '14 at 13:04
  • The point of bitmasking auth methods is to allow libcurl to pick the one it considers best out of the ones the server supports. – Daniel Stenberg Sep 28 '14 at 08:49
  • @ren You can have an SPN for both your FQDN and any CNAMEs, or your short name, etc. You needn't have only one. – Edward Thomson Sep 28 '14 at 17:20
0

I've actually went and registered to the libcurl mailing list and got an answer pretty fast,

the response is below,

I'm attempting to use libcurl to connect to a web server that supports both, but some clients can't do kerberos.

When you say some clients can't do Kerberos what do you mean and what limitation do you have that is preventing this being used? Is it a limitation that means libcurl can't or shouldn't use Kerberos?

I'm setting CURLOPT_HTTPAUTH to CURLAUTH_GSSNEGOTIATE | CURLAUTH_NTLM

a) What version of libcurl are you using? From the output it looks like a version prior to 7.38.0 - if this is the case you might want to ignore my questions before and including this section and jump to my comments about upgrading ;-) b) What platform are you using? Windows, Linux, etc... c) If you are using Windows are you using a version of libcurl that was compiled against Windows SSPI or one that was compiled with a GSS-API library (such as MIT Kerberos or Heimdal)?

Should libcurl fallback to NTLM?

No...

Unfortunately I'm not one of our HTTP experts so I could be wrong here but I'll try and answer the question with my curl authentication hat on and some limited HTTP knowledge ;-)

My understanding is that the Negotiate (SPNEGO) authentication mechanism will try to perform Kerberos and then fall back to NTLM as part of its communication with the server if Kerberos fails. As such you will only see "WWW-Authorization: Negotiate" and "WWW-Authenticate: Negotiate" headers from the client and server respectively rather than a combination of the previous and "WWW-Authorization: NTLM" and "WWW-Authenticate: NTLM".

As such libcurl doesn't need to do the fall back, per se, as the SPNEGO communication will handle it for us ;-)

Am I doing something else wrong?

We fixed a number of issues in 7.38.0 relating to Negotiate with the main ones being:

  • We weren't using the correct SPNEGO OID when compiled with a GSS-API library
  • The fall back to NTLM wasn't performed if Kerberos failed
  • Deprecated CURLAUTH_GSSNEGOTIATE and introduced CURLAUTH_NEGOTIATE

As such, I would recommend you:

  • Upgrade to 7.38.0
  • Use CURLAUTH_NEGOTIATE instead of CURLAUTH_GSSNEGOTIATE |CURLAUTH_NTLM

will check and update...

ren
  • 21
  • 1
  • 5