I'm desiging a scripting language binding for interfacing with AD
(and other LDAP services). Currentlyy the target language is PHP but I
will likey be doing Python as well as possibly others. Anyway I thought
I would consult the community before writing this up so if you have the
time (this is somewhat lengthy) I would apprecitate your feedback.

The only requirements for the binding is that it have full coverage WRT
getting, modifying, adding, deleting, and searching and that it be
as simple as possible but no simpler as one would expect when using a
scripting language.

The simplest "getting" case is easy. You create an associative array with
the names of the attributes you're interested in and call a function that
returns an associative array of attributes with values. Consider the
following script:

  $attrs = array("userPrincipalName", "userAccountControl");
  $acct = account_get(NULL, "[EMAIL PROTECTED]", $attrs);
  echo "userPrincipalName: " . $acct['userPrincipalName'] . "\n";
  echo "userAccountControl: " . $acct['userAccountControl'] . "\n";

This might print:

  userPrincipalName: [EMAIL PROTECTED]
  userAccountControl: 544

This doesn't address data type issues however. How do I specify that
an attribute is a string, binary and/or multivalued? It seems there are
three solutions to this.

1) Create a local database of metadata indicating that an attribute is
multivalued or not and string or binary. This is pretty much what Java's
JNDI does (albeit somewhat clumsey IMO).

2) Provide functions to query the context object such as account_get_str
or account_get_binary, account_get_multivalued_str, .. etc. This is
pretty much what the Microsoft ADSI providers do.

3) Provide attribute modifiers with the attribute names array to tell
the binding to construct arrays for multivalued attributes, convert
strings, etc.

The first option is a reasonable solution.  The second option seems like
it's not "as simple as possible but not simpler" as it is tantamount to
explicit type casting and the scriptor is required to repeatedly assert
the type by using the approriate function.  The third option is nice
because the objects are automatically typed correctly.

If we explore the 3rd option, consider the following code that prints
all memberOf attributes:

  $attrs = array("multivalued(memberOf)");
  $acct = account_get(NULL, "[EMAIL PROTECTED]", $attrs);
  $mos = $acct['memberOf'];
  foreach ($mos as $mo) {
      echo "memberOf: $mo\n";

The key part above is the "multivalued(...)" function-like modifier
which indicates that $acct['memberOf'] should be an array of strings.
A function-like modifier is used to clearly separate it from existing
attribute modifiers like 'jpegPhoto;binary' that are passed through to
the raw LDAP api.

If no attribute modifiers or function-like modifers are specified the
attribute is assumed to be a string and will be converted from UTF-8 to
the locale encoding. To specify a multivalued binary array is desired
one would use "multivalued(name;binary)".

This method is also extensible. There could be function-like modfiers
for converting values to base64 or converting a binary sid to a sid
string (this would not be reasonable with the first option). Consider
the following example:

  $attrs = array("userPrincipalName",
  $acct = account_get(NULL, "[EMAIL PROTECTED]", $attrs);
  foreach ($acct as $name => $value) {
      if (!is_array($value)) {
          echo "$name: $value\n";
      } else {
          foreach ($value as $v) {
              echo "$name: $v\n";

This might print the following:

  userPrincipalName: [EMAIL PROTECTED]
  objectGUID: Szm2n2e8M0SA1Hz0QGgOnw==
  objectSid: S-1-5-21-4133388447-792352518-2001609813-1159
  memberOf: CN=Managers,CN=Users,DC=example,DC=com
  memberOf: CN=CMS Admin,CN=Users,DC=example,DC=com

To modify an entry the $attrs array is reused like:

  $attrs = array("distingushedName", "displayName");
  $acct = account_get(NULL, "[EMAIL PROTECTED]", $attrs);
  $acct['displayName'] = "James T. Kirk";
  account_modify(NULL, $acct, $attrs);

Searching might look like the following:

  $attrs = array("userPrincipalName", "multivalued(memberOf)");
  $accts = account_search(NULL,
              "DC=example,DC=com", "sub", $attrs, "(objectClass=user)");
  foreach ($accts as $acct) {
      echo "userPrincipalName: " . $acct['userPrincipalName'] . "\n";
      $mos = $acct['memberOf'];
      foreach ($mos as $mo) {
          echo "  memberOf: $mo\n";

So what do you think? Does anyone see any problem with any of this? Does
anyone have any ideas for improvments?

Thanks for your time,

Michael B Allen
PHP Active Directory SSO
List info   : http://www.activedir.org/List.aspx
List FAQ    : http://www.activedir.org/ListFAQ.aspx
List archive: http://www.mail-archive.com/activedir@mail.activedir.org/

Reply via email to