Alterar uma senha de usuário do Windows Active Directory e LDS por meio do LDAP

Este artigo descreve como alterar uma senha de usuário do Windows Active Directory e LDS por meio do LDAP.

Aplica-se a: Windows Active Directory
Número original do KB: 269190

Resumo

Com base em determinadas restrições, você pode definir uma senha do Windows Active Directory e dos Serviços de Diretório Leve (LDS) por meio do Protocolo de Acesso ao Diretório Leve (LDAP). Este artigo descreve como definir ou alterar o atributo de senha.

Essas etapas também se aplicam ao Adam (Modo de Aplicativo do Active Directory) e aos usuários do LDS e aos objetos userProxy da mesma forma que feita com os usuários do AD. Confira dicas adicionais no final do artigo para obter detalhes.

Mais informações

A senha é armazenada no banco de dados AD e LDS em um objeto de usuário no atributo unicodePwd . Esse atributo pode ser gravado em condições restritas, mas não pode ser lido. O atributo só pode ser modificado; ele não pode ser adicionado na criação de objeto ou consultado por uma pesquisa.

Para modificar esse atributo, o cliente deve ter uma conexão TLS (Segurança de Camada de Transporte) de 128 bits/SSL (Secure Socket Layer) com o servidor. Uma sessão criptografada usando chaves de sessão criadas por SSP usando o NTLM (Windows New Technology LAN Manager) ou Kerberos também é aceitável desde que o comprimento mínimo da chave seja atendido.

Para que essa conexão seja possível usando o TLS/SSL:

  • O servidor deve possuir um certificado de servidor para uma conexão RSA de 128 bits.
  • O cliente deve confiar na autoridade de certificado (AC) que gerou o certificado do servidor.
  • O cliente e o servidor devem ser capazes de criptografia de 128 bits.

A sintaxe do atributo unicodePwd é octet-string; no entanto, o serviço de diretório espera que a cadeia de caracteres octet contenha uma cadeia de caracteres UNICODE (como o nome do atributo indica). Isso significa que todos os valores para esse atributo passado em LDAP devem ser cadeias de caracteres UNICODE codificadas por BER (Regras Básicas de Codificação) como uma cadeia de caracteres de octet. Além disso, a cadeia de caracteres UNICODE deve começar e terminar entre aspas que não fazem parte da senha desejada.

Há duas maneiras possíveis de modificar o atributo unicodePwd . O primeiro é semelhante a uma operação de senha de alteração de usuário regular. Nesse caso, a solicitação de modificação deve conter uma operação de exclusão e adição. A operação de exclusão deve conter a senha atual com aspas ao seu redor. A operação de adição deve conter a nova senha desejada com aspas ao seu redor.

A segunda maneira de modificar esse atributo é análoga a um administrador redefinindo uma senha para um usuário. Para fazer isso, o cliente deve associar como usuário com permissões suficientes para modificar a senha de outro usuário. Essa solicitação de modificação deve conter uma única operação de substituição pela nova senha desejada cercada por aspas. Se o cliente tiver permissões suficientes, essa senha se tornará a nova senha, independentemente da senha antiga.

As duas funções a seguir fornecem exemplos dessas operações:

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;
}

Dica

  • Para configurar instâncias LDS usando objetos UserProxy para redefinições de senha, você precisa permitir a delegação restrita da conta de serviço LDS (padrão: conta de computador LDS) para os controladores de domínio caso o logon do usuário use Kerberos.
  • Se você estiver usando a associação simples LDAP, precisará usar o Windows Server 2022 ou uma versão mais recente e definir uma entrada de registro para encaminhar as credenciais de sessão LDAP de administrador para o Controlador Domínio do Active Directory:
    Chave do Registro: HKLM\system\currentcontrolset\services<LDS Instance>\Parameters
    Entrada do Registro: permitir o tipo de logon ClearText
    Tipo: REG_DWORD
    Dados: 0: não permitir o encaminhamento de credenciais (Padrão)
              1: permitir o encaminhamento de credenciais para redefinição de senha
  • Observe que a alteração em ambos os casos significa que o servidor LDS deve ser considerado um dispositivo de Camada 0, pois pode iniciar tarefas sensíveis à segurança no Controlador de Domínio.

Aplicável a

  • 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