Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to track inactive AD users? 1

Status
Not open for further replies.

ak8899

Technical User
Feb 27, 2002
118
CH
Hello

I am looking for a commercial solution for the following problem:


We have users (WinXPsp2) who do not periodically logout/login to the AD (Win2k3), some just hybernate all the time...(we don't want to disable the possibility to hibernate).

Now we look for a SW that scans the AD for those "inactive" users (last logon date) and sends them an email asking
to logoff and logon. If possible at certain intervals.

I found Netwrix's "Inactive User Tracker" but AFAIK this SW doesn't offer user notification, it only notifes the administrator and does actions like disable/move account, or set randomized password.

Does anyone know of such a software?
or do we have to "script" it...



regards,
Alain
 
I've never heard of such software, but here's a script I use. I think it originally was written by Markdmac, with a few modifications by me. It will create a .csv (in the folder where the script resides) with a list of user display names and last logon date.

The difficulty with this is that each domain controller stores the last time a user authenticated to it. There is no domain-wide variable that holds the last time they logged onto the domain. This script searches all DCs and reports the latest one, which should give you what you are looking for.

Code:
' LastLogon.vbs
' VBScript program to determine when each user in the domain last logged
' on.
'
' ----------------------------------------------------------------------
' Copyright (c) 2002 Richard L. Mueller
' Hilltop Lab web site - [URL unfurl="true"]http://www.rlmueller.net[/URL]
' Version 1.0 - December 7, 2002
' Version 1.1 - January 17, 2003 - Account for null value for lastLogon.
' Version 1.2 - January 23, 2003 - Account for DC not available.
' Version 1.3 - February 3, 2003 - Retrieve users but not contacts.
' Version 1.4 - February 19, 2003 - Standardize Hungarian notation.
' Version 1.5 - March 11, 2003 - Remove SearchScope property.
' Version 1.6 - May 9, 2003 - Account for error in IADsLargeInteger
'                             property methods HighPart and LowPart.
' Version 1.7 - January 25, 2004 - Modify error trapping.
'
' Because the lastLogon attribute is not replicated, every Domain
' Controller in the domain must be queried to find the latest lastLogon
' date for each user. The lastest date found is kept in a dictionary
' object. The program first uses ADO to search the domain for all Domain
' Controllers. The AdsPath of each Domain Controller is saved in an
' array. Then, for each Domain Controller, ADO is used to search the
' copy of Active Directory on that Domain Controller for all user
' objects and return the lastLogon attribute. The lastLogon attribute is
' a 64-bit number representing the number of 100 nanosecond intervals
' since 12:00 am January 1, 1601. This value is converted to a date. The
' last logon date is in UTC (Coordinated Univeral Time). It must be
' adjusted by the Time Zone bias in the machine registry to convert to
' local time.
'
' 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.




Dim objRootDSE, strConfig, objConnection, objCommand, strQuery
Dim objRecordSet, objDC
Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
Dim strDN, dtmDate, objDate, lngDate, objList, strUser
Dim strBase, strFilter, strAttributes, lngHigh, lngLow
Dim resultText, filespec

' Use a dictionary object to track latest lastLogon for each user.
Set objList = CreateObject("Scripting.Dictionary")
objList.CompareMode = vbTextCompare

' Obtain local Time Zone bias from machine registry.
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

' Determine configuration context and DNS domain from RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strConfig = objRootDSE.Get("configurationNamingContext")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

' Use ADO to search Active Directory for ObjectClass nTDSDSA.
' This will identify all Domain Controllers.
Set objCommand = CreateObject("ADODB.Command")
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
objCommand.ActiveConnection = objConnection

strBase = "<LDAP://" & strConfig & ">"
strFilter = "(objectClass=nTDSDSA)"
strAttributes = "AdsPath"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"

objCommand.CommandText = strQuery
objCommand.Properties("Page Size") = 100
objCommand.Properties("Timeout") = 60
objCommand.Properties("Cache Results") = False

Set objRecordSet = objCommand.Execute

' Enumerate parent objects of class nTDSDSA. Save Domain Controller
' AdsPaths in dynamic array arrstrDCs.
k = 0
Do Until objRecordSet.EOF
  Set objDC = _
    GetObject(GetObject(objRecordSet.Fields("AdsPath")).Parent)
  ReDim Preserve arrstrDCs(k)
  arrstrDCs(k) = objDC.DNSHostName
  k = k + 1
  objRecordSet.MoveNext
Loop

' Retrieve lastLogon attribute for each user on each Domain Controller.
For k = 0 To Ubound(arrstrDCs)
  strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
  strFilter = "(&(objectCategory=person)(objectClass=user))"
  strAttributes = "displayName,lastLogon,sAMAccountName"
  strQuery = strBase & ";" & strFilter & ";" & strAttributes _
    & ";subtree"
  objCommand.CommandText = strQuery
  On Error Resume Next
  Set objRecordSet = objCommand.Execute
  If Err.Number <> 0 Then
    On Error GoTo 0
    Wscript.Echo "Domain Controller not available: " & arrstrDCs(k)
  Else
    On Error GoTo 0
    Do Until objRecordSet.EOF
      strDN = objRecordSet.Fields("displayName")
			strID = objRecordSet.Fields("sAMAccountName")
      lngDate = objRecordSet.Fields("lastLogon")
      On Error Resume Next
      Set objDate = lngDate
      If Err.Number <> 0 Then
        On Error GoTo 0
        dtmDate = #1/1/1601#
      Else
        On Error GoTo 0
        lngHigh = objDate.HighPart
        lngLow = objDate.LowPart
        If lngLow < 0 Then
          lngHigh = lngHigh + 1
        End If
        If (lngHigh = 0) And (lngLow = 0 ) Then
          dtmDate = #1/1/1601#
        Else
          dtmDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
            + lngLow)/600000000 - lngBias)/1440
        End If
      End If
      If objList.Exists(strDN) Then
        If dtmDate > objList(strDN) Then
          objList(strDN) = dtmDate
        End If
      Else
        objList.Add strDN, dtmDate
      End If
      objRecordSet.MoveNext
    Loop
  End If
