Skip to content

Conversation

MaximeKjaer
Copy link
Contributor

What's the problem?

The current handling of cname is not always spec-compliant. The spec requires the Kerberos server to essentially echo back cname and crealm to the client. However, in some scenarios, Kerberos.NET responds with a slightly different cname.

This is an issue for Kerberos clients that check that the cname in the response exactly matches what was in the request (such as MIT krb5, see code pointer).

The current handling of cname is only subtly wrong. It works in the most common scenario (let's call this scenario 1), where:

  • cname is ["username", "realm"]
  • crealm is "realm"

However, it does not work in this scenario (let's call this scenario 2):

  • cname is ["username"]
  • crealm is "realm"

This latter scenario can occur in practice. For instance, see the Wireshark trace below, where a Linux client got a referral TGT from an on-prem AD DS server. The cname only has one part.

image

Using this referral TGT gave

  • Bugfix
  • New Feature

What's the solution?

Currently Kerberos.NET uses crealm and cname from the request to Find an IKerberosPrincipal, and then re-constructs cname and crealm fields in the response from the found principal.

However, this conversion from cname/crealm to IKerberosPrincipal isn't injective. In both scenarios 1 and 2, we can find the same client principal from the cname and crealm fields. When we convert that principal back to cname and crealm, we don't necessarily get the same values back.

The solution is to copy cname and crealm from the request. This aligns with the spec, section 3.3.3 Generation of KRB_TGS_REP Message:

By default, the address field, the client's name and realm, the list of transited realms, the time of initial authentication, the expiration time, and the authorization data of the newly-issued ticket will be copied from the TGT or renewable ticket.

  • Includes unit tests
  • Requires manual test

What issue is this related to, if any?

None.

{
if (request.ClientName == null)
{
throw new InvalidOperationException("Client name must be provided when IsolateRealmsConsistently is set");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a little hacky to reuse IsolateRealmsConsistently, but adding a second flag maybe feels like overkill.

Also, if no client name is set, we could fall back to inferring it from the request.Principal -- just to maintain backwards compat. But falling back to cname inferred from request.Principal means the response might not be spec-compliant (cname could be different from what's in the request)

@MaximeKjaer MaximeKjaer changed the title Fix cname handling Ensure cname precisely matches what was in request Oct 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant