Microsoft KB Archive/269190

= How To Change a Windows 2000 User's Password Through LDAP =

Article ID: 269190

Article Last Modified on 6/29/2004

-

APPLIES TO


 * Microsoft Windows 2000 Server
 * Microsoft Windows 2000 Advanced Server
 * Microsoft Windows 2000 Professional Edition
 * Microsoft Windows 2000 Datacenter Server

-



This article was previously published under Q269190



SUMMARY
You can set a Windows 2000 user's password through the Lightweight Directory Access Protocol (LDAP) given certain restrictions. This article describes how to set or change the password attribute.



MORE INFORMATION
The password is stored in the Active Directory on a user object in the unicodePwd attribute. This attribute can be written under restricted conditions, but it cannot be read. The attribute can only be modified; it cannot be added on object creation or queried by a search. In order to modify this attribute, the client must have a 128-bit Secure Socket Layer (SSL) connection to the server. For this connection to be possible, the server must possess a server certificate for a 128-bit RSA connection, the client must trust the certificate authority (CA) that generated the server certificate, and both client and server must be capable of 128-bit encryption.

The syntax of the unicodePwd attribute is octet-string; however, the directory service expects that the octet-string will contain a UNICODE string (as the name of the attribute indicates). This means that any values for this attribute passed in LDAP must be UNICODE strings that are BER-encoded (Basic Encoding Rules) as an octet-string. In addition, the UNICODE string must begin and end in quotes that are not part of the desired password.

There are two possible ways to modify the unicodePwd attribute. The first is similar to a normal &quot;user change password&quot; operation. In this case, the modify request must contain both a delete and an add operation. The delete operation must contain the current password with quotes around it. The add operation must contain the desired new password with quotes around it.

The second way to modify this attribute is analogous to an administrator resetting a password for a user. In order to do this, the client must bind as a user with sufficient permissions to modify another user's password. This modify request should contain a single replace operation with the new desired password surrounded by quotes. If the client has sufficient permissions, this password become the new password, regardless of what the old password was.

The following two functions provide examples of these operations: 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&quot;unicodePwd&quot;; 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&quot;unicodePwd&quot;; 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&quot;\&quot;%s\&quot;&quot;,pszNewPassword); wsprintf(pszOldPasswordWithQuotes,L&quot;\&quot;%s\&quot;&quot;,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&quot;\nPassword succesfully changed!\n&quot;); else wprintf(L&quot;\nPassword change failed!\n&quot;);

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&quot;unicodePwd&quot;; 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&quot;\&quot;%s\&quot;&quot;,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&quot;\nPassword succesfully set!\n&quot;); else wprintf(L&quot;\nPassword set failed!\n&quot;);

return err; }

Keywords: kbhowto kbmsg KB269190

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.