|
|
Created:
6 years, 5 months ago by david.woodhouse Modified:
3 years, 3 months ago Reviewers:
asanka, dwmw2 CC:
chromium-reviews, cbentzel+watch_chromium.org Base URL:
https://chromium.googlesource.com/chromium/src.git@master Project:
chromium Visibility:
Public. |
DescriptionAdd NTLM single-sign-on support via Samba's ntlm_auth helper
With this, we can finally be as compatible as Firefox w.r.t. SSO within
a Windows-dominated corporate network. Kerberos *often* fails due to SPN
mismatch and/or reverse DNS issues, and the Windows users (and Firefox
users) never notice because they silently fall back to NTLM.
Chrome users, on the other hand, lose. Until now.
BUG=53186
R=asanka@chromium.org, cbentzel@chromium.org
Patch Set 1 #Patch Set 2 : Review feedback #
Messages
Total messages: 23 (1 generated)
Thanks for the patch - and I see that you are using Intel's CLA as well as have added yourself to AUTHORS. I may take one more day before I can get to this.
Thanks. Should I not have added myself explicitly to AUTHORS? The tools seemed to be complaining until I did so.
On 2014/07/16 15:00:12, david.woodhouse wrote: > Thanks. Should I not have added myself explicitly to AUTHORS? The tools seemed > to be complaining until I did so. No, adding to AUTHORS is correct.
On 2014/07/16 15:33:28, cbentzel wrote: > On 2014/07/16 15:00:12, david.woodhouse wrote: > > Thanks. Should I not have added myself explicitly to AUTHORS? The tools seemed > > to be complaining until I did so. > > No, adding to AUTHORS is correct. Before getting into code details, there's two architectural concerns I have with this: a) Right now it forks off a separate ntlm_auth process for each challenge. This might be a fairly high number in cases such as session restore when going through an authenticating proxy. Does the ntlm_auth IPC protocol support multiplexing requests/responses so only a single ntlm_auth process would be needed? If not, we may still be able to serialize access to ntlm_auth in the browser process (waiting to issue new requests until after responses are received) although this may come at latency expense. b) There's a number of potentially blocking IO calls done on the IO thread which is not allowed (doesn't look like you are doing non-blocking IO on the pipe fds, access() is called directly on the IO thread, etc.) This will also ultimately need unit tests but I want to make sure that we agree on general architectural direction before proceeding down that path.
Thanks for the review. In fact let's start with a higher-level architectural review, just to make sure we're all on the same page. As noted in the bug there are other approaches we could use. Firstly we could rely on GSS-NTLMSSP entirely and *just* do this through GSSAPI, thus simplifying matters somewhat. However, as also noted in the bug that is all bleeding-edge stuff and I have fairly much the only machine in the world on which it'll actually work today; I don't think that's the right approach for Chrome to take. A second option is to use libwbclient instead of spawning ntlm_auth. That would involve finding it with dlopen() and making a deal with the Samba folks to ensure its ABI remains stable enough for that, since it currently has an soname ending in '.0' and isn't really designed with that use case in mind. But it would certainly make the multiplexing easier. But spawning ntlm_auth is the standard interface that everyone else uses, and I think it does make most sense if we can do it that way. So let's take a look at the points you raised... (a) It's not possible to actually *multiplex* authentications through the same ntlm_auth process, but you *can* use the same one for multiple authentications. After you're done with one authentication, you can send 'YR' again to start a new authentication exchange. You don't have to close it and start a new one. So we could have a 'pool' of one or more ntlm_auth helpers. The naïve implementation of this would have a given ntlm_auth process 'blocked' having given us the type1 negotiation packet, waiting for the challenge to come back from the server in order for us to complete the exchange and let the next request have a go. However, we don't have to do it like that. The response from 'YR' (the type1 negotiation packet') is the same every time, and is interchangeable. So we can always leave the ntlm_auth helper in the state where it's waiting for the 'TT' to actually do the authentication, and use it "instantaneously" when required without blocking it for any length of time. I'm *utterly* unfamiliar with the Chrome code base and the facilities which would let me manage such a 'pool' (even a trivial pool-of-one with the appropriate locking) but I can have a go if that's the way we want to do it. (b) The reads on the pipe are "effectively" non-blocking. We don't actually read from it until there's something there, and then we *know* that it'll end with a newline and we read until the newline. So unless you have an ntlm_auth implementation that's returning nonsense, you'll never have a problem. We could make it handle that failure mode just by setting O_NONBLOCK on the pipe fd and it'll all Just Work™ because read_line() will return failure if there isn't a newline there to be read and it gets -EAGAIN. In fact, I thought we already had but I don't see it now that I look for it. I think that's a one-liner, right? For the *writes* on the pipe, you're correct that they're "blocking". But they're never going to block. This isn't a bulk data transport; this is a single line being written to the pipe, and we never write another line until we've got the response. There are no circumstances in which it's actually going to block, unless you're already swapping heavily and your userspace processes are 'blocking' already. And even then it's no different to the experience you already have in that situation. I really wasn't going to bother about that. However, if we implement a 'pool' then we have to be able to return ERR_IO_PENDING at this point anyway and feed the challenge to an ntlm_auth helper when one becomes available. So handling this in a "truly" non-blocking way is easy enough to do.
On 2014/07/18 11:30:28, david.woodhouse wrote: > Thanks for the review. In fact let's start with a higher-level architectural > review, just to make sure we're all on the same page. As noted in the bug there > are other approaches we could use. Firstly we could rely on GSS-NTLMSSP entirely > and *just* do this through GSSAPI, thus simplifying matters somewhat. However, > as also noted in the bug that is all bleeding-edge stuff and I have fairly much > the only machine in the world on which it'll actually work today; I don't think > that's the right approach for Chrome to take. Sounds like a good long-term solution, but not good for now. > > A second option is to use libwbclient instead of spawning ntlm_auth. That would > involve finding it with dlopen() and making a deal with the Samba folks to > ensure its ABI remains stable enough for that, since it currently has an soname > ending in '.0' and isn't really designed with that use case in mind. But it > would certainly make the multiplexing easier. Prefer to avoid the approach of dlopen'ing external .so's. > > But spawning ntlm_auth is the standard interface that everyone else uses, and I > think it does make most sense if we can do it that way. So let's take a look at > the points you raised... Yes, this is likely the best approach for now (although I do like the GSSAPI approach longer term). > > (a) It's not possible to actually *multiplex* authentications through the same > ntlm_auth process, but you *can* use the same one for multiple authentications. > After you're done with one authentication, you can send 'YR' again to start a > new authentication exchange. You don't have to close it and start a new one. So > we could have a 'pool' of one or more ntlm_auth helpers. The naïve > implementation of this would have a given ntlm_auth process 'blocked' having > given us the type1 negotiation packet, waiting for the challenge to come back > from the server in order for us to complete the exchange and let the next > request have a go. However, we don't have to do it like that. The response from > 'YR' (the type1 negotiation packet') is the same every time, and is > interchangeable. So we can always leave the ntlm_auth helper in the state where > it's waiting for the 'TT' to actually do the authentication, and use it > "instantaneously" when required without blocking it for any length of time. I'm > *utterly* unfamiliar with the Chrome code base and the facilities which would > let me manage such a 'pool' (even a trivial pool-of-one with the appropriate > locking) but I can have a go if that's the way we want to do it. Thanks for all of the information here. The pooled approach in general seems preferable, but may be more engineering effort than is worth it. Chrome limits to 32 sockets/proxy/profile. Assuming only one proxy and typically one profile, we could probably afford to have 32 simultaneous processes and not have to implement a pool - especially since this will only happen for users who have /usr/bin/ntlm_auth as well as an NTLM authenticating proxy. My main concern is if there are multiple profiles, multiple proxies, or if other Chromium ports (Opera, Yandex, etc.) have looser limits. Asanka, do you have any thoughts here? > > (b) The reads on the pipe are "effectively" non-blocking. We don't actually read > from it until there's something there, and then we *know* that it'll end with a > newline and we read until the newline. So unless you have an ntlm_auth > implementation that's returning nonsense, you'll never have a problem. We could > make it handle that failure mode just by setting O_NONBLOCK on the pipe fd and > it'll all Just Work™ because read_line() will return failure if there isn't a > newline there to be read and it gets -EAGAIN. In fact, I thought we already had > but I don't see it now that I look for it. I think that's a one-liner, right? > > For the *writes* on the pipe, you're correct that they're "blocking". But > they're never going to block. This isn't a bulk data transport; this is a single > line being written to the pipe, and we never write another line until we've got > the response. There are no circumstances in which it's actually going to block, > unless you're already swapping heavily and your userspace processes are > 'blocking' already. And even then it's no different to the experience you > already have in that situation. I really wasn't going to bother about that. > > However, if we implement a 'pool' then we have to be able to return > ERR_IO_PENDING at this point anyway and feed the challenge to an ntlm_auth > helper when one becomes available. So handling this in a "truly" non-blocking > way is easy enough to do.
On the number of connections... note that this is for standard HTTP auth too, not just proxies. (In fact I hadn't even tested it with proxy auth so will do that ASAP.) At least NTLM auth is remembered for the lifetime of the connection though, unlike Kerberos auth with IIS by default which is per-request. (Cf. AuthPersistNonNTLM setting). -- dwmw2 (Apologies for HTML and top-posting; Android mailer is broken.) To unsubscribe from this group and stop receiving emails from it, send an email to chromium-reviews+unsubscribe@chromium.org.
On 2014/07/18 19:17:15, david.woodhouse wrote: > On the number of connections... note that this is for standard HTTP auth too, > not just proxies. (In fact I hadn't even tested it with proxy auth so will do > that ASAP.) Agreed. Worst-case could be higher for server auth since we allow more sockets (128). In practice I don't think this will be much of an issue - our instrumentation shows NTLM used far more in proxies than servers and it would require all servers to ask for NTLM auth. > > At least NTLM auth is remembered for the lifetime of the connection though, > unlike Kerberos auth with IIS by default which is per-request. (Cf. > AuthPersistNonNTLM setting). > > -- > dwmw2 > (Apologies for HTML and top-posting; Android mailer is broken.) > > To unsubscribe from this group and stop receiving emails from it, send an email > to mailto:chromium-reviews+unsubscribe@chromium.org.
OK... so assuming Asanka concurs (and I'm interpreting your own opinion correctly) that implementing a pool of these helpers is overkill, what's left to do? Are you happy with my response about the 'non-blocking' thing? How about I: - Actually work out how to set the O_NONBLOCK flag using your portable runtime and do that. - Retest, including proxy auth this time. - Add an environment variable or some way to change that hard-coded /usr/bin/ntlm_auth to allow us to use a different implementation for testing. Then I think we're ready to look at how to actually test it? And with an ntlm_auth implementation that just has a hard-coded domain/user/password hopefully this can mostly parallel the existing NTLM auth tests (where do I find/run those?)
On 2014/07/19 07:32:11, david.woodhouse wrote: > OK... so assuming Asanka concurs (and I'm interpreting your own opinion > correctly) that implementing a pool of these helpers is overkill, what's left to > do? Sorry again for delay - traveling for work and at a conference. I agree that for now we can stick with the existing architecture. > > Are you happy with my response about the 'non-blocking' thing? It didn't cover the access() case in the constructor. > > How about I: > > - Actually work out how to set the O_NONBLOCK flag using your portable runtime > and do that. > - Retest, including proxy auth this time. > - Add an environment variable or some way to change that hard-coded > /usr/bin/ntlm_auth to allow us to use a different implementation for testing. > > Then I think we're ready to look at how to actually test it? And with an > ntlm_auth implementation that just has a hard-coded domain/user/password > hopefully this can mostly parallel the existing NTLM auth tests (where do I > find/run those?) I'm worried that running a separate binary is going to increase the potential for test flakiness (which means that it will get disabled) - although that will be the closest to integration tests. Let me think about if there's a good way to mock out the pipe communication so this will simply test the sending/receiving of data. It's also possible that we simply unit test the response parsing logic.
On Wed, 2014-07-23 at 14:50 +0000, cbentzel@chromium.org wrote: > > Are you happy with my response about the 'non-blocking' thing? > > It didn't cover the access() case in the constructor. If access() on a file in /usr/bin is going to block, then even paging in a page of a shared library from /usr/lib is going to block. We don't need to care about the former any more than we need to mlockall() to prevent the latter from being needed, surely? > I'm worried that running a separate binary is going to increase the > potential for test flakiness (which means that it will get disabled) - although that > will be the closest to integration tests. > > Let me think about if there's a good way to mock out the pipe communication > so this will simply test the sending/receiving of data. It's also possible > that we simply unit test the response parsing logic. I don't think we really need to mock the pipe communication. Just use a 'test' helper with hard-coded username/password instead of the real one. In libsoup there's an environment variable SOUP_NTLM_AUTH_DEBUG which allows us to override the path to the helper, used for precisely that purpose. -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation
Apologies for the delay. Is there a way to check for SPN binding in ntlm_auth without cracking the token open? I'm okay with not using a pool of workers for now, but I'd like to measure the active process count. I don't know what the overhead of running ntlm_auth is, but I'm assuming it's small? Does it talk to a daemon and if so what are its constraints? Also are you familiar with the availability and use of winbind on Mac OS X? Interestingly Heimdal (used on Mac OS X) has supported using NTLMSSP over GSSAPI for quite some time. Once again I'm not familiar about its prevalence or how well it does single sign-on. Speaking of SSO, the ntlm_portable implementation was designed for use with explicit credentials (where the use is prompted for username/password). Adding winbind support would change the assumptions made in the code about when it's alright to respond to a challenge using the NTLM handler. I don't think we should respond with default credentials every time we see a 401. But rather let's respect the UrlSecurityManager's decision on whether default credentials should be used for a specific target. See http_auth_handler_negotiate.cc. What do you think about handling Negotiate? If the underlying GSSAPI implementation fails, we could resort to invoking ntlm_auth there as well. This would deal with servers that expect to use NTLMSSP, but advertises Negotiate rather than NTLM as the supported auth scheme. You might find base/async_socket_io_handler.h useful for dealing with the async waits.
On Wed, 2014-07-23 at 19:11 +0000, asanka@chromium.org wrote: > Apologies for the delay. > > Is there a way to check for SPN binding in ntlm_auth without cracking > the token open? No, I don't believe so. What exactly did you want to check? > I'm okay with not using a pool of workers for now, but I'd like to > measure the active process count. I don't know what the overhead of > running ntlm_auth is, but I'm assuming it's small? Does it talk to a > daemon and if so what are its constraints? Also are you familiar with > the availability and use of winbind on Mac OS X? Yes, it's very small. It just talks to the running winbind dæmon. Apple have moved away from Samba in recent versions of OS X, so ntlm_auth doesn't exist there any more. I have been talking to the folks using Macs within Intel about this, and they don't have a good solution for automatic NTLM auth at all. > I don't think we should respond with default credentials every time > we see a 401. But rather let's respect the UrlSecurityManager's > decision on whether default credentials should be used for a specific > target. See http_auth_handler_negotiate.cc. OK, I'll look into that. Thanks. > What do you think about handling Negotiate? If the underlying GSSAPI > implementation fails, we could resort to invoking ntlm_auth there as > well. This would deal with servers that expect to use NTLMSSP, but > advertises Negotiate rather than NTLM as the supported auth scheme. I think that would require that we implement SPNEGO for ourselves, and add the NTLMSSP OID into the list of mechanisms we offer. It's not good enough just to step in if the SPNEGO *fails*, because it's too late by then. So we'd have to do the whole SPNEGO thing and handle the negotiation of mechanisms, using GSSAPI for everything *except* NTLMSSP and doing NTLMSSP for ourselves. That would be possible, but I wouldn't advocate it. The GSS-NTLMSSP module, as well as whatever Heimdal has, *already* provides this functionality the "right way". Granted, it's far from ubiquitous but in the meantime, fallback from Negotiate to 'WWW-Authenticate: NTLM' is good enough to cover the vast majority of cases. It's relatively rare that we *need* NTLMSSP-in-Negotiate, and bare 'NTLM' isn't offered. At least in my experience. -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation
On 2014/07/23 20:03:46, david.woodhouse wrote: > On Wed, 2014-07-23 at 19:11 +0000, mailto:asanka@chromium.org wrote: > > Apologies for the delay. > > > > Is there a way to check for SPN binding in ntlm_auth without cracking > > the token open? > > No, I don't believe so. What exactly did you want to check? SPN binding mitigates against credential reflection attacks. We would eventually like to only allow NTLM to use default credentials if SPN binding is being used. So far this hasn't been an issue on Posix because we didn't support default credentials for NTLM at all, but this CL will change that. > > I'm okay with not using a pool of workers for now, but I'd like to > > measure the active process count. I don't know what the overhead of > > running ntlm_auth is, but I'm assuming it's small? Does it talk to a > > daemon and if so what are its constraints? Also are you familiar with > > the availability and use of winbind on Mac OS X? > > Yes, it's very small. It just talks to the running winbind dæmon. Are there any constraints we need to worry about with the winbind daemon? Or does it take all we can throw at it? > Apple have moved away from Samba in recent versions of OS X, so > ntlm_auth doesn't exist there any more. I have been talking to the folks > using Macs within Intel about this, and they don't have a good solution > for automatic NTLM auth at all. > > > I don't think we should respond with default credentials every time > > we see a 401. But rather let's respect the UrlSecurityManager's > > decision on whether default credentials should be used for a specific > > target. See http_auth_handler_negotiate.cc. > > OK, I'll look into that. Thanks. > > > What do you think about handling Negotiate? If the underlying GSSAPI > > implementation fails, we could resort to invoking ntlm_auth there as > > well. This would deal with servers that expect to use NTLMSSP, but > > advertises Negotiate rather than NTLM as the supported auth scheme. > > I think that would require that we implement SPNEGO for ourselves, and > add the NTLMSSP OID into the list of mechanisms we offer. It's not good > enough just to step in if the SPNEGO *fails*, because it's too late by > then. So we'd have to do the whole SPNEGO thing and handle the > negotiation of mechanisms, using GSSAPI for everything *except* NTLMSSP > and doing NTLMSSP for ourselves. > > That would be possible, but I wouldn't advocate it. The GSS-NTLMSSP > module, as well as whatever Heimdal has, *already* provides this > functionality the "right way". Granted, it's far from ubiquitous but in > the meantime, fallback from Negotiate to 'WWW-Authenticate: NTLM' is > good enough to cover the vast majority of cases. It's relatively rare > that we *need* NTLMSSP-in-Negotiate, and bare 'NTLM' isn't offered. At > least in my experience. To clarify, I meant using winbind if the underlying GSSAPI implementation failed to give us a token (i.e. because none of the available mechanisms are willing to authenticate against the target or if no credentials are available for any mechanism). What's the status of the 'gss-spnego-client' protocol for ntlm_auth? Ideally we'd wrap the token with SPNEGO, but in reality I believe raw NTLMSSP tokens are also accepted for most servers expecting Negotiate (including IIS). > > -- > David Woodhouse Open Source Technology Centre > mailto:David.Woodhouse@intel.com Intel Corporation
On Wed, 2014-07-23 at 20:14 +0000, asanka@chromium.org wrote: > SPN binding mitigates against credential reflection attacks. We would > eventually like to only allow NTLM to use default credentials if SPN > binding is being used. So far this hasn't been an issue on Posix > because we didn't support default credentials for NTLM at all, but > this CL will change that. Winbind doesn't support this, although for GSS-NTLMSSP we're pondering a patch which would let the client pass in a client_target_info blob to be signed and included in the nt_response. That would mostly be available via on the libwbclient interface, although we could probably make it possible through ntlm_auth too. But any such change would take a while to propagate, of course. The simple answer is 'no'. > > > I'm okay with not using a pool of workers for now, but I'd like to > > > measure the active process count. I don't know what the overhead of > > > running ntlm_auth is, but I'm assuming it's small? Does it talk to a > > > daemon and if so what are its constraints? Also are you familiar with > > > the availability and use of winbind on Mac OS X? > > > Yes, it's very small. It just talks to the running winbind dæmon. > > Are there any constraints we need to worry about with the winbind daemon? Or > does it take all we can throw at it? Yes, fairly much. If it has credentials, it handles the NTLM challenge/response entirely for you. (Actually, even if doesn't have creds, it can ask for a password and then still do it all for you. But there's no a lot of point in using it in that mode.) > To clarify, I meant using winbind if the underlying GSSAPI > implementation failed to give us a token (i.e. because none of the > available mechanisms are willing to authenticate against the target or > if no credentials are available for any mechanism). OK, so you propose that *after* a full SPNEGO exchange has failed (with or without the GSS-NTLMSSP mech being tries), we could try NTLM for ourselves within 'Authorization: Negotiate'? I suppose that might work. It's only worth it if the server didn't offer WWW-Authenticate: NTLM though, right? If it did, we might as well use that. And if we're going to do this, we should support *all* NTLM auth methods with it (winbind, SSPI as well as our manual implementation). > What's the status of the 'gss-spnego-client' protocol for ntlm_auth? Hm, not sure. At first glance I can't make sense of it. It seems to always want a base64 token to be passed in. I can't see how to make it *generate* the negTokenTarg that we need to start the conversation with the server. $ /usr/bin/ntlm_auth --helper-protocol gss-spnego-client --use-cached-creds --username dwoodhou --target-service HTTP --target-hostname dwoodhou-linux.ger.corp.intel.com YR Got 'YR' from squid (length: 2). SPNEGO query [YR] too short BH SPNEGO query too short > Ideally we'd wrap the token with SPNEGO, but in reality I believe raw > NTLMSSP tokens are also accepted for most servers expecting Negotiate > (including IIS). Right. Although SPNEGO for "I support only NTLMSSP. Like it or lump it" is not stunningly difficult to do :) -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation
message: On 2014/07/24 01:02:55, david.woodhouse wrote: > On Wed, 2014-07-23 at 20:14 +0000, mailto:asanka@chromium.org wrote: > > SPN binding mitigates against credential reflection attacks. We would > > eventually like to only allow NTLM to use default credentials if SPN > > binding is being used. So far this hasn't been an issue on Posix > > because we didn't support default credentials for NTLM at all, but > > this CL will change that. > > Winbind doesn't support this, although for GSS-NTLMSSP we're pondering a > patch which would let the client pass in a client_target_info blob to be > signed and included in the nt_response. That would mostly be available > via on the libwbclient interface, although we could probably make it > possible through ntlm_auth too. But any such change would take a while > to propagate, of course. > > The simple answer is 'no'. Ah. Hmm. For the short term going through UrlSecurityManager would be enough since we aren't enforcing SPN binding elsewhere. But we'd need to revisit this when we do. > > To clarify, I meant using winbind if the underlying GSSAPI > > implementation failed to give us a token (i.e. because none of the > > available mechanisms are willing to authenticate against the target or > > if no credentials are available for any mechanism). > > OK, so you propose that *after* a full SPNEGO exchange has failed (with > or without the GSS-NTLMSSP mech being tries), we could try NTLM for > ourselves within 'Authorization: Negotiate'? This cycle could fail earlier if, for example, gss_init_sec_context returns GSS_S_NO_CRED or GSS_S_FAILURE due to there being no usable credentials or none of the mechanisms supporting the target principal. > I suppose that might work. > It's only worth it if the server didn't offer WWW-Authenticate: NTLM > though, right? If it did, we might as well use that. And if we're going > to do this, we should support *all* NTLM auth methods with it (winbind, > SSPI as well as our manual implementation). So as far as implementations go we have: NTLM auth scheme: - Posix * Built-in NTLMv1 implementation: Supports explicit credentials. * winbind: Supports implicit credentials. - Windows * SSPI: Supports both explicit and implicit credentials. Negotiate auth scheme: - Posix * GSSAPI implementation: Support implicit credentials with Kerberos (Mac OS X also supports NTLMSSP). * winbind [possibly]: Supports implicit credentials with NTLMSSP. - Windows * SSPI: Supports both explicit and implicit credentials with Kerberos or NTLMSSP or others. The reason I wanted to think about using multiple implementations is that unfortunately credentials visible and usable by each implementation are different. So on Posix, if someone wants to use explicit credentials with NTLM, then they'd be out of luck with winbind. Similarly, if someone wants to use credentials from winbind, but the server only advertises Negotiate, they'd be out of luck with GSSAPI on Posix. However, supporting this would add a lot of complexity and I don't have numbers to justify this additional cost. Chris: any thoughts here? > > What's the status of the 'gss-spnego-client' protocol for ntlm_auth? > > Hm, not sure. At first glance I can't make sense of it. It seems to > always want a base64 token to be passed in. I can't see how to make it > *generate* the negTokenTarg that we need to start the conversation with > the server. > > $ /usr/bin/ntlm_auth --helper-protocol gss-spnego-client --use-cached-creds > --username dwoodhou --target-service HTTP --target-hostname > http://dwoodhou-linux.ger.corp.intel.com > YR > Got 'YR' from squid (length: 2). > SPNEGO query [YR] too short > BH SPNEGO query too short > > > Ideally we'd wrap the token with SPNEGO, but in reality I believe raw > > NTLMSSP tokens are also accepted for most servers expecting Negotiate > > (including IIS). > > Right. Although SPNEGO for "I support only NTLMSSP. Like it or lump it" > is not stunningly difficult to do :) :)
On Thu, 2014-07-24 at 21:26 +0000, asanka@chromium.org wrote: > message: On 2014/07/24 01:02:55, david.woodhouse wrote: > Ah. Hmm. For the short term going through UrlSecurityManager would be enough > since we aren't enforcing SPN binding elsewhere. But we'd need to revisit > this when we do. Right. > So as far as implementations go we have: You've only captured half the fun here... :) > NTLM auth scheme: > - Posix > * Built-in NTLMv1 implementation: Supports explicit credentials. > * winbind: Supports implicit credentials. Winbind also supports explicit credentials. If it doesn't have cached creds, it'll *ask* you for the password. My patch currently treats that as a failure mode and falls back to our own internal NTLMv1 code when that happens, but we don't *have* to. And there's also GSSAPI, if you have GSS-NTLMSSP. That supports explicit credentials today, if you use gss_acquire_cred_with_password(). And with my patches it supports implicit creds from winbind too. > - Windows > * SSPI: Supports both explicit and implicit credentials. > > Negotiate auth scheme: > - Posix > * GSSAPI implementation: Support implicit credentials with Kerberos (Mac > OS X also supports NTLMSSP). Again GSSAPI supports explicit credentials too, if you use gss_acquire_cred_with_password() — it'll go get you a TGT if you ask it nicely. And the situation is the same as above for GSS-NTLMSSP, of course. > * winbind [possibly]: Supports implicit credentials with NTLMSSP. I really think you don't want this. Stick with GSSAPI. > - Windows > * SSPI: Supports both explicit and implicit credentials with Kerberos or > NTLMSSP or others. But I fear we are getting a little off course, talking about how to handle Negotiate in addition to bare NTLM in 'WWW-Authenticate: NTLM'. > The reason I wanted to think about using multiple implementations is that > unfortunately credentials visible and usable by each implementation are > different. So on Posix, if someone wants to use explicit credentials with > NTLM, then they'd be out of luck with winbind. Which is why, of course, my implementation is careful to fall back to allowing explicit credentials when winbind doesn't work. (For values of "doesn't work" which include actually *trying* to authenticate, but with outdated credentials.) > Similarly, if someone wants to use credentials from winbind, but the > server only advertises Negotiate, they'd be out of luck with GSSAPI on > Posix. Right, bit isn't that *extremely* rare? If a server is going to accept NTLMSSP within Negotiate:, then it's fairly certain to offer "WWW-Authenticate: NTLM" too. That's *why* I'm happy to handle Negotiate and bare NTLM differently. Sure, it'd be nice if NTLMSSP in Negotiate worked — but GSS-NTLMSSP is coming and it's going to fix that. It's already *working* for my users now that I've shipped them the patched version, and Simo is on IRC right now making encouraging noises about merging my patches. What's *more* important in the short term is making bare NTLM work, using the ntlm_auth helper that everything *else* uses. That's sufficient as the immediate fix, until such time as GSS-NTLMSSP saves the world for us. Personally, I'm happy to submit a patch that relies purely on GSS-NTLMSSP instead. As discussed, though, I didn't think it was the right thing to do for Chrome. -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation
I've just uploaded a new version of the patch with the following changes: - Honour --auth-server-whitelist for NTLM SSO with winbind. - Add CHROME_NTLM_AUTH_HELPER environment variable, to assist with testing. - Fix default creds usage when multiple schemes can use them. Once I started playing with --auth-server-whitelist, I noticed that the Negotiate scheme would "use up" the default credentials, and then the HttpAuthHandler wouldn't let NTLM try to use them. When we give up and disable a scheme, we should set default_credentials_used_ to false to allow the next scheme to try them. I can't see how to get an incremental patch between the two versions I've submitted, although the comments about rebasing did seem to quite strongly imply that the tools would do that for us (well, for *you* since I'm asking you to review this code). So here's an incremental diff I made myself, just in case... diff --git a/net/http/http_auth_controller.cc b/net/http/http_auth_controller.cc index 9cc57de..69bbdfc 100644 --- a/net/http/http_auth_controller.cc +++ b/net/http/http_auth_controller.cc @@ -435,8 +435,12 @@ void HttpAuthController::InvalidateCurrentHandler( if (action == INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS) InvalidateRejectedAuthFromCache(); - if (action == INVALIDATE_HANDLER_AND_DISABLE_SCHEME) + if (action == INVALIDATE_HANDLER_AND_DISABLE_SCHEME) { DisableAuthScheme(handler_->auth_scheme()); + // This scheme might have been tried with the default credentials, but + // the *next* one is still allowed to try them. + default_credentials_used_ = false; + } handler_.reset(); identity_ = HttpAuth::Identity(); } diff --git a/net/http/http_auth_handler_ntlm.h b/net/http/http_auth_handler_ntlm.h index 7d5c7a8..47d1975 100644 --- a/net/http/http_auth_handler_ntlm.h +++ b/net/http/http_auth_handler_ntlm.h @@ -100,7 +100,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler, #endif #if defined(NTLM_PORTABLE) - HttpAuthHandlerNTLM(); + HttpAuthHandlerNTLM(URLSecurityManager* url_security_manager); #endif #if defined(NTLM_SSPI) HttpAuthHandlerNTLM(SSPILibrary* sspi_library, ULONG max_token_length, @@ -155,6 +155,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler, #endif #if defined(NTLM_PORTABLE) + const char *helpername_; int ntlm_write_pipe_; int ntlm_read_pipe_; base::ProcessHandle ntlm_auth_handle_; @@ -176,9 +177,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler, // "Proxy-Authenticate" response header. std::string auth_data_; -#if defined(NTLM_SSPI) URLSecurityManager* url_security_manager_; -#endif }; } // namespace net diff --git a/net/http/http_auth_handler_ntlm_portable.cc b/net/http/http_auth_handler_ntlm_portable.cc index b3b7067..d38228c 100644 --- a/net/http/http_auth_handler_ntlm_portable.cc +++ b/net/http/http_auth_handler_ntlm_portable.cc @@ -634,8 +634,13 @@ HttpAuthHandlerNTLM::generate_random_proc_ = GenerateRandom; HttpAuthHandlerNTLM::HostNameProc HttpAuthHandlerNTLM::get_host_name_proc_ = GetHostName; -HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() { - try_winbind_ = !access("/usr/bin/ntlm_auth", X_OK); +HttpAuthHandlerNTLM::HttpAuthHandlerNTLM( + URLSecurityManager* url_security_manager) + : url_security_manager_(url_security_manager) { + helpername_ = getenv("CHROME_NTLM_USER_HELPER"); + if (!helpername_) + helpername_ = "/usr/bin/ntlm_auth"; + try_winbind_ = !access(helpername_, X_OK); ntlm_write_pipe_ = -1; ntlm_read_pipe_ = -1; ntlm_auth_handle_ = -1; @@ -675,7 +680,7 @@ bool HttpAuthHandlerNTLM::start_ntlm_helper_() { base::LaunchOptions options; base::FileHandleMappingVector fds_to_remap; - args.push_back("/usr/bin/ntlm_auth"); + args.push_back(helpername_); args.push_back("--helper-protocol"); args.push_back("ntlmssp-client-1"); args.push_back("--use-cached-creds"); @@ -776,10 +781,16 @@ void HttpAuthHandlerNTLM::OnFileCanReadWithoutBlocking(int fd) { } bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() { - // Always return true if it looks like the winbind helper even might be - // available; we can't check properly yet because we need to do that - // asynchronously. - return try_winbind_; + // Always return true (assuning the UrlSecurityManager permits it) if + // it looks like the winbind helper even might be available; we can't + // check properly yet because we need to do that asynchronously. + if (!try_winbind_) + return false; + if (target_ == HttpAuth::AUTH_PROXY) + return true; + if (!url_security_manager_) + return false; + return url_security_manager_->CanUseDefaultCredentials(origin_); } int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() { @@ -861,7 +872,8 @@ int HttpAuthHandlerNTLM::Factory::CreateAuthHandler( // method and only constructing when valid. // NOTE: Default credentials are not supported for the portable implementation // of NTLM. - scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM); + scoped_ptr<HttpAuthHandler> tmp_handler( + new HttpAuthHandlerNTLM(url_security_manager())); if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) return ERR_INVALID_RESPONSE; handler->swap(tmp_handler); -- David Woodhouse Open Source Technology Centre David.Woodhouse@intel.com Intel Corporation
Ping? -- dwmw2 To unsubscribe from this group and stop receiving emails from it, send an email to chromium-reviews+unsubscribe@chromium.org.
On 2015/03/12 10:34:47, dwmw2_infradead.org wrote: > Ping? > > -- > dwmw2 > > To unsubscribe from this group and stop receiving emails from it, send an email > to mailto:chromium-reviews+unsubscribe@chromium.org. Why did this one stop? :(
On Mon, 2015-11-02 at 14:41 +0000, jahestad@gmail.com wrote: > > Why did this one stop? :( > > https://codereview.chromium.org/388063005/ No idea :( -- dwmw2 To unsubscribe from this group and stop receiving emails from it, send an email to chromium-reviews+unsubscribe@chromium.org.
cbentzel@chromium.org changed reviewers: - cbentzel@chromium.org |