3.6. Setting up Cross Realm Authentication
Cross-realm authentication is the term which is used to describe situations in which clients (typically users) of one realm use Kerberos to authenticate to services (typically server processes running on a particular server system) which belong to a realm other than their own.
For the simplest case, in order for a client of a realm named
A.EXAMPLE.COM
to access a service in the
B.EXAMPLE.COM
realm, both realms must share a key for a principal named
krbtgt/[email protected]
, and both keys must have the same key version number associated with them.
To accomplish this, select a very strong password or passphrase, and create an entry for the principal in both realms using kadmin
.
kadmin: add_principal krbtgt/[email protected]
Enter password for principal "krbtgt/[email protected]":
Re-enter password for principal "krbtgt/[email protected]":
Principal "krbtgt/[email protected]" created.
quit
kadmin: add_principal krbtgt/[email protected]
Enter password for principal "krbtgt/[email protected]":
Re-enter password for principal "krbtgt/[email protected]":
Principal "krbtgt/[email protected]" created.
quit
Use the get_principal
command to verify that both entries have matching key version numbers (kvno
values) and encryption types.
Security-conscious administrators may attempt to use the add_principal
command's -randkey
option to assign a random key instead of a password, dump the new entry from the database of the first realm, and import it into the second. This will not work unless the master keys for the realm databases are identical, as the keys contained in a database dump are themselves encrypted using the master key.
Clients in the A.EXAMPLE.COM
realm are now able to authenticate to services in the B.EXAMPLE.COM
realm. Put another way, the B.EXAMPLE.COM
realm now trusts the A.EXAMPLE.COM
realm, or phrased even more simply, B.EXAMPLE.COM
now trusts A.EXAMPLE.COM
.
This brings us to an important point: cross-realm trust is unidirectional by default. The KDC for the
B.EXAMPLE.COM
realm may trust clients from the
A.EXAMPLE.COM
to authenticate to services in the
B.EXAMPLE.COM
realm, but the fact that it does has no effect on whether or not clients in the
B.EXAMPLE.COM
realm are trusted to authenticate to services in the
A.EXAMPLE.COM
realm. To establish trust in the other direction, both realms would need to share keys for the
krbtgt/[email protected]
service (take note of the reversed in order of the two realms compared to the example above).
If direct trust relationships were the only method for providing trust between realms, networks which contain multiple realms would be very difficult to set up. Luckily, cross-realm trust is transitive. If clients from A.EXAMPLE.COM
can authenticate to services in B.EXAMPLE.COM
, and clients from B.EXAMPLE.COM
can authenticate to services in C.EXAMPLE.COM
, then clients in A.EXAMPLE.COM
can also authenticate to services in C.EXAMPLE.COM
, even if C.EXAMPLE.COM
doesn't directly trust A.EXAMPLE.COM
. This means that, on a network with multiple realms which all need to trust each other, making good choices about which trust relationships to set up can greatly reduce the amount of effort required.
Now you face the more conventional problems: the client's system must be configured so that it can properly deduce the realm to which a particular service belongs, and it must be able to determine how to obtain credentials for services in that realm.
First things first: the principal name for a service provided from a specific server system in a given realm typically looks like this:
service/[email protected]
In this example, service is typically either the name of the protocol in use (other common values include ldap, imap, cvs, and HTTP) or host, server.example.com is the fully-qualified domain name of the system which runs the service, and EXAMPLE.COM
is the name of the realm.
To deduce the realm to which the service belongs, clients will most often consult DNS or the domain_realm
section of /etc/krb5.conf
to map either a hostname (server.example.com) or a DNS domain name (.example.com) to the name of a realm (EXAMPLE.COM).
Having determined to which realm a service belongs, a client then has to determine the set of realms which it needs to contact, and in which order it must contact them, to obtain credentials for use in authenticating to the service.
This can be done in one of two ways.
The default method, which requires no explicit configuration, is to give the realms names within a shared hierarchy. For an example, assume realms named A.EXAMPLE.COM
, B.EXAMPLE.COM
, and EXAMPLE.COM
. When a client in the A.EXAMPLE.COM
realm attempts to authenticate to a service in B.EXAMPLE.COM
, it will, by default, first attempt to get credentials for the EXAMPLE.COM
realm, and then to use those credentials to obtain credentials for use in the B.EXAMPLE.COM
realm.
The client in this scenario treats the realm name as one might treat a DNS name. It repeatedly strips off the components of its own realm's name to generate the names of realms which are "above" it in the hierarchy until it reaches a point which is also "above" the service's realm. At that point it begins prepending components of the service's realm name until it reaches the service's realm. Each realm which is involved in the process is another "hop".
For example, using credentials in
A.EXAMPLE.COM
, authenticating to a service in
B.EXAMPLE.COM
has three hops:
A.EXAMPLE.COM → EXAMPLE.COM → B.EXAMPLE.COM
.
Another example, using credentials in
SITE1.SALES.EXAMPLE.COM
, authenticating to a service in
EVERYWHERE.EXAMPLE.COM
can have several series of hops:
SITE1.SALES.EXAMPLE.COM →
SALES.EXAMPLE.COM →
EXAMPLE.COM →
EVERYWHERE.EXAMPLE.COM
SITE1.SALES.EXAMPLE.COM
and
SALES.EXAMPLE.COM
share a key for
krbtgt/[email protected]
There can even be hops between realm names whose names share no common suffix, such as
DEVEL.EXAMPLE.COM
and
PROD.EXAMPLE.ORG
.
DEVEL.EXAMPLE.COM →
EXAMPLE.COM →
COM →
ORG →
EXAMPLE.ORG →
PROD.EXAMPLE.ORG
The more complicated, but also more flexible, method involves configuring the capaths
section of /etc/krb5.conf
, so that clients which have credentials for one realm will be able to look up which realm is next in the chain which will eventually lead to the being able to authenticate to servers.
The format of the capaths
section is relatively straightforward: each entry in the section is named after a realm in which a client might exist. Inside of that subsection, the set of intermediate realms from which the client must obtain credentials is listed as values of the key which corresponds to the realm in which a service might reside. If there are no intermediate realms, the value "." is used.
For example:
[capaths]
A.EXAMPLE.COM = {
B.EXAMPLE.COM = .
C.EXAMPLE.COM = B.EXAMPLE.COM
D.EXAMPLE.COM = B.EXAMPLE.COM
D.EXAMPLE.COM = C.EXAMPLE.COM
}
Clients in the A.EXAMPLE.COM
realm can obtain cross-realm credentials for B.EXAMPLE.COM
directly from the A.EXAMPLE.COM
KDC.
If those clients wish to contact a service in the
C.EXAMPLE.COM
realm, they will first need to obtain necessary credentials from the
B.EXAMPLE.COM
realm (this requires that
krbtgt/[email protected]
exist), and then use
those
credentials to obtain credentials for use in the
C.EXAMPLE.COM
realm (using
krbtgt/[email protected]
).
If those clients wish to contact a service in the D.EXAMPLE.COM
realm, they will first need to obtain necessary credentials from the B.EXAMPLE.COM
realm, and then credentials from the C.EXAMPLE.COM
realm, before finally obtaining credentials for use with the D.EXAMPLE.COM
realm.
Without a capath entry indicating otherwise, Kerberos assumes that cross-realm trust relationships form a hierarchy.
Clients in the A.EXAMPLE.COM
realm can obtain cross-realm credentials from B.EXAMPLE.COM
realm directly. Without the "." indicating this, the client would instead attempt to use a hierarchical path, in this case:
A.EXAMPLE.COM → EXAMPLE.COM → B.EXAMPLE.COM