簡體   English   中英

使用 PHP 腳本更改 Active Directory 用戶密碼

[英]Changing Active Directory user password with PHP script

我正在嘗試使用一個非常簡單的PHP腳本來更改我的Active Directory域中的用戶密碼

這是我在網上找到的一些腳本:

<?php
$uid = 'Mohammed Noureldin';
$newPassword = '5omeGoodP@ssword';
$bindDn = 'CN=Administrator,OU=UsersOU,DC=example,DC=local';
$bindPassword = 'An0therGoodP@ssword';
$baseDn = 'OU=UsersOU,DC=example,DC=local';
$protocolVersion = 3;

$ldap = ldap_connect('localhost');
if (!ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, $protocolVersion))
{
    exit('Failed to set protocol version to '.$protocolVersion);
}
// bind anonymously so that we can verify if the server really is running
ldap_bind($ldap);
if (ldap_errno($ldap) !== 0)
{
    exit('Could not connect to LDAP server');
}

// now bind with the correct username and password
ldap_bind($ldap, $bindDn, $bindPassword);
if (ldap_errno($ldap) !== 0)
{
    exit('ERROR: '.ldap_error($ldap));
}

$searchResults = ldap_search($ldap, $baseDn, 'cn='.$uid);
// no matching records
if ($searchResults === false)
{
    exit('No user found');
}

if (!is_resource($searchResults))
{
    exit('Error in search results.');
}
// create the unicode password
$len = strlen($newPassword);
$newPass = '"';
for ($i = 0; $i < $len; $i++)
{
    $newPass .= "{$newPassword{$i}}\000";
}
$newPass .= '"';

$entry = ldap_first_entry($ldap, $searchResults);
if (!is_resource($entry))
{
    exit('Couldn\'t get entry');
}
$userDn = ldap_get_dn($ldap, $entry);
if (!$userDn)
{
exit('Errrrrrrrrr1');

}
if (!ldap_modify($ldap, $userDn, array('unicodePwd' => $newPass)))
{
exit(ldap_errno($ldap)." ". ldap_error($ldap));

}
?>

此 PHP 頁面的輸出是此錯誤消息:

53 服務器不願意執行

並且腳本根本不起作用(用戶的密碼沒有更改)。

我知道 AD 將密碼存儲在 unicodePwd 字段中的主要原則(如果到目前為止仍然如此),並且我知道我必須使用安全連接並且我正在使用它(希望它正確設置)。

我在谷歌上搜索了該錯誤消息,但找不到任何功能解決方案。

我還嘗試了一些其他腳本,但這是迄今為止最好的腳本,因為其他腳本在之前的某些步驟中給了我一些錯誤(例如綁定)。

我真的很感謝任何幫助解決這個問題,或者甚至另一個功能腳本可能是一個好主意! 提前致謝。

除非您通過 SSL/TLS 連接,否則您不得使用此方法更改密碼。 如果您在 Google 或 Bing 上搜索unicodePwd一詞,因為您已經將其包含在您的帖子中,那么第一個(如果不是一個)結果將是unicodePwdMSDN 文檔,它在前三個句子中說明:

此屬性由 LDAP Modify 在以下受限條件下寫入。 Windows 2000 操作系統服務器要求客戶端具有到 DC 的 128 位(或更好)SSL/TLS 加密連接才能修改此屬性。 在 Windows Server 2003 操作系統、Windows Server 2008 操作系統、Windows Server 2008 R2 操作系統、Windows Server 2012 操作系統、Windows Server 2012 R2 操作系統和 Windows Server 2016 Technical Preview 操作系統上,DC 還允許修改 unicodePwd受 128 位(或更好)簡單身份驗證和安全層 (SASL) 層加密而不是 SSL/TLS 保護的連接上的屬性。 在 Windows Server 2008、Windows Server 2008 R2、Windows Server 2012、Windows Server 2012 R2 和 Windows Server 2016 Technical Preview 中,如果 dSHeuristics 屬性的 fAllowPasswordOperationsOverNonSecureConnection 啟發式(第 6.1.1.2.4.1.2 節)為 true 並且 Active Directory作為 AD LDS 運行,則 DC 允許通過既不是 SSL/TLS 加密也不是 SASL 加密的連接修改 unicodePwd 屬性。 LDAP 搜索永遠不會返回 unicodePwd 屬性。

如果您只是對unicodePwd執行簡單的搜索,那么您將獲得的第一個結果之一是關於如何執行此操作的STEP BY STEP CODE

https://support.microsoft.com/en-us/kb/269190

意識到我參加這個派對晚了一年; 但是在解決類似問題的同時發現了這篇文章......

懷疑 ldaps 正在/正在提供托管此 php 腳本(linux?)的服務器不信任的證書; OP 提到已更改代碼以使用 ldaps 並退出('無法連接到 LDAP 服務器'); 但是通過 Apache Directory Studio 連接正常,它可能位於信任證書的機器上(即信任 DC 的加入域的工作站)。