Next

resultText = "User,Last Logon" & vbCrLf

' Output latest lastLogon date for each user.
For Each strUser In objList
	If objList(strUser) = "1/1/1601" Then
		resultText = resultText &  strUser & "," & "NEVER USED" & vbCrLf
	Else
		resultText = resultText &  strUser & "," & objList(strUser) & vbCrLf
	End If
Next

filespec = ".\LastLogons.csv"

Set fso = CreateObject("Scripting.FileSystemObject")
If (fso.FileExists(filespec)) Then
	fso.DeleteFile(filespec)
End if
Set ts = fso.CreateTextFile (filespec, ForWriting)
ts.write resultText
MsgBox "Done"

' Clean up.
objConnection.Close
Set objRootDSE = Nothing
Set objConnection = Nothing
Set objCommand = Nothing
Set objRecordSet = Nothing
Set objDC = Nothing
Set objDate = Nothing
Set objList = Nothing
Set objShell = Nothing



Thanks,
Andrew

[medal] Hard work often pays off over time, but procrastination pays off right now!
 
Hi Andrew

many thanks!




regards,
Alain
 
Hi Zelandakh

I found 3rd party tools that do a logoff after a certain time of inactivity or at a scheduled time, etc.
But I could not find a tool that actually logs off the user or reboots the machine based on the last logon date, eg. when the user has not logged in for n days then logout/reboot.

If you know such a tool then please let me know!

Thanks,
Alain
 
Just a few practical suggestions...

Set a password policy for 60 days. That should get your users to log on and log off on a regular basis and improve your network security.

Time policies are another possibility.

Patch management software, such as Patchlink or SMS would give you an excuse to wake up the machines and boot off users at least once a month.

Based on your existing reporting software, disable user accounts that have not changed their passwords for twice the length of your password policy.

PSC

Governments and corporations need people like you and me. We are samurai. The keyboard cowboys. And all those other people out there who have no idea what's going on are the cattle. Mooo! --Mr. The Plague, from the movie "Hackers
 
You can also use a windows update server to push MS patches and force reboots (for free).

Thanks,
Andrew

[medal] Hard work often pays off over time, but procrastination pays off right now!
 
yes, that's one option I am looking at.

Thanks,
Alain
 
acl03,
I thought I was the only one collecting Mark's scripts!
 
and potentially lose data.

Yes, make sure you have a good test system :)

Thanks,
Andrew

[medal] Hard work often pays off over time, but procrastination pays off right now!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top