joeware - never stop exploring... :)

Information about joeware mixed with wild and crazy opinions...

AdFind -filterbreakdown

by @ 8:13 pm on 11/26/2008. Filed under tech

So you have this big nasty LDAP filter and for some reason it isn’t working and by that I mean when you submit the query it comes back and says invalid filter or maybe it doesn’t return what you expect for the data set. You know if you could just see the filter in a “nice” format you could probably figure out what is going on…

Well certainly I have thought that on more than one occasion and usually it was Exchange or sometimes some third party app that generated that nasty LDAP filter that I had to try and figure out what was wrong with…

For example… say you have this lovely filter (some of you may recognize it…)

(& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(!(homeMDB=*))(!(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=user)(|(homeMDB=*)(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=contact))(objectCategory=group)(objectCategory=publicFolder)(objectCategory=msExchDynamicDistributionList) ))

Certainly that is easy to read… (reread with sarcastic sneer…)

If you have enough permissions on the Domain Controller you can throw it through AdFind with the -stats+ or -stats+only switches and you get to see something like

Filter Breakdown:

(
(&
   (mailNickname=*)
   (|
     (&
       (objectCategory=CN=Person,CN=Schema,CN=Configuration,DC=joeware,DC=local)
       (objectClass=user)
       (!
         (homeMDB=*)
       )
       (!
         (msExchHomeServerName=*)
       )
     )
     (&
       (objectCategory=CN=Person,CN=Schema,CN=Configuration,DC=joeware,DC=local)
       (objectClass=user)
       (|
         (homeMDB=*)
         (msExchHomeServerName=*)
       )
     )
     (&
       (objectCategory=CN=Person,CN=Schema,CN=Configuration,DC=joeware,DC=local)
       (objectClass=contact)
     )
     (objectCategory=CN=Group,CN=Schema,CN=Configuration,DC=joeware,DC=local)
     (objectCategory=CN=ms-Exch-Public-Folder,CN=Schema,CN=Configuration,DC=joeware,DC=local)
     (objectCategory=CN=ms-Exch-Dynamic-Distribution-List,CN=Schema,CN=Configuration,DC=joeware,DC=local)
   )
)
)

which is at least an order of magnitude easier to read.

But what if your filter is…

(& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(!(homeMDB=*))((!(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=user)(|(homeMDB=*)(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=contact))(objectCategory=group)(objectCategory=publicFolder)(objectCategory=msExchDynamicDistributionList) ))

and you run that through AdFind…

The filter is syntactically incorrect (can you see the error?) so you will see…

ldap_get_next_page_s: [JOEWARE-DC1.joeware.local] Error 0x57 (87) – Filter Error

Yeah that isn’t so helpful and –stats doesn’t make it any more helpful because there is no stats info coming back from the server. So then you stare at it for a while, curse the LDAP format, maybe twirl your pencil, try to figure out who to send it to to tell you what is wrong with it (and I am not the person despite the hundreds of requests I get to look at LDAP filters…). Etc etc etc ad nauseum… Until finally you paste it into notepad or some other text editor and start manually breaking it up…

I was doing that for like the thousandth time in my career and said, god, someone should write a tool that can parse this out like my AdFind does for the STATS output… and then I sat back, smacked my forehead. Yes, I am not always super bright with things I personally need…  So I started looking at the AdFind source to see how easy I could break this little functionality out of that portion of my code. When I did that I also reworked the parsing logic because quite frankly, it did not follow the K.I.S.S philosophy of “Keep It Simple Dumbass”. The new function is cleaner and more stable.

So now you can do something like

F:\Dev\Current\CPP\AdFind\Debug>adfind -filterbreakdown "(& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(!(homeMDB=*))((!(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=user)(|(homeMDB=*)(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=contact))(objectCategory=group)(objectCategory=publicFolder)(objectCategory=msExchDynamicDistributionList) ))"

AdFind V01.39.00cpp ***BETA*** Joe Richards (joe@joeware.net) November 2008

Filter Breakdown:

(&
  (mailnickname=*)
  (|
    (&
      (objectCategory=person)
      (objectClass=user)
      (!
        (homeMDB=*)
      )
      (
       (!
         (msExchHomeServerName=*)
       )
      )
      (&
        (objectCategory=person)
        (objectClass=user)
        (|
          (homeMDB=*)
          (msExchHomeServerName=*)
        )
      )
      (&
        (objectCategory=person)
        (objectClass=contact)
      )
      (objectCategory=group)
      (objectCategory=publicFolder)
      (objectCategory=msExchDynamicDistributionList)
    )
  )

WARNING: Parens don’t match up properly, not all open
         parens were matched with close parens.

Note: This is not necessarily the filter that the query processor will
      process, instead it is a simple text parsing of the supplied filter.

 

And here is the same filter without the mistake

F:\Dev\Current\CPP\AdFind\Debug>adfind -filterbreakdown "(& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(!(homeMDB=*))(!(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=user)(|
(homeMDB=*)(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=contact))(objectCategory=group)(objectCategory=publicFolder)(objectCategory=msExchDynamicDistributionList) ))"

