Cambio de una contraseña de usuario de Windows Active Directory y LDS mediante LDAP

En este artículo se describe cómo cambiar una contraseña de usuario de Windows Active Directory y LDS mediante LDAP.

Se aplica a: Windows Active Directory
Número de KB original: 269190

Resumen

En función de ciertas restricciones, puede establecer una contraseña de Windows Active Directory y Lightweight Directory Services (LDS) a través del Protocolo ligero de acceso a directorios (LDAP). En este artículo se describe cómo establecer o cambiar el atributo de contraseña.

Estos pasos también se aplican al modo de aplicación de Active Directory (ADAM) y a los usuarios LDS y a los objetos userProxy de la misma manera que se hace con los usuarios de AD. Consulte sugerencias adicionales al final del artículo para obtener más información.

Más información

La contraseña se almacena en la base de datos AD y LDS en un objeto de usuario en el atributo unicodePwd . Este atributo se puede escribir en condiciones restringidas, pero no se puede leer. El atributo solo se puede modificar; no se puede agregar al crear objetos ni consultarlo una búsqueda.

Para modificar este atributo, el cliente debe tener una conexión de seguridad de la capa de transporte (TLS) de 128 bits/Capa de sockets seguros (SSL) al servidor. Una sesión cifrada con claves de sesión creadas por SSP mediante Windows New Technology LAN Manager (NTLM) o Kerberos también es aceptable siempre y cuando se cumpla la longitud mínima de la clave.

Para que esta conexión sea posible mediante TLS/SSL:

  • El servidor debe poseer un certificado de servidor para una conexión RSA de 128 bits.
  • El cliente debe confiar en la entidad de certificación (CA) que generó el certificado de servidor.
  • Tanto el cliente como el servidor deben ser capaces de cifrado de 128 bits.

La sintaxis del atributo unicodePwd es octeto-cadena; sin embargo, el servicio de directorio espera que la cadena octeto contendrá una cadena UNICODE (como indica el nombre del atributo). Esto significa que los valores de este atributo pasados en LDAP deben ser cadenas UNICODE codificadas en BER (reglas de codificación básicas) como octeto-cadena. Además, la cadena UNICODE debe comenzar y terminar entre comillas que no forman parte de la contraseña deseada.

Hay dos maneras posibles de modificar el atributo unicodePwd . La primera es similar a una operación de cambio de contraseña de usuario normal. En este caso, la solicitud de modificación debe contener tanto una operación de eliminación como una operación de adición. La operación de eliminación debe contener la contraseña actual con comillas alrededor de ella. La operación de adición debe contener la nueva contraseña deseada con comillas alrededor de ella.

La segunda manera de modificar este atributo es análoga a la de un administrador que restablece una contraseña para un usuario. Para ello, el cliente debe enlazarse como usuario con permisos suficientes para modificar la contraseña de otro usuario. Esta solicitud de modificación debe contener una operación de reemplazo única con la nueva contraseña deseada entre comillas. Si el cliente tiene permisos suficientes, esta contraseña se convierte en la nueva contraseña, independientemente de cuál fuera la contraseña anterior.

Las dos funciones siguientes proporcionan ejemplos de estas operaciones:

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

Sugerencia

  • Para configurar instancias LDS mediante objetos UserProxy para el restablecimiento de contraseña, debe permitir la delegación restringida de la cuenta de servicio LDS (predeterminada: cuenta de equipo LDS) a los controladores de dominio en caso de que el inicio de sesión del usuario use Kerberos.
  • Si usa el enlace simple ldap, debe usar Windows Server 2022 o una versión más reciente y establecer una entrada del Registro para reenviar las credenciales de sesión LDAP de administrador al controlador Dominio de Active Directory:
    Clave del Registro: HKLM\system\currentcontrolset\services<LDS Instance>\Parameters
    Entrada del Registro: Permitir tipo de inicio de sesión de ClearText
    Tipo: REG_DWORD
    Datos: 0: No permitir el reenvío de credenciales (valor predeterminado)
              1: Permitir el reenvío de credenciales para el restablecimiento de contraseña
  • Tenga en cuenta que el cambio en ambos casos significa que el servidor LDS debe considerarse un dispositivo de nivel 0, ya que puede iniciar tareas sensibles a la seguridad en el controlador de dominio.

Se aplica a

  • Windows Server 2012 Datacenter
  • Windows Server 2012 Standard
  • Windows Server 2012 R2 Centro de datos
  • 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