Active Directory LDAP PwdLastSet attribute

M

martybruce

I have some VB.net code.

Basically when the user logs into the app. It checks to see if the
user's AD account password has expired. If so, It will prompt the
user to change it.

mydn = GetDN(txtUsername.Text)

Dim adsPath As String = "LDAP://" & mydn
objUser = New DirectoryEntry(adsPath, txtUsername.Text,
txtOld.Text)
objUser.Invoke("ChangePassword", New Object()
{Trim(txtOld.Text),Trim(txtNew.Text)})
objUser.CommitChanges()

This will change the users password.... if the account password is not
expired. Basically it can't log into AD to change the password
because of the expiration. I could use an admin accout to change. But
I want to use this to verify the users old password for security.

If I could find away to set the PwdLastSet attribute to a date less
than 90 days ago before I tried to set the password, I would be
golden.

I have tried to set the userAccountControl to a value of &H10000,
which is suppose to set the account never to expire. But that is not
working. I think because the group policy of taking priority over the
local account setting.

I have seen plenty of code to set the PwdLastSet to zero to force the
account to expire. Has anyone been able to translate the 64int back
into a date?


Thanks for your help....
 
M

martybruce

I have someVB.netcode.

Basically when the user logs into the app. It checks to see if the
user's AD accountpasswordhasexpired. If so, It will prompt the
user to change it.

mydn = GetDN(txtUsername.Text)

Dim adsPath As String = "LDAP://" & mydn
objUser = New DirectoryEntry(adsPath, txtUsername.Text,
txtOld.Text)
objUser.Invoke("ChangePassword", New Object()
{Trim(txtOld.Text),Trim(txtNew.Text)})
objUser.CommitChanges()

This will change theuserspassword.... if the accountpasswordis notexpired. Basically it can't log into AD to change thepassword
because of the expiration. I could use an admin accout to change. But
I want to use this toverifytheusersoldpasswordfor security.

If I could find away to set the PwdLastSet attribute to a date less
than 90 days ago before I tried to set thepassword, I would be
golden.

I have tried to set the userAccountControl to a value of &H10000,
which is suppose to set the account never to expire. But that is not
working. I think because the group policy of taking priority over the
local account setting.

I have seen plenty of code to set the PwdLastSet to zero to force the
account to expire. Has anyone been able to translate the 64int back
into a date?

Thanks for your help....

My other option is to do something like....

Dim usr As DirectoryEntry = New DirectoryEntry
usr.Path = "LDAP://" & mydn
usr.AuthenticationType =
AuthenticationTypes.Secure
Dim password As Object() = New Object()
{txtNew.Text}
Dim ret As Object = usr.Invoke("SetPassword",
txtNew.Text)
usr.CommitChanges()
usr.Close()

Which will set the password without login credentials.

However.... How can I verify a users expired password? If the
password is expired, how can I check to see if the pwd is correct?
 
M

martybruce

My other option is to do something like....

Dim usr As DirectoryEntry = New DirectoryEntry
usr.Path = "LDAP://" & mydn
usr.AuthenticationType =
AuthenticationTypes.Secure
Dim password As Object() = New Object()
{txtNew.Text}
Dim ret As Object = usr.Invoke("SetPassword",
txtNew.Text)
usr.CommitChanges()
usr.Close()

Which will set the password without login credentials.

However.... How can I verify a users expired password? If the
password is expired, how can I check to see if the pwd is correct?

Ok... I got it.... You have to set the PwdLastSet to a -1... that will
make the account's pwdlastset date to today's date... If the password
fails to change, it will relock the account

Here is my code if it might help someone...

'---------------------------------------------------------
'Unexpire the password so the user can setup
Dim usr As DirectoryEntry = New DirectoryEntry
usr.Path = "LDAP://" & mydn 'mydn is equal
to CN=fname lname,CN=Users,DN=yourcompany,DN=com
'usr.AuthenticationType =
AuthenticationTypes.Secure
usr.Properties("pwdLastSet").Value = -1
usr.CommitChanges()
'-----------------------------------------------

'-----------------------------------------------
'Set the Password
Dim adsPath As String = "LDAP://" & mydn
Dim objUser1 As DirectoryEntry
objUser1 = New DirectoryEntry(adsPath,
txtUsername.Text, txtOld.Text)
objUser1.Invoke("ChangePassword", New Object()
{txtOld.Text, Trim(txtNew.Text)})
objUser1.CommitChanges()
'If it fails, it will reexpire the account

'------------------------------------------------------------

errlbl2.Text = "Your Password has been
Changed"

Catch ex As Exception
errlbl2.Text = "Password Change FAILED. Either
your old password was incorrect or new password was too simular to
your name or an old password."

'ReExpire the Account
Dim mydn2 = GetDN(txtUsername.Text)
Dim usr As DirectoryEntry = New DirectoryEntry
usr.Path = "LDAP://" & mydn2
usr.AuthenticationType =
AuthenticationTypes.Secure
usr.Properties("pwdLastSet").Value = 0
usr.CommitChanges()
'Done expiring
 
C

cab0san

I know it's nothing new, but it's really handy to use the SearchResult
class to get long integers without using the COM classes.
Make sure you load the searcher with the properties you need...

something like this snippett...

Dim sr As DirectoryServices.SearchResult

.... do some search

Dim lastset As Long = sr.Properties("pwdlastset")(0)

Dim dateLastSet as Date = Date.FromFileTimeUtc(lastset)

.... and thanks for your post, it has helped!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top