Closed Bug 302209 Opened 19 years ago Closed 19 years ago

enable use of gssapi32.dll on windows

Categories

(Core :: Networking, defect)

x86
Windows XP
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: Bienvenu, Assigned: Bienvenu)

References

Details

(Keywords: fixed1.8)

Attachments

(2 files, 2 obsolete files)

A bit of history first: I've been trying to add gssapi authentication support to
mailnews (imap/pop3/smtp), with an MIT Kerberos distribution. The server
advertises AUTH=GSSAPI. Darin suggested trying the negotiate auth module. I
plugged nsIAuthModule calls into the core mailnews protocol code and the imap
code. I develop on Windows, so the negotiate auth module uses SSPI. That didn't
work with the MIT Kerberos distribution, though perhaps I needed to extend the
way we were using SSPI (if you have any info on that, cneberg, it would be very
useful). In any case, I decided to try to add the ability to optionally use
GSSAPI32.dll on Windows, if it was present. I hacked the make file a bit and
tweaked nsNegotiateAuthGSSAPI.cpp so that it used the __stdcall calling
convention on Windows. Simon Wilkinson tweaked the same file so that if a user
name was passed in, it would do SASL instead of negoitate auth. The comment in
the patch says

        // We've completed the GSSAPI portion of the handshake, and are
        // now ready to do the SASL security layer and authzid negotiation
 
I'll attach the patch so you can see what's going on.

Darin wanted me to run all this by you, cneberg, and your input would be greatly
appreciated. I'm a total neophyte in this area. My plan is to do the following:

1.Add to cvs our own stand-alone version of gssapi.h, provided by Douglas
Engert, so that we don't need to use the system one.
2. Remove the configure.in grief we go through to find gssapi.h
3. Build nsNegotiateAuthGSSAPI.cpp on windows (I'll need to rename the
nsNegotiateAuth class in either or both of nsNegotiateAuthGSSAPI.cpp and
nsNegotiateAuthSSPI.cpp, and add a custom constructor that chooses the right one
based on the platform.

4. Add a component to nsNegotiateAuthFactory for gssapi, which would construct
the nsNegotiateAuth in nsNegotiateAuthGSSAPI.cpp with an arg to the constructor
to tell it to do gssapi/sasl. The contractId would be
NS_AUTH_MODULE_CONTRACTID_PREFIX "gssapi". If it's possible to use SSPI to do
auth=GSSAPI, then I'll need the factory to dynamically detect if gssapi32.dll is
installed, at least on windows.

5.Add support for gssapi/sasl in nsNegotiateAuthGSSAPI.cpp
6. Use NS_AUTH_MODULE_CONTRACTID_PREFIX "gssapi" in the imap/pop3/smtp code.
This is just to show what what was done to nsNegotiateAuthGSSAPI to do
SASL/GSSAPI. I'm looking for feedback on the basic approach. As I said, I would
clean this up to allow the constructor to determine if we're doing sasl,
instead of checking if there's a username. If you think this should be broken
into a different .cpp file as well, with some shared code, that's an other
option.
Cool. The SASL Gssapi code was one of the areas I was wanting to help
investigate next. I've been working on Bug 280792 which overlaps with this one,
but without the SASL slant.  I've been working on a patch which attempts to do
item 3 on your list so gssapi.dll and sspi can both be around on windows.  I'll
probably have a chance to post it here tomorrow.
Great, thx, Christopher. I'll wait for your patch before proceeding since there
might be conflicts. I'll attach the standalone gssapi.h, though perhaps you have
your own?
Firstly, some comments on the SSPI/MIT Kerberos For Windows issue.

As far as I'm aware, SSPI can only deal with initial credentials obtained at
login by machines which are members of an Active Directory realm. If you're
using Leash32 (MIT's credentials manager), then SSPI will never see the
credentials that it obtains. If you want to do Kerberos authentication using
credentials in the MIT credcache, you have to use the MIT Kerberos
implementation. However, MIT Kerberos can use credentials which were obtained by
SSPI. All in all - MIT's implementation is more flexible, but does require
additional libraries to be installed on the machine.

If you're getting in to interface redefinition, it would be really good to have
the following:

*) A way of constraining the mechanism OIDs which are attempted. The SASL
'GSSAPI' name is confusing - it actually only applies to using the Kerberos
mechanism. If you're doing SPENGO, then your mechanism name should be
GSS-SPNEGO. It would be good to allow the calling function to control this,
according to which SASL mechanism they're offering. This will be an issue when
using SSPI.

*) A way of NextToken indicating that authentication negotiation is complete. At
the moment the only way for the client to tell that its authenticated is to wait
for the server's response.

