locked
How to Check User Password has been expired. RRS feed

  • Question

  • Hi,

    Today I implemented Password Policy and forget to set "Password never expires" for one important users. after implementing policy within one minute i set the option for that user.  Policy is implemented successfully , That User is not logged in so,  Is there any way that i can check whether password for that user has been expired or not . When I run query that user exist in password never expire list.

    Regards

    Usman Ghani


    Usman Ghani - MCITP Exchange 2010

    Sunday, November 24, 2013 4:27 PM

Answers

  • You said the user shows up in query for "never expire list."

    This user ALWAYS will show up in that list, because you told us that YOU set that user "one minute after you implmented the policy." If  you set the user for "password never expires," then the user ALWAYS will show up in the query for "pwd never expire list." I am not understanding what you need to do. Please give more clear information. Otherwise, the below script will list all users whose password is set to "never expire."

    Please remember to "Mark as Answer," if this resolves your issue. You may mark more than one answer, if more than one person answers your question.

    Save as something like c:\scripts\pwdnoexpire.vbs

    Change directory to that folder: cd/d c:\scripts

    Run like this: cscript pwdnoexpire.vbs

    Sorry - I had to modify the below script so it only writes out lines IF "pwdexpired" = "YES"

    So it is now updated, with the "ofile.writeline" in the correct place.

    Once script is done, type: "notepad pwdneverexpires.csv"

    And that will open it and let you quickly check it.

    If you have LARGE number of passwords not expiring, you also can open the file in Excel and sort it.

    Set WshShell = WScript.CreateObject("WScript.Shell") strVer = "Ver 1.0 " Set FileSystem = WScript.CreateObject("Scripting.FileSystemObject") Set oFile = FileSystem.CreateTextFile("PWDNeverExpires.csv", true) strDomain = WshShell.ExpandEnvironmentStrings("%USERDOMAIN%") strUserName = WshShell.ExpandEnvironmentStrings("%USERNAME%") strOS = WshShell.ExpandEnvironmentStrings("%OS%") strMessage = strMessage & "Hit Cancel to quit" strTitle = "Domain to Search" 'Get Domain Name UserDomain = InputBox(strMessage, strTitle, strDomain) strMessage = "" strTitle = "" strMessage = "This may take a few minutes. . ." WshShell.Popup strMessage,2,"One moment please. . . " strMessage = "" Set objDomain = GetObject("WinNT://" & UserDomain) objDomain.Filter = Array("User") For Each objUser In objDomain 'Attempt to bind to the user Set UserName = GetObject("WinNT://"& UserDomain &"/"& objUser.Name &",User") 'Check password attribute objPwdExpires = UserName.Get("UserFlags") If (objPwdExpires And &H10000) <> 0 Then objPwdExpiresTrue = "Yes" strPwdExpires = "Date Set: " msgPwdExpires = "Password Set to Never Expire: "

      oFile.WriteLine (UserName.fullname & "," & UserName.name & "," & msgPwdExpires &  objPwdExpiresTrue & "," & strPwdExpires & objUser.PasswordExpirationDate)

    Else objPwdExpiresTrue = "No" strPwdExpires = "Password Expires: " msgPwdExpires = "Password Set to Never Expire: " End If Set UserName = Nothing Next Wscript.Echo "Password Check Complete"

    SOURCE OF THE ABOVE SCRIPT:

    http://www.thedailyadmin.com/2009/05/vbscript-to-find-users-with-password.html


    tnjman





    • Edited by TNJMAN Sunday, November 24, 2013 5:03 PM unclear
    • Proposed as answer by Michael_LS Monday, December 2, 2013 1:19 AM
    • Marked as answer by Michael_LS Tuesday, December 3, 2013 6:47 AM
    Sunday, November 24, 2013 4:34 PM
  • "Password never expires" on an account will always take precedence over any password policy

    Enfo Zipper
    Christoffer Andersson – Principal Advisor
    http://blogs.chrisse.se - Directory Services Blog

    • Proposed as answer by Michael_LS Monday, December 2, 2013 1:19 AM
    • Marked as answer by Michael_LS Tuesday, December 3, 2013 6:48 AM
    Sunday, November 24, 2013 5:06 PM