AdFind V01.39.00cpp ***BETA*** Joe Richards (joe@joeware.net) November 2008

Filter Breakdown:

(&
  (mailnickname=*)
  (|
    (&
      (objectCategory=person)
      (objectClass=user)
      (!
        (homeMDB=*)
      )
      (!
        (msExchHomeServerName=*)
      )
    )
    (&
      (objectCategory=person)
      (objectClass=user)
      (|
        (homeMDB=*)
        (msExchHomeServerName=*)
      )
    )
    (&
      (objectCategory=person)
      (objectClass=contact)
    )
    (objectCategory=group)
    (objectCategory=publicFolder)
    (objectCategory=msExchDynamicDistributionList)
  )
)

Note: This is not necessarily the filter that the query processor will
      process, instead it is a simple text parsing of the supplied filter.

 

Still not the EASIEST to see the problem but it is a heck of lot easier to see than it was before.

Here is an example of a non-Exchange related filter

(&(&(objectcategory=person)(objectclass=user)(!(cn=_*))(!(userAccountControl:1.2.840.113556.1.4.803:=65536))(!(isCriticalSystemObject=TRUE)))(&(whenChanged<=20081120000000.0Z)(|(&(whenCreated<=20080926000000.0Z)(|(&(pwdLastSet<=128669508314632476)(lastlogontimestamp<=128669508314632476))(&(pwdLastSet<=128617668314632476)(pwdLastSet>=1))(&(lastlogontimestamp=*)(pwdLastSet=0)(lastlogontimestamp<=128669508314632476))))(&(!(lastlogontimestamp=*))(pwdLastSet=0)(whenCreated<=20081026000000.0Z)))))

and here it is after going through the filter breakdown in AdFind…

(&
  (&
    (objectcategory=person)
    (objectclass=user)
    (!
      (cn=_*)
    )
    (!
      (userAccountControl:1.2.840.113556.1.4.803:=65536)
    )
    (!
      (isCriticalSystemObject=TRUE)
    )
  )
  (&
    (whenChanged<=20081120000000.0Z)
    (|
      (&
        (whenCreated<=20080926000000.0Z)
        (|
          (&
            (pwdLastSet<=128669508314632476)
            (lastlogontimestamp<=128669508314632476)
          )
          (&
            (pwdLastSet<=128617668314632476)
            (pwdLastSet>=1)
          )
          (&
            (lastlogontimestamp=*)
            (pwdLastSet=0)
            (lastlogontimestamp<=128669508314632476)
          )
        )
      )
      (&
        (!
          (lastlogontimestamp=*)
        )
        (pwdLastSet=0)
        (whenCreated<=20081026000000.0Z)
      )
    )
  )
)

Its actually sort of readable!!!

This is but one cool change amongst a bunch of changes in the new version of AdFind. As mentioned previously, the goal for the release of AdFind V01.39.00 is sometime towards the end of December.

 

   joe

Rating 3.00 out of 5

4 Responses to “AdFind -filterbreakdown”

  1. Scotte says:

    Now the parens just need to be color coded and we’ll be all set. 🙂

    Nice job.

  2. Tomek says:

    That’s cool … I will sent this to some exchange admins struggling with weired queries for GALs in their organizations.

  3. Pat says:

    Rocks as always 🙂 I guess it shouldn’t be that complicated to even find where the filter is lacking the opening/closing bracket. BTW I dont think coloring this stuff is going to be very helpfull while running in cmd.exe ;-). Keep up the good work 🙂

  4. Mike Kline says:

    adfind just keeps getting better, I keep telling people to use it. This is going to be very helpful. Thanks again joe!!

[joeware – never stop exploring… :) is proudly powered by WordPress.]