Canonical clients in AS-REQ for non-TGS server principals

Jakob Uhd Jepsen juj at
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 

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 

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) &&
         if (!canon_ok && (request->kdc_options & 
             canon_ok = krb5_principal_compare_any_realm(context,
     } 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, 
         || !krb5_principal_compare(context, 
as_reply->enc_part2->server, as_reply->ticket->server)

Jakob Uhd Jepsen
Systems Engineer
juj at

More information about the krbdev mailing list