LDAP を使用して Windows Active Directory と LDS のユーザー パスワードを変更する

この記事では、LDAP を使用して Windows Active Directory と LDS のユーザー パスワードを変更する方法について説明します。

適用対象: Windows Active Directory
元の KB 番号: 269190

概要

特定の制限に基づいて、ライトウェイト ディレクトリ アクセス プロトコル (LDAP) を使用して、Windows Active Directory およびライトウェイト ディレクトリ サービス (LDS) パスワードを設定できます。 この記事では、パスワード属性を設定または変更する方法について説明します。

これらの手順は、AD ユーザーと同じ方法で Active Directory アプリケーション モード (ADAM) と LDS ユーザーと userProxy オブジェクトにも適用されます。 詳細については、記事の最後にある追加のヒントを参照してください。

詳細

パスワードは、 unicodePwd 属性のユーザー オブジェクトの AD データベースと LDS データベースに格納されます。 この属性は、制限された条件下で書き込むことができますが、読み取ることはできません。 属性は変更することしかできません。オブジェクトの作成時に追加したり、検索でクエリを実行したりすることはできません。

この属性を変更するには、クライアントにサーバーへの 128 ビットトランスポート層セキュリティ (TLS)/Secure Socket Layer (SSL) 接続が必要です。 Windows New Technology LAN Manager (NTLM) または Kerberos を使用して SSP によって作成されたセッション キーを使用した暗号化されたセッションも、最小キーの長さが満たされている限り許容されます。

TLS/SSL を使用してこの接続を可能にするには、次のようにします。

  • サーバーは、128 ビット RSA 接続用のサーバー証明書を所有している必要があります。
  • クライアントは、サーバー証明書を生成した証明機関 (CA) を信頼する必要があります。
  • クライアントとサーバーの両方が 128 ビット暗号化に対応している必要があります。

unicodePwd 属性の構文は octet-string です。ただし、ディレクトリ サービスは、オクテット文字列に UNICODE 文字列が含まれていることを想定しています (属性の名前が示すように)。 つまり、LDAP で渡されるこの属性の値は、BER でエンコードされた UNICODE 文字列 (基本エンコード規則) をオクテット文字列として指定する必要があります。 さらに、UNICODE 文字列は、目的のパスワードの一部ではない引用符で始まり、終わる必要があります。

unicodePwd 属性を変更するには、2 つの方法があります。 1 つ目は、通常のユーザー変更パスワード操作に似ています。 この場合、変更要求には削除操作と追加操作の両方が含まれている必要があります。 削除操作には、引用符で囲まれた現在のパスワードが含まれている必要があります。 追加操作には、引用符で囲まれた目的の新しいパスワードが含まれている必要があります。

この属性を変更する 2 つ目の方法は、ユーザーのパスワードをリセットする管理者に似ています。 これを行うには、クライアントは、別のユーザーのパスワードを変更するための十分なアクセス許可を持つユーザーとしてバインドする必要があります。 この変更要求には、引用符で囲まれた新しい目的のパスワードで 1 回の置換操作が含まれている必要があります。 クライアントに十分なアクセス許可がある場合、このパスワードは、古いパスワードが何であったかに関係なく、新しいパスワードになります。

次の 2 つの関数は、これらの操作の例を示しています。

