Krb5 1.10 — add default referral feature


## FEATURE

Two new realm configuration parameters:

* `default_referral_realm` (string, default none)
* `cross_realm_default_referral` (boolean, default false)

If default_referral_realm is set, then the KDC will issue referrals to the specified realm for TGS requests otherwise qualifying for a referral but lacking a static realm mapping, as long as the presented TGT is not cross-realm (setting `cross_realm_default_referral` omits that check).

## RATIONALE

I’ll explain by way of the real motivating situation for us. We have two realms:

  AD: Windows AD
UNIX: MIT Kerberos on Unix

We have two-way trust between these realms, and AD provides referrals to Unix via top-level name translation rules. Our hosts have a mix of realms in the same DNS domains, so static realm-mapping rules don’t work for us; we use _kerberos DNS TXT records for Unix clients to get host realm memberships. Consider the scenario of a client with Unix TGT accessing a Windows-realm service, say an OpenSSH client logging into the Bitvise WinSSHD server.

1. client acquires TGT for user@UNIX -> krbtgt/UNIX@UNIX
1. client correctly identifies the server in the AD realm
1. client obtains a cross-realm ticket krbtgt/AD@UNIX from Unix
1. client uses that to obtain an SSH service ticket host/foo@AD
1. client successfull logs into the SSH server (we use AD altSecurityIdentity attributes to authorize Unix principals to their corresponding AD accounts)

So far, so good. However, the client also requests GSSAPI delegation via SSH. This succeeds, and klist on the Windows side shows a forwarded TGT for krbtgt/AD@UNIX. This TGT works for accessing further Unix-realm services -- but access to AD services fails, even though the analogous situation with a Unix client would succeed.

The reason this fails is that Windows always assumes the realm of the TGT issuer for all requests, and relies on referrals to locate the correct realm if necessary. Say the remote Windows session now wants to access LDAP on a domain controller dc; Windows then queries a Unix KDC for ldap/dc@UNIX (because the TGT was issued by the Unix realm). This fails, because our Unix KDCs do not issue referrals.

The MIT KDC can do referrals, but only for hosts with static realm mappings in krb5.conf. Since in our case the realm mappings are in the DNS, this doesn’t work for us.

My patch allows the KDC to issue referrals to a designated default realm, in our case the AD realm. The trick is to avoid referral loops, and I do that by refusing to issue a default referral if the presented TGT is cross-realm; this indicates that the client has already consulted the other realm, so sending them back again would be pointless.

Certainly, using this feature with more than two realms would be less straightforward, and there are various corner cases to consider. However, I imagine our case may be quite common, and it has proved to solve the problem perfectly for us, so I thought I’d send it along for consideration. Other use cases include Unix clients using delegation to Microsoft SQL Server for “bulk insert” (in which the dataserver accesses a CIFS filesystem using the client’s credentials), and “chained queries” (in which the dataserver issues further queries to other dataservers using the client’s credentials).

This does have the unfortunate effect of making some error messages less comprehensible. For example, a client which requests a ticket for a non-existent principal may bounce through two referrals back to a Unix KDC, which then answers with a KDC policy error due to the lineage check, rather than “no such principal.” It might be good to re-order the lineage check to restore a more helpful error message. Actually, in my case I may remove the lineage check altogether, since it doesn’t apply to me: I have only two realms and they are both mine, so I am not worried about rogue transitively-trusted realms not under my control.

Thanks,

Richard E. Silverman