Inhaltsverzeichnis > Erweiterter Umgang mit AD Objekten > LDAP Search Werkstatt > Gesperrte User Accounts suchen
    
    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://domain/user 
    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