objectGUID, objectSID, etc in Active Directory are handy identifiers and need to be dealt with better. Need an approach such at:

- determine binary values from ldap schema
- have a field that lists are the binary attributes

CommentFileSizeAuthor
#15 jpegphoto_binary.png243.1 KBpxljedi

Comments

cgmonroe’s picture

FYI - In D6's ldap_integration, I've added a "binary_puid" field / checkbox to the admin screen. I did this because there does not seem to be an clear cut way to determine if the puid attribute will be binary or string (it's all string to PhP and is_binary() function won't work until 6.0...).

Using that, I've created a couple of "helper" functions to "extract" the puid from an ldap entry and to create a ldap filter to find the LDAP object with a search.

Note that since AD is probably going to be the main use for binary PUIDs, I've done MS Style endian translations to the binary value. This makes it match what other LDAP/MS Tools display for a string value. This only happens for 16 bit binary values... if the binary is another size, it's just converted to a hex string.

Here's the helper function code I'm building D6's PUID support on (not in Git yet...)

/**
 * Extracts the puid value from an ldap search result with binary handling
 *
 * @param Mixed $server The server object or sid
 * @param Array $ldap_entry LDAP search or retrieveAttributes result for single dn.
 */
function ldapauth_extract_puid( $server, $ldap_entry ) {
  if ( is_numeric( $server )) {
    $server = ldapauth_server_load($server);
  }
  $puid = $ldap_entry[strtolower($server->puid_attr)][0];
  if ( $puid && $server->binary_puid ) {
    if (strlen($puid) == 16) {  // Assume a binary GUID ala MS
      $hex_string = bin2hex($puid);
      // (MS?) GUID are displayed with first three GUID parts as "big endian"
      // Doing this so String value matches what other LDAP tool displays for AD.
      $puid=strtoupper(substr( $hex_string, 6, 2) . substr( $hex_string, 4, 2) .
        substr( $hex_string, 2, 2) . substr( $hex_string, 0, 2) . '-' .
        substr( $hex_string, 10, 2) . substr( $hex_string, 8, 2) . '-' .
        substr( $hex_string, 14, 2) . substr( $hex_string, 12, 2) . '-' .
        substr( $hex_string, 16, 4) . '-' . substr( $hex_string, 20, 12));
    }
    else {
      $puid = bin2hex($puid);
    }
  }
  return $puid;
}
/**
 * Create a "binary safe" LDAP search filter for finding objects from puid.
 *
 * @param Mixed $server Server object or sid
 * @param String $puid The puid value from ldapauth_users
 */
function ldapauth_puid_filter( $server, $puid ) {
  if ( is_numeric( $server )) {
    $server = ldapauth_server_load($server);
  }
  $filter = $server->puid_attr . "=";
  $match = '';
  if ( $server->binary_puid ) {
    // Is it a simple Hex string
    if ( preg_match('/^[a-f0-9]+$/i', $puid ) ) {
      for ( $i=0; $i < strlen($puid); $i=$i+2 ) {
        $match .= '\\' . substr($puid, $i, 2);
      }
    }
    elseif ( preg_match('/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i', $puid)) {
      // Reconstruct proper "memory" order from GUID string.
      $hex_string = str_replace('-','',$puid);
      $puid = substr( $hex_string, 6, 2) . substr( $hex_string, 4, 2) .
        substr( $hex_string, 2, 2) . substr( $hex_string, 0, 2) .
        substr( $hex_string, 10, 2) . substr( $hex_string, 8, 2) .
        substr( $hex_string, 14, 2) . substr( $hex_string, 12, 2) .
        substr( $hex_string, 16, 4) . substr( $hex_string, 20, 12);
      for ( $i=0; $i < strlen($puid); $i=$i+2 ) {
        $match .= '\\' . substr($puid, $i, 2);
      }
    }
  }
  else {
    $match = $puid;
  }
  return $filter . $match;
}

johnbarclay’s picture

Thanks. this will be essential for the PUID implementation in 7.x. I hadn't thought about the need to query these PUIDs, but they are useless if they can't be queried. I looked through the adLDAP documentation and don't see them dealing with binary attributes at all (http://adldap.sourceforge.net/wiki/doku.php?id=documentation).

johnbarclay’s picture

Thanks for following through on this. Here's a related issue #1512562: Ldap query: views plugin throwing errors related to "ldap_views_plugin_query_ldap::$where" also. Seems like maybe an ldapAttribute class may be in order. I thought about an ldap attribute field type that has a binary flag, but most of the config forms aren't using entities and fields.

cgmonroe’s picture

Hmm, mapping ldap into an SQL based views engine seems like it would open up a never ending set of issues, performance headaches and the like.

I wonder if the time would be better spent creating an ldap field type with a matching sync. To use ldap data with views or any Drupal module you just create a content type with ldap fields. Then define how often you want them synced. Duplication of data but it limits where the disparate worlds meet and doesn't limit how ldap data can play in the Drupal node world.

Ideally, this (or any generic ldap attribute handler) probably should look at the LDAP schema to get data type and decide how to handle it base on this. But this needs to be cached in the DB since schema access is an expensive operation.

johnbarclay’s picture

The ldap_feeds module is for this sort of synching. It is going to have the same binary issues. If someone wants to keep the field data in an entity, they would use feeds to bring it in periodically. Then views to display it. The problem is feeds is a bit of work to set up.