ULONG ChangeUserPassword(WCHAR* pszUserDN, WCHAR* pszOldPassword,WCHAR* pszNewPassword)
{
    ULONG err = 1;
    LDAPMod modNewPassword;
    LDAPMod modOldPassword;
    LDAPMod *modEntry[3];
    BERVAL newPwdBerVal;
    BERVAL oldPwdBerVal;
    BERVAL *newPwd_attr[2];
    BERVAL *oldPwd_attr[2];
    WCHAR pszNewPasswordWithQuotes[1024];
    WCHAR pszOldPasswordWithQuotes[1024];
    
    // Build an array of LDAPMod.
    
    // For setting unicodePwd, this MUST be a double op.
    modEntry[0] = &modOldPassword;
    modEntry[1] = &modNewPassword;
    modEntry[2] = NULL;
    
    // Build mod struct for unicodePwd Add.
    modNewPassword.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
    modNewPassword.mod_type =L"unicodePwd";
    modNewPassword.mod_vals.modv_bvals = newPwd_attr;
    
    // Build mod struct for unicodePwd Delete.
    modOldPassword.mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
    modOldPassword.mod_type =L"unicodePwd";
    modOldPassword.mod_vals.modv_bvals = oldPwd_attr;
    
    // Password will be single valued, so we only have one element.
    newPwd_attr[0] = &newPwdBerVal;
    newPwd_attr[1]= NULL;
    oldPwd_attr[0] = &oldPwdBerVal;
    oldPwd_attr[1]= NULL;
    
    // Surround the passwords in quotes.
    wsprintf(pszNewPasswordWithQuotes,L"\"%s\"",pszNewPassword);
    wsprintf(pszOldPasswordWithQuotes,L"\"%s\"",pszOldPassword);
    
    // Build the BER structures with the UNICODE passwords w/quotes.
    newPwdBerVal.bv_len = wcslen(pszNewPasswordWithQuotes) * sizeof(WCHAR);
    newPwdBerVal.bv_val = (char*)pszNewPasswordWithQuotes;
    oldPwdBerVal.bv_len = wcslen(pszOldPasswordWithQuotes) * sizeof(WCHAR);
    oldPwdBerVal.bv_val = (char*)pszOldPasswordWithQuotes;
    
    // Perform single modify.
    err = ldap_modify_s(ldapConnection,
    pszUserDN,
    modEntry
    );
    
    if (err == LDAP_SUCCESS )
    wprintf(L"\nPassword successfully changed!\n");
    else
    wprintf(L"\nPassword change failed!\n");
    
    return err;
}
    
ULONG SetUserPassword(WCHAR* pszUserDN, WCHAR* pszPassword)
{
    ULONG err = 1;
    LDAPMod modPassword;
    LDAPMod *modEntry[2];
    BERVAL pwdBerVal;
    BERVAL *pwd_attr[2];
    WCHAR pszPasswordWithQuotes[1024];
    
    // Build an array of LDAPMod.
    // For setting unicodePwd, this MUST be a single op.
    modEntry[0] = &modPassword;
    modEntry[1] = NULL;
    
    // Build mod struct for unicodePwd. 
    modPassword.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
    modPassword.mod_type =L"unicodePwd";
    modPassword.mod_vals.modv_bvals = pwd_attr;
    
    // Password will be single valued, so we only have one element.
    pwd_attr[0] = &pwdBerVal;
    pwd_attr[1]= NULL;
    
    // Surround the password in quotes.
    wsprintf(pszPasswordWithQuotes,L"\"%s\"",pszPassword);
    
    // Build the BER structure with the UNICODE password.
    pwdBerVal.bv_len = wcslen(pszPasswordWithQuotes) * sizeof(WCHAR);
    pwdBerVal.bv_val = (char*)pszPasswordWithQuotes;
    
    // Perform single modify.
    err = ldap_modify_s(ldapConnection,
    pszUserDN,
    modEntry
    );
    
    if (err == LDAP_SUCCESS )
    wprintf(L"\nPassword succesfully set!\n");
    else
    wprintf(L"\nPassword set failed!\n");
    
    return err;
}

ヒント

  • パスワード リセットに UserProxy オブジェクトを使用して LDS インスタンスを構成するには、ユーザー ログオンで Kerberos が使用されている場合に備えて、LDS サービス アカウント (既定: LDS コンピューター アカウント) をドメイン コントローラーに制限付き委任できるようにする必要があります。
  • LDAP 簡易バインドを使用している場合は、Windows Server 2022 以降のバージョンを使用し、管理者 LDAP セッション資格情報を Active Directory ドメイン コントローラーに転送するレジストリ エントリを設定する必要があります。
    レジストリ キー: HKLM\system\currentcontrolset\services<LDS Instance>\Parameters
    レジストリ エントリ: ClearText ログオンの種類を許可する
    種類: REG_DWORD
    データ: 0: 資格情報の転送を許可しない (既定値)
              1: パスワード リセットの資格情報の転送を許可する
  • どちらの場合もこの変更は、ドメイン コントローラーでセキュリティに依存するタスクを開始できるため、LDS サーバーを階層 0 デバイスと見なす必要があることを意味します。

適用対象

  • Windows Server 2012 Datacenter
  • Windows Server 2012 Standard
  • Windows Server 2012 R2 Datacenter
  • Windows Server 2012 R2 Standard
  • Windows Server 2016
  • Windows Server 2019
  • Windows Server 2022
  • Windows 8.1 Enterprise
  • Windows 8.1 Pro
  • Windows 10
  • Windows 11