Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / active-directory

SDK Documentation Inconsistency: Supported Kerberos Token Claims Types

5.00/5 (1 vote)
6 Oct 2022CPOL4 min read 3.8K  
When retrieving claims information from user token, SDK documentation concerning the supported data types is incorrect.
When retrieving claims information from the user token, the SDK documentation mentions that the claims can come in the form of several supported datatypes. When I was setting up a test for dealing with each type, a number of those types were impossible to set up in Active Directory. It turns out that Active Directory itself only supports a subset.

Introduction

Over the past weeks, I've been writing an open version of whoami. As part of displaying the user's token claims, I use GetTokenInformation to retrieve that information from the user token. A user or device claim can have different datatypes, which depend on the type of the attribute. However, it turned out to be impossible to test all supported datatypes.

I am documenting it here in case someone ever runs into the same issue so they don't have to spend a day tracking down the issue.

Datatype Documentation

The documentation for GetTokenInformation specifies that the following datatypes are supported for claims:

Value Meaning
CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64
0x0001

The Values member refers to an array of LONG64 values.
CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64
0x0002

The Values member refers to an array of ULONG64 values.
CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING
0x0003

The Values member refers to an array of pointers to Unicode string values.
CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN
0x0004

The Values member refers to an array of CLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE values.
CLAIM_SECURITY_ATTRIBUTE_TYPE_SID
0x0005

The Values member refers to an array of CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE values where the pValue member of each CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE is a PSID.
CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN
0x0006

The Values member refers to an array of ULONG64 values where each element indicates a Boolean value. The value 1 indicates TRUE and the value 0 indicates FALSE.
CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING
0x0010

The Values member refers to an array of CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE values.

However, no matter what I did, even after modifying the AD schema in my sandbox, I could not set up a claim with CLAIM_SECURITY_ATTRIBUTE_TYPE_SID or CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING datatype. I also didn't find CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN but that is just a string so that didn't matter. The main reason I wanted to set up those claims types was that I wanted to see how whoami displayed such claims, so that I could format my output the same way.

The Documentation Inconsistency

Eventually after a lot of searching, I found the relevant Directory Services protocol documentation. This clearly documents the datatype of user claims on the Directory Services side:

C++
typedef struct _CLAIM_ENTRY {
  CLAIM_ID Id;
  CLAIM_TYPE Type;
  [switch_is(Type), switch_type(CLAIM_TYPE)]
    union {
    [case(CLAIM_TYPE_INT64)]
      struct {
      [range(1, 10*1024*1024)] ULONG ValueCount;
      [size_is(ValueCount)] LONG64* Int64Values;
    };
    [case(CLAIM_TYPE_UINT64)]
      struct {
      [range(1, 10*1024*1024)] ULONG ValueCount;
      [size_is(ValueCount)] ULONG64* Uint64Values;
    };
    [case(CLAIM_TYPE_STRING)]
      struct {
      [range(1, 10*1024*1024)] ULONG ValueCount;
      [size_is(ValueCount), string] LPWSTR* StringValues;
    };
    [case(CLAIM_TYPE_BOOLEAN)]
      struct {
      [range(1, 10*1024*1024)] ULONG ValueCount;
      [size_is(ValueCount)] ULONG64* BooleanValues;
    };
    [default]       ;
  } Values;
} CLAIM_ENTRY,
 *PCLAIM_ENTRY;

This proves conclusively that on the Directory Services side, SID and Octet string are not supported claims types. This also means that the documentation for GetTokenInformation is incorrect.

Or rather, what I suspect is that the team who defined the interface for GetTokenInformation simply took the list of supported attribute types. Technically, every AD attribute could be used as a claims type, so rather than worry about what is currently supported as claims types, the interface has the typedefs to deal with future changes.

Thoughts about those Unsupported datatypes

After thinking about it for a bit, I've come to the conclusion that those unsupported datatypes do not make sense in the context of user claims.

Consider SID attributes. For example, if you want to link object A to object B, you could use a SID attribute. Conceivably, you could then define a claims type to put a requirement on this link. For example, only users whose user account is linked to a given SID can access resource R. Then again, you can also implement this using a Distinguished Name. It would also have the advantage that it's user readable, and transferrable when object B is migrated (because a DN can be reusable but an SID isn't).

An Octet string has even less possible use cases that I can see. It's basically a binary blob. Sure, you could put a whole lot of things into an Octet string. Hashes, encrypted information, certificates, whatever. The problem there would be for Kerberos to do something sensible with that information to make a yes / no decision about granting access. It would require a lot of additional complexity and it would essentially be something that looks suspiciously like a certificate which already has good support.

I've not seen a way to set up a FQBN claim either, but that is less of a problem because it's essentially just a string so IF we would receive it, we can read it like any other string.

Conclusion

For the purpose of testing, it is currently impossible to do anything with those unsupported datatypes, so you don't have to worry about them. The best thing to do in my opinion is to handle the datatypes that are supported, and trigger an error on the other type identifiers. Should Microsoft ever get around to support them, you at least get a proper error message.

History

  • 7th October, 2022: First version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)