Closed Bug 237586 Opened 20 years ago Closed 20 years ago

Implement negotiateauth using SSPI for Windows

Categories

(Core :: Networking, enhancement)

x86
Windows NT
enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla1.8alpha2

People

(Reporter: darin.moz, Assigned: darin.moz)

References

Details

(Keywords: fixed-aviary1.0, fixed1.7.5)

Attachments

(4 files, 5 obsolete files)

Implement negotiateauth using SSPI for Windows.

This is a followup to bug 17578.  In that bug, we enabled support for
Microsoft's Negotiate auth protocol using GSSAPI.  Under Windows, we need to use
SSPI instead.
Depends on: 17578
Status: NEW → ASSIGNED
Depends on: 241124
Target Milestone: --- → mozilla1.8alpha
Attached patch v0 patch (obsolete) — Splinter Review
this is a partial patch.  some changes to configure.in are still needed, and
this patch depends on my patch for bug 241124.
Attached patch configure.in changes (obsolete) — Splinter Review
Attachment #146893 - Flags: review?(cls)
Attached patch v1 patch (obsolete) — Splinter Review
OK, this might work... I still don't have a good Negotiate auth test case )-:
Attachment #146889 - Attachment is obsolete: true
Comment on attachment 146893 [details] [diff] [review]
configure.in changes

-if test `echo "$MOZ_EXTENSIONS" | grep -c negotiateauth` -ne 0; then
+if test -n "$USE_GSSAPI" -a test `echo "$MOZ_EXTENSIONS" | grep -c
negotiateauth` -ne 0; then

That should be:
test <expr> -a <expr>
or 
test <expr> && test <expr>
.
The latter will not evaluate the second expression if the first fails.	Other
than that, it looks good.
Attachment #146893 - Flags: review?(cls) → review-
cls: oh, right... thanks for catching that!
Attachment #146893 - Attachment is obsolete: true
Attachment #147218 - Flags: review?(cls)
Attachment #147218 - Flags: review?(cls) → review+
Attached patch v1.1 patch (obsolete) — Splinter Review
revised patch now that the negotiateauth refactorization patch has landed on
the trunk.
Attachment #146896 - Attachment is obsolete: true
Comment on attachment 147254 [details] [diff] [review]
v1.1 patch

cneberg (or anyone else cc'd on this bug): can you please test this out on a
win32 box?  thanks!
Attachment #147254 - Flags: superreview?(bryner)
Attachment #147254 - Flags: review?(cneberg)
I'll give it a try.
So, does implementing negotiateauth using SSPI not have the same problems that
NTLM had? didn't that use to crash?
It fails, error message below.  I tried to do a little debugging on my own, but
haven't figured out the problem.   I tried changing the servicename from
HTTP@FQDN to to HTTP/FQDN because I'm guessing that is more correct for the
SSPI, but I'm not sure.  This did not fix the problem.  If you have anything
else for me to try let me know.

InitializeSecurityContext failed
rc=-2146893055
Attachment #147254 - Flags: review?(cneberg) → review-
Attachment #147254 - Flags: superreview?(bryner)
That error code is SEC_E_INVALID_HANDLE.  Hmm... I must have done something silly.
Comment on attachment 147254 [details] [diff] [review]
v1.1 patch

>+    if (inToken) {
...
>+        ctxIn = &mCtxt;
>+    }
>+    else {
...
>+        ctxIn = NULL;
>+    }
...
>+    rc = (sspi->InitializeSecurityContext)(&mCred,
>+                                           ctxIn,

in fact, i think the problem is in the above code.  i should only
assign ctxIn to the address of mCtxt if InitializeSecurityContext
has been called at least once already.

new patch coming up.
Attached patch v1.2 patch (obsolete) — Splinter Review
Actually, the problem was with the Reset function.  It should not have been
destroying the CredHandle object.  I tested this patch with a mock server that
just generates a 401 response with a "WWW-Authenticate: Negotiate" header. 
SSPI generated a SPNEGO response, so I think there's a chance this patch will
actually work.	I haven't confirmed the patch beyond that though.  Again,
please help me test this.  Thanks!
Attachment #147254 - Attachment is obsolete: true
Kerberos works if HTTP@ is changed to HTTP/ to create the service principal.  
Should DsMakeSpn be used to do do this? 

Oddities:
It doesn't use the reverse DNS name for forming the SPN like IE 6.0 normally
does (IE is somewhat erratic on what it chooses) instead it uses the same name
you use in the URL. (Maybe DsMakeSpn would fix this?)

Negotiate fails over to NTLM if Kerberos fails, so our current pref defaults are
wrong for use with the SSPI. We really need a GUI so users can set their
intranet domain, but without this the only secure default is to disable it.

In addition, the SSPI is different than GSSAPI, SSPI will only delegate if an AD
system administrator configures a special flag on the service called
OK-AS-DELEGATE.   This allows the AD sys admins to control delegation.  IE
always enables delegation to the SSPI, but it only succeeds if that flag is set.
 (I varified this in my tests). I suggest we do the same thing and always enable
delegation.

Suggested Win32 defaults

network.negotiate-auth.delegation-uris   ""
network.negotiate-auth.trusted-uris      "https://, http://"

When testing this bug I noticed that the prefs are not working correctly, when a
list of schemes is used, only the last one is matched against, the eariler ones
are ignored. 
Oops. Sorry, reverse the values for the prefs for default.

network.negotiate-auth.delegation-uris   "https://, http://"
network.negotiate-auth.trusted-uris      ""
Bug 242446 added with fix for nsHttpNegotiateAuth::MatchesBaseURI not working
correctly.
I also read somewhere that SSPI delegation requires mutual-auth.  Is that correct?
I'm not sure(In reply to comment #18)
> I also read somewhere that SSPI delegation requires mutual-auth.  Is that correct?

I don't know what the SSPI spec says, but delegation worked fine to the apache
server I tested with the current patch. I had no problems.  I can check against
IIS next week and see if it cares. (I realize it makes no security sense to put
the check in the server, but I'll test it anyway.)

IE always asks for mutual auth but doesn't seem to ever check the reply. So I'm
not even sure why they ask for it...
Patch (v1.2) seems to work for me when "HTTP@" is changed to "HTTP/" in
nsHttpNegotiateAuth.cpp line 159.

Test server is Apache 2.0.49 with CVS version of mod_auth_kerb.
(In reply to comment #15)
> It doesn't use the reverse DNS name for forming the SPN like IE 6.0 normally
> does (IE is somewhat erratic on what it chooses) instead it uses the same name
> you use in the URL. (Maybe DsMakeSpn would fix this?)

I noticed this as well. It would be nice if the Mozilla service principal was
same as used by IE. Based on my experiences I thought IE will lookup the
canonical hostname and use that as service principal hostname. Is this (how IE
will form the SPN) documented somewhere ?
Target Milestone: mozilla1.8alpha1 → mozilla1.8alpha2
Depends on: 246861
Hmm... DsMakeSpn seems to only be available on Windows XP or Windows 2000
Professional, or otherwise it requires the Active Directory Client Extension.

I'm happy to add code to nsNegotiateAuthSSPI.cpp that canonicalizes the hostname
and generates a SPN from that (with HTTP/ prepended).  We could try using
DsMakeSpn if it happens to be available, but it seems clear to me that we cannot
rely on that always being present.
Attached patch v1.3 patchSplinter Review
OK, this patch addresses the SPN canonicalization issue.  I've written a
function that maps the "HTTP@host" SPN to "HTTP/cname".  This is only done for
the SSPI code path.

This patch also corrects an infinite loop that can occur if the server responds
to the client's authorization attempt with a brand new "WWW-Authenticate:
Negotiate NTLM" header.  This can easily happen when NTLM is used because the
server might reject the user's credentials.  We want to make sure that when
this happens we give up on Negotiate and use the second challenge.

To canonicalize the SPN, I used nsIDNSService::resolveHost.  This method blocks
the calling thread until the lookup completes, which might seem problematic for
performance; however, I doubt it will be an issue because we will most likely
already have the hostname stored in the DNS cache.  The CNAME I'm using is the
CNAME that is returned with the original DNS "A" query.  I'm not doing a
reverse lookup.  Perhaps I should since that's what the GSSAPI seems to do;
however... I'm not too worried since site admins can ensure that the CNAME
returned with "A" queries is correct.
Attachment #147332 - Attachment is obsolete: true
I think this patch necessitates that we change the default trusted URIs to none.
 It is no longer sufficient to limit the default trusted URIs to https:// since
that would allow a hacker to setup a https:// site to sniff NTLM v1 hashes. 
That might be too much of a security risk.  I think the only sane thing to do
for now is to ship Moz with an empty whitelist.

At some point, we should maybe implement some UI to allow the user to configure
the whitelist.  I.e., it'd be nice if we prompted the user when a site they are
loading is not on the whitelist.  And, there should be a way for the user to
configure the whitelist without resorting to about:config.

I understand that a hidden pref to configure the whitelist is probably still
useful in a lot of cases, so there is hopefully value in having this feature in
mozilla but default disabled.
Attachment #152203 - Flags: review?(cneberg)
(In reply to comment #24)
> I think this patch necessitates that we change the default trusted URIs to none.
>  It is no longer sufficient to limit the default trusted URIs to https:// since
> that would allow a hacker to setup a https:// site to sniff NTLM v1 hashes. 
> That might be too much of a security risk.  I think the only sane thing to do
> for now is to ship Moz with an empty whitelist.

Without any sort of visible UI, most people will have no clue how to enable this
feature.  At this point, I think we *REALLY* need some visible configuration
knobs for this feature in the "Security" panel.

By the way - howcome "about:prefs" doesn't work in Firefox??  How is one
supposed to edit all of the hidden preferences without knowing what
they are in the first place?

> 
> At some point, we should maybe implement some UI to allow the user to configure
> the whitelist.  I.e., it'd be nice if we prompted the user when a site they are

I think by disabling the lists, you are effectively disabling this feature so
some sort of UI is almost a necessity in order to enable it again.



I'd really like to see this feature get added to FFox 1.0, and with any luck Moz
1.7.1 as well.
Flags: blocking1.7.1?
Flags: blocking-aviary1.0?
Attachment #152207 - Flags: review?(cneberg)
Flags: blocking-aviary1.0RC1+
Flags: blocking-aviary1.0?
Flags: blocking-aviary1.0-
I'm on vacation now. I'll have time to look at this on Tuesday. Do we have to
change the defaults in all.js for every platform?  The security threat is only
for Windows, keeping the old default still makes sense for every other platform.
Maybe we could leave all.js blank and set the default in the C code, or else we
can start to discuss a gui layout, I'll do my best to help with it if it means
we could get in in time of the next release.
> I'm on vacation now. I'll have time to look at this on Tuesday.

No problem.  Happy 4th! ;-)


> Do we have to
> change the defaults in all.js for every platform?  The security threat is only
> for Windows, keeping the old default still makes sense for every other 
> platform.

The challenge really is that we don't even know what the underlying GSSAPI
implementation might do.  It is not inconceivable that GSSAPI may one day
implement NTLM via SPNEGO.  Perhaps it'll have its own way of knowing the user's
logon.  We shouldn't depend on the fact that GSSAPI only provides Kerberos via
SPNEGO.

This gets back to my reasons for filing the bug on implementing SPNEGO inside
Mozilla.  Clearly that has the advantage of allowing Mozilla to know what
protocols are being used since it would be responsible for selecting the protocols.

So, unless we write our own SPNEGO implementation, I think we have to assume
that all domains are untrusted by default.


> Maybe we could leave all.js blank and set the default in the C code, or else 
> we can start to discuss a gui layout, I'll do my best to help with it if it 
> means we could get in in time of the next release.

We need to get Ben Goodger involved with this soon if we want to get some UI
added to Firefox 1.0.
Bug 249942 created for GUI issues.  I've got a couple of ideas I'm attaching to
that bug.
Blocks: 250014
Comment on attachment 152203 [details] [diff] [review]
v1.3 patch

SSPI works fine using both NTLM and Kerberos. 

The area I'm not sure of is your Makefile.in changes. In my first attempt I
didn't get Negotiate support functioning without FORCE_SHARED_LIBS = 1 but it
could be my build environment. I'm recompiling now and will check it in the
morning. But provided you've tried this and got it to succeed r=cneberg

Also does
SHORT_LIBNAME need defined?
Attachment #152203 - Flags: review?(cneberg) → review+
Comment on attachment 152207 [details] [diff] [review]
changes to all.js

Looks good
Attachment #152207 - Flags: review?(cneberg) → review+
> The area I'm not sure of is your Makefile.in changes. In my first attempt I
> didn't get Negotiate support functioning without FORCE_SHARED_LIBS = 1 but it
> could be my build environment. I'm recompiling now and will check it in the
> morning. But provided you've tried this and got it to succeed r=cneberg

Interesting... the patch definitely does work fine under Win2k.  I tested it
against a Win2k3 server.


> Also does
> SHORT_LIBNAME need defined?  

Good question.  I think that might only be necessary for OS/2, but perhaps I
should use it for Win32 as well since we certainly define USE_SHORT_LIBNAME in
configure.in for Win32 builds.
Attachment #152203 - Flags: superreview?(bryner)
(In reply to comment #33)
> > The area I'm not sure of is your Makefile.in changes. In my first attempt I
> > didn't get Negotiate support functioning without FORCE_SHARED_LIBS = 1 but it
> > could be my build environment. I'm recompiling now and will check it in the
> > morning. But provided you've tried this and got it to succeed r=cneberg
> 
> Interesting... the patch definitely does work fine under Win2k.  I tested it
> against a Win2k3 server.

My build completed overnight and worked fine with no changes.
Patch v1.3 built with Mozilla 1.8a1 on Windows works fine for me as well,
including the CNAME resolution.

Regarding the comment about getting this included in 1.7.1, does that mean it
would be possible to build the NegotiateAuth extension as an XPI that could be
installed on top of an existing Mozilla 1.7 installation ? I recall trying to
compile patch v1.2 with Mozilla 1.7 sources and it failed to build so I guess
the code would need to be somehow adapted to Moz 1.7.
(In reply to comment #35)
> Patch v1.3 built with Mozilla 1.8a1 on Windows works fine for me as well,
> including the CNAME resolution.
> 
> Regarding the comment about getting this included in 1.7.1, does that mean it
> would be possible to build the NegotiateAuth extension as an XPI that could be
> installed on top of an existing Mozilla 1.7 installation ? I recall trying to
> compile patch v1.2 with Mozilla 1.7 sources and it failed to build so I guess
> the code would need to be somehow adapted to Moz 1.7.

Not without backporting the patch.  This patch uses updates to the nsIauthModule
API not in Mozilla 1.7 or Firefox 9.1.

http://lxr.mozilla.org/mozilla/source/netwerk/base/public/nsIAuthModule.idl
http://lxr.mozilla.org/mozilla1.7/source/netwerk/base/public/nsIAuthModule.idl
I am hoping to get approval to land this patch along with the interface changes
onto the 1.7 and aviary-1.0 branches.
Attachment #152203 - Flags: superreview?(bryner) → superreview+
Comment on attachment 152203 [details] [diff] [review]
v1.3 patch

requesting approval to land this patch for 1.8a2.  it's important to maximize
field testing for this patch.

it would also be ideal to get this on the 1.7 branch since that will be a long
lived branch, which many enterprise customers will be using.
Attachment #152203 - Flags: approval1.8a2?
Attachment #152203 - Flags: approval1.7.2?
Comment on attachment 152203 [details] [diff] [review]
v1.3 patch

Agreed -- test coverage and feedback from the field for this sort of thing is
what alphas are all about. a=shaver for 1.8a2
Attachment #152203 - Flags: approval1.8a2? → approval1.8a2+
fixed-on-trunk for mozilla 1.8 alpha 2
Status: ASSIGNED → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
In reply to comment #25

> By the way - howcome "about:prefs" doesn't work in Firefox??  How is one
> supposed to edit all of the hidden preferences without knowing what
> they are in the first place?

because it is about:config.
Comment on attachment 152203 [details] [diff] [review]
v1.3 patch

a=mkaply for 1.7.2

We want this on the stable branch for "corporate" users
Attachment #152203 - Flags: approval1.7.2? → approval1.7.2+
fixed1.7.2 and fixed-aviary1.0, which entailed landing the patches in this bug
as well as the required changes to nsIAuthModule that occured in bug 241124.
Keywords: fixed1.7.2
Whiteboard: fixed-aviary1.0
fixed-aviary1.0 is available as a real keyword now :)
Keywords: fixed-aviary1.0
Whiteboard: fixed-aviary1.0
Now that this is fixed on 1.7 branch, should it now be possible to build a 1.7
branch build and selectively copy certain files over an existing 1.7
installation to get it to support Negotiate ? As long as the number/size of
files needed is low, this would be easier than having to install a completely
new version just to get NegotiateAuth support.

Searching for nsIAuthModule in lxr.mozilla.org would suggest that this could be
done but I'm not entirely sure of side-effects. Anyone willing to guess what
will happen ?
(In reply to comment #45)
Answering to myself. I've been successful in getting Negotiate to work with an
already-installed 1.7.1 by replacing msgbsutl.dll, necko.dll and pipnss.dll with
versions from 1.7 branch build and installing negotiateauth.dll. Needed to run
regxpcom before Negotiate would work.
> Answering to myself. I've been successful in getting Negotiate to work with an
> already-installed 1.7.1 by replacing msgbsutl.dll, necko.dll and pipnss.dll with
> versions from 1.7 branch build and installing negotiateauth.dll. Needed to run
> regxpcom before Negotiate would work.

yes, that will work.  you might want to update necko.xpt since it makes
reference to the nsIAuthModule interface which changed in the newer 1.7 builds.
The xpinstall/packager/packages-win change that was made citing this bug uses
forward-slashes instead of backslashes.  I'm not sure if that's a problem.
thanks dbaron!
correction to slashes checked in.
Comment on attachment 155659 [details] [diff] [review]
use backslashes instead

this doesn't appear to have caused any actual problems.
Attachment #155659 - Flags: approval1.7.3?
Comment on attachment 155659 [details] [diff] [review]
use backslashes instead

a=mkaply
Attachment #155659 - Flags: approval1.7.3? → approval1.7.3+
> a=mkaply

fixed1.7.3
Flags: blocking1.7.x?
Blocks: 320349
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: