8

I have googled how to list locked out accounts and found two methods so far, both of which don't work...

Saved query - (&(&(&(objectCategory=Person)(objectClass=User)(lockoutTime>=1))))

Lists a number of accounts, many of which are not locked out. If I unlock one that I happen to know is locked out, it still gets returned by the query.

Powershell command - Search-ADAccount -LockedOut

Does nothing.

So either - Am I doing something wrong? Or - Is there a method that actually works?

MrVimes
  • 773
  • 2
  • 14
  • 29
  • Just a small note: In order to manage domain with commands included in AD PowerShell module (including use of Search-ADAccount commandlet) you should have Active Directory Web Services (ADWS) service must be installed on at least one domain controller in this domain. But I guess this is not an issue because if you haven't ADWS instance you get error message notifying you about it. – Mikhail Jul 24 '13 at 07:00

1 Answers1

11

I would not necessarily trust Get-ADUser -LDAPFilter "(&(objectCategory=Person)(objectClass=User)(lockoutTime>=1))" -Properties LockedOut, as it is not returning reliable results for me either, but then, I'm also unable to directly contact my PDCe at this time. For best results, you would want to directly target your PDC-emulator, as it always has the most up-to-date information on account lockouts throughout the domain.

That's what I am wagering that you're witnessing here is a delay in replication:

... account lockout is urgently replicated to the primary domain controller (PDC) emulator role owner and is then urgently replicated to the following:

• Domain controllers in the same domain that are located in the same site as the PDC emulator.

• Domain controllers in the same domain that are located in the same site as the domain controller that handled the account lockout.

• Domain controllers in the same domain that are located in sites that have been configured to allow change notification between sites (and, therefore, urgent replication) with the site that contains the PDC emulator or with the site where the account lockout was handled. These sites include any site that is included in the same site link as the site that contains the PDC emulator or in the same site link as the site that contains the domain controller that handled the account lockout.

In addition, when authentication fails at a domain controller other than the PDC emulator, the authentication is retried at the PDC emulator. For this reason, the PDC emulator locks the account before the domain controller that handled the failed-password attempt if the bad-password-attempt threshold is reached. For more information about how the PDC emulator role owner manages password changes and account lockouts, see "Managing Flexible Single-Master Operations" in this book.

So try Search-ADAccount -LockedOut -Server DC-PDCE and see if your results are any better.

Also, here's something else to consider when building queries around the lockoutTime attribute:

This attribute value is only reset when the account is logged onto successfully. This means that this value may be non zero, yet the account is not locked out. To accurately determine if the account is locked out, you must add the Lockout-Duration to this time and compare the result to the current time, accounting for local time zones and daylight savings time.

Edit: By way of reverse engineering Microsoft.ActiveDirectory.Management.dll, I can tell you that Search-ADAccount -LockedOut, which seems to me to produce pretty reliable results, runs the following code:

else if ((bool) this._paramSet.LockedOut)
      {
        list.Add(ADAccountFactory<ADAccount>.AttributeTable[cmdletSessionInfo.ConnectedADServerType]["AccountLockoutTime"].InvokeToSearcherConverter(ADOPathUtil.CreateFilterClause(ADOperator.Ge, "AccountLockoutTime", (object) 1), cmdletSessionInfo));
        this.OutputFilterFunction = new ADGetCmdletBase<SearchADAccountParameterSet, ADAccountFactory<ADAccount>, ADAccount>.OutputFilterDelegate(this.FilterIsLockedOut);
      }
      if (list.Count > 0)
        this.OutputSearchResults(list.Count != 1 ? ADOPathUtil.CreateAndClause(list.ToArray()) : list[0]);
      else
        this.OutputSearchResults((IADOPathNode) null);

So it appears that Search-ADAccount -LockedOut is looking at the AccountLockoutTime attribute too!

Edit some more for great justice: Richard Mueller, Dir. Services MVP, says this:

You cannot use the userAccountControl attribute to identify users that are locked out. There is a bit of userAccountControl documented for this, but it is not used.

I can verify this thusly:

PS C:\Users\ryan> $(Search-ADAccount -LockedOut).Count
11
PS C:\Users\ryan> $(Get-ADUser -LDAPFilter "(&(objectCategory=User)(userAccountControl:1.2.840.113556.1.4.803:=16))").Count
0

Finally, I'd like to end on this blog post on the topic, which explains why the lockoutTime>=1 is approaching the best solution, but that's only part of the story. You need to further filter down the list to include only the users where their lockoutTime is greater than $(your domain lockout duration) minutes in the past.

Ryan Ries
  • 55,481
  • 10
  • 142
  • 199
  • I'm going to be interested to find documentation of when that `userAccountControl` bit stopped being valid. It worked fine in the past, if memory serves. It makes me wonder if the functionality was removed in a later revision of the AD code. Hmm... – Evan Anderson Jul 19 '13 at 18:26
  • Well I hate to keep appealing to authority, but Richard Mueller says it hasn't worked since Windows 2000. – Ryan Ries Jul 19 '13 at 18:41
  • I suspect that it works in Windows 2000 when there are Windows NT 4.0 Domain Controllers present, because it would need to be there to facilitate replication to DCs that have a SAM. I don't have a test environment spun up for NT 4.0 anymore (I deleted all those old VMs) but I am definitely going to try it out. There would *have* to be a way for SAM-only DCs to be able to be aware of account lockout-- that's the only way that I can see it working. – Evan Anderson Jul 19 '13 at 18:43
  • @EvenAnderson I whole-heartedly support your research and enthusiastically await your test results. :) – Ryan Ries Jul 19 '13 at 18:47