Jump to content

Recommended Posts

Posted (edited)
  On 5/21/2014 at 3:56 PM, water said:

If you run _AD_GetObjectProperties for the user, what's the value of property "lockouttime"?

 

locked:

lockoutTime = 2014/05/20 10:41:06

not locked:

lockoutTime = 1601/01/01 00:00:00

Edited by Tim33
Posted

How long do you lock a user?

Do you use the fine grained password policy?

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted (edited)

  On 5/22/2014 at 11:17 AM, water said:

How long do you lock a user?

Do you use the fine grained password policy?

 

How long do you lock a user?

Account lockout duration: 0 minutes

Account lockout threshold: 5 invalid logon attempts

Reset account lockout counter after: 3 minutes

 

Do you use the fine grained password policy?

No

 

Edited by Tim33
Posted

Lockout duration 0 minutes means that the user has to  be unlocked by an administrator.. Is this correct?

But in this case the function should set the return value to 1 and @error to -1.

Strange.

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

If you run this script, what do you get?

#include <AD.au3>

; Open Connection to the Active Directory
_AD_Open()
If @error Then Exit MsgBox(16, "Active Directory Example Skript", "Function _AD_Open encountered a problem. @error = " & @error & ", @extended = " & @extended)

; Get the password info
Global $aAD_PwdInfo[13][2] = [[12],["Maximum Password Age (days)"],["Minimum Password Age (days)"],["Enforce Password History (# of passwords remembered)"], _
        ["Minimum Password Length"],["Account Lockout Duration (minutes)"],["Account Lockout Threshold (invalid logon attempts)"],["Reset account lockout counter after (minutes)"], _
        ["Password last changed (YYYY/MM/DD HH:MM:SS local time)"],["Password expires (YYYY/MM/DD HH:MM:SS local time)"],["Password last changed (YYYY/MM/DD HH:MM:SS UTC)"], _
        ["Password expires (YYYY/MM/DD HH:MM:SS UTC)"],["Password properties"]]

Global $aTemp = _AD_GetPasswordInfo()
For $iCount = 1 To $aTemp[0]
    $aAD_PwdInfo[$iCount][1] = $aTemp[$iCount]
Next
$aAD_PwdInfo[0][0] = $aTemp[0]

_ArrayDisplay($aAD_PwdInfo, "Active Directory Functions - Example 1")

; Close Connection to the Active Directory
_AD_Close()

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

Water,

As relates to our question of slowness in Windows 8, the _AD_GetGroupMembers function returns fairly quickly, as does the _AD_GetObjectsInOU function. Is there a "hybrid" type function to allow me to GetGroupMembers and get a list of their properties all in one call?

Thanks again for all your help!!!

Posted (edited)

  On 5/22/2014 at 2:29 PM, water said:

 

If you run this script, what do you get?

#include <AD.au3>

; Open Connection to the Active Directory
_AD_Open()
If @error Then Exit MsgBox(16, "Active Directory Example Skript", "Function _AD_Open encountered a problem. @error = " & @error & ", @extended = " & @extended)

; Get the password info
Global $aAD_PwdInfo[13][2] = [[12],["Maximum Password Age (days)"],["Minimum Password Age (days)"],["Enforce Password History (# of passwords remembered)"], _
        ["Minimum Password Length"],["Account Lockout Duration (minutes)"],["Account Lockout Threshold (invalid logon attempts)"],["Reset account lockout counter after (minutes)"], _
        ["Password last changed (YYYY/MM/DD HH:MM:SS local time)"],["Password expires (YYYY/MM/DD HH:MM:SS local time)"],["Password last changed (YYYY/MM/DD HH:MM:SS UTC)"], _
        ["Password expires (YYYY/MM/DD HH:MM:SS UTC)"],["Password properties"]]

Global $aTemp = _AD_GetPasswordInfo()
For $iCount = 1 To $aTemp[0]
    $aAD_PwdInfo[$iCount][1] = $aTemp[$iCount]
Next
$aAD_PwdInfo[0][0] = $aTemp[0]

_ArrayDisplay($aAD_PwdInfo, "Active Directory Functions - Example 1")

; Close Connection to the Active Directory
_AD_Close()

 

12|

Maximum Password Age (days)|31

Minimum Password Age (days)|1

Enforce Password History (# of passwords remembered)|6

Minimum Password Length|6

Account Lockout Duration (minutes)|-15372286728.0913

Account Lockout Threshold (invalid logon attempts)|5

Reset account lockout counter after (minutes)|3

Password last changed (YYYY/MM/DD HH:MM:SS local time)|2012/05/14 11:08:22

Password expires (YYYY/MM/DD HH:MM:SS local time)|

Password last changed (YYYY/MM/DD HH:MM:SS UTC)|2012/05/14 09:08:22

Password expires (YYYY/MM/DD HH:MM:SS UTC)|

Password properties|0

---

Lockout duration 0 minutes means that the user has to  be unlocked by an administrator.. Is this correct?

Yes

 

Edited by Tim33
Posted
  On 5/22/2014 at 2:59 PM, JoshuaBarnette said:

Water,

As relates to our question of slowness in Windows 8, the _AD_GetGroupMembers function returns fairly quickly, as does the _AD_GetObjectsInOU function. Is there a "hybrid" type function to allow me to GetGroupMembers and get a list of their properties all in one call?

Thanks again for all your help!!!

Unfortunately not. Because you have to query two different objects: the group for the members attribute and the members for their properties.

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

  On 5/22/2014 at 2:59 PM, Tim33 said:

Lockout duration 0 minutes means that the user has to  be unlocked by an administrator.. Is this correct?

Yes

What do you get for domainControllerFunctionality, domainFunctionality and forestFunctionality when you run the _AD_ListRootDSEAttributes.au3 example script?

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

I ask because I think the value for Account Lockout Duration (minutes) is quite strange (-15372286728.0913).

Maybe they added something new to the latest Windows vesion?

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

  On 5/22/2014 at 3:29 PM, water said:

What do you get for domainControllerFunctionality, domainFunctionality and forestFunctionality when you run the _AD_ListRootDSEAttributes.au3 example script?

 

domainControllerFunctionality|5

domainFunctionality|5

forestFunctionality|5

 

Posted

So this is a Windows 2012 domain. I wil check what has changed.

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

What do you get written to the console when you run this exampel script:

#AutoIt3Wrapper_AU3Check_Parameters= -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#AutoIt3Wrapper_AU3Check_Stop_OnWarning=Y
; *****************************************************************************
; Example 1
; Get the domain password policy and the password info for the current user
; *****************************************************************************
#include <AD.au3>

; Open Connection to the Active Directory
_AD_Open()
If @error Then Exit MsgBox(16, "Active Directory Example Skript", "Function _AD_Open encountered a problem. @error = " & @error & ", @extended = " & @extended)

; Get the password info
Global $aAD_PwdInfo[13][2] = [[12],["Maximum Password Age (days)"],["Minimum Password Age (days)"],["Enforce Password History (# of passwords remembered)"], _
        ["Minimum Password Length"],["Account Lockout Duration (minutes)"],["Account Lockout Threshold (invalid logon attempts)"],["Reset account lockout counter after (minutes)"], _
        ["Password last changed (YYYY/MM/DD HH:MM:SS local time)"],["Password expires (YYYY/MM/DD HH:MM:SS local time)"],["Password last changed (YYYY/MM/DD HH:MM:SS UTC)"], _
        ["Password expires (YYYY/MM/DD HH:MM:SS UTC)"],["Password properties"]]

Global $aTemp = _AD_GetPasswordInfoEX()
For $iCount = 1 To $aTemp[0]
    $aAD_PwdInfo[$iCount][1] = $aTemp[$iCount]
Next
$aAD_PwdInfo[0][0] = $aTemp[0]

_ArrayDisplay($aAD_PwdInfo, "Active Directory Functions - Example 1")

; Close Connection to the Active Directory
_AD_Close()

Func _AD_GetPasswordInfoEX($sObject = @UserName)

    If _AD_ObjectExists($sObject) = 0 Then Return SetError(1, 0, "")
    If StringMid($sObject, 3, 1) <> "=" Then $sObject = _AD_SamAccountNameToFQDN($sObject) ; sAMAccountName provided
    Local $iError = 0
    Local $aPwdInfo[13] = [12]
    Local $oObject = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain)
    $aPwdInfo[1] = Int(__AD_Int8ToSec($oObject.Get("maxPwdAge"))) / 86400 ; Convert to Days
    $aPwdInfo[2] = __AD_Int8ToSec($oObject.Get("minPwdAge")) / 86400 ; Convert to Days
    $aPwdInfo[3] = $oObject.Get("pwdHistoryLength")
    $aPwdInfo[4] = $oObject.Get("minPwdLength")
    ; Account lockout duration: http://msdn.microsoft.com/en-us/library/ms813429.aspx
    Local $oTemp = $oObject.Get("lockoutDuration")
ConsoleWrite("High: " & $oTemp.HighPart & " " & Hex($oTemp.HighPart,8) & @LF)
ConsoleWrite("Low : " & $oTemp.LowPart & " " & Hex($oTemp.LowPart,8) & @LF)
    If $oTemp.HighPart = 0x7FFFFFFF And $oTemp.LowPart = 0xFFFFFFFF Then
        $aPwdInfo[5] = 0 ; Account has to be unlocked manually by an admin
    Else
        $aPwdInfo[5] = __AD_Int8ToSec($oTemp) / 60 ; Convert to Minutes
    EndIf
    $aPwdInfo[6] = $oObject.Get("lockoutThreshold")
    $aPwdInfo[7] = __AD_Int8ToSec($oObject.Get("lockoutObservationWindow")) / 60 ; Convert to Minutes
    Local $oUser = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sObject)
    Local $sPwdLastChanged = $oUser.Get("PwdLastSet")
    Local $iUAC = $oUser.userAccountControl
    ; Has user account password been changed before?
    If $sPwdLastChanged.LowPart = 0 And $sPwdLastChanged.HighPart = 0 Then
        $iError += 3
        $aPwdInfo[8] = "1601/01/01 00:00:00"
        $aPwdInfo[10] = "1601/01/01 00:00:00"
    Else
        Local $sTemp = DllStructCreate("dword low;dword high")
        DllStructSetData($sTemp, "Low", $sPwdLastChanged.LowPart)
        DllStructSetData($sTemp, "High", $sPwdLastChanged.HighPart)
        ; Have to convert to SystemTime because _Date_Time_FileTimeToStr has a bug (#1638)
        Local $sTemp2 = _Date_Time_FileTimeToSystemTime(DllStructGetPtr($sTemp))
        $aPwdInfo[10] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        ; Convert PwdlastSet from UTC to Local Time
        $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2))
        $aPwdInfo[8] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        ; Is user account password set to expire?
        If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Or $aPwdInfo[1] = 0 Then
            If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Then $iError += 2
            If $aPwdInfo[1] = 0 Then $iError += 4 ; The Maximum Password Age is set to 0 in the domain. Therefore, the password does not expire
        Else
            $aPwdInfo[11] = _DateAdd("d", $aPwdInfo[1], $aPwdInfo[10])
            $sTemp2 = _Date_Time_EncodeSystemTime(StringMid($aPwdInfo[11], 6, 2), StringMid($aPwdInfo[11], 9, 2), StringMid($aPwdInfo[11], 1, 4), StringMid($aPwdInfo[11], 12, 2), StringMid($aPwdInfo[11], 15, 2), StringMid($aPwdInfo[11], 18, 2))
            ; Convert PasswordExpires from UTC to Local Time
            $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2))
            $aPwdInfo[9] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        EndIf
    EndIf
    $aPwdInfo[12] = $oObject.Get("pwdProperties")
    Return SetError($iError, 0, $aPwdInfo)

EndFunc   ;==>_AD_GetPasswordInfo

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

  On 5/26/2014 at 8:10 AM, water said:

 

What do you get written to the console when you run this exampel script:

#AutoIt3Wrapper_AU3Check_Parameters= -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#AutoIt3Wrapper_AU3Check_Stop_OnWarning=Y
; *****************************************************************************
; Example 1
; Get the domain password policy and the password info for the current user
; *****************************************************************************
#include <AD.au3>

; Open Connection to the Active Directory
_AD_Open()
If @error Then Exit MsgBox(16, "Active Directory Example Skript", "Function _AD_Open encountered a problem. @error = " & @error & ", @extended = " & @extended)

; Get the password info
Global $aAD_PwdInfo[13][2] = [[12],["Maximum Password Age (days)"],["Minimum Password Age (days)"],["Enforce Password History (# of passwords remembered)"], _
        ["Minimum Password Length"],["Account Lockout Duration (minutes)"],["Account Lockout Threshold (invalid logon attempts)"],["Reset account lockout counter after (minutes)"], _
        ["Password last changed (YYYY/MM/DD HH:MM:SS local time)"],["Password expires (YYYY/MM/DD HH:MM:SS local time)"],["Password last changed (YYYY/MM/DD HH:MM:SS UTC)"], _
        ["Password expires (YYYY/MM/DD HH:MM:SS UTC)"],["Password properties"]]

Global $aTemp = _AD_GetPasswordInfoEX()
For $iCount = 1 To $aTemp[0]
    $aAD_PwdInfo[$iCount][1] = $aTemp[$iCount]
Next
$aAD_PwdInfo[0][0] = $aTemp[0]

_ArrayDisplay($aAD_PwdInfo, "Active Directory Functions - Example 1")

; Close Connection to the Active Directory
_AD_Close()

Func _AD_GetPasswordInfoEX($sObject = @UserName)

    If _AD_ObjectExists($sObject) = 0 Then Return SetError(1, 0, "")
    If StringMid($sObject, 3, 1) <> "=" Then $sObject = _AD_SamAccountNameToFQDN($sObject) ; sAMAccountName provided
    Local $iError = 0
    Local $aPwdInfo[13] = [12]
    Local $oObject = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain)
    $aPwdInfo[1] = Int(__AD_Int8ToSec($oObject.Get("maxPwdAge"))) / 86400 ; Convert to Days
    $aPwdInfo[2] = __AD_Int8ToSec($oObject.Get("minPwdAge")) / 86400 ; Convert to Days
    $aPwdInfo[3] = $oObject.Get("pwdHistoryLength")
    $aPwdInfo[4] = $oObject.Get("minPwdLength")
    ; Account lockout duration: http://msdn.microsoft.com/en-us/library/ms813429.aspx
    Local $oTemp = $oObject.Get("lockoutDuration")
ConsoleWrite("High: " & $oTemp.HighPart & " " & Hex($oTemp.HighPart,8) & @LF)
ConsoleWrite("Low : " & $oTemp.LowPart & " " & Hex($oTemp.LowPart,8) & @LF)
    If $oTemp.HighPart = 0x7FFFFFFF And $oTemp.LowPart = 0xFFFFFFFF Then
        $aPwdInfo[5] = 0 ; Account has to be unlocked manually by an admin
    Else
        $aPwdInfo[5] = __AD_Int8ToSec($oTemp) / 60 ; Convert to Minutes
    EndIf
    $aPwdInfo[6] = $oObject.Get("lockoutThreshold")
    $aPwdInfo[7] = __AD_Int8ToSec($oObject.Get("lockoutObservationWindow")) / 60 ; Convert to Minutes
    Local $oUser = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sObject)
    Local $sPwdLastChanged = $oUser.Get("PwdLastSet")
    Local $iUAC = $oUser.userAccountControl
    ; Has user account password been changed before?
    If $sPwdLastChanged.LowPart = 0 And $sPwdLastChanged.HighPart = 0 Then
        $iError += 3
        $aPwdInfo[8] = "1601/01/01 00:00:00"
        $aPwdInfo[10] = "1601/01/01 00:00:00"
    Else
        Local $sTemp = DllStructCreate("dword low;dword high")
        DllStructSetData($sTemp, "Low", $sPwdLastChanged.LowPart)
        DllStructSetData($sTemp, "High", $sPwdLastChanged.HighPart)
        ; Have to convert to SystemTime because _Date_Time_FileTimeToStr has a bug (#1638)
        Local $sTemp2 = _Date_Time_FileTimeToSystemTime(DllStructGetPtr($sTemp))
        $aPwdInfo[10] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        ; Convert PwdlastSet from UTC to Local Time
        $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2))
        $aPwdInfo[8] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        ; Is user account password set to expire?
        If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Or $aPwdInfo[1] = 0 Then
            If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Then $iError += 2
            If $aPwdInfo[1] = 0 Then $iError += 4 ; The Maximum Password Age is set to 0 in the domain. Therefore, the password does not expire
        Else
            $aPwdInfo[11] = _DateAdd("d", $aPwdInfo[1], $aPwdInfo[10])
            $sTemp2 = _Date_Time_EncodeSystemTime(StringMid($aPwdInfo[11], 6, 2), StringMid($aPwdInfo[11], 9, 2), StringMid($aPwdInfo[11], 1, 4), StringMid($aPwdInfo[11], 12, 2), StringMid($aPwdInfo[11], 15, 2), StringMid($aPwdInfo[11], 18, 2))
            ; Convert PasswordExpires from UTC to Local Time
            $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2))
            $aPwdInfo[9] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        EndIf
    EndIf
    $aPwdInfo[12] = $oObject.Get("pwdProperties")
    Return SetError($iError, 0, $aPwdInfo)

EndFunc   ;==>_AD_GetPasswordInfo

 

High: -2147483648 80000000

Low : 0 00000000

Posted

So if you change line

If $oTemp.HighPart = 0x7FFFFFFF And $oTemp.LowPart = 0xFFFFFFFF Then

to

If $oTemp.HighPart = 0x80000000 And $oTemp.LowPart = 0x00000000 Then

do you get the correct result?

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted (edited)

  On 5/26/2014 at 9:28 AM, water said:

So if you change line

If $oTemp.HighPart = 0x7FFFFFFF And $oTemp.LowPart = 0xFFFFFFFF Then

to

If $oTemp.HighPart = 0x80000000 And $oTemp.LowPart = 0x00000000 Then

do you get the correct result?

 

Maximum Password Age (days)|31

Minimum Password Age (days)|1

