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

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?
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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 (
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)
hberensonAuthor Commented:
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.
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

>> 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.
hberensonAuthor Commented:
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))

hberensonAuthor Commented:
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.


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
hberensonAuthor Commented:
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.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.