LDAP backed = Server 2008 Active Directory

If an LDAP attribute is empty or in AD, and Login Sync is enabled, the user receives an SQL error:

PDOException: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: '[roomNumber]' for column 'ldap_user_last_checked_value' at row 1: INSERT INTO {field_data_ldap_user_last_checked} (entity_type, entity_id, revision_id, bundle, delta, language, ldap_user_last_checked_value) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6); Array ( [:db_insert_placeholder_0] => user [:db_insert_placeholder_1] => 127 [:db_insert_placeholder_2] => 127 [:db_insert_placeholder_3] => user [:db_insert_placeholder_4] => 0 [:db_insert_placeholder_5] => und [:db_insert_placeholder_6] => [roomNumber] ) in field_sql_storage_field_storage_write() (line 448 of /var/www/html/new.wysu/modules/field/modules/field_sql_storage/field_sql_storage.module).

The user login is successful, however.

How to reproduce:

  1. Configure Provisioning from LDAP to Drupal Mappings to map an empty attribute [roomNumber] to a Drupal field "Unix Timestamp of...
  2. Login with a user

Workaround: Manually assign a value to the desired attribute you wish to provision.

This is probably easy enough to fix if all that needs to be done is some simple isset() validation. Would be happy to look into it myself. Thoughts?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

johnbarclay’s picture

Sounds correct. Please take a look.

The other issue with mappings currently is they only know how to map to simple user fields. See #1841514: LDAP User: Data type mapping for Profile Fields. Feeds is still in the alpha stages for d7, so I don't think we can count on it in the long haul.

musicalvegan0’s picture

I've tracked down the issue to ldap_servers_token_replace() in ldap_servers.token.inc. However, the issue is a bit more complicated than I originally thought.

When an LDAP attribute is empty, ldap_servers_token_replace() inserts the name of the attribute as its value. This is fine to prevent empty strings for values, but when the string disagrees with the data type in the database (ie, integer in this case), an error is thrown.

You can easily test this by taking an empty text field in LDAP and linking it to a user field type, like first name. When the user logs in, you'll see [givenname] as the value of the user's first name, so long as synchornization from LDAP to Drupal is enabled.

I see only one good solution to fix this. Check the data type of the DB and insert a default value that matches the data type if the value pulled from the LDAP resource is not set. However, having a hard-coded default value may be confusing to users. Therefore, on the profile mapping page, add an option for the user to set a default value for empty data. Have the form validate the default data depending on the user field the attribute is mapping to.

Of course, there is always the chance that the data pulled from LDAP will not match the datatype in the DB. A better error should be sent to the user indicating that this is case. This error should precede and thus prevent a DB transaction.

I'm attaching a patch that modifies ldap_servers_token_replace() to replace empty data types with an empty string ('') as opposed to the attribute name. This at least will make it easier to detect if the data needs to be replaced by a default value.

I can look into data type validation based on the DB, but the learning curve is pretty steep for me. I may need a few nudges in the right direction. Any particular methods or classes I should have a look at? I've not done any Drupal DB development before.

musicalvegan0’s picture

Attaching a patch with correct author information. The other patch can be deleted.

johnbarclay’s picture

I committed this with a couple of changes to deal with case sensitivity. See http://drupalcode.org/project/ldap.git/commitdiff/1817cb30e700c4587aeb95...

Note the old // @todo refers to the problem you fixed :)

johnbarclay’s picture

Status: Active » Needs review

Can you test this also.

musicalvegan0’s picture

After testing, I can confirm that the patch replaces empty LDAP values with an empty string; this seems like more logical behavior. This produces a slightly different error message, as is expected:

PDOException: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: '' for column 'ldap_user_last_checked_value' at row 1: INSERT INTO {field_data_ldap_user_last_checked} (entity_type, entity_id, revision_id, bundle, delta, language, ldap_user_last_checked_value) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6); Array ( [:db_insert_placeholder_0] => user [:db_insert_placeholder_1] => 127 [:db_insert_placeholder_2] => 127 [:db_insert_placeholder_3] => user [:db_insert_placeholder_4] => 0 [:db_insert_placeholder_5] => und [:db_insert_placeholder_6] => ) in field_sql_storage_field_storage_write() (line 448 of /var/www/html/new.wysu/modules/field/modules/field_sql_storage/field_sql_storage.module).