Enforce Password History (# of passwords remembered)|6

Minimum Password Length|6

Account Lockout Duration (minutes)|0

Account Lockout Threshold (invalid logon attempts)|5

Reset account lockout counter after (minutes)|3

Password last changed (YYYY/MM/DD HH:MM:SS local time)|2012/05/14 11:08:22

Password expires (YYYY/MM/DD HH:MM:SS local time)|

Password last changed (YYYY/MM/DD HH:MM:SS UTC)|2012/05/14 09:08:22

Password expires (YYYY/MM/DD HH:MM:SS UTC)|

Password properties|0

 

Edited by Tim33
Posted

Great:

So this should give you the correct result:

#include <AD.au3>
_AD_Open()
If _AD_IsObjectLockedEX("timtest") Then
    ConsoleWrite("locked. @error = " & @error & ", @extened = " & @extended & @CRLF)
Else
    ConsoleWrite("not locked. @error = " & @error & ", @extened = " & @extended & @CRLF)
    _AD_Close()
EndIf

Func _AD_IsObjectLockedEX($sObject = @UserName)
    If Not _AD_ObjectExists($sObject) Then Return SetError(1, 0, 0)
    Local $sProperty = "sAMAccountName"
    If StringMid($sObject, 3, 1) = "=" Then $sProperty = "distinguishedName"; FQDN provided
    $__oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain & ">;(" & $sProperty & "=" & $sObject & ");ADsPath;subtree"
    Local $oRecordSet = $__oAD_Command.Execute ; Retrieve the ADsPath for the object
    Local $sLDAPEntry = $oRecordSet.fields(0).Value
    Local $oObject = __AD_ObjGet($sLDAPEntry) ; Retrieve the COM Object for the object
    Local $oLockoutTime = $oObject.LockoutTime
    ; Object is not locked out
    If Not IsObj($oLockoutTime) Then Return
    ; Calculate lockout time (UTC)
    Local $sLockoutTime = _DateAdd("s", Int(__AD_LargeInt2Double($oLockoutTime.LowPart, $oLockoutTime.HighPart) / (10000000)), "1601/01/01 00:00:00")
    ; Object is not locked out
    If $sLockoutTime = "1601/01/01 00:00:00" Then Return
    ; Get password info - Account Lockout Duration
    Local $aTemp = _AD_GetPasswordInfoEX($sObject)
    ; if lockout duration is 0 (= unlock manually by admin needed) then no calculation is necessary. Set @error to -1 (minutes till the account is unlocked)
    If $aTemp[5] = 0 Then Return SetError(-1, 0, 1)
    ; Calculate when the lockout will be reset
    Local $sResetLockoutTime = _DateAdd("n", $aTemp[5], $sLockoutTime)
    ; Compare to current date/time (UTC)
    Local $sNow = _Date_Time_GetSystemTime()
    $sNow = _Date_Time_SystemTimeToDateTimeStr($sNow, 1)
    If $sResetLockoutTime >= $sNow Then Return SetError(_DateDiff("n", $sNow, $sResetLockoutTime), 0, 1)
    Return
EndFunc   ;==>_AD_IsObjectLockedEX

Func _AD_GetPasswordInfoEX($sObject = @UserName)
    If _AD_ObjectExists($sObject) = 0 Then Return SetError(1, 0, "")
    If StringMid($sObject, 3, 1) <> "=" Then $sObject = _AD_SamAccountNameToFQDN($sObject) ; sAMAccountName provided
    Local $iError = 0
    Local $aPwdInfo[13] = [12]
    Local $oObject = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain)
    $aPwdInfo[1] = Int(__AD_Int8ToSec($oObject.Get("maxPwdAge"))) / 86400 ; Convert to Days
    $aPwdInfo[2] = __AD_Int8ToSec($oObject.Get("minPwdAge")) / 86400 ; Convert to Days
    $aPwdInfo[3] = $oObject.Get("pwdHistoryLength")
    $aPwdInfo[4] = $oObject.Get("minPwdLength")
    ; Account lockout duration: http://msdn.microsoft.com/en-us/library/ms813429.aspx
    Local $oTemp = $oObject.Get("lockoutDuration")
    If $oTemp.HighPart = 0x80000000 And $oTemp.LowPart = 0x00000000 Then
        $aPwdInfo[5] = 0 ; Account has to be unlocked manually by an admin
    Else
        $aPwdInfo[5] = __AD_Int8ToSec($oTemp) / 60 ; Convert to Minutes
    EndIf
    $aPwdInfo[6] = $oObject.Get("lockoutThreshold")
    $aPwdInfo[7] = __AD_Int8ToSec($oObject.Get("lockoutObservationWindow")) / 60 ; Convert to Minutes
    Local $oUser = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sObject)
    Local $sPwdLastChanged = $oUser.Get("PwdLastSet")
    Local $iUAC = $oUser.userAccountControl
    ; Has user account password been changed before?
    If $sPwdLastChanged.LowPart = 0 And $sPwdLastChanged.HighPart = 0 Then
        $iError += 3
        $aPwdInfo[8] = "1601/01/01 00:00:00"
        $aPwdInfo[10] = "1601/01/01 00:00:00"
    Else
        Local $sTemp = DllStructCreate("dword low;dword high")
        DllStructSetData($sTemp, "Low", $sPwdLastChanged.LowPart)
        DllStructSetData($sTemp, "High", $sPwdLastChanged.HighPart)
        ; Have to convert to SystemTime because _Date_Time_FileTimeToStr has a bug (#1638)
        Local $sTemp2 = _Date_Time_FileTimeToSystemTime(DllStructGetPtr($sTemp))
        $aPwdInfo[10] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        ; Convert PwdlastSet from UTC to Local Time
        $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2))
        $aPwdInfo[8] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        ; Is user account password set to expire?
        If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Or $aPwdInfo[1] = 0 Then
            If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Then $iError += 2
            If $aPwdInfo[1] = 0 Then $iError += 4 ; The Maximum Password Age is set to 0 in the domain. Therefore, the password does not expire
        Else
            $aPwdInfo[11] = _DateAdd("d", $aPwdInfo[1], $aPwdInfo[10])
            $sTemp2 = _Date_Time_EncodeSystemTime(StringMid($aPwdInfo[11], 6, 2), StringMid($aPwdInfo[11], 9, 2), StringMid($aPwdInfo[11], 1, 4), StringMid($aPwdInfo[11], 12, 2), StringMid($aPwdInfo[11], 15, 2), StringMid($aPwdInfo[11], 18, 2))
            ; Convert PasswordExpires from UTC to Local Time
            $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2))
            $aPwdInfo[9] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        EndIf
    EndIf
    $aPwdInfo[12] = $oObject.Get("pwdProperties")
    Return SetError($iError, 0, $aPwdInfo)