As I said to David when I sent him the patch, the code is really the bare
minimum to get SASL working - I tried to make the changes have as little general
impact as possible.
We hadn't talked about changing interfaces, just the implementations, and the
contract id's that are used to create the appropriate object that implements the
nsIAuthModule interface. In any case, I don't know how Darin feels about
changing nsIAuthModule - it's not frozen, so I guess it's technically possible.
So the GetNextToken implementation knows whether further round trips are needed,
w/o having to parse the data that comes back from the server?
Ah. Ok. 

Yes - gss_init_sec_context's return value indicates whether the connection is
complete (by returning GSS_S_COMPLETE), or if further packets are expected from
the server (GSS_S_CONTINUE_NEEDED). In the SASL case, the context is complete
one round trip after the GSS handshake is completed. So NextToken can tell with
each packet whether its the final one of the handshake or not - it just doesn't
share that information with the rest of the world.
It should be easy enough to invent a success code that can be used to convey
addition state from GetNextToken.
Darin, you mean roll it up in the return value so we don't have to change the
interface? That's OK with me...
yes.  we could use return codes (nsresult values in our case) just like GSSAPI
does ;-)
So there is no integrity or privacy protection with this patch, correct? Do you
have a URL which documents gssapi IMAP?
(In reply to comment #3)
> Great, thx, Christopher. I'll wait for your patch before proceeding since there
> might be conflicts. I'll attach the standalone gssapi.h, though perhaps you have
> your own?

I don't have my own gssapi.h.  I had considered it but didn't know the
ramifications.  But, if you have reason to believe there will be less problems
using a custom version then jumping through hoops to find the system version,
then I'm game.

We can probably do the same sort of thing for the SSPI. 
SSPI/Kerberos Interoperability with GSSAPI
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/sspi_kerberos_interoperability_with_gssapi.asp

Could we just make nsIAuthModule more general and create a wrap and unwrap
function? Would that suffice so that we don't need all of the sasl code in the
kerberos module?
>So there is no integrity or privacy protection with this patch, correct?
I believe that's correct. Simon could say for sure, and why that is, I assume.
> Do you have a URL which documents gssapi IMAP?
I don't - I googled for a bit and couldn't find anything.

I think having our own gssapi.h is the way to go. I've got one that works on
Windows, and I believe the guy who sent it to me used it on Linux. I'll attach
it, and finding out what kind of license I can slap on it.
Attached file standalone gssapi.h (obsolete) —
If anyone wants to try this file on linux/mac, that would be useful. It builds
on windows when I change nsNegotiateAuthGSSAPI.h to just include this gssapi.h
>Could we just make nsIAuthModule more general and create a wrap and unwrap
>function? Would that suffice so that we don't need all of the sasl code in the
>kerberos module?

I think we could just have different negotiateAuth class for the gssapi/sasl
stuff, or use a sub-class. But I think the auth module implementation should be
doing the wrap/unwrap stuff itself, and hide that detail from the consumers. But
I may not understand what you're suggesting. 
Replying to lots of comments here. Bear with me.

comment#10: There is no support for integrity or privacy protection in this
patch. To do this, you'd need to implement SASL security layers. This would
require additional interface-fu, as you need to be able to call gss_unwrap() for
all incoming packets, and gss_wrap with all outgoing ones. Supporting security
layers in the future would be a Good Thing, IMHO, so maybe that should be
considered when deciding on the way to integrate GSSAPI.

comment#10: GSSAPI IMAP is defined by a number of RFCs. RFC2222 defines SASL,
and the GSSAPI SASL mechanism. Its use within IMAP is defined in the IMAP RFC.
I'd suggest also reading the rfc2222bis I-D, and the revised GSSAPI SASL
mechanism I-D, which clarify a number of implementation points. See
http://www.faqs.org/rfcs/rfc2222.html ,
http://www.ietf.org/internet-drafts/draft-ietf-sasl-rfc2222bis-11.txt and 
http://www.ietf.org/internet-drafts/draft-ietf-sasl-gssapi-02.txt

comment#11: The GSSAPI C bindings are defined by RFC2744. Appendix A of this
document provides a definitive gssapi.h header file, which will be correct for
all conformant GSSAPI implementations.

comment#11: It did occur to me whether it might be easier just to create a
'GSSAPI' module which exposes NextToken(), Wrap(), and Unwrap() functionality.
Doing this would make it easier to add security layers in the future.

comment#13: The header file you have attached is from the Globus GSSAPI
implementation. It contains references to non-standard functions and flags.
I don't think that you should use it in its current form.
Why are you writing your own sasl implementation rather than just linking in
either the system sasl libs, or trying to do something with mozilla's ldap sasl
libs?
mailnews already has its own SASL implementation. The CRAM-MD5, NTLM, MSN, PLAIN
and LOGIN methods implemented within AuthLogin() are all SASL mechanisms. So the
code doesn't create a new implementation, rather just extend an existing one.

The additional code in the patch David attached for NegotiateAuth is the sum
total of what is required to do SASL/GSSAPI - I think that adding a dependency
on Cyrus SASL, plus having to implement for Windows anyway, would be
signifcantly more work and more code.

IMHO Cyrus SASL has made people think that SASL implementations are heavyweight
(and even to think that there's such a thing as a 'SASL implementation' - you
don't implement SASL, you implement the mechanisms individually - SASL is just a
framework for defining how you define a mechanism) They're not - its the glue
that the Cyrus libraries have to make them all things to all people that adds to
the code bulk.
OK, I've removed the non-standard stuff that I could find from this gssapi.h -
it should be pretty close to what's in the rfc now with <platform-specific>
stuff filled in.
Attachment #190794 - Attachment is obsolete: true
Attached file add license
Does this look OK? I put our license notice in, and put the author of rfc 2744
as the original author. Since the RFC says clients *should* include this header
file, I doubt they care much about it :-)
Attachment #190836 - Attachment is obsolete: true
Attachment #190882 - Flags: review?(cneberg)
(In reply to comment #17)
> mailnews already has its own SASL implementation.

Ok thanks for clearing that up.  

I think nsIAuthModule interface should have a Wrap and Unwrap function.  I can
add these functions to both SSPI and GSSAPI Kerberos.   Then you should make a
new nsIAuthModule for gss-sasl (or whatever you want to call it).  It will
create a component of either gss or sspi and call their wrap and unwrap
functions as needed.  Then you won't have to duplicate your sasl code twice, you
can ignore the differences between the kerberos implementations, and we will
have the start of an implementation to do security layers at a later point.  You
can put all of your logic under your aut module's GetNextToken and leave the
Wrap and Unwrap of your module empty for the time being.  How does that sound?
(In reply to comment #20)
That sounds good. The only other requirement here would be that GetNextToken()
has a set of return codes that differentiate between partial
(GSS_S_CONTINUE_NEEDED) and complete success. The gss-sasl implementation would
need this to tell when to start its bit of the handshake.

Is there a pref to determine whether to do gss or sspi?

> That sounds good. The only other requirement here would be that GetNextToken()
> has a set of return codes that differentiate between partial
> (GSS_S_CONTINUE_NEEDED) and complete success. The gss-sasl implementation would
> need this to tell when to start its bit of the handshake.

Fine.  I will also probably need some flags which specify the gss-mech to use.
(You probably really want kerberos not SPNEGO even it is available)

> 
> Is there a pref to determine whether to do gss or sspi?

Your module would probably have to determine which one it wanted to use since
gssapi and sspi will really be two different nsIAuthModule implementations.  I
was going to create a pref in bug 280792 in the http layer to let the user
decide.  You could base your decision on the exact same pref or a different one
depending on what your needs are.
I was hoping to be able to get this into 1.5, which is probably going to stop
accepting new features in a week or so - does anyone think that's undoable/crazy?

Does anyone need anything from me? I'm ready and willing to help with any of this.
(In reply to comment #23)
> I was hoping to be able to get this into 1.5, which is probably going to stop
> accepting new features in a week or so - does anyone think that's undoable/crazy?

I'll try to do as much of the kerberos changes as possible this weekend.

There were a few problem areas for negotiateauth and HTTP authentication
initially and to save time I'd like to document them here so you can consider
them and fix them in parallel if you forsee the same problems ocurring in mail.

Can mailnews handling the following scenarios adequately? Kerberos is different
than every other auth protocol because it normally doesn't make sense to retry
kerberos if auth fails for some reason.  It either succeeds or fails on the
first try then you need to fail over to another authentication type transparently. 
 
senario's

1.   The gss auth module can't be loaded.
2.   The module can be loaded but getNextToken fails because the user has no
credentials.
3.   getNextToken succeeds and sends a token but that token is rejected by the
server.
4.   getNextToken succeeds and sends a token but that token is rejected by the
server, then multi-trip auth protocol like NTLM is called next.   Between the
first and second trip for NTLM, you want it to remember that mail is doing NTLM
and not go back and try kerberos again between the attempts and get into an
infinite loop.

we fail over on all the secure auth mechanisms because some servers claim to
support a particular mechanism but fail. Simon is making sure we propagate the
various failures in gssapi auth to the code that does the failover.
Close this bug?  Either -> Resolved Fixed or maybe mark it as a dup of 280792?
Status: NEW → RESOLVED
Closed: 19 years ago
Resolution: --- → FIXED
Keywords: fixed1.8
Comment on attachment 190882 [details]
add license

cancelling obsolete request.
Attachment #190882 - Flags: review?(cneberg)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: