Modify

Opened 13 years ago

Closed 12 years ago

#7999 closed enhancement (fixed)

LDAP bind using login creds

Reported by: shawn.ohail@… Owned by: branson
Priority: normal Component: DirectoryAuthPlugin
Severity: normal Keywords:
Cc: Trac Release: 0.12

Description

Nice plugin, thanks for writing it.

I was wondering if it's possible to bind to the ldap server using the login username/password and using that as the test for successful authentication. One other question then pops up, if we bind this way will we still be able to get the person's real name and email address to populate the session_attribute table?

Attachments (0)

Change History (7)

comment:1 Changed 13 years ago by John Hampton

Priority: normallow
Status: newassigned

So, I think I understand your question. I'll go with a long explanation and you can tell me that I misunderstood everything later.

The plugin does bind to the AD server using the creds supplied by the user logging into Trac. In fact, this is the only way that I know of to actually check whether or not they typed in the correct password.

That being said, I think you're interested in getting rid of the need to specify the bind_dn and bind_passwd options in the trac.ini

Obviously, it would require a code change to remove the need for bind_dn and bind_passwd. However, that's not to say it can't be done.

The bigger problem is in mapping usernames to DNs. To bind to AD, one needs a DN in the form of:

cn=Test M. User,ou=Users,dc=domain,dc=com

Rarely, however, do the login name (sAMAccountName attribute) and the cn portion match. A method for mapping sAMAccountName to DN would be needed. However, it may not be possible. For instance, in my organization, sAMAccountNames are first initial, middle initial, lastname. The cn, however, is the full name with the middle initial. There is no way to map from sAMAccountName to DN. Because of this, we bind as a known user, bind_dn, and then look for the sAMAccountName.

If we allow anonymous queries to AD (not the default as far as I am aware), then we could do the search for sAMAccountName without using bind_dn

If you have other suggestions, or perhaps even a patch, I'd be happy to consider them. I don't have an environment where I can play around with anonymous binds, so, without a patch, I'm not sure how quickly this will be implemented.

comment:2 Changed 13 years ago by Shawn O'Hail

I think I follow what you're saying. To perform auth:

  1. You bind using bind_dn and do a search for the login name to get the DN.
  2. You bind again, using the located DN and login password.

I'm not a python guy, but i am a perl guy. There is a class, Authen::Simple::ActiveDirectory, which does auth via AD, but does not require the same bind_dn account info that this plugin requires. Looking at the perl code they bind using the string 'username@domain' and login password. The host it binds to is the domain name itself.

So bind( username@…, password ) to the server example.com.

So, in this way, can your plugin attempt to bind as the users's principal and avoid a separate bind account? If so, then I wonder if you're still able to look up attributes such as real name and password.

I'll try to have a look at your code and see if I can make this change. Not a python or LDAP guy but I would love to get this working for Trac!

comment:3 in reply to:  2 ; Changed 13 years ago by John Hampton

Priority: lownormal

Replying to spohail:

I think I follow what you're saying. To perform auth:

  1. You bind using bind_dn and do a search for the login name to get the DN.
  2. You bind again, using the located DN and login password.

Exactly

So bind( username@…, password ) to the server example.com.

Apparently, that also works. This is what I get for misunderstanding the documentation. I realize now that there is a slight difference between binding and authenticating. When binding using the full dn, it forces authentication using that object. However, once can also simply authenticate using the username@domain, and, if I read it correctly, domain\username should work also.

So, in this way, can your plugin attempt to bind as the users's principal and avoid a separate bind account? If so, then I wonder if you're still able to look up attributes such as real name and password.

In order to get full name, and email address we will still have to do a search and bind, but we should be able to do that with the authentication of the user.

I'll try to have a look at your code and see if I can make this change. Not a python or LDAP guy but I would love to get this working for Trac!

So, if you still feel inclined, you're more than welcome to try to make a patch. I will also try to find some time to adjust the code to make this possible. Thanks for helping me learn something.

comment:4 Changed 13 years ago by Shawn O'Hail

Off the bat, for performance sake, I replaced _get_user_dn() with:

    def _get_user_dn(self, user):
        return '%s@%s' % ( user, self.ads );

I messed around with this for quite a while, and best I can tell, unless you mangle the existing functionality or store login passwords for retrieval later, there's no clean way around having the extra account. Not a big deal though, I can work with it as is. The only thing I would change is upon login, update the session_attributes table with the current email/full name values from LDAP in case a) the user wasn't in LDAP the last time /admin/accounts/users was hit or b) this info changed.

Between this plugin, FlexibleAssignToPlugin, and this patch, I have everything I need.

comment:5 in reply to:  3 Changed 13 years ago by olaf.meeuwissen@…

Replying to pacopablo:

Replying to spohail:

So bind( username@…, password ) to the server example.com.

Apparently, that also works. This is what I get for misunderstanding the documentation. I realize now that there is a slight difference between binding and authenticating. When binding using the full dn, it forces authentication using that object. However, once can also simply authenticate using the username@domain, and, if I read it correctly, domain\username should work also.

I've been experimenting a bit on what is needed to bind. These are the conclusions regarding the strings I tried for bind_dn:

  • using my distinguishedName fails to bind
  • using my mail attribute fails to bind
  • using my sAMAccountName attribute fails to bind
  • using my userPrincipalName binding succeeds. The value of this attribute is formatted as an email address but different from mail.
  • using the /o and /cn of the legacyExchangeDN in a domain\username binding succeeds. The /cn is identical to my sAMAccountName.
  • same when using the information from msExchADCGlobalNames
  • in all cases, case is irrelevant

I should add that we have had a domain name change. My mail attribute uses the new domain name, but the userPrincipalName still uses the old domain name. This value also uses my sAMAccountName as the username part.

Hope this helps.

comment:6 Changed 12 years ago by branson

Owner: changed from John Hampton to branson
Status: assignednew

So some points here:

  • AD does not allow anonymous bind unless the registry is hacked. SO not sure that allowing search via anonymous is valid.
  • if we tried to use the user/pass of the current user, we'd have to cache that password somewhere locally using reversable encryption. This is a Bad Idea(tm) from a security POV.
  • you can use {user}@{realm} in some cases.. and we could flag to support that as the username if you wanted. Might even be able to extend to validate against multiple realms that way. Would take some coding, and I dont' have a multi-realm AD config to test with ;-)
  • it's fairly trivial to setup a non-priv'd user for AD ( cn=search,cn=users,dc=ad,dc=com ) to perform searches .. but no logins.

comment:7 Changed 12 years ago by branson

Resolution: fixed
Status: newclosed

So .. I have fixed several things on this that you might find useful:

  • Renamed the plugin to DirectoryAuthPlugin
  • Now can do anonymous and SSL based bind.
  • Name and email are now populating to the session table.. and you can select the vars that are used

I am gonna close this as I think it's fixed now. If you find trouble .. please open a new ticket.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain branson.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.