EndFunc   ;==>_AD_GetPasswordInfoEX

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted (edited)

This should work as well. Could you please test both versions?

#include <AD.au3>
_AD_Open()
If _AD_IsObjectLockedEX("timtest") Then
    ConsoleWrite("locked. @error = " & @error & ", @extened = " & @extended & @CRLF)
Else
    ConsoleWrite("not locked. @error = " & @error & ", @extened = " & @extended & @CRLF)
    _AD_Close()
EndIf

Func _AD_IsObjectLockedEX($sObject = @UserName)
    If Not _AD_ObjectExists($sObject) Then Return SetError(1, 0, 0)
    Local $sProperty = "sAMAccountName"
    If StringMid($sObject, 3, 1) = "=" Then $sProperty = "distinguishedName"; FQDN provided
    $__oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain & ">;(" & $sProperty & "=" & $sObject & ");ADsPath;subtree"
    Local $oRecordSet = $__oAD_Command.Execute ; Retrieve the ADsPath for the object
    Local $sLDAPEntry = $oRecordSet.fields(0).Value
    Local $oObject = __AD_ObjGet($sLDAPEntry) ; Retrieve the COM Object for the object
    Local $oLockoutTime = $oObject.LockoutTime
    ; Object is not locked out
    If Not IsObj($oLockoutTime) Then Return
    ; Calculate lockout time (UTC)
    Local $sLockoutTime = _DateAdd("s", Int(__AD_LargeInt2Double($oLockoutTime.LowPart, $oLockoutTime.HighPart) / (10000000)), "1601/01/01 00:00:00")
    ; Object is not locked out
    If $sLockoutTime = "1601/01/01 00:00:00" Then Return
    ; Get password info - Account Lockout Duration
    Local $aTemp = _AD_GetPasswordInfoEX($sObject)
    ; if lockout duration is 0 (= unlock manually by admin needed) then no calculation is necessary. Set @error to -1 (minutes till the account is unlocked)
    If $aTemp[5] = 0 Then Return SetError(-1, 0, 1)
    ; Calculate when the lockout will be reset
    Local $sResetLockoutTime = _DateAdd("n", $aTemp[5], $sLockoutTime)
    ; Compare to current date/time (UTC)
    Local $sNow = _Date_Time_GetSystemTime()
    $sNow = _Date_Time_SystemTimeToDateTimeStr($sNow, 1)
    If $sResetLockoutTime >= $sNow Then Return SetError(_DateDiff("n", $sNow, $sResetLockoutTime), 0, 1)
    Return
EndFunc   ;==>_AD_IsObjectLockedEX

