Notifica scadenza password al logon in Windows 7

notifypsw01

In Windows 7 la notifica della scadenza della password è visualizzata per qualche secondo nella barra inferiore dello schermo, in genere cinque giorni prima come default. Purtroppo la notifica non è molto visibile e se non si nota immediatamente, inevitabilmente la password di sistema scade pregiudicando la funzionalità dei servizi di rete.

notifypsw02

Per risolvere questo possibile inconveniente ed avere una notifica più chiara, è possibile visualizzare dei popup durante la fase di login e/o inviare una email direttamente nella casella dell’utente.

 

Visualizzare un popup al logon

Visualizzare un popup al logon può essere una prima soluzione. Questo può essere effettuato con uno script .vbs lanciato tramite GPO. Nello script utilizzato nell’esempio, la variabile warningDays determina quanti giorni prima visualizzare il popup di notifica.

'========================================
' First, get the domain policy.
'========================================
Dim oDomain
Dim oUser
Dim maxPwdAge
Dim numDaysA
Dim warningDays
warningDays = 14
Set LoginInfo = CreateObject("ADSystemInfo") 
Set objUser = GetObject("LDAP://" & LoginInfo.UserName & "") 

strDomainDN = UCase(LoginInfo.DomainDNSName) 
strUserDN = LoginInfo.UserName

Set oDomain = GetObject("LDAP://" & strDomainDN)
Set maxPwdAge = oDomain.Get("maxPwdAge")

'========================================
' Calculate the number of days that are
' held in this value.
'========================================
numDays = CCur((maxPwdAge.HighPart * 2 ^ 32) + _
maxPwdAge.LowPart) / CCur(-864000000000)
'WScript.Echo "Maximum Password Age: " & numDays

'========================================
' Determine the last time that the user
' changed his or her password.
'========================================
Set oUser = GetObject("LDAP://" & strUserDN)

'========================================
' Add the number of days to the last time
' the password was set.
'========================================
whenPasswordExpires = DateAdd("d", numDays, oUser.PasswordLastChanged)
fromDate = Date
daysLeft = DateDiff("d",fromDate,whenPasswordExpires)

'WScript.Echo "Password Last Changed: " & oUser.PasswordLastChanged
if (daysLeft < warningDays) and (daysLeft > -1) then
Msgbox "La password scade tra " & daysLeft & " giorni" & " il " & _
  whenPasswordExpires &chr(13) & chr(13) & "Premi CTRL + ALT + CANC " &_ 
    "e seleziona l'opzione 'Cambia password'.", 0, "AVVISO SCADENZA PASSWORD"
End if

'========================================
' Clean up.
'========================================
Set oUser = Nothing
Set maxPwdAge = Nothing
Set oDomain = Nothing

Per eseguire lo script durante la fase di login, creare una nuova GPO tramite il tool Group Policy Management. Selezionare con il tasto destro del mouse la voce Group Policy Objects > New.

notifypsw03

Assegnare un nome alla nuova GPO e cliccare su OK.

notifypsw04

Editare la GPO creata e posizionarsi sull’opzione User Configuration > Policies > Windows Settings > Scripts (Logon/Logoff) e cliccare con il tasto destro del mouse su Logon > Properties.

notifypsw05

Nella sezione Scripts, cliccare il bottone Add e tramite Browse specificare il file .vbs da utilizzare.

notifypsw06

Selezionare lo script e cliccare su Open.

notifypsw07

Impostato lo script .vbs, cliccare su OK per salvare la configurazione.

notifypsw08

Effettuare il link della nuova GPO creata alla OU corretta.

notifypsw09

Effettuato il logon al sistema, l’esecuzione dello script visualizza il popup di notifica.

notifypsw10

 

Invio email di notifica

Per rendere la notifica di scadenza della password più chiara e completa, è possibile associare al logon, oltre al popup, anche l’invio di una email all’indirizzo dell’utente. L’email viene inviata tramite uno script in PowerShell eseguito al logon in aggiunta al precedente script .vbs. Lo script utilizzato nell’esempio è stato prelevato dal sito www.rlmueller.net e customizzato in base alle specifiche esigenze.

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)
    
    # Format date to dd/mm/yyyy
    $PwdWarning = ‘{0:dd/MM/yyyy}’ -f $PwdExpires

    # 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 $PwdWarning"
        SendEmail $Mail $Notice
        "Email sent to $Name ($Mail), password expires $PwdWarning"
    }
    Else
    {
        "$Name has no email, but password expires $PwdWarning"
        "DN: $DN"
    }
}

Come già visto in precedenza, editare la GPO creata in precedenza e posizionarsi sull’opzione User Configuration > Policies > Windows Settings > Scripts (Logon/Logoff) e cliccare con il tasto destro del mouse su Logon > Properties. Selezionare la sezione PowerShell Scripts e cliccare sul bottone Add. Tramite Browse specificare, in questo caso, lo script .ps1 da utilizzare.

notifypsw11

Selezionare lo script .ps1 e cliccare su Open.

notifypsw12

Per specificare eventualmente una sequenza di esecuzione degli script, configurare l’opzione “For this GPO, run scripts in the following order”. Cliccare su OK per salvare le impostazioni.

notifypsw13

Effettuando il logon alla rete, oltre alla visualizzazione del popup configurato inizialmente, l’utente riceverà nella propria casella di posta una email di notifica.

notifypsw14

La scelta di notificare la scadenza della password tramite popup, tramite email o utilizzando entrambe le soluzioni dipende dalle esigenze o dalle policy aziendali. La notifica potrebbe essere effettuata visualizzando inizialmente il popup e successivamente anche con la email.

Aggiornamento 25/08/2014

Per far funzionare correttamente lo script powershell senza avere il problema delle email generate per ogni utente che effettua il login, eseguire lo script giornalmente tramite il Task Scheduler di Windows rimuovendo lo script dalla GPO. Creare un nuovo task nel Task Scheduler ed imposta i parametri in questo modo:

  • Action: Start a program
  • Program/Script: powershell.exe
  • Add arguments (optional): -f “C:\Scripts\psw_warning_email.ps1?

Configurare l’esecuzione specificando le seguenti opzioni:

  • Use the following user account: a Domain Admin account
  • Run whether user is logged on or not
  • Run with highest privileges

scadenza password Windows 7 1

12 Comments

  1. Marco 10/01/2013
  2. Patrizio 26/02/2013
    • Paolo 26/02/2013
  3. Danilo 02/05/2013
    • Paolo 02/05/2013
      • Danilo 02/05/2013
        • frin 27/05/2013
          • Paolo 27/05/2013
  4. frin 27/05/2013
  5. Carlo 10/07/2013
    • Paolo Valsecchi 11/07/2013
  6. marco 19/08/2014