Active Directory unicodePwd

In case anyone else ever needs this:

You can change the password of an Active Directory account by changing the unicodePwd attribute (or setting it, for that matter, for new accounts). However, you have to jump through some security hoops.

First, you have to use TLS (and if you're using OpenLDAP clients, make sure that TLS_CACERT in your ldap.conf points to the right root cert). Since you're using TLS, if you're using GSSAPI, you need to tell GSSAPI not to negotiate a security or privacy layer since AD doesn't support nested security or privacy layers. (Dumb.) The magic incantation for ldap.conf is SASL_SECPROPS minssf=0,maxssf=0.

Then you need to set the attribute. Windows uses little-endian UCS-2 as the character set (which they, unhelpfully, call "Unicode" in all their articles, as if there's only one Unicode encoding). Perl, for example, defaults to big-endian UCS-2 if you just say to use UCS-2.

The password also has to be enclosed in double-quotes. The double-quotes aren't part of the password. I have no idea why Windows does this.

So, to transform the password in a Perl script into the string that AD wants, try: encode("ucs-2le", qq{"$password"}). (This assumes you're using the Encode module that comes with Perl 5.8 and takes care of the charset issues for you.) Then, if you're putting that password in LDIF (because, for instance, you're piping it into ldapadd), you need to base64-encode it. Use MIME::Base64 and then call the encode_base64 function. Finally, you can take the resulting string and put it into the LDIF as:

unicodePwd:: <base64-encoded-string>

It took Ross and I far too long to figure this out. Ross found the last key detail in some web site where the person was byteswapping the encoded output to get around the little- vs. big-endian problem.

Posted: 2007-07-12 21:13 — Why no comments?

Thank you! This was very useful :)

BTW: On Linux, if you have the recode utility installed, you can use the following shell command to generate the unicodePwd value:

echo -n '"mypassword"' | recode latin1..utf-16le/base64

(assuming that the password is in latin-1).

Posted by Markku at 2007-12-19 11:13

Last modified and spun 2017-11-30