Printout Header
RSS Feed

Gesperrte Benutzer im Active Directory suchen und finden


Wir benutzen für diese Suche das Active Directory Attribut lockoutTime, in dem angegeben wird, wann der Benutzer das letzte Mal gesperrt wurde - es handelt sich hierbei um eine Interval-angabe im Microsoft Integer8 Format. Aber die Suche nach Konten, deren lockoutTime-Wert größer als Null ist, führt nicht unmittelbar zum Ziel. Denn wenn der Account nach einer Weile vom System wieder automatisch entsperrt wird, wird die lockoutTime dieses Accounts zunächst nicht auf Null gesetzt. Man muß also anhand der lockoutTime und der Domain Account Lockout Policy berechnen, ob der Account noch wirklich gesperrt ist.

Vorsicht: Gesperrte Benutzer dürfen nicht mit deaktivierten Benutzern verwechselt werden. Lesen Sie dazu auch den SelfADSI-Artikel "Unlock : Entsperren von Active Directory Benutzerkonten".

Zur allgemeinen Erläuterung von LDAP-Suchvorgängen lesen Sie das SelfADSI-Kapitel "LDAP Objekte im Verzeichnis suchen".


Alle gesperrten Benutzer-Accounts der eigenen Domäne finden


Dieses Script findet alle gesperrten Benutzern der Domäne, in der der aktuell angemeldete Benutzer Mitglied ist. Wenn die Sperre vom System automatisch wieder aufgehoben wird, dann wird der entsprechende Zeitpunkt pro Benutzer angegeben. Dazu ist anfangs das Auslesen der Sperrdauer aus dem Attribut lockoutDuration am Domänenobjekt selbst notwendig. An dieser Stelle benötigt man eine spezielle Umwandlungsfunktion des Wertes in eine entsprechende Minuten-Zeitdauer, auch später bei der Berechnung des Lockout-Zeitpunktes ist eine ähnliche Umwandlung notwendig:

ldapFilter = "(&(sAMAccountType=805306368)(lockoutTime>=1))"

Set rootDSE = GetObject("LDAP://rootDSE")
domainDN = rootDSE.Get("defaultNamingContext")

Set objDomain = GetObject("LDAP://" & domainDN)
Set interval = objDomain.lockoutDuration
domainLockout = LargeIntegerToMinutes(interval)

If (domainLockout > 0) then
    WScript.Echo "Domain lockout duration is: " & domainLockout & " minutes"
Else
    WScript.Echo "Domain lockout duration is permanent until the Admin unlocks the accounts"
End If
WScript.Echo "Locked accounts:"
WScript.Echo

Set ado = CreateObject("ADODB.Connection")
ado.Provider = "ADSDSOObject"
ado.Open "ADSearch"
Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & ";distinguishedName,lockoutTime;subtree")

While Not objectList.EOF
    If (domainLockout > 0) then
        dateTime = objectList.Fields("lockoutTime")
        lockOutTime = LargeIntegerToDate(dateTime)
        userLockoutLeft = domainLockout - DateDiff("n", lockOutTime, Now)
        If (userLockoutLeft > 0) Then
            WScript.Echo objectList.Fields("distinguishedName")
            WScript.Echo "User is locked out (for " & userLockoutLeft & " more minutes)"
            WScript.Echo
        End If
    Else
        WScript.Echo objectList.Fields("distinguishedName")
    End If

    objectList.MoveNext
Wend


'_______________________________________________________________________________________ [ LargeIntegerToDate ]
'
'
Function LargeIntegerToDate(value)
'nimmmt einen Microsoft LargeInteger Wert (Integer8) und gibt das entsprechende Datum plus Uhrzeit zurück

    Set sho = CreateObject("Wscript.Shell")
    timeShiftValue = sho.RegRead("HKLM\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")
    If IsArray(timeShiftValue) Then
        timeShift = 0
        For i = 0 To UBound(timeShiftValue)
            timeShift = timeShift + (timeShiftValue(i) * 256^i)
        Next
    Else
        timeShift = timeShiftValue
    End If

    i8High = value.HighPart
    i8Low = value.LowPart
    If (i8Low < 0) Then
        i8High = i8High + 1
    End If

    If (i8High = 0) And (i8Low = 0) Then
        LargeIntegerToDate = #1/1/1601#
    Else
        LargeIntegerToDate = #1/1/1601# + (((i8High * 2^32) + i8Low)/600000000 - timeShift)/1440
    End If
End Function


'_______________________________________________________________________________________ [ LargeIntegerToMinutes ]
'
'
Function LargeIntegerToMinutes(value)
'nimmmt einen Microsoft LargeInteger Wert (Integer8) und gibt das entsprechende ...
'... Zeitinterval in Minuten zurück (-1 für "Never")

    If (value.HighPart = -2147483648) And (value.LowPart = 0) then
        LargeIntegerToMinutes = -1
    Else
        i8High = value.HighPart
        i8Low = value.LowPart
        If (i8Low < 0) Then
            i8High = i8High + 1
        End If

        LargeIntegerToMinutes = -(((i8High * 2^32) + i8Low)/600000000)
    End If
End Function


Alle gesperrten Benutzer-Accounts finden - Kurzversion 1


Die kürzere Variante, die jedoch einen zusätzlichen Bindvorgang direkt mit jedem zu prüfenden Account beinhaltet - es wird hier keine Zeitangabe über die Dauer der Sperrung ausgegeben und deswegen werden die Konvertierungsfunktionen für die Integer8-Werte nicht benötigt. Allerdings müssen wir hier jeden Benutzer über den ADSI WinNT-Provider verbinden, um die API-Property IsAccountLocked zu prüfen, und dafür brauchen wir den NetBIOS-Namen der Domäne - er wird durch die Benutzung des ADSystemInfo COM Objektes am Anfang des Scripts ermittelt:

Const ADS_UF_LOCKOUT = 16

ldapFilter = "(&(sAMAccountType=805306368)(lockoutTime>=1))"

Set rootDSE = GetObject("LDAP://rootDSE")
domainDN = rootDSE.Get("defaultNamingContext")

Set aio = CreateObject("ADSystemInfo")
domainNETBios = aio.DomainShortName


WScript.Echo "Locked accounts:"
WScript.Echo

Set ado = CreateObject("ADODB.Connection")
ado.Provider = "ADSDSOObject"
ado.Open "ADSearch"

Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & ";distinguishedName,samAccountName;subtree")
While Not objectList.EOF
    userLogonName = domainNETBios & "/" & objectList.Fields("samAccountName")
    Set user = GetObject("WinNT://" & userLogonName)                                'Syntax=>   WinNT://Domäne/Benutzer 

    if (user.IsAccountLocked) then
        WScript.Echo objectList.Fields("distinguishedName")
    End if

    objectList.MoveNext
Wend


Alle gesperrten Benutzer-Accounts finden - Kurzversion 2 (>Windows 2003)


Eine Abwandlung der kurzen Variante, die allerdings nur in Umgebungen ab Windows 2003 funktioniert: Man muß hier das Attribut msDS-User-Account-Control-Computed auslesen (es ist ein Constructed Attribut und läßt sich nicht direkt bei der Suche verwenden) und überprüfen, ob in dessen Bitfeld das Flag UF_LOCKOUT (16) gesetzt ist.

Const ADS_UF_LOCKOUT = 16

ldapFilter = "(&(sAMAccountType=805306368)(lockoutTime>=1))"

Set rootDSE = GetObject("LDAP://rootDSE")
domainDN = rootDSE.Get("defaultNamingContext")

WScript.Echo "Locked accounts:"
WScript.Echo

Set ado = CreateObject("ADODB.Connection")
ado.Provider = "ADSDSOObject"
ado.Open "ADSearch"
Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & ";ADSPath,distinguishedName;subtree")

While Not objectList.EOF
    Set user = GetObject(objectList.Fields("ADSPath"))

    user.GetInfoEx Array("msDS-User-Account-Control-Computed"), 0
    flags = user.Get("msDS-User-Account-Control-Computed")
    if (flags and ADS_UF_LOCKOUT) then
        WScript.Echo objectList.Fields("distinguishedName")
    End if


    objectList.MoveNext
Wend



Tweet