PHP - Modifier le mot de passe Windows dans Active Directory

réf : http://msdn.microsoft.com/en-us/library/cc223248%28PROT.13%29.aspx
       http://support.microsoft.com/kb/263991/en-us


Comment modifier l'attribut unicodePwd en PHP avec les librairies LDAP ?

On trouve beaucoup de prose sur le sujet dans les forums, mais d'après mes essais, les snippets fournis fonctionnent plutôt mal.
Pourtant, en lisant la documentation de Microsoft, la démarche est assez claire :

  • l'attribut unicodePwd ne peut pas être mis à jour lors de la création d'une entrée, mais seulement en modification,
  • la connexion à Active Directory doit se faire en SSL (ldaps, sur le port 636 par défaut) (voir ici comment activer ldaps sur l'AD),
  • le mot de passe doit être encadré par deux double-quotes,
  • la chaîne de caractères obtenue doit être encodée en UTF-16,
  • le tout doit être encodé en BER (mais cette tâche est a priori réalisée par la bibliothèque LDAP de PHP lors de la soumission de la requête de modification).
Ce qui donne quelque chose d'assez simple finalement :

# Définition des constantes
define("LDAP_HOST", "ldaps://mon.active.directory/");
define("LDAP_PORT", 636);
define("LDAP_RDN", "CN=Administrateur,CN=Users,DC=mon,DC=active,DC=directory");
//  un compte Administrateur nécessaire pour écrire dans AD (ou simplement avec des droits d'administrateur)
define("LDAP_PASSWD", "Maude Passe");                           

# Fonction de connexion à l'AD.
# Cette fonction renvoie une connexion à l'AD.
function connect_AD() {
  $ldap_con = ldap_connect(LDAP_HOST, LDAP_PORT);
  ldap_set_option($ldap_con, LDAP_OPT_REFERRALS, 0);
         // option nécessaire pour une recherche depuis la racine du domaine le cas échéant
  ldap_set_option($ldap_con, LDAP_OPT_PROTOCOL_VERSION, 3);
        // option nécessaire pour une recherche sur AD
  ldap_bind($ldap_con, LDAP_RDN, LDAP_PASSWD);
        // bind nécessaire pour lire/écrire sur AD. Les options doivent être placées AVANT le bind.
  return $ldap_con;
}

# Fonction de mise à jour du mot de passe d'un DN.
function set_password($dn,$password) {
    $password = "\"".$password."\""; 
       
// On ajoute les double-quotes autour du password
    $entry['unicodePwd'] = mb_convert_encoding($password, "UTF-16LE"); 
         // On encode en UTF-16 (
    $ldap_con = connect_AD();
        // Connexion à l'AD
    $change = ldap_mod_replace($ldap_con, $dn, $entry);
        
// On modifie le mot de passe
    ldap_close($ldap_con);
    return $change;
       
// Retourne TRUE si le password a été modifié, FALSE sinon   
}

Cet exemple fonctionne même si vos utilisateurs choisissent des mots de passe avec des accents par exemple. Il faut juste s'assurer que tous les formulaires de soumission du mot de passe (pour modifier ce dernier ou les formulaires qui vont authentifier, comme CAS) soient encodés de la même façon (UTF-8 par exemple), chose que l'on pourra aisément faire en envoyant avant toute autre chose un header de déclaration de l'encodage :
header ('Content-Type: text/html; charset=utf-8');
Penser aussi bien sûr à l'encodage du source php dans l'éditeur (en utf-8 par exemple).
Comments