Once again, for clarification, I'd like to assert that this has to be fixed with some validation shortly before the DB commit. I'll have a look at doing that this weekend.

johnbarclay’s picture

Status: Needs review » Needs work

Its also odd that ldap user is trying to insert a token into ldap_user_last_checked_value field. Do you have room number mapped to ldap_user_last_checked_value for testing purposes; or is the code broken in ldap_user. The intent is for ldap_user to automatically populate ldap_user_last_checked_value with a unix time.

musicalvegan0’s picture

Yes, for testing I had the Unix Timestamp mapped to the roomNumber attribute. With this configuration, I performed two tests:

  1. No Drupal to LDAP mappings configured; only LDAP to Drupal mappings configured. Obviously, Drupal would not be updating user-set LDAP attributes in this case.
  2. Various LDAP to Drupal mappings configured; essentially reversing what I had in my LDAP to Drupal mappings.

The SQL error was produced only on the first test.

musicalvegan0’s picture

Contrary to comment #8, it appears that new users receive the error even when test #2 is performed. I just created a new LDAP user and attempted to login and received the SQL error from comment #6.

johnbarclay’s picture

Version: 7.x-2.0-beta2 » 7.x-2.x-dev
johnbarclay’s picture

Title: LDAP User Module: Empty LDAP values produce error on login » LDAP User Module: ProvisionEmpty LDAP values produce error on login

I think these scenarios need to be addressed as far as error catching and validation. I will try to work them into the simpletests. 1-2, 2-1, and 2-2 are particularly hard to validate. Sounds like your use case is 1-2.

  1. Provisioning to Drupal
    1. A value is being mapped to a missing User field.
    2. A value is being mapped to a user field. The value is of the wrong datatype (int, null, empty, etc)
    3. A non existent ldap attribute is being mapped to a user field
  2. Provisioning to LDAP
    1. A user property or field is being mapped to a missing ldap attribute.
    2. A user property or field is being mapped to an ldap attribute. The value is of the wrong datatype (int, null, empty, etc)
    3. A non existent user property or field is being mapped to an ldap attribute
musicalvegan0’s picture

I think having simpletests to check for some of these is a great idea, at least in the short run. It would at least force the user to verify at configuration that there won't be any provisioning problems.

johnbarclay’s picture

Component: Code » SimpleTests
jdowner12’s picture

Hi I'm having an issue that sounds like it could be a duplicate of this and wanted to run it by the folks working on it. I can reproduce this problem on beta 3 and latest DEV Build. I've included a PDF with errors from my syslog and the user setup.

Problem statement:
LDAP User Module is not pushing attributes of type --user tokens-- that have been setup in the Provisioning from Drupal to LDAP Mappings section to and OPN LDAP server. If I restore back to beta 2 users are created without error.

froboy’s picture

The problem with all of the patches above is that '' (the empty string) is just that... a string. Assigning a string to an int will fail, so if the $result is '' then we should return NULL instead of ''. I've modified the return value of ldap_servers_token_replace to return ($result == '') ? NULL : $result;.

I've attached a patch. We've tested that this on top of #3 above fixes all of our "incorrect integer value" errors.

johnbarclay’s picture

At first look, it seems like #15 and #4 would only work for text of form: "[dn]","[mail]", etc.

$text such as "[cn]@my.org", and "[displayName] [sn]", would fail.

I added some more simpletests for tokens such as"[cn]@my.org", and "[displayName] [sn]"

I also commited the last line of patch #15 (returns NULL instead of '').

Can you run the simpletests for ldap_server against these patches?

yalet’s picture

I manually applied what was left over from #15 (the part that hasn't been committed yet), and ran the ldap_server simpletests. All the tests passed.

johnbarclay’s picture

Component: SimpleTests » Code
Status: Needs work » Reviewed & tested by the community

This is good. I'll apply this next time I'm patching.

recrit’s picture

re-roll of the patch with latest 7.x-2.x as of 279842c

johnbarclay’s picture

Status: Reviewed & tested by the community » Fixed

thanks. this is committed.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.