FIM, the openldapXMA and MD5 passwords

I had a problem today setting userPassword in openLDAP 3, using the openldapXMA on FIM 2010. I needed to encode the password with MD5 and it looks like there is a change with the .NET libraries running on Windows 2008 x64.

I’ve had a few problems with the published examples on Md5 encoding, and was side-tracked for a while by some forum threads which seemed to indicate you had to use UTF7 encoding for it to work. Once it was pointed out to me that only passwords with simple ASCII characters were syncing correctly then it was clear I had to look futher.

In the end the solution was simple – you can UTF8 encode the password, but you have to remember to return the hash in a Base64 string. This apparently has something to do with running on a 64-bit OS, which of course FIM does.

        public string GenerateMD5Hash(string myString)
        {
            MD5 md5 = System.Security.Cryptography.MD5.Create();
            byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(myString);
            byte[] hash = md5.ComputeHash(inputBytes);
            return Convert.ToBase64String(hash);
        }

Then, when setting the initial userPassword in your provisioning code:

        CSEntry("userPassword").Value = "{MD5}" & GenerateMD5Hash("FirstP@ssword")

Password Sync

It is simple enough to modify the openldapXMA Password Extension to set the hashed password.

In OpenLDAPUtils.cs add the GenerateMD5Hash function I included above.

Then change the SetPassword subroutine in the same file:

        public void SetPassword(string newPassword, CSEntry csentry)
        {
            DirectoryAttributeModification pwdChange = new DirectoryAttributeModification();

            pwdChange.Name = "userPassword";
            // CW: Changed to use an MD5 hash
            // pwdChange.Add(newPassword);
            pwdChange.Add("{MD5}" + GenerateMD5Hash(newPassword));
            pwdChange.Operation = DirectoryAttributeOperation.Replace;

            ModifyRequest request = new ModifyRequest(csentry.DN.ToString(), pwdChange);
            try
            {
                DirectoryResponse response = m_Ldap.SendRequest(request);
            }
            catch (Exception e)
            {
                MiisExceptionsManager.ReportErrorToMiis(e.Message);

            }

        }