Implementing RBCD

Isaac Boukris iboukris at
Thu Mar 21 18:20:27 EDT 2019


I'm working on implementing resource-based-constrained-delegation
functionality in MIT code, which moves the authorization attributes
from the impersonating account to the target account and essentially
allows for cross-realm S4U2Proxy.

I've uploaded some network traces of RBCD exchange to:

Here are the changes to the flow, compared to the old protocol as far
as I understand, based partly on MS-SFU but mostly on observations
(including some of my own interpretation).

Intro note: service-a is the impersonating service, and service-b is
the target one. Also note, a new padata PA-PAC-OPTIONS was added, for
the client to signal that it supports rbcd (in the relevant requests),
and for the KDC to ack on it via returned encrypted padata.

1) First, service-a acquires a ticket on behalf of the client to self
(regular or via S4U2Self). According to MS-SFU the ticket is
no longer required to be forwardable, but in that case, conditions may
a) the service has to check whether the impersonated client is
sensitive and not allowed to be delegated, by checking the relevant
bit in UserAccountControl field in the KERB_VALIDATION_INFO inside the
PAC. If the client is sensitive the service must fail the request.
b) otherwise, if the ticket is not forwardable but the client is
nonsensitive then the service SHOULD locate a DS_BEHAVIOR_WIN2012 DC
for the following S4U2Proxy request (presumably, a KDC that does not
support rbcd will reject a non-forwardable ticket).

[notes: both these requirements are challenging:
The first would involve full decoding of the PAC, while I think it
could be a good idea to have it in krb5 library (for other purposes as
well), I only have a vague idea of what NDR decoding actually means,
and as far as I remember Greg was not fond of this idea in the past.
However I think it may not be a must, since the next KDC MUST do the
same check anyway (per MS-SFU and we could also check the
reply encrypted-padata to make sure the KDC supports rbcd.
The second requirement involves an RPC call (as per MS-KILE) but here
as well I think we could skip it and just try other KDCs in case of

2) At this point we assume the service has an SPN of the target
service (with no realm), so it sends an S4U2Proxy request to a KDC in
its own realm including padata PA-PAC-OPTIONS. If service a and b are
in the same realm then the KDC replies with a service ticket and
that's it. If however service-b is in a different realm, the KDC
replies with a referral TGT to the next realm where cname is still of
service-a but the PAC is of the impersonated client, to be used as a
secondary-referral later on. In addition, the PAC includes
PAC_S4U_DELEGATION_INFO field, and it is signed including the realm -
same as in cross-realm S4U2Self requests.

3) Now, service-a needs to identify service-b's realm, and to acquire
referral TGT on behalf of itself to that realm. To do so, service-a
requests a simple ticket to service-b from its own realm, follows
referrals till it gets a service ticket, and voila it knows the target
realm and has a referral TGT for it.
Then, using the secondary-referral as tgt (with the PAC of the
impersonated client), service-a requests a TGT referral to the target
realm (that is, sname is krbtgt) and follows referrals as necessary
(from a KDC in the realm of the secondary-referral). Note that in case
of a direct trust (not transitive) the secondary-referral is already
for the target realm and no actual request is needed (also note that
if a krbtgt request is needed, Windows client adds padata
PA-PAC-OPTIONS so we should add it too, but it looks like Windows KDC
doesn't care about it).

4) The next step, using its own referral as tgt, and the
secondary-referral as secondary ticket, service-a requests a S4U2Proxy
requests from a KDC in target realm including padata PA-PAC-OPTIONS
and the KDC replies with a service ticket where the cname is of the
impersonated client (and so is the PAC).
I'm not sure where it takes the client name from, I suspect it takes
it from the PAC signature by decomposing it, since the name-type gets
lost in the process and it always ends up as KRB5_NT_MS_PRINCIPAL
(which also means this type name supports enterprise-name like, with
an @ sign).

So far, I managed to get MIT client to work against Windows KDC, see POC at:

Note, the last commit fixes referrals to work correctly in transitive
trust which I didn't get right at first. I didn't want to squash since
it is more horrible than the first one (as soon as I get something
presentable I'll open a wip PR).

My planning is currently as follows:
- implement the client code properly, I think it might be a good idea
to move some logic from get_creds.c to s4u_creds.c to simplify it
(especially the referral-chasing), but I'm still unclear.
- add basic KDC support, leaving authdata handling to KDB plugin (but
we might need to provide it with more info).
- add tests, possibly using own authdata implementation (similar to
what I experiment with in PR 894).
- manually test windows clients against MIT KDC by plugging it with (a
patched) SambaAD (I'd also try to test trust with Windows KDC).



More information about the krbdev mailing list