3

I am using Powershell to determine the password expiry date for domain accounts. I have used the following command to get this information:

Get-ADUser -Filter {SamAccountName -eq "<username>"} -Properties "DisplayName" , "msDS-UserPasswordExpiryTimeComputed"

I then covert this value to a meaningful date by using:

[datetime]::FromFileTime(<computed filetime from above command>)

This works fine for all the domains I use, except one. In that domain I get a value of 9223372036854775807 as the msDS-UserPasswordExpiryTimeComputed. I am not able to use the FromFileTime function to convert this number into a date. It throws as error. Upon researching I have found that this number means that the password is set not to expire. However, I know that passwords do expire in this domain. Further, the PasswordNeverExpires property from the Get-ADUser cmdlet shows as False.

How can I get 9223372036854775807 from msDS-UserPasswordExpiryTimeComputed attribute and get a False from the PasswordNeverExpires property? This seems like a contradiction. What am I missing? Are there other situations when msDS-UserPasswordExpiryTimeComputed could be 9223372036854775807 too? Thanks.

user8148945
  • 55
  • 1
  • 6
  • As an aside: Using a script block (`{ ... }`) as a `-Filter` argument is [best avoided](https://stackoverflow.com/a/44184818/45375). – mklement0 Jul 04 '18 at 16:39

2 Answers2

3

The documentation lists several conditions in which msDS-UserPasswordExpiryTimeComputed returns 9223372036854775807 aka 0x7fffffffffffffff aka [int64]::MaxValue (TO refers to a given target object):

If any of the ADS_UF_SMARTCARD_REQUIRED, ADS_UF_DONT_EXPIRE_PASSWD, ADS_UF_WORKSTATION_TRUST_ACCOUNT, ADS_UF_SERVER_TRUST_ACCOUNT, ADS_UF_INTERDOMAIN_TRUST_ACCOUNT bits is set in TO!userAccountControl, then TO!msDS-UserPasswordExpiryTimeComputed = 0x7FFFFFFFFFFFFFFF.
[...]
Else, if Effective-MaximumPasswordAge = 0x8000000000000000, then TO!msDS-UserPasswordExpiryTimeComputed = 0x7FFFFFFFFFFFFFFF (where Effective-MaximumPasswordAge is defined in [MS-SAMR] section 3.1.1.5).


Without knowing all the details, it seems that the msDS-UserPasswordExpiryTimeComputed property returning 0x7FFFFFFFFFFFFFFF indicates that there is effectively no password expiration, for a variety of reasons, only one of which is PasswordNeverExpires being set to $True.

Therefore, you could filter out such values:

Get-ADUser -Filter "SamAccountName -eq '<username>'" `
           -Properties DisplayName, msDS-UserPasswordExpiryTimeComputed |                    #`
  Where { $_.msDS-UserPasswordExpiryTimeComputed -ne 0x7FFFFFFFFFFFFFFF } | ForEach {
      # ...
      $dt = [datetime]::FromFileTime($_.msDS-UserPasswordExpiryTimeComputed)
    }

It may even be possible to incorporate the test for 0x7FFFFFFFFFFFFFFF into the -Filter argument.

As an aside: Note that I've used a string rather than a script block ({ ... }) as the -Filter argument, because using script blocks is best avoided.

mklement0
  • 382,024
  • 64
  • 607
  • 775
1

I don't have a DC at the moment to test but theoretically this can work.

  1. Get the Password Policy of the domain with Get-ADDefaultDomainPasswordPolicy -Identity Domain.com

  2. Get the passwordLastSet property of a user like this: (Get-ADUser -Identity <UserName> -Properties *).PasswordlastSet and convert to appropriate [datetime] object based on the domain's Culture: Ref Get-Culture. DateTime format may change based on regional settings like US and UK.

  3. Now that you have the passwordpolicy of say 60 days and the passwordlastset date, it is simple math to determine if the password is expiring or not.

Alternately, on 2016 servers, you can also use something like:

Search-ADAccount -AccountExpiring -TimeSpan 10.00:00:00
Sid
  • 2,586
  • 1
  • 11
  • 22