ldaptor icon indicating copy to clipboard operation
ldaptor copied to clipboard

Proof of concept for SASL GSSAPI Client Authentication

Open schlenk opened this issue 9 years ago • 9 comments

A proof of concept SASL / GSSAPI client authentication for ldaptor.

At the moment it is just ldaptor-search upgraded to do SASL-GSSAPI when asked to.

If you are in a Windows Domain with a domain user, you can use it as is, if you have kerberos_sspi installed.

python ldaptor-search --bind-sasl-mech GSSAPI 
   --service-location="CN=Users,DC=example,DC=com:dc.example.com" 
   --base "CN=Users,DC=example,DC=com" "(objectClass=*)" "cn"

Its not yet done or fully integrated (or doc'ed), but i wanted some feedback before going further, to not waste too much work.

I have a few questions about going forward with it:

  1. How to handle the optional dependencies to https://pypi.python.org/pypi/kerberos or (Windows) https://pypi.python.org/pypi/kerberos-sspi ?
  2. API thoughts on entry.bind() with SASL. The currently existing API is a bit clumsy when needing more than a single roundtrip. So i added a sasl_ctx parameter that does the repeated bind requests directly. Any different plans on how this should work?
  3. Should this be in ldaptor at all, or should it be external in some way?
  4. How about other SASL mechanisms?
  5. What other stuff (docs, tests, etc.) would be needed to land this?

This does too much still, due to bugs in pykerberos/kerberos_sspi (see may-day/kerberos-sspi#3 ).

schlenk avatar Feb 04 '16 18:02 schlenk

Can you do a rebase against master?

psi29a avatar Jun 07 '16 15:06 psi29a

I'm thinking it might be useful to use the Twisted plugin system[1] to add available authentication schemes to the utility. Not sure if we can use Twisted cred [2] with ldaptor, but it seems like if it wouldn't be too hard to move in that direction, we should try it, since it might mean we could leverage other existing authN mechanisms that have been written using cred.

For the optional depedndencies-- can you just try importing one module and if it fails fall back to the other, and then if that fails then don't include that authN option in the list of available command line options?

Also, I know Twisted has its own command line options abstraction, but it might be simpler to go with argparse from the standard library, which tends to give more of the default behaviors I expect for command line utilities without having to poke around as much.

SASL is a pretty common option in the LDAP world so I wouldn't be opposed to seeing it included in ldaptor. That said, if I understand correctly, the idea is that it separates authentication protocols from application protocols. So if we could get this to work with Twisted cred, it might be useful as a standalone release (txGSSAPI?). I quick google search did turn up some random code that purports to implement GSSAPI for Twisted cred [3], but I didn't test it out or look closely.

Docs are important. In fact, until you made this pull request, I didn't realize ldaptor had any built in command line tools, because the docs don't mention them! I'd suggest maybe a new sub-section in the "User's Guide" section for "Built in command line tools". I'd give some short examples on usage. Some pointers for adding additional authN plugins would be awesome. If it seems to cluttered in the User Guide, maybe it could go in the Cookbook section?

Thanks, Carl

[1] https://twistedmatrix.com/documents/current/core/howto/tap.html [2] https://twistedmatrix.com/documents/current/core/howto/cred.html [3] http://www.ofchk.biz/server_source/calendar_server/src/twistedcaldav/authkerb.py

cwaldbieser avatar Jun 07 '16 22:06 cwaldbieser

seems my git skills are a bit rusty... :-(, not sure if i messed up things.

schlenk avatar Jun 08 '16 15:06 schlenk

Coverage Status

Coverage decreased (-1.02%) to 86.028% when pulling e27d7797ac1b7e571a31b4d3ad2de0e431c2d99d on schlenk:gssapi into 42ce8595409a34c97d04eba5598909a3b825bdb8 on twisted:master.

coveralls avatar Jun 08 '16 15:06 coveralls

Coverage Status

Coverage decreased (-1.0%) to 86.028% when pulling fec75d23e3d432acae638ec07281bf8f7bf1fa16 on schlenk:gssapi into 9380c5522c39d9b3286538d58bb1c8503ac2ca84 on twisted:master.

coveralls avatar Jun 08 '16 16:06 coveralls

Coverage Status

Coverage decreased (-1.0%) to 86.028% when pulling fec75d23e3d432acae638ec07281bf8f7bf1fa16 on schlenk:gssapi into 9380c5522c39d9b3286538d58bb1c8503ac2ca84 on twisted:master.

coveralls avatar Jun 08 '16 16:06 coveralls

Awesome... all the builds work but pyflakes says: ldaptor/usage.py:113: local variable 'MECHANISM' is assigned to but never used

Coverage is also not that great, it could use some test cases to see if anything is breaking.

@cwaldbieser: I agree with everything you've typed. I would like to see this PR using Twisted Cred if possible. I like the idea of making this plugable.

We can move to using argparse in another PR to keep this one to the point.

Same with documentation, it doesn't have to go in this PR but eventually the CLI tools should be covered.

psi29a avatar Jun 08 '16 17:06 psi29a

@cwaldbieser: Agreed. Will have a look how cred fits into it and what to do about some docs. Docs might fit in well in an extra PR.

You are right that SASL is a way to decouple the auth protocol from the application protocol. But sadly it is more than just that. It also includes an negotiable extra layer to provide message integrity and privacy. So in the worst case one has the funny layering of LDAP inside TLS, secured by SASL message integrity handling Kerberos messages secured by GSSAPI. A little bit of overkill.

So having it pluggable isn't that hard (i know because it is pluggable in the Tcl stdlib SASL implementation [http://core.tcl.tk/tcllib/doc/trunk/embedded/www/tcllib/files/modules/sasl/sasl.html]). Just need to generalize the SASL_GSSAPIClientContext a bit to become a generic SASL_ClientContext and then plugin the specific mechanisms.

schlenk avatar Jun 08 '16 18:06 schlenk

I did take a look at the bind() method in entry.BaseLDAPEntry. You are correct that it doesn't seem flexible for anything other than a simple BIND. In fact, it pre-supposes that you are BINDing with a DN, which could be a problem in some instances (e.g. a SASL "external" mechanism-- see python-ldap for an example[1]).

I would say to keep things flexible, it should probably have a parameter list like bind(**kwds) and the docstring would have to say what the valid parameter combos are, as they can vary pretty significantly from method to method. You might even need to just indicate that you need to refer to the authN provider docs for what parameters to pass outside of a simple BIND.

For BINDs that don't use DNs, one might have to do a more low-level request with the ldaptor.protocols.ldap.ldapclient.LDAPClient for now. Maybe someone can build a useful abstraction at a later time.

Thanks, Carl

[1] https://www.python-ldap.org/doc/html/ldap-sasl.html#examples-for-ldap-sasl

cwaldbieser avatar Jun 08 '16 19:06 cwaldbieser