After upgrading to beta3, any new LDAP user that logs in after the first time receives and error message

"Another user already exists in the system with the same login name"

My user conflict setting is:

Associate local account with the LDAP entry

Thoughts?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

cgmonroe’s picture

Hmm, tried to reproduce it here but no joy. Are you using another authentication method with this? E.g. CAS or Webserver Auth.

First, check the watchdog logs for messages. The "user exists" message means that the ldapauth_drupal_user_lookup function did not return a user account. If it is something other than a straight "can't find user", there should be a watchdog entry (the user does not see it for security / don't scare end users reasons).

The logic for this depends if you are using Persistent Unique IDs (PUIDs) or not... For the "no PUIDs" method, it is:

  1. a straight drupal user load by name call generally using the name entered on the login form (Generally, because there is a new hook that lets you alter this before looking up drupal users).
  2. If there is no user found, it just returns and the create a new user code kicks in.
  3. If there is a user found, a check to see if it is already an LDAP user is done. (could be from a different LDAP server or base dn).
  4. If it is an existing LDAP user, then the DNs for the found account and authenticated user are compared...
  5. If these don't match, then an error is thrown and the new user can't be created.
  6. If they do match, the existing ldap account is associated with the login dn (this is to handle updates/server moves smoothly.. if you have two users with the same DNs... then your LDAP setup is in trouble.)

I think something may be happening in the code to map existing ldap users. (Step 6).

A quick test for this would be to go to a problem user's profile and use the new "Convert them back to a Drupal user". Then see if they can log in.

If that is the case, then some steps to take to debug this would be:

Get the latest -dev version, in the Global LDAP auth settings is a new option to turn on extra watchdog logging. This will give you information about the dn the login id/password was mapped to.

You can find the conflicting user's LDAP information by viewing their user profile.

Look at the two DNs and see what the differences are. There may be some inconsistencies due to older code (pre Beta2?). If this can be identified, then maybe some bulk correction code can be done.

tfheen’s picture

I have the same problem and tracked it down to having multiple LDAP servers and ldapauth_drupal_user_lookup now comparing the sids between the current LDAP server and the user in drupal.

I don't think that's reasonable, I think it should just look at the DNs and if you have multiple LDAP servers with overlapping, non-identical DNs in, you'll get chaos, so don't do that. Checking that the user comes from the same LDAP server means you've suddenly broken failover between different LDAP servers, which I don't think it's the intention at all.


diff --git a/sites/all/modules/ldap_integration/includes/ldap.core.inc b/sites/all/modules/ldap_integration/includes/ldap.core.inc
index 2bfde2a..148422e 100644
--- a/sites/all/modules/ldap_integration/includes/ldap.core.inc
+++ b/sites/all/modules/ldap_integration/includes/ldap.core.inc
@@ -424,12 +424,8 @@ function ldapauth_drupal_user_lookup( $ldap, $name, $dn, &$error, $puid=NULL ) {
     if ( $account->ldap_authentified ) {
       // Do DNs map
       if ( drupal_strtolower($account->ldap_dn) == drupal_strtolower($dn)) {
-        $old_server = ldapauth_server_load($account->ldap_config);
-        // Do sids match or old sid does not exist
-        if ( $account->ldap_config == $sid || empty( $old_server )) {
-          $account->ldap_puid = $name;  // Default if puid attr not set.
-          return $account;
-        }
+       $account->ldap_puid = $name;  // Default if puid attr not set.
+       return $account;
       }
       return FALSE;
     }

is the fix I've used on my end, and it seems to work fine.

cgmonroe’s picture

I reconstructed the thoughts behind this test and am not sure just removing it is a good idea...

This test is there to prevent some possible security problems. For example, suppose you have a set up with two authentication sources, the company's internal LDAP directory server and a second LDAP server for customers. Suppose the neophyte LDAP admin put users under the ou=People branch on both servers.... I know, bad practice, but a common "take the defaults" problem.

So, staff user, Ima Admin (uid=iadmin) gets married and goes on her honeymoon... While she is gone the HR folks cause her DN uid and cn to change from iadmin to inewname. But her iadmin Drupal account still exists.... So, a new customer Irma Admin registers.... and whoa... now has assumed iadmin rights.... Not a good thing.

Not a common thing, but it could happen.

So what about replicated/backup servers? This sort of problem is what the new Persistent Unique ID support is for. This lets you tie Drupal users to the PUID attribute. It doesn't matter which server you come from or if your name has changed. The LDAP object is mapped to Drupal User via this Persistent and Unique attribute. Both AD and LDAP have service attributes that get copied when the entry is replicated. AD uses ObjectGUID and modern LDAP uses EntryUUID. Alternatively, you can use a locally defined attribute (e.g. employee num, etc).

But it seems like there can still be transition state here... One way to deal with it might be to recreate your LDAP entries and make sure the old users don't have an sid that exists.

Another possibility would be to just add another "security" option that turns this test on and off. This may be the best option. Let people decide how paranoid they want to be.

Bottom line is that if you want to have safe LDAP server redundancy, you should look at the PUID code. There is a README specific to this in the distro.

mightaswell’s picture

Thanks guys for the replies. I think I may be on to something here.. In two new cases, I noticed that the users had been moved to a different OU after they had logged in to the Drupal site. Moving users to different OUs does occur often here as we have multiple physical locations and non stop reoganization (ugh).

I'll check with my AD admin to see if there is a PUID I can use. Will this solve the changing OUs for some users? Will I need to bulk update something or will it be picked up when the user logs in.

Thanks.

Chris

cgmonroe’s picture

Re: OU changing

Yes, this will handle this if the user has been mapped to a PUID. Basically, there is a new table called ldapauth_users that contains Drupal UIDs and PUIDs. If there is a uid that matches the LDAP authenticated PUID, this will always be the "found account"... regardless of DN or server changes. It's designed to handle name changes and server/OU moves.

Re: Update

As long as the normal user mapping logic works (e.g. LDAP authenticated users have same server / same dn), the ldapauth_users table will be populated with PUID info as people log in. (or via the new ldapsync module).

Basically, if ldapauth_user does not have a matching PUID for the user, the code checks to see if there is a match by user name. If there is a match the code handles the non-ldap user / ldap user cases.

For the non-ldap user case, the user is returned (and mapping handled via the standard map non-LDAP user to LDAP user code/ admin settings.

For the user is an existing ldap user case, it checks if dn and server matches and then creates a new ldapauth_users entry that maps the Drupal user to the PUID.

Of course, any problem users whose's DN or server has changed may have to be re-mapped as ldap users. Either by using the "convert user back to Drupal User option in their profile and using the map non-LDAP drupal users to LDAP user id's process as they log in or are "synced".

pumpkinkid’s picture

I have the exact same problem... Any luck narrowing it down?

pumpkinkid’s picture

Never mind... Added "objectGUID" to persistent and Unique User Id Attribute and that seemed to have done the trick!

albert9000’s picture

I added "objectGUID" and that fixed the issue for some users, but now other users are getting this error "User, username, already associated with a different LDAP user"

****Edit****

In the end I had to revert to Beta2

LarryChew’s picture

I had the same problem after updating LDAP data to an existing Drupal user. I went into MySQL, removed user from ldapauth_user
table and didn't work. I then changed the user table's "mode", "sort", and "data" fields back to look like other people's and that fixed my problem (for that user).

[from reading #1 above]
I don't see a "Convert them back to a Drupal user" option in my user profiles.
I'm on version beta 3 +12.

cgmonroe’s picture

Re: #8 Fixing by modifying user

An easier alternative to doing this for individual users is to use the new "Convert to local user" option by:

  • Go to their profile page as a user with the "administer users" permission
  • Use the "Convert from LDAP user to local Drupal user" link.

Re: Larger issue

The underlying problem here is that beta2 had some severe security holes that needed to be plugged. Here's an example issue:

#1317704: same uid on two different ldap servers able to log into drupal and claim same drupal user.

The basic problem is that the older versions just said, if I have a user id and matching password in LDAP, any Drupal id with a matching user name will be associated with this. In other words, there was an assumption that user names were unique, both within individual LDAP servers and across all LDAP servers. However, LDAP does not enforce unique user names... in fact, it is designed to ALLOW such things. You can have a jsmith in ou=Employees and in ou=Clients. This false assumption leads to a lot of possible situation that one person can be granted access to another person's id.

This possible identity confusion is a totally unacceptable for any authentication method. However, this raises the issue.. how do to identify users as they are "moved" between LDAP OUs and servers. As said before, this is what the PUID attribute setting is designed to do.

However, this issue has pointed out that there can be "transition" problems.

In order to add the PUID tracking (FYI - stored in the ldapauth_users table) to existing users (transition users), the user logging on needs to be definitively and securely "map-able" to the Drupal id. This is done by looking at the ldap info stored in the Drupal user data. This information should be updated each time that a user logs in and should contain the server and dn that matches the authenticating user. If they match, the Drupal uid is mapped to the PUID and life if good. The user can move around in LDAP and their Drupal account will follow them.

However, if the local Drupal info does not match the authenticating user's server and dn, the PUID association can not be made. And you get the "user can not be created" problem. Unfortunately, I can't see a secure "auto-magically" handle these transition problems without re-opening the security holes.

A manual solution

However, I just checked in (and will be in the next -dev build) a new ldaphelp module version that includes a "User Info" tab. This tab will let you list all LOCAL "ldap authenticated" users and see the current local info about related server id and DN. In addition, it will show you the PUID Status of each user (e.g. PUID not used, PUID not set, PUID set).

There is an option on the form that generates this to "verify" the local information against the LDAP server. This will check that the local information matches the current LDAP information.

This should help people with transitional problems identify users who can not definitively be matched to their LDAP info. E.g., if the verify status says "User not found" and you're NOT using PUID. Or "User not found / PUID can not be set for this user" if you are converting to PUIDs.

Once you identify the problem users, the way to correct the problem is to:

  • Make sure that the LDAPAuth module settings have "User Conflict - Associate local account with LDAP entry" set.
  • Click on the name in the User Info list (take you to user profile)
  • Use the "convert from LDAP to local user" link

Next time user logs in or ldapsync is used, the LDAP associations will be set up correctly.

Please note this new code is not optimized for 1000s of users. (patches welcome)

koglinjg’s picture

Status: Needs work » Active
FileSize
14.33 KB

I have made a patch that allows the user to choose between 4 security levels for matching local drupal users to ldap accounts. This only applies when not using PUID.

The no, medium and paranoid already existed as checks, I just named them, and allow you to pick which checks you care about.

Go to /admin/settings/ldap/ldapauth/ under "Security Options" there is now "Choose security mode"

The light check is one I wrote as a compromise to no security and medium, which was too strict for me to use yet. In our use case users are frequently moved between OU's, so doing a full match of the CN,OU's and DC's would fail because the OU's did not match. This method compares the CN and DC's concatenated together between the local users cache and the response from the server.

Paranoid Security. Local account to ldap account matching requires a full match of the CN, OU, DN and the serverid from the ldap config.
Medium Security. Local account to ldap account matching requires a full match of the CN, OU, DN
Light Security. Local account to ldap accout matching only requires the CN and baseDN match the servers CN and base DN.
No Security. Local account to ldap accout matching does not do any extra verification (same as beta2)

I have also added some ldapath debug statements so if you check the box for extra debugging, there is now some more info.

Also made a small fix to the ldapauth help module that was not reporting the "Create new Drupal user if not present" status correctly.

cd to your modules folder (/sites/all/modules or /sites/default/modules or somewhere else)

patch -p1 < patch-file.patch

Don't use this patch, it does not work. See comment #16

I will work on on recreating this patch, this weekend when I can test it.

koglinjg’s picture

Status: Active » Needs review

Forgot to change the status to needs review. Sorry for the double post :/

gp177’s picture

Were any database updates included in moving from beta2 to beta3?

Initially, it looks to me like simply reverting the module to beta2 may be best fix.

koglinjg’s picture

FileSize
157.33 KB
7.9 KB

The ldapauth module had 3 database updates, ldapauth_update_N() 6004-6006.

Attached is a diff of the ldapauth.install file and a full diff between beta2 and beta3.

gp177’s picture

I should have thought to have done a diff between ldapauth.install across those verions, thanks.

Looking over the diff it doesn't look to me like reverting the code from beta2 to beta3 should break anything (and my own internal testing suggests this as well).

However, I would like to hear from the module developer as they are far more familiar with this update.

We have controls in place that insure our only LDAP directy contains unique user names.

kim-day’s picture

Status: Needs review » Needs work
FileSize
1.67 KB

A couple of days ago I updated from beta2 to beta3 and started experiencing the same issue as the rest of you here. I needed an immediate fix so I've downgraded from beta3 to beta2 for now and that seems to be working as a short term fix.

I tried applying the patch in #11 to beta3 and ran into several problems:

1) the patch did not apply cleanly - below are those errors and attached is the rejects file.

patching file ldap_integration/includes/ldap.core.inc
Hunk #2 succeeded at 689 with fuzz 2 (offset -22 lines).
patching file ldap_integration/ldapauth.admin.inc
Hunk #2 succeeded at 83 (offset -6 lines).
Hunk #3 FAILED at 161.
1 out of 3 hunks FAILED -- saving rejects to file ldap_integration/ldapauth.admin.inc.rej
patching file ldap_integration/ldapauth.module
Hunk #3 FAILED at 434.
Hunk #4 FAILED at 475.
Hunk #5 succeeded at 543 (offset -12 lines).
Hunk #6 succeeded at 613 (offset -14 lines).
2 out of 6 hunks FAILED -- saving rejects to file ldap_integration/ldapauth.module.rej
patching file ldap_integration/ldaphelp/ldaphelp_status.inc
Hunk #1 FAILED at 165.
1 out of 1 hunk FAILED -- saving rejects to file ldap_integration/ldaphelp/ldaphelp_status.inc.rej

2) The site would not allow ldap login after the patch (trying to login gave an HTTP Error 500).

koglinjg’s picture

Status: Active » Needs work

Thanks for posting the issue with that patch, not quite sure how I managed to mangle it. I was able to reproduce the issue and I plan to work on it this weekend.

WorldFallz’s picture

It's been a while since this issue has been updated, but I just ran into this myself. Any chance someone has an updated patch?

WorldFallz’s picture

Status: Needs work » Needs review
FileSize
13.15 KB

I checked out a fresh copy of ldap_integration-6.x-1.x-dev, applied the patch manually, tested with my users, and rerolled it. Updated patch attached.

zeezhao’s picture

Thanks for re-rolling the patch in #19.

I did some testing with this, and there still appears to be a problem in logic with the latest patch and dev version.

I keep getting this error:

Error looking up user in LDAP: Supplied dn not found! sid= …

Even though users do exist in ldap, and get created when I revert to an older version of ldap_integration I had from 2011-09-03.

The errors happen with or without PUID set. I am using "Mixed mode" authentication mode. But happens also in "LDAP directory only" mode too.

Please is there something else I need to do?

edit1:
I switched "Turn on extra Watchdog logging" and it appears to be matching new users with blank uid as this message is now logged:

authenticate: User, xyz, was linked to existing Drupal account, (uid=).
authenticate: User, xyz, was marked as blocked in Drupal database.

The user 'xyz' does not exist in database as I have checked users able manually.

edit2:
It appears to create the first new user that tries to login. Then after that every other new user gets the error message above. Hence probably an issue with a cache? Not very familiar with the code, so will appreciate any help. Thanks.

kenorb’s picture

Tested dev+patch, but still I've the error:

Another user already exists in the system with the same login name. You should contact the system administrator in order to solve this conflict.

It seems that it's trying to create another user in includes/ldap.core.inc where is another check, so I don't know what's going on.
It seems that all beta3 and dev versions are affected, but not beta2.

When downgraded to 6.x-1.0-beta2 it works perfect, so it looks like some kind of regression.

$ drush vget ^ldapauth
ldapauth_alter_email_field: "0"
ldapauth_alter_username_field: "0"
ldapauth_create_users: 1
ldapauth_disable_pass_change: 0
ldapauth_forget_passwords: 1
ldapauth_login_conflict: "1"
ldapauth_login_process: "0"
ldapauth_sync_passwords: 1

Tested both ldapauth_login_process and ldapauth_login_conflict with different values.

zeezhao’s picture

In relation to #20, I should also add that using multiple ldap servers. But stillsame issue if only 1 server enabled. Please has anyone got a version that works? Thanks.

kenorb’s picture

Issue summary: View changes
Status: Needs review » Closed (outdated)

The 6.x most likely is not supported anymore. Feel free to re-open for 7.x