Canonical clients in AS-REQ for non-TGS server principals
Jakob Uhd Jepsen
juj at one.com
Tue Feb 7 09:58:54 EST 2017
I have run into a limitation of the AS-REQ protocol, when used with
canonical clients, that I am not sure why exists. Our code is using v
1.12.1 kerberos, though from what I can tell, this bit has not been
changed in a long time and is still present in the latest release
version. It was introduced back in 2009 in commit
589ad211b633c9319a074c032c47db6b7bd62237
The relevant method is verify_as_reply in get_in_tkt.c
What I am attempting to do, it use an AS-REQ/AS-REP exchange to get a
ticket from an NT-ENTERPRISE client to a service, that is *not* the TGS
service. I do not want a TGT, but a direct service ticket. I also want
the client to be the canonical client. It seems this is not allowed, and
I am trying to understand why. There are no cross-realm shennanigans in
out setup to complicate matters.
(For context, I've pasted in the relevant code at the bottom of this).
Specifically, the canon_req field is set for a canonicalize request or
an enterprise client. In the case of client canoncialization, both of
these will be true. Yet due to the stipulation that the server principal
be a TGS for canon_ok to be true, we end up in the if branch following
this. Here, the AS-REP is checked to see if the request client and the
as_reply client are identical. If the KDC canonicalized the client, this
may not be the case, and the whole exchanged ends up with a
KRB5_KDCREP_MODIFIED error.
It doesn't seem that the intent of the comment to prevent servers to
change, matches the full effect of the code, when used in this manner.
Is there are reason I'm not seeing, why canonicalizing client names in
this instance should not be allowed?
/*
* We only allow the AS-REP server name to be changed if the
* caller set the canonicalize flag (or requested an enterprise
* principal) and we requested (and received) a TGT.
*/
canon_req = ((request->kdc_options & KDC_OPT_CANONICALIZE) != 0) ||
request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL ||
(request->kdc_options & KDC_OPT_REQUEST_ANONYMOUS);
if (canon_req) {
canon_ok = IS_TGS_PRINC(request->server) &&
IS_TGS_PRINC(as_reply->enc_part2->server);
if (!canon_ok && (request->kdc_options &
KDC_OPT_REQUEST_ANONYMOUS)) {
canon_ok = krb5_principal_compare_any_realm(context,
as_reply->client,
krb5_anonymous_principal());
}
} else
canon_ok = 0;
if ((!canon_ok &&
(!krb5_principal_compare(context, as_reply->client,
request->client) ||
!krb5_principal_compare(context, as_reply->enc_part2->server,
request->server)))
|| !krb5_principal_compare(context,
as_reply->enc_part2->server, as_reply->ticket->server)
....
<SNIP>
.....
} return KRB5_KDCREP_MODIFIED;
--
--
Jakob Uhd Jepsen
Systems Engineer
juj at one.com
More information about the krbdev
mailing list