How can I configure server wide cross realm authentication on an openssh server using kerberos without having to add principles for both realms in the .k5login file?


When given an account name (provided by SSH) and a principal name, the Kerberos library uses the krb5_kuserok() function to allow or deny access.

By default, krb5_kuserok() allows access if the principal name is listed in ~/.k5userok. If that file doesn't exist, it checks whether the krb5_aname_to_localname() function returns the same account name.

Now, by default, krb5_aname_to_localname() returns the principal name (without realm) if the principal has exactly one name component and its realm exactly matches the system's default realm; otherwise it returns the whole principal name with realm.

So the easiest way to change this is to teach krb5_aname_to_localname() how to translate foreign principal names. There are several methods:

If you want a simple one-to-one mapping for the whole realm, you can write a translation rule in krb5.conf that simply removes the realm. (Note that these examples are for MIT Kerberos; you will need to adjust them somewhat for Heimdal.)

        NULLROUTE.EU.ORG = {
                auth_to_local = RULE:[1:$1@$0](.*@EXAMPLE\.COM)s/@.*//
                auth_to_local = RULE:[1:$1@$0](.*@ATHENA\.MIT\.EDU)s/@.*/@athena/
                auth_to_local = DEFAULT

In this example, [1:...] checks that the "local" (left) side has exactly one component; [1:$1@$0] constructs a single string from the 1st component + an @ + the realm name (essentially resulting in the original principal name); (.*@EXAMPLE\.COM) matches the constructed string against a regex to verify that it ends with a specified realm name; s/@.*// replaces the regex @.* (everything following the @ sign) with an empty string. The result will be used as the system account name.

The second rule works the same way, but replaces the realm with "@athena", resulting in usernames like root@athena. I'm just including it as an example as the SSSD LDAP/AD client can use this syntax, allowing for multiple realms per host.

The third rule just what I've described in the beginning.

If you only want to map specific names, you can add an auth_to_local_names section; the configuration would look like this: (note: Heimdal uses auth_to_local)

        default_realm = NULLROUTE.EU.ORG

        NULLROUTE.EU.ORG = {
                auth_to_local_names = {
                        grawity/admin@EXAMPLE.COM = grawity
                        root@ATHENA.MIT.EDU = root

This translates only two principal names into a single local account.

If you're looking for an automated method, recent versions of MIT Kerberos have an API for "localauth" plugins which can provide their own implementations for both the authorization check as well as the principal/account translation.

For example, the SSSD IPA/AD client has recently (about a month ago) started providing its own plugin for translating principal names of FreeIPA and Active Directory users.

  • 1
    Thanks grawity. Your 1st solution was spot on. I will note that you have to have the auth_to_local = DEFAULT line too for the local REALM to function. – Iain Conochie Sep 9 '14 at 12:32
  • You deserve so many more points for this than you got. This answer set me on the right direction to fixing our setup to work without .k5login files. We ended up using a rule like RULE:[1:$1@$0], which works in conjunction with RFC tools.ietf.org/html/rfc6806.html – Ben Aug 5 '15 at 6:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.