Func _AD_GetPasswordInfoEX($sObject = @UserName)
    If _AD_ObjectExists($sObject) = 0 Then Return SetError(1, 0, "")
    If StringMid($sObject, 3, 1) <> "=" Then $sObject = _AD_SamAccountNameToFQDN($sObject) ; sAMAccountName provided
    Local $iError = 0
    Local $aPwdInfo[13] = [12]
    Local $oObject = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain)
    $aPwdInfo[1] = Int(__AD_Int8ToSec($oObject.Get("maxPwdAge"))) / 86400 ; Convert to Days
    $aPwdInfo[2] = __AD_Int8ToSec($oObject.Get("minPwdAge")) / 86400 ; Convert to Days
    $aPwdInfo[3] = $oObject.Get("pwdHistoryLength")
    $aPwdInfo[4] = $oObject.Get("minPwdLength")
    ; Account lockout duration: http://msdn.microsoft.com/en-us/library/ms813429.aspx
#cs
    Local $oTemp = $oObject.Get("lockoutDuration")
    If $oTemp.HighPart = 0x80000000 And $oTemp.LowPart = 0x00000000 Then
        $aPwdInfo[5] = 0 ; Account has to be unlocked manually by an admin
    Else
        $aPwdInfo[5] = __AD_Int8ToSec($oTemp) / 60 ; Convert to Minutes
    EndIf
#ce
    $aPwdInfo[5] = __AD_Int8ToSec($oObject.Get("lockoutDuration")) / 60 ; Convert to Minutes
    If $aPwdInfo[5] < 0 Or $aPwdInfo[5] > 99999 Then $aPwdInfo[5] = 0
    $aPwdInfo[6] = $oObject.Get("lockoutThreshold")
    $aPwdInfo[7] = __AD_Int8ToSec($oObject.Get("lockoutObservationWindow")) / 60 ; Convert to Minutes
    Local $oUser = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sObject)
    Local $sPwdLastChanged = $oUser.Get("PwdLastSet")
    Local $iUAC = $oUser.userAccountControl
    ; Has user account password been changed before?
    If $sPwdLastChanged.LowPart = 0 And $sPwdLastChanged.HighPart = 0 Then
        $iError += 3
        $aPwdInfo[8] = "1601/01/01 00:00:00"
        $aPwdInfo[10] = "1601/01/01 00:00:00"
    Else
        Local $sTemp = DllStructCreate("dword low;dword high")
        DllStructSetData($sTemp, "Low", $sPwdLastChanged.LowPart)
        DllStructSetData($sTemp, "High", $sPwdLastChanged.HighPart)
        ; Have to convert to SystemTime because _Date_Time_FileTimeToStr has a bug (#1638)
        Local $sTemp2 = _Date_Time_FileTimeToSystemTime(DllStructGetPtr($sTemp))
        $aPwdInfo[10] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        ; Convert PwdlastSet from UTC to Local Time
        $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2))
        $aPwdInfo[8] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        ; Is user account password set to expire?
        If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Or $aPwdInfo[1] = 0 Then
            If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Then $iError += 2
            If $aPwdInfo[1] = 0 Then $iError += 4 ; The Maximum Password Age is set to 0 in the domain. Therefore, the password does not expire
        Else
            $aPwdInfo[11] = _DateAdd("d", $aPwdInfo[1], $aPwdInfo[10])
            $sTemp2 = _Date_Time_EncodeSystemTime(StringMid($aPwdInfo[11], 6, 2), StringMid($aPwdInfo[11], 9, 2), StringMid($aPwdInfo[11], 1, 4), StringMid($aPwdInfo[11], 12, 2), StringMid($aPwdInfo[11], 15, 2), StringMid($aPwdInfo[11], 18, 2))
            ; Convert PasswordExpires from UTC to Local Time
            $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2))
            $aPwdInfo[9] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1)
        EndIf
    EndIf
    $aPwdInfo[12] = $oObject.Get("pwdProperties")
    Return SetError($iError, 0, $aPwdInfo)
EndFunc   ;==>_AD_GetPasswordInfoEX
Edited by water

My UDFs and Tutorials:

  Reveal hidden contents

 

Posted

Locks great.

I think I will change the UDF to version 2. Because this is the only function I understand how it works ;)

My UDFs and Tutorials:

  Reveal hidden contents

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...