The ldap_views module has its use case. It just needs some work to deal with binary fields.

I can see 2 useful fields:
1) ldap attribute configuration (attribute name, is binary, multiple values, sid).
2) ldap synch field as you described (ldap attribute configuration field options + synch options)

The ldap synch field could automatically be synched with no user configuration which is nice. But we would still need to set up synching with ldap user profile, ldap user properties, ldap user profile 2, etc fields. So I'm not sure if an ldap synch field would end up saving time.

maybe one of us should do a prototype of an ldap_synch field? I think it would be its own module, and not be in ldap_user or ldap_server.

figureone’s picture

I have a suggestion for dealing with binary attributes, and wanted some feedback from you guys. This method would be much easier to implement than building a separate ldapAttribute class, but as far as I can see it only applies to the Views integration with ldap_query.

Suggestion: when building an LDAP Query (/admin/config/people/ldap/query/add), there is a textarea field for "Attributes to return":
* Field: Attributes to return. (attributes_str)
* Desc: Enter as comma separated list. DN is automatically returned. Leave empty to return all attributes. e.g. objectclass,objectcategory,name,cn,samaccountname

In this field, when referring to binary attributes, we can suffix ";binary" to any attribute to indicate that it should be treated as binary. Then we can just base64_encode() those attributes so they don't cause problems.

Note 1: There's some precedent for doing things this way. See: this comment in an unrelated project.

Note 2: The patch submitted in #1512562: Ldap query: views plugin throwing errors related to "ldap_views_plugin_query_ldap::$where" created a specific check for the "jpegPhoto" field (which is always binary), and base64_encode()'s that field, but does not address any other binary fields.

Thoughts on this? If you guys approve I can start working on a patch that implements this.

johnbarclay’s picture

I think this convention makes sense for UIs where:
(1) the attribute names are entered in as text
(2) the attribute names are not stored in fields

johnbarclay’s picture

I think the binary qualifier needs to be more generic so it will be more useful throughout the ldap module. For example:

[jpegPhoto;tobase64] [jpegPhoto:0;tobase64] would signify converting to base64. each qualifier could be mapped directly to a function. eg.

[jpegPhoto:0;tobase64] would be processed by ldap_server_toBase64().

johnbarclay’s picture

7.x-2.0 release blocker

johnbarclay’s picture

Title: LDAP Server: Need method for dealing with binary attributes » LDAP *: Need method for dealing with binary attributes

Todos:

implement binary qualifier to ldap tokens
get ldap user interface to map qualifiers to checkboxes on UI (perhaps the binary flag needs to be a pull down to accomodate different types of binary conversions needed). Or maybe just take the checkbox out and have the token indicate conversion such as [uiuceduregistryuniqueid;tobase64]; then put the pulldown in later after this is all implemented.
implement hook_ldap_server_ldap_attr_value_alter() drupal alter function for a single ldap value which passes token flags (tobase64) and ldap entry.
implement ldap_server_ldap_server_ldap_attr_value_alter() function.
document in ui and .api file.

johnbarclay’s picture

Component: Code » SimpleTests

I implemented this as follows:

The following ldap tokens will work, where guid:0 is just an example attribute

  • [guid:0;base64_encode] = apply base64_encode() function to value
  • [guid:0;bin2hex] = apply bin2hex() function to value
  • [guid:0;msguid] = apply ldap_servers_msguid() function to value
  • [guid:0;binary] = apply ldap_servers_binary() function to value. this is the most generic binary function

Anything checked as binary in the ldap interfaces, will be treated as [guid:0;binary]

base64_encode and bin2hex just use the php functions.
msguid uses cgmonroe's current code for msguids
binary uses cgmonroe's code which determines what to do based on the length of the string.

ldap_servers_msguid() and ldap_servers_binary() are the two functions used for these.

I have unit tests for the tokens themselves in the most recent commit, but want more integration tests still. But please test if you have use cases for this.

johnbarclay’s picture

Assigned: Unassigned » johnbarclay
johnbarclay’s picture

Assigned: johnbarclay » Unassigned
pxljedi’s picture

StatusFileSize
new243.1 KB

Hi,

I've updated to the ldap-7.x-2.x-dev version of the LDAP module and I'm still having issues with jpegphoto coming in as binary.

See screen shot.

Any suggestions on how to fix?

Thanks! :)

Pxl

pxljedi’s picture

Hi,

I now know what the problem is, but am not certain how to fix it. When I looked at the source code for the img src, it's showing the html character code and not the < > around the img src.

How can I fix this so the image is rendering properly? I've looked in the ldap views files, but am not finding where the HTML is being stripped out.

If this can be fixed in the LDAP views, that would be preferable, but I would like to know how to fix if it's not going to be addressed in the module development.

Thanks for any and all help!

Pxl

figureone’s picture

Note: pxljedi's issue is addressed in another thread.

liam morland’s picture

A similar issue is being discussed in the cas_attributes module in #1929418: Don't run binary data, such as GUID, through check_plain().

larowlan’s picture

Issue summary: View changes
Issue tags: +Needs tests

Adding tag

grahl’s picture

Component: SimpleTests » Code
Status: Active » Closed (outdated)

If displaying binary data in Views with LDAP Query is still an issue, please open a separate issue, the rest seems to work fine as far as I can tell.