All replies

  • You said the user shows up in query for "never expire list."

    This user ALWAYS will show up in that list, because you told us that YOU set that user "one minute after you implmented the policy." If  you set the user for "password never expires," then the user ALWAYS will show up in the query for "pwd never expire list." I am not understanding what you need to do. Please give more clear information. Otherwise, the below script will list all users whose password is set to "never expire."

    Please remember to "Mark as Answer," if this resolves your issue. You may mark more than one answer, if more than one person answers your question.

    Save as something like c:\scripts\pwdnoexpire.vbs

    Change directory to that folder: cd/d c:\scripts

    Run like this: cscript pwdnoexpire.vbs

    Sorry - I had to modify the below script so it only writes out lines IF "pwdexpired" = "YES"

    So it is now updated, with the "ofile.writeline" in the correct place.

    Once script is done, type: "notepad pwdneverexpires.csv"

    And that will open it and let you quickly check it.

    If you have LARGE number of passwords not expiring, you also can open the file in Excel and sort it.

    Set WshShell = WScript.CreateObject("WScript.Shell") strVer = "Ver 1.0 " Set FileSystem = WScript.CreateObject("Scripting.FileSystemObject") Set oFile = FileSystem.CreateTextFile("PWDNeverExpires.csv", true) strDomain = WshShell.ExpandEnvironmentStrings("%USERDOMAIN%") strUserName = WshShell.ExpandEnvironmentStrings("%USERNAME%") strOS = WshShell.ExpandEnvironmentStrings("%OS%") strMessage = strMessage & "Hit Cancel to quit" strTitle = "Domain to Search" 'Get Domain Name UserDomain = InputBox(strMessage, strTitle, strDomain) strMessage = "" strTitle = "" strMessage = "This may take a few minutes. . ." WshShell.Popup strMessage,2,"One moment please. . . " strMessage = "" Set objDomain = GetObject("WinNT://" & UserDomain) objDomain.Filter = Array("User") For Each objUser In objDomain 'Attempt to bind to the user Set UserName = GetObject("WinNT://"& UserDomain &"/"& objUser.Name &",User") 'Check password attribute objPwdExpires = UserName.Get("UserFlags") If (objPwdExpires And &H10000) <> 0 Then objPwdExpiresTrue = "Yes" strPwdExpires = "Date Set: " msgPwdExpires = "Password Set to Never Expire: "

      oFile.WriteLine (UserName.fullname & "," & UserName.name & "," & msgPwdExpires &  objPwdExpiresTrue & "," & strPwdExpires & objUser.PasswordExpirationDate)

    Else objPwdExpiresTrue = "No" strPwdExpires = "Password Expires: " msgPwdExpires = "Password Set to Never Expire: " End If Set UserName = Nothing Next Wscript.Echo "Password Check Complete"

    SOURCE OF THE ABOVE SCRIPT:

    http://www.thedailyadmin.com/2009/05/vbscript-to-find-users-with-password.html


    tnjman





    • Edited by TNJMAN Sunday, November 24, 2013 5:03 PM unclear
    • Proposed as answer by Michael_LS Monday, December 2, 2013 1:19 AM
    • Marked as answer by Michael_LS Tuesday, December 3, 2013 6:47 AM
    Sunday, November 24, 2013 4:34 PM
  • "Password never expires" on an account will always take precedence over any password policy

    Enfo Zipper
    Christoffer Andersson – Principal Advisor
    http://blogs.chrisse.se - Directory Services Blog

    • Proposed as answer by Michael_LS Monday, December 2, 2013 1:19 AM
    • Marked as answer by Michael_LS Tuesday, December 3, 2013 6:48 AM
    Sunday, November 24, 2013 5:06 PM
  • Or, I have 'agepwdrpt.bat' that runs 'agepwdrpt.vbs' script and outputs to a LOG.txt file.

    I think I "stole / borrowed" this code from various sources, including Mr. R. Mueller and then I tweaked it for my needs - don't forget to change the "MYDOMAIN.COM" lines to match YOUR environment!

    HINT: CHANGE THE "FILTER" LINE (65535), because that is the attribute for "never expire." You can comment out that line and see if it returns any expire info. Play around with that "FILTER" section - you can change the output log to include each person, with their "pwd expiration date," "last login time," "pwd last set date," etc. - so, also
    change OUTPUT LOG to include those above-mentioned fields you desire to see in the log.

    rem - save this as c:\scripts\agepwdrpt.bat
    rem - after the below 'agepwdrpt.vbs' also is saved, run: rem - c:\scripts\agepwd.bat rem rem This is "agepwdrpt.bat" (it invokes agepwdrpt.vbs) @echo off %systemroot%\system32\cscript.exe c:\scripts\agepwdrpt.vbs > c:\scripts\agepwdrpt-LOG.txt rem - END of agepwdrpt.bat 'CREDIT: R. Mueller and others - this script is a mix ' of pieces from R. Mueller & other authors, tweaked ' to meet my needs for reporting AD password expiry info ' 'This is agepwdrpt.vbs (the above .bat file runs this. ' Save this as c:\scripts\agepwdrpt.vbs ' ' agepwdrpt.vbs ' VBScript to find all user accounts where the password ' is about to expire in a specified number of days. ' Option Explicit Dim adoCommand, adoConnection, strBase, strFilter, strAttributes, strUserDN, strGrpName Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, objUser Dim dtmDate1, dtmDate2, intDays, strName, strEmail Dim lngSeconds1, str64Bit1, lngSeconds2, str64Bit2 Dim objShell, lngBiasKey, lngBias, k Dim objDomain, objMaxPwdAge, lngHighAge, lngLowAge, sngMaxPwdAge Dim objDate, dtmPwdLastSet, dtmExpires Dim arrEmails, strItem, strPrefix ' Specify number of days. Any users whose password expires within this many days after today will be processed. intDays = 7 ' Determine domain maximum password age policy in days. Set objRootDSE = GetObject("LDAP://RootDSE") strDNSDomain = objRootDSE.Get("DefaultNamingContext") Set objDomain = GetObject("LDAP://" & strDNSDomain) Set objMaxPwdAge = objDomain.MaxPwdAge ' Account for bug in IADslargeInteger property methods. lngHighAge = objMaxPwdAge.HighPart lngLowAge = objMaxPwdAge.LowPart If (lngLowAge < 0) Then lngHighAge = lngHighAge + 1 End If ' Convert from 100-nanosecond intervals into days. sngMaxPwdAge = -((lngHighAge * 2^32) _ + lngLowAge)/(600000000 * 1440) ' Determine the password last changed date such that the password ' would just now be expired. We will not process users whose ' password has already expired. dtmDate1 = DateAdd("d", - sngMaxPwdAge, Now()) ' Determine the password last changed date such that the password ' will expire intDays in the future. dtmDate2 = DateAdd("d", intDays - sngMaxPwdAge, Now()) ' Obtain local Time Zone bias from machine registry. ' This bias changes with Daylight Savings Time. Set objShell = CreateObject("Wscript.Shell") lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\" _ & "TimeZoneInformation\ActiveTimeBias") If (UCase(TypeName(lngBiasKey)) = "LONG") Then lngBias = lngBiasKey ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then lngBias = 0 For k = 0 To UBound(lngBiasKey) lngBias = lngBias + (lngBiasKey(k) * 256^k) Next End If ' Convert the datetime values to UTC. dtmDate1 = DateAdd("n", lngBias, dtmDate1) dtmDate2 = DateAdd("n", lngBias, dtmDate2) ' Find number of seconds since 1/1/1601 for these dates. lngSeconds1 = DateDiff("s", #1/1/1601#, dtmDate1) lngSeconds2 = DateDiff("s", #1/1/1601#, dtmDate2) ' Convert the number of seconds to a string ' and convert to 100-nanosecond intervals. str64Bit1 = CStr(lngSeconds1) & "0000000" str64Bit2 = CStr(lngSeconds2) & "0000000" ' Setup ADO objects. Set adoCommand = CreateObject("ADODB.Command") Set adoConnection = CreateObject("ADODB.Connection") adoConnection.Provider = "ADsDSOObject" adoConnection.Open "Active Directory Provider" Set adoCommand.ActiveConnection = adoConnection ' Search entire Active Directory domain. strBase = "<LDAP://" & strDNSDomain & ">" ' Filter on user objects where the password expires between the ' dates specified, the account is not disabled, password never ' expires is not set, password not required is not set, ' and password cannot change is not set. strFilter = "(&(objectCategory=person)(objectClass=user)" _ & "(pwdLastSet>=" & str64Bit1 & ")" _ & "(pwdLastSet<=" & str64Bit2 & ")" _ & "(!userAccountControl:1.2.840.113556.1.4.803:=2)" _ & "(!userAccountControl:1.2.840.113556.1.4.803:=65536)" _ & "(!userAccountControl:1.2.840.113556.1.4.803:=32)" _ & "(!userAccountControl:1.2.840.113556.1.4.803:=48))" ' Comma delimited list of attribute values to retrieve. strAttributes = "distinguishedName,sAMAccountName,mail,proxyAddresses,pwdLastSet" ' Construct the LDAP syntax query. strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree" adoCommand.CommandText = strQuery adoCommand.Properties("Page Size") = 100 adoCommand.Properties("Timeout") = 30 adoCommand.Properties("Cache Results") = False ' Run the query. Set adoRecordset = adoCommand.Execute ' Enumerate the resulting recordset. Do Until adoRecordset.EOF ' Retrieve values. strUserDN = adoRecordset.Fields("distinguishedName").Value strName = adoRecordset.Fields("sAMAccountName").Value strEmail = adoRecordset.Fields("mail").Value & "" arrEmails = adoRecordset.Fields("proxyAddresses").Value If (strEmail = "") And (IsNull(arrEmails) = False) Then ' Select primary email address. For Each strItem In arrEmails strPrefix = Left(strItem, 5) If (strPrefix = "SMTP:") Or (strPrefix = "X400:") Then strEmail = Mid(strItem, 6) Exit For End If Next End If ' Determine when password expires. ' The pwdLastSet attribute should always have a value assigned, ' but other Integer8 attributes representing dates could be "Null". If (TypeName(adoRecordset.Fields("pwdLastSet").Value) = "Object") Then Set objDate = adoRecordset.Fields("pwdLastSet").Value dtmPwdLastSet = Integer8Date(objDate, lngBias) Else dtmPwdLastSet = #1/1/1601# End If dtmExpires = DateAdd("d", sngMaxPwdAge, dtmPwdLastSet) If (strEmail <> "") Then ' Send an email message to the user ' Wscript.Echo "strEmail = " & strEmail Set objUser = GetObject("LDAP://" & strUserDN) strGrpName = "Maintenance" 'Write ALL users pwdlast changed & pwd expires to a list 'Uncomment line below to get age report for ALL USERS" ' Wscript.Echo strName & "^ Password expires: ^" & CStr(dtmExpires) & "^ Last changed: ^" & dtmPwdLastSet If IsMember(strGrpName) Then Call SendEmailMessage(strEmail, strName, dtmExpires) Wscript.Echo strName & "^ Message SENT to ^" & strEmail & "^ in Group: ^" & strGrpName Else ' Wscript.Echo strName & "^ Message NOT SENT to ^" & strEmail & "^ Not a member of ^" & strGrpName End If Else Wscript.Echo strName & "^ NO EMAIL ADDRESS!" End If ' Move to the next record in the recordset. adoRecordset.MoveNext Loop ' Clean up. adoRecordset.Close adoConnection.Close Function Integer8Date(ByVal objDate, ByVal lngBias) ' Function to convert Integer8 (64-bit) value to a date, adjusted for ' local time zone bias. Dim lngAdjust, lngDate, lngHigh, lngLow lngAdjust = lngBias lngHigh = objDate.HighPart lngLow = objDate.LowPart ' Account for error in IADsLargeInteger property methods. If (lngLow < 0) Then lngHigh = lngHigh + 1 End If If (lngHigh = 0) And (lngLow = 0) Then lngAdjust = 0 End If lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _ + lngLow) / 600000000 - lngAdjust) / 1440 ' Trap error if lngDate is ridiculously huge. On Error Resume Next Integer8Date = CDate(lngDate) If (Err.Number <> 0) Then On Error GoTo 0 Integer8Date = #1/1/1601# End If On Error GoTo 0 End Function Sub SendEmailMessage(ByVal strDestEmail, ByVal strNTName, ByVal dtmDate) ' Send email message. Dim objMessage If (strDestEmail = "") Then Exit Sub End If Set objMessage = CreateObject("CDO.Message") objMessage.Subject = "WARNING! Please change your Windows password soon. Your password will expire on " & CStr(dtmDate) ' Hard code sender email address. objMessage.From = "administrator@MYDOMAIN.COM" objMessage.To = strDestEmail objMessage.TextBody = "As part of the " & strGrpName & " group, you are being notified if your password expires in " & intDays & " days or less. " & vbcrlf _ & "The password for your account: " & strNTName _ & ", will expire on: " & CStr(dtmDate) & vbcrlf _ & vbcrlf & "Please log into Webmail (or log onto a workstation) and change your password." objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/sendusing")=2 'Name or IP of remote SMTP server objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/smtpserver") _ ="MYSMTP-SERVER.MYDOMAIN.COM" 'Server port objMessage.Configuration.Fields.Item _ ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") _ =25 objMessage.Configuration.Fields.Update objMessage.Send End Sub '-------------------------------------------------------- ' IsMember Function '-------------------------------------------------------- Function IsMember(strGroup) ' Function to test one user for group membership. ' objUser is the user object with global scope. ' strGroup is the NT Name of the group to test. ' objGroupList is a dictionary object with global scope. ' Returns True if the user is a member of the group. Dim objGroup, objGroupList If IsEmpty(objGroupList) Then Set objGroupList = CreateObject("Scripting.Dictionary" ) objGroupList.CompareMode = vbTextCompare For Each objGroup In objUser.Groups objGroupList(objGroup.sAMAccountName) = True Next End If IsMember = objGroupList.Exists(strGroup) End Function ' ' END of agepwdrpt.vbs


    tnjman

    Sunday, November 24, 2013 7:38 PM