Microsoft Timestamp / Interval Attributes with Integer8 Syntax
On this web page we want to have a look at the numeric directory attributes which are used by Microsoft to express Date and Time values or Time Intervals. Examples for such attributes:
accountExpires | User objects Computer objects |
The date and time when the regarding account cannot be used any more. |
badPasswordTime | User objects Computer objects |
The date and time when the regarding account has entered a bad password the last time. |
lastLogoff | User objects Computer objects |
The date and time when the regarding account has logged off the last time (this isn't used in current AD versions). |
lastLogon | User objects Computer objects |
The date and time when the regarding account has logged on to the domain (this is NOT replicated between domain controllers, so if you want to know the exact logon time for a certain user, you have to check all domain controllers) |
lastLogonTimestamp | User objects Computer objects |
The date and time when the regarding account has logged on to the domain. The lastLogonTimestamp value is replicated between DCs, but only when the logon time is older than 2 weeks - this avoids replication traffic but shows us the accounts which hasn't been active for a long time. |
lockoutDuration | Domain objects | This is the time interval which determines how long an account is locked at the intruder lockout mechanism. |
lockOutObservationWindow | Domain objects | This is the time interval in which the user cannot enter a false password too often without being locked by the intruder lockout mechanism. |
lockoutTime | User objects Computer objects |
For locked accounts, this is the date and time when the account was locked out. |
maxPwdAge | Domain objects | This is the time interval which determines the maximal password age for all users in the domain. |
minPwdAge | Domain objects | This is the time interval which determines the minimal password age for all users in the domain. |
msDS-LastFailed InteractiveLogonTime |
User objects |
The date and time when the regarding account failed to logon with an CTRL-ALT-DEL interactive logon. This doesn't return values on LDAP requests in AD versions older than 2008. |
msDS-LastSuccessful InteractiveLogonTime |
User objects |
The date and time when the regarding user did logon successfully with an CTRL-ALT-DEL interactive logon. This doesn't return values on LDAP requests in AD versions older than 2008. |
msDS-UserPassword ExpiryTimeComputed |
User objects Computer objects |
The date and time when the password of the regarding user will be expired. This constructed attribute is described in the MSDN website, but doesn't return values on LDAP requests in AD versions older than 2008. |
pwdLastSet | User objects | The date and time when the regarding user changed his password the last time. |
The basic LDAP attribute data type of these attributes is a Microsoft proprietary LDAP attribute syntax named Large Integer - it is often referred to as Integer8 because it's a signed numeric value which is 8 Bytes (64 bit) long. The possible range of a Microsoft Large Integer is this:
Minimum value: -9223372036854775808 (-2^63) or hex 0x8000000000000000 |
Maximum value: 9223372036854775807 (2^63 - 1) orhex 0x7FFFFFFFFFFFFFFF |
So how is Microsoft using these really huge numbers as timestamp or interval values? As 'easy' as that:
- In some cases, an Integer8 value has to be interpreted as a date and time value. It can be read as a Microsoft Filetime structure then, expressing the 100-nanosecond steps since 12:00 AM, January 1, 1601.
- In other cases, an Integer8 value has to be interpreted as a time interval. Time intervals are always negative numbers. Their absolute value can be read as a Microsoft Filetime structure then, expressing 100-nanosecond steps which determine the length of the time interval.
In the ADSI API, Integer8 values are handled by accessing two 32 bit parts of the value: the HighPart and the LowPart. You should keep in mind that Active Directory stores all date and time values internally in the UTC format (Universal Coordinated Time) - this is (almost) the former Greenwich Meantime (GMT). So if your Systems are for example in Pacific Standard Time (PST, which is GMT-8), so you have to recalculate the Integer8 attribute values if you want to know the date and times in your local time.
Another important detail: You have to use the GetEx method to read a Large Integer/Integer8 attribute in an ADSI script. If you just try to read those attributes with Get, this runtime error will occur: 0x800a01b6 (-2146827850) METHOD_OR_PROPERTY_NOT_SUPPORTED.
So here is the script code to convert an Integer8 into a date and time, including the local time zone adjustment (we take the time abbreviation from UTC from the registry). Another sub function shows how to convert a date to Integer8:
Other tools to convert Microsoft Large Integer / Integer8 values to dates
There are several other tools to convert an Microsoft Large Integer (Integer8) value to a date.
LEX - The LDAP Explorer
LEX - The LDAP Explorer (a commercial powerful LDAP browser I developed) has special attribute editors for Large Integer values which have to be interpreted as Timestamps and Intervals:
LEX Editor for Microsoft Integer8 Timestamps:
LEX Editor for Microsoft Integer8 Intervals:
W32TM
On the command line interface of each Windows machine since Windows Server 2003, you can use the W32TM.EXE command to convert an Integer8 to a date with this syntax:
W32TM /ntte <integer8-value>
REPADMIN
On the command line interface of a domain controller, you cold use the REPADMIN.EXE command (on Windows 2000/2003 servers, you have to install the Ressource Kit to get REPADMIN.EXE). You can use this syntax:
REPADMIN /showtime <integer8-value>
But you have to omit the last 7 digits of the Large Integer, because REPADMIN wants to calculate with seconds and not with nanoseconds: