We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you a podcast all about Citrix Workspace, moving to the cloud, and analytics & intelligence. Episode 2 coming soon!Listen Now


Use DirectorySearcher to check if a password is in the password history

hberenson asked
Medium Priority
Last Modified: 2012-06-21
Is it possible to use the DirectorySearcher to check if a password is in the user's password history?  I assume I want to query against the AD's ntpwdhistory property.  Of course, those passwords are encrypted.  So do I have to encrypt the password before I try to send in the search, or is DirectorySearcher (or rather, the underlying api) smart enough to do this for me?  Other ideas on how to accomplish this?
Watch Question

Ouch!   This can probably be done... but it will definately be a "non-trival" task.   It will require a lot of low-level (and undocumented) API calls.

The solution will look nothing like a familiar framework DirectorySearcher solution!

The "bible" of low-level APIs is Windows NT/2000 Native API Reference (http://www.amazon.com/gp/product/1578701996/sr=8-1/qid=1143038091/ref=pd_bbs_1/102-6485229-5903316?%5Fencoding=UTF8)

That's not possible. In the ntPwdHistory attribute, password history is stored in OWF format. You cannot derive the clear password out of the attribute nor you can compare with any form of string. If you happen to find anything that could do that, it's certainly not supported by $MS.

I post some comments in your Q in W2K3 TA. I hope it can help you in solving this problem.

Graye, the book looks very interesting. I think I'm gonna buy it :o)


Hmmm.  My root problem is that a call to change the password is silently failing (i.e. appears to succeed) if the password is on the history list.  So how do I tell the user that their change was unsuccessful?  Should it be returning an error?

This is someone elses code, so I need to take a closer look and post a code fragment.

>> My root problem is that a call to change the password is silently failing...
Silently failing is not a normal behaviour of ADSI. When a change password failed because of any reason, it should returns an error message, something like this.

"Logon failure: unknown user name or bad password"

As you can see, the message is vague and is not telling anything about the nature of the error. So you're pretty out of luck if you want to distinguish whether the problem is caused of wrong user name or password, or domain password complexity violation, or the password is already listed in the password history.

Btw, can you post the piece of code that's failing? maybe someone could see something not obvious that's causing the problem.


Slightly edited code is below.  Note that no error is ever trapped.

On Error GoTo errhandler

Dim objPerson As IADsUser
Dim objContainer As IADsContainer
Dim szConnString As String
Dim objLdap As IADsOpenDSObject
objLdap = GetObject("LDAP:")
szConnString="LDAP://CN="& szSAMAccountName &",OU="& sOU & "," & ADRoot
objLdap = GetObject("LDAP:")
' Get a container object from the connection string.
objPerson = objLdap.OpenDSObject(szConnString, _
                                                     ADUsername, _
                       ADPassword, _
With objPerson
        .SetPassword (sPassword)
        .AccountDisabled = False
End With
Response.Redirect("/Support/UnSuccessful.aspx?LogID=" & Log(Err.Description, "ResetPassword", szSAMAccountName, -1))



Some more testing has revealed this is even more interesting than originally described.  The above code DOES change the password even if it is on the password history list.  On the other hand, if it violates the password complexity rules then it traps to errhandler.
Obviously the code is about resetting a password, not changing a password. The SetPassword method disregard password age and password history policies, but it does check on password complexity. If your objective is to provide a facility for your users to change their password, you should then use ChangePassword method instead.


Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts


Thanks!  The guy who did this used the same function both for reset password and change password; he just validated the old password before calling this function in the case of a user doing a change password.  I'll create a new function that uses the changepassword method.
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.