Hi everyone,
(I sent this question in august last year, but had no replies. Trying
once again as I'm running into the same problem).
While playing with Ldap, Squirrelmail and an Active Directory server I
ran into a limitation of the PHP ldap_modify function.
In general, an (non-PHP) ldap_modify will allow you to add, replace and
delete several attributes for a DN in one single transaction. The PHP
Ldap extension is based on OpenLDAP, and this functionality is indeed
available in OpenLDAP [1]. It takes a null-terminated array of
modify-structs as it's main argument, and one of the entries of these
structs is the type of operation that is requested: add, replace or delete.
The PHP ldap_modify works a bit different: it takes a single array of
attributes and values. A normal value and attribute combination will
replace the current value for the attribute. An empty value for an
attribute will cause the attribute to be deleted ('replaced by
nothing'). In fact, in PHP the ldap_modify is just an alias for the
function ldap_modify_replace.
In almost all cases this is hardly an issue and one can use several
seperate ldap_modify statements in sequence. But sometimes, there is a
real need for the complete ldap_modify functionality. Imagine for
instance the LDIF statement below:
dn: cn=test,cn=users,dc=test,dc=local
changetype: modify
delete: unicodePwd
unicodePwd:: IgBvAGwAZABwAGEAcwBzAHcAbwByAGQAIgA=
add: unicodePwd
unicodePwd:: IgBuAGUAdwBwAGEAcwBzAHcAbwByAGQAIgA=
With this statement I delete one specific value from a (write-only)
attribute, and at the same time add a new one. This happens to be the
way to allow a 'mere' user to change their Active Directory password via
Ldap [2]. By supplying the old password (as BER encoded wchars), the
user shows that they actually know the old password and are permitted to
remove it, and set a new one. This, of course, has to be done in a
single transaction. And a simple Ldap replace operation won't suffice
here, either.
So I'm happily plodding along extending the change_ldappass plugin for
Squirrelmail, and one by one I get rid of all the obstacles [3]. Except
for this last one: it simply can't be done in PHP. Works from the
command-line or perl, but not here.
My suggestion (or request): extending the PHP ldap_modify statement to
work similar to most other ldap_modify's out there. Unfortunately,
because currently ldap_modify and ldap_modify_replace are simply the
same function, doing this properly requires a bit of thought in order
not to break existing applications. But I feel having a 'complete'
ldap_modify in PHP is something worth having, not just in the one case
illustrated above.
Possible solutions:
- Extend the current ldap_modify to take more arguments, like so:
bool ldap_modify (resource link_identifier, string dn, array add-entry
[, array replace-entry, array delete-entry]);
ldap_modify should behave like presently, except when the two extra
arrays are present.
-
Go for a clean break and make ldap_modify a seperate function from
ldap_modify_replace once again. The data to be modified could be either
passed as three single arrays, or an array with an extra 'dimension' to
specify the kind of operation to be performed, e.g.
$entry["add"]["attribute"][0] = value
$enrty["add"]["attribute"][1] = value
$entry["delete"]["attribute"][0] = value
$entry["replace"]["attribute"][0] = value
etc. -
Create a new function, e.g. ldap_modify_complete that is separate
from the current ldap_modify and uses one of the syntaxes described above.
What would the 'proper' way be to accomplish this change? Assuming the
developpers share my view of it being neccesary?
I've looked at the ldap.c source and actually implementing this doesn't
seem too much of a challenge.
Regards, Paul Boven.
[1] http://www.openldap.org/software/man.cgi?query=ldap_modify
[2] http://support.microsoft.com/?kbid=269190
[3] In brief: building PHP with OpenLDAP and SSL support, importing the
AD's certificate into OpenSSL, building OpenLDAP with SSL support (and
GSSAPI is helpfull too), figuring out the 'encoding' for the passwords.