# PSPwdExpires.ps1 # PowerShell script to find all user accounts where the password # is about to expire in a specified number of days. # # ---------------------------------------------------------------------- # Copyright (c) 2011 Richard L. Mueller # Hilltop Lab web site - http://www.rlmueller.net # Version 1.0 - March 23, 2011 # Version 1.1 - April 6, 2011 - Added email function. # # This program assumes there is one password policy for the domain. The # program finds all users whose password will expire in the specified # period. # # You have a royalty-free right to use, modify, reproduce, and # distribute this script file in any way you find useful, provided that # you agree that the copyright owner above has no warranty, obligations, # or liability for such use. Trap {"Error: $_"; Break;} # Specify number of days. Any users whose passwords expire within # this many days after today will be processed. $intDays = 14 # Email settings. $Script:From = "myemailaddress@mydomain.com" $Script:Subject = "Password Expiration Notice" $Server = "smtp.mydomain.com" $Port = 25 $Client = New-Object System.Net.Mail.SmtpClient $Server, $Port # You may need to provide credentials. $Client.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials Function SendEmail($To, $Body) { $Message = New-Object System.Net.Mail.MailMessage ` $Script:From, $To, $Script:Subject, $Body $Client.Send($Message) } # Retrieve Domain maximum password age policy, in days. $D = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() $Domain = [ADSI]"LDAP://$D" $MPA = $Domain.maxPwdAge.Value # Convert to Int64 ticks (100-nanosecond intervals). $lngMaxPwdAge = $Domain.ConvertLargeIntegerToInt64($MPA) # Convert to days. $MaxPwdAge = -$lngMaxPwdAge/(600000000 * 1440) # Determine the password last changed date such that the password # would just now be expired. We will not process any users whose # password has already expired. $Now = Get-Date $Date1 = $Now.AddDays(-$MaxPwdAge) # Determine the password last changed date such the password # will expire $intDays in the future. $Date2 = $Now.AddDays($intDays - $MaxPwdAge) # Convert from PowerShell ticks to Active Directory ticks. $64Bit1 = $Date1.Ticks - 504911232000000000 $64Bit2 = $Date2.Ticks - 504911232000000000 $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.PageSize = 200 $Searcher.SearchScope = "subtree" # 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. $Searcher.Filter = "(&(objectCategory=person)(objectClass=user)" ` + "(pwdLastSet>=" + $($64Bit1) + ")" ` + "(pwdLastSet<=" + $($64Bit2) + ")" ` + "(!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))" $Searcher.PropertiesToLoad.Add("sAMAccountName") > $Null $Searcher.PropertiesToLoad.Add("pwdLastSet") > $Null $Searcher.PropertiesToLoad.Add("mail") > $Null $Searcher.PropertiesToLoad.Add("proxyAddresses") > $Null $Searcher.SearchRoot = "LDAP://" + $Domain.distinguishedName $Results = $Searcher.FindAll() ForEach ($Result In $Results) { $Name = $Result.Properties.Item("sAMAccountName") $PLS = $Result.Properties.Item("pwdLastSet") $Mail = $Result.Properties.Item("mail") $Addresses = $Result.Properties.Item("proxyAddresses") If ($PLS.Count -eq 0) { $Date = [DateTime]0 } Else { # Interpret 64-bit integer as a date. $Date = [DateTime]$PLS.Item(0) } # Convert from .NET ticks to Active Directory Integer8 ticks. # Also, convert from UTC to local time. $PwdLastSet = $Date.AddYears(1600).ToLocalTime() # Determine when password expires. $PwdExpires = $PwdLastSet.AddDays($MaxPwdAge) # Determine email address. If ("$Mail" -eq "") { ForEach ($Address In $Addresses) { $Prefix = $Address.SubString(0, 5) If (($Prefix -ceq "SMTP:") -or ($Prefix -ceq "X400:")) { $Mail = $Address.SubString(5) Break } } } If ("$Mail" -ne "") { $Notice = "Password for user $Name must be changed by $PwdExpires" SendEmail $Mail $Notice "Email sent to $Name ($Mail), password expires $PwdExpires" } Else { "$Name has no email, but password expires $PwdExpires" "DN: $DN" } }