要正確解決此問題,請調查您的私鑰基礎結構(一個大主題,從這里開始: https : //social.technet.microsoft.com/wiki/contents/articles/2980.ldap-over-ssl-ldaps-certificate.aspx

或者,只需告訴 php 服務器信任 LDAP 自簽名證書,請參見: Authenticating a self-signed certificate for LDAPS connection

要在開始之前驗證這種情況(即不建議在生產中使用),請考慮在 php 主機(假定為 linux 服務器)上配置 LDAP,以通過執行 put 忽略由證書頒發機構/信任引起的錯誤

TLS_REQCERT never

在/etc/ldap/ldap.conf末尾(更改后重啟apache/webserver)

正如 Ryan Ries 所指出的,您必須建立安全連接才能更改密碼,但您發布的代碼並沒有這樣做。

有問題的代碼是:

$ldap = ldap_connect('localhost');

如您所見,這會造成不安全的連接。

要建立安全連接,您需要指定一個 LDAPS URI:

$ldap = ldap_connect('ldaps://localhost');

您創建的 unicode 密碼錯誤。 這是至少適用於我在 Server 2012 上的代碼。

// create the unicode password
$newpassword = "\"" . $newpassword . "\"";
$len = strlen($newpassword);
for ($i = 0; $i < $len; $i++) $newpass .= "{$newpassword{$i}}\000";
$entry["unicodePwd"] = $newpass;

// Modify the password
if (ldap_mod_replace($ldap, $userDn, $entry))
{
  exit("Successfully updated password!");
}

請注意我如何使用新密碼對 " 進行編碼,這就是讓它為我工作的技巧。

$server = "ldaps://172.1.200.1:636";
$dn = "dc=srv,dc=world";
$message = array();

function changePassword($server,$dn,$user,$oldPassword,$newPassword,$newPasswordCnf){
  global $message;

  error_reporting(0);
  putenv('LDAPTLS_REQCERT=allow');
  $con=ldap_connect($server);
  ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
  ldap_set_option($con, LDAP_OPT_REFERRALS, 0);

  $findWhat = array ("cn","mail");
  $findWhat = array();
  $findWhere = $dn;
  $findFilter = "(sAMAccountName=$user)";

  $ldaprdn = 'mydomain' . "\\" . $user;
  $ldapbind = ldap_bind($con, $ldaprdn, $oldPassword);
  if ($ldapbind) {
      $message[] = "ldapbind  ($ldapbind) with sAMAccountName=$user";
  } else {
    $error = ldap_error($con);
    $errno = ldap_errno($con);
    $message[] = "ldapbind error $errno - $error";
    ldap_close($con);
    return false;
  }
  $sr = ldap_search($con,$dn,$findFilter,$findWhat);
  $records = ldap_get_entries($con, $sr);

 if ($records["count"] != "1") {
    $message[] = "Error E100 - Wrong user or password.";
    return false;
  }else {
    $message[] = "Found user <b>".$records[0]["cn"][0]." DN=".$records[0]["dn"]." </b>". print_r($records[0],true);
  }


  $entry = array();
  #seems a more correct way that handles complicated characters
  $entry["unicodePwd"] = iconv("UTF-8", "UTF-16LE", '"' . $newPassword . '"');
  # base64_encode is only needed in ldif text files !
  #$entry["unicodePwd"] = base64_encode($newPassw);

  $result = ldap_modify($con,$records[0]["dn"],$entry);
  if ($result === false){
    $message[] = $newpass.",".$entry["unicodePwd"]." Your password was not changed . with:".print_r($result, true);
    $error = ldap_error($con);
    $errno = ldap_errno($con);
    $message[] = "$errno - $error";
  }
  else {
    $message[] = " Your password has been changed. ";
    //mail($records[0]["mail"][0],"Password change notice : ".$user,"Your password has just been changed.");
    }
ldap_close($con);
}

我正在將 SAMBA 4.11 作為 AD/DC 運行,並且不得不使用ldap_modify_batch來使其正常工作。

$modifs = [
            [
                    "attrib"  => "unicodePwd",
                    "modtype" => LDAP_MODIFY_BATCH_REMOVE,
                    "values"  => [iconv("UTF-8", "UTF-16LE", '"' . $curPassword . '"')],
            ],
            [
                    "attrib"  => "unicodePwd",
                    "modtype" => LDAP_MODIFY_BATCH_ADD,
                    "values"  => [iconv("UTF-8", "UTF-16LE", '"' . $newPassword . '"')],
            ],
    ];
    $result = ldap_modify_batch($ldapconn, $dn, $modifs);
    error_log("Batch modify result:".print_r($result, true));
    $errorMessage = ldap_errno($ldapconn)." ". ldap_error($ldapconn);
    error_log("$errorMessage:".$errorMessage);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM