2012-12-23 1 views
2

Cela fait quelques jours que je suis perplexe. J'ai essayé différentes solutions en vain. S'il vous plaît aider ...Modifier le mot de passe AD à l'aide de PHP/COM/ADSI/LDAP

Problème: Nous avons deux contrôleur de domaine, qui ne sont pas sous notre gestion. Nous sommes en mesure de se connecter via LDAP sur le port 389, mais ne pouvons pas se connecter en toute sécurité sur le port 636.

Nous développons un système permettant un certain nombre d'installations en libre-service, dont un outil de récupération de mot de passe. Cela fonctionne jusqu'à réinitialiser le mot de passe des utilisateurs.

J'ai trouvé un code via the PHP manual qui semble faire ce dont nous avons besoin, mais je n'arrive pas à le faire fonctionner.

C'est le code que j'ai donc loin

if ($caller==="change"){ 
if (($newPword1 === NULL)||($newPword1 === "")){ return false;} 
if (($newPword2 === NULL)||($newPword2 === "")){ return false;} 
if ($newPword1 != $newPword2) { 
    $result["ERROR"]="1"; 
    $result["DETAILS"]="Your new password and the confirmation must match!"; 
    exit(); 
} 
try { 
    $adldap = new adLDAP(); 
} catch (adLDAPException $e) { 
    $result["ERROR"]="1"; 
    $result["DETAILS"]="An error occurred in adLDAP"; 
    echo json_encode($result); 
    exit(); 
} 

$userinfo = $adldap->user()->info($username, array("givenname","dn","lockouttime")); 
$res = $userinfo[0]["lockouttime"]; 
$userDN = $userinfo[0]["dn"]; 
$firstName = $userinfo[0]["givenname"]; 
$authUser = $adldap->authenticate($username,$currentPword); 
if ($authUser){ 
    try { 
     $adminUsername = $domain."\\".$adminUsername; 
     $srvDN = "LDAP://".$server."/"; 

     try { 
      $ADSI = new COM("LDAP:"); 
     } catch (exception $e){ 
      $result["ERROR"]="1"; 
      $result["ERRORmsg"]=$e->getMessage(); 
      echo json_encode($result); 
      exit(); 
     } 
     try { 
      $user = $ADSI->OpenDSObject($srvDN.$userDN, $adminUsername, $adminPassword, 1); 
     } catch (exception $e){ 
      $result["ERROR"]="2"; 
      $result["ERRORmsg"]= $e->getMessage(); 
      echo json_encode($result); 
      exit(); 
     } 
     try { //set password 
      if ($user){ 
       $result["object"]="Success"; 
      } else { 
       $result["object"]="Failed"; 
      } 
      $user->SetPassword($newPword1); //line:114 -> error occurring on this line 
      $user->SetInfo(); 
      $result["ERROR"]="0"; 
      $result["DETAILS"]="Thank you $firstName[0]<br><strong>Your password has been changed</strong><br><br>This may take up to 30 minutes to take effect depending on your location"; 
     } catch (exception $e) { 
      $result["ERROR"]="3"; 
      $result["ERRORmsg"]=$e." - ".$e->getMessage(); 
      $result["DETAILS"]="An Error Occurred."; 
     } 
     unset($user); 
     unset($ADSI); 
    } catch (exception $e){ 
     $result["ERROR"]="1"; 
     $result["DETAILS"]="An Error Occurred in the ADSI COM"; 
     echo json_encode($result); 
     exit(); 
    } 
} else { 
    if ($res[0] != "0"){ 
     $result["ERROR"]="1"; 
     $result["DETAILS"]="Im sorry $firstName[0].<br>Your account is now locked. Please contact the IT Service Desk for advice"; 
    } else { 
     $result["ERROR"]="1"; 
     $result["DETAILS"]="Im sorry $firstName[0].<br>Your current password is incorrect"; 
    } 
} 

Dans les tests $result["object"] retours "succès". Mais le code semble échouer sur la ligne $user->SetPassword($newPword1);.

L'erreur qui est renvoyée est:

ERROR -> "3" 
object -> "Success" 
ERRORmsg -> "exception 'com_exception' with message '<b>Source:</b> Unknown<br/><b>Description:</b> Unknown' in C:\inetpub\wwwroot\<path>\<filename>.php:114 
Stack trace: 
#0 C:\inetpub\wwwroot\<path>\<filename>.php(114): variant->SetPassword('[email protected]') 
#1 {main} - <b>Source:</b> Unknown<br/><b>Description:</b> Unknown" 
DETAILS -> "An Error Occurred." 

Le code ci-dessus est dans un php doc sur un serveur Web IIS qui est appelé par une page visible de l'utilisateur via https

Êtes-vous en mesure de offrir des conseils ou des conseils?

+1

Je suis assez sûr que AD est assez difficile de ne pas mettre les mots de passe sur LDAP en texte clair. Vous en avez besoin pour activer SSL sur LDAP. – geoffc

+1

Avez-vous essayé phpLdapAdmin? –

+0

** UPDATE 29 décembre 12 à 16: 46 ** J'ai pu prouver depuis que 'new COM (" LDAP: ")' s'initialise avec succès et '$ ADSI-> OpenDSObject' ouvre avec succès l'objet AD. J'ai essayé contre d'autres comptes AD utilisateur et le script échoue sur la même ligne ** Dec 29 '12 à 17:57 ** ont remplacé '$ user-> SetPassword ($ newPword1);' avec '$ user-> Put ("pwdLastSet", 0); 'et il a correctement mis à jour l'attribut AD approprié. Donc, cela montre que la connexion ADSI fonctionne – ChrisM

Répondre

1

Je fais à peu près la même chose et je l'ai maintenant fait fonctionner, au moins lors du ciblage d'un serveur 2k8R2 DC.

Je ne sais pas pourquoi vous obtenez l'échec que vous êtes, mais deux ou trois choses que j'ai trouvé utile sont:

1) Dans votre gestionnaire catch() récupérer l'erreur renvoyée de SetPassword() , le processus et l'afficher comme suit

$rawErr = $e->getCode(); 
$processedErr = $rawErr + 0x100000000; 
printf('Error code 0x%x', $processedErr); 

Ensuite, voir si vous pouvez trouver la liste here. Vous pouvez également trouver this utile.

2) Essayez de faire varier l'appel de SetPassword() à ChangePassword(). Cela nécessite que vous saisissiez également l'ancien mot de passe mais que vous ayez des exigences de privilèges moins strictes sur le contrôleur de domaine. Si vous pouvez obtenir que cela fonctionne, il pourrait suggérer que votre problème avec SetPassword() est que le compte administrateur que vous utilisez pour authentifier dans l'appel OpenDSObject() n'a pas les privilèges suffisants sur le domaine cible. Un mot d'avertissement cependant à propos de ChangePassword() qui est que, contrairement à SetPassword(), la politique de mot de passe est strictement appliquée. Vous devez donc prendre en compte des éléments tels que l'âge et la complexité du mot de passe, ainsi que l'historique. Je suis venu décoller sur ce dernier.

Très bonne chance, Ian.

+0

Salut Ian, Merci pour l'entrée. En réponse: 1) Je vais ajouter dans le code d'erreur supplémentaire. De mémoire le code d'erreur retourné n'était pas dans la liste selfADSI, je pense qu'il était -215 ... mais vérifiera et confirmera ceci. 2) Le compte de service que j'utilise a des privilèges d'administrateur de domaine. Ce niveau sera réduit à des privilèges élevés sur les objets utilisateur une fois que le code fonctionnera. Instructions des pouvoirs en place, une vérification stricte est en place pour appliquer la politique de mot de passe de domaine. Je travaille sur une solution SASL/GSS-API/Kerberos. Est-ce que le code postal une fois de travail. Comment avez-vous obtenu le vôtre? – ChrisM

0

J'ai trouvé que le système d'exploitation que vous utilisez a un impact direct sur l'utilisation de ce code. Je faisais mon travail de développement sur mon bureau en utilisant une version locale IIS (Windows 7 Enterprise, IIS 7.5) et je continuais à courir dans cette erreur inconnue.

Cependant, une fois que j'ai testé mon code de réinitialisation de mot de passe ADSI sur un serveur réel (Windows Server 2008 R2), cela a fonctionné parfaitement.


Pour référence: Le code d'erreur que je suis arrivé (en utilisant la réponse de Ian) était 0x80020009 qui semble être lié à cette question: (Registering a dll returns 0x80020009 error)

Ainsi, tout ce qui va mal semble être plus profond que ADSI et PHP/COM.

REMARQUE: Comme chrismale, j'ai pu utiliser la connexion ADSI pour demander des informations l'échec ne se produisait que quand j'ai essayé d'utiliser SetPassword()

Questions connexes