AD Is Full of Bitmasks, Decipher Them with Powershell

Active Directory uses bit masks, or bit fields, or bit flags or bit maps or whatever you want to call them.  Anyway, AD uses them, a lot.  Let's say you're digging deep into Active Directory internals, and you want to see all the attributes in your schema that are eligible for being made confidential.  We know that something called "base schema attributes" cannot be made confidential, and that we know whether an attribute is a base schema attribute or not based on a certain bit that is set in that attribute's systemFlags attribute.

Get-ADObject -LDAPFilter "(objectClass=attributeSchema)" `
             -SearchBase (Get-ADRootDSE).schemaNamingContext `
             -Properties SystemFlags

That'll give us all attributes (regardless to what type of object they apply) in the schema, including their systemFlags property.  Problem is, the systemFlags property is all condensed into an integer, and unless you're Rain Man and have no problems doing it all in your head, you might like it if that systemFlags property were translated into something more meaningful.

This is where the magic of enumerations comes in.

Add-Type -TypeDefinition @'
    [System.Flags]
    public enum SystemFlagsAttr : uint
    {
        FLAG_ATTR_NOT_REPLICATED         = 0x00000001,
        FLAG_ATTR_REQ_PARTIAL_SET_MEMBER = 0x00000002,
        FLAG_ATTR_IS_CONSTRUCTED         = 0x00000004,
        FLAG_ATTR_IS_OPERATIONAL         = 0x00000008,
        FLAG_SCHEMA_BASE_OBJECT          = 0x00000010,
        FLAG_ATTR_IS_RDN                 = 0x00000020,
        FLAG_DISALLOW_MOVE_ON_DELETE     = 0x02000000,
        FLAG_DOMAIN_DISALLOW_MOVE        = 0x04000000,
        FLAG_DOMAIN_DISALLOW_RENAME      = 0x08000000,
        FLAG_CONFIG_ALLOW_LIMITED_MOVE   = 0x10000000,
        FLAG_CONFIG_ALLOW_MOVE           = 0x20000000,
        FLAG_CONFIG_ALLOW_RENAME         = 0x40000000,
        FLAG_DISALLOW_DELETE             = 0x80000000
    }
'@

So a smart reader already knows that since we are looking for "base schema objects," which in the enum above equates to 0x10 hex, which is 16 decimal which is the fourth bit... then it becomes pretty easy to spot all the attributes that have a SystemFlags of 16 in our above Powershell command. But what about when bit 4 and bit 2 and bit 26 are all turned on?  This is why enums are our friends.  Let's retry our Powershell command using the enum now:

Get-ADObject -LDAPFilter "(objectClass=attributeSchema)" `
             -SearchBase (Get-ADRootDSE).schemaNamingContext `
             -Properties SystemFlags | `
             Select Name, `
             @{n='SystemFlags'; e={[Enum]::Parse('SystemFlagsAttr', $_.SystemFlags)}}

Now it's a lot more readable:

...
ms-DS-Service-AuthN-Policy-BL    FLAG_ATTR_NOT_REPLICATED, FLAG_SCHEMA_BASE_OBJECT
ms-DS-Assigned-AuthN-Policy      FLAG_SCHEMA_BASE_OBJECT
ms-DS-Assigned-AuthN-Policy-BL   FLAG_ATTR_NOT_REPLICATED, FLAG_SCHEMA_BASE_OBJECT
...

Pretty easy to filter those results and see which attributes are base schema attributes, and which are not.

Lastly, as an exercise I will leave to the reader, you can also use the SearchFlags (not SystemFlags) property of an attribute to determine whether the attribute is already set as confidential or not.

    [System.Flags]
    public enum SearchFlags
    {
        fATTINDEX              = 0x0001,
        fPDNTATTINDEX          = 0x0002,
        fANR                   = 0x0004,
        fPRESERVEONDELETE      = 0x0008,
        fCOPY                  = 0x0010,
        fTUPLEINDEX            = 0x0020,
        fSUBTREEATTINDEX       = 0x0040,
        fCONFIDENTIAL          = 0x0080,
        fNEVERVALUEAUDIT       = 0x0100,
        fRODCFilteredAttribute = 0x0200,
        fEXTENDEDLINKTRACKING  = 0x0400,
        fBASEONLY              = 0x0800,
        fPARTITIONSECRET       = 0x1000
    }
Comments are closed