![]() | ![]() |
ftp://athena-dist.mit.edu/pub/kerberos/Kerberos-5 is the current version, and Kerberos-4 is no longer actively developed at MIT. Even so, Kerberos-4 is still in use in many contexts, especially bundled into commercial systems (e.g., Sun Solaris, Transarc AFS). SSH1 supports Kerberos-5, and OpenSSH/1 supports Kerberos-4. The current draft of the SSH-2 protocol doesn't yet define a Kerberos authentication method, but as this book went to press SSH 2.3.0 was released with "experimental" Kerberos-5 support, which we haven't covered here (but which should work substantially as described with SSH1).
[139]Although, if remote login access to a KDC is desired, SSH is a good way to do it!
[140]SSH2 has recently moved towards this model. It is similarly organized as a set of libraries implementing the SSH-2 protocol, accessed via an API by client and server programs.
[141]Actually, the secret key derived from the user's password, but the distinction isn't relevant here.A stolen Kerberos ticket cache can be the target of a dictionary attack, but with an important difference: user passwords aren't present. The keys in the cache belong to server principals, and moreover, they are typically generated randomly and hence less vulnerable to a dictionary attack than user passwords. Sensitive keys are stored only on the KDCs, under the theory that it is much easier to effectively secure a small set of limited-use machines, rather than a large set of heterogeneous, multipurpose servers and workstations over which the administrator may have little control. Much of Kerberos's complexity results from this philosophy.
http://web.mit.edu/kerberos/www/
[142]This was the case in Kerberos-4. In fact, Kerberos-5 principals have a realm, plus any number of "components" -- the first two of which are conventionally used as the name and instance, as in Kerberos-4.
kinit assumes that since your username is res and the host spot is in the realm FIDO, you want to obtain credentials for the principal res@FIDO. If you had wanted a different principal, you could have supplied it as an argument to kinit.[res@spot res]$ kinit Password for res@FIDO : *********
So far, you have only one ticket, for the service krbtgt/FIDO@FIDO. This is your Kerberos TGT, and it is your initial credential: proof to be presented later to the KDC that you have successfully authenticated yourself as res@FIDO. Note that the TGT has a validity period: it expires in 10 hours. After that, you must do another kinit to reauthenticate yourself.[res@spot res]$ klist Ticket cache: /tmp/krb5cc_84629 Default principal: res@FIDO Valid starting Expires Service principal 07/09/00 23:35:03 07/10/00 09:35:03 krbtgt/FIDO@FIDO
The -a option to this kerberized telnet client tells it to do auto-login: that is, it attempts to negotiate Kerberos authentication with the remote side. It succeeds: the remote side accepts your Kerberos identification, and allows you to log in without providing a password. If you return to spot and do a klist, you will see what happened:[res@spot res]$ telnet -a rover Trying 10.1.2.3... Connected to rover (10.1.2.3). Escape character is '^]'. [Kerberos V5 accepts you as "res@FIDO"] Last login: Sun Jul 9 16:06:45 from spot You have new mail. [res@rover res]$
Note that you now have a second ticket, for the service " host/rover@FIDO". This principal is used for remote login and command execution services on the host rover, such as kerberized telnet, rlogin, rsh, etc. When you ran telnet -a rover, the telnet client requested a ticket for host/rover@FIDO from the KDC, supplying your TGT with the request. The KDC validated the TGT, verifying that you had recently identified yourself as res@FIDO , and issued the ticket. telnet stored the new ticket in your Kerberos ticket cache, so that the next time you connect to rover, you can just use the cached ticket instead of contacting the KDC again (at least, until the ticket expires). It then presented the host/rover@FIDO ticket to the telnet server, which verified it and in turn believed that the client had been identified as res@FIDO to the KDC.[res@spot res]$ klist Ticket cache: /tmp/krb5cc_84629 Default principal: res@FIDO Valid starting Expires Service principal 07/09/00 23:35:03 07/10/00 09:35:03 krbtgt/FIDO@FIDO 07/09/00 23:48:10 07/10/00 09:35:03 host/rover@FIDO
[res@spot res]$ telnet -a -l bob rover Trying 10.1.2.3... Connected to rover (10.1.2.3). Escape character is '^]'. [Kerberos V5 accepts you as "res@FIDO"]
Note that authentication was still successful: the telnet server accepted you as res@FIDO. The authorization decision failed, though: Kerberos decided that the principal res@FIDO was not allowed to access the account bob@rover . Bob can allow you to log into his account by creating the file rover:~bob/.k5login, and placing a line in it containing your principal name, res@FIDO. He would also have to place his own principal in there, since if a .k5login file exists, it overrides the default authorization rule, and Bob would be unable to log into his own account. So Bob's authorization file would look like this:telnetd: Authorization failed.
rover:~bob/.k5login: bob@FIDO res@FIDO
Two notes on doing this build:# SSH1 only $ configure ... --with-kerberos5=/path/to/kerberos ...
# cd your_Kerberos_library_directory # ln -s libk5crypto.a libcrypto.a
TIP: If you compile in Kerberos support, the resulting SSH programs work only on a system with Kerberos installed, even if you aren't using Kerberos authentication. The programs will likely refer to Kerberos shared libraries that must be present for the programs to run. Also, SSH performs Kerberos initialization on startup and expects a valid host Kerberos configuration file ( /etc/krb5.conf ).After installation, we recommend setting the serverwide configuration keyword KerberosAuthentication in /etc/sshd_config to "yes" for clarity, even though it is on by default:
Additionally, the host/server@REALM principal must be in the KDC database, and its key must be stored in /etc/krb5.keytab on the server. Once running with Kerberos support, SSH1 operates essentially as we described for kerberized telnet; Figure 11-12 illustrates the process. [Section 11.4.3.4, "Running a kerberized application"] On the client, simply run kinit to obtain your Kerberos TGT, and then try ssh -v. If Kerberos authentication succeeds, you will see:# SSH1 only KerberosAuthentication yes
and in the server log:$ ssh -v server ... server: Trying Kerberos V5 authentication. server: Kerberos V5 authentication accepted. ...
Kerberos authentication accepted joe@REALM for login to account joe from client_host
This fallback is useful as a fail-safe: if the KDC isn't functioning, you can still authenticate by your OS password (although public-key would be a stronger failsafe authentication method). Another feature of kerberized password authentication is that sshd stores your TGT upon login, so you don't need to run kinit and retype your password to get Kerberos credentials on the remote host.# SSH1, OpenSSH KerberosOrLocalPasswd yes
(The -n switch tells klist to display the addresses by number, rather than translating them to names.) Host spot 's IP address is 10.1.2.1, and so the KDC issues the TGT limited to use from that address. If spot has multiple network interfaces or addresses, they are listed here as well. When you obtain subsequent service tickets based on this TGT, they are also limited to the same set of addresses. Now, imagine you connect to an SSH server on the other side of a NAT gateway, which is rewriting your (the client's) IP address, but the KDC is inside the NAT boundary, with you. When you obtain the service ticket from the KDC, it contains your real IP address. The SSH server, however, sees your NAT'd address as the source of the connection, notes that this doesn't match the address encoded in the ticket, and refuses authentication. In this case, ssh -v reports:[res@spot res]$ klist -a -n Ticket cache: /tmp/krb5cc_84629 Default principal: res@FIDO Valid starting Expires Service principal 07/09/00 23:35:03 07/10/00 09:35:03 krbtgt/FIDO@FIDO Addresses: 10.1.2.1 07/09/00 23:48:10 07/10/00 09:35:03 host/rover@FIDO Addresses: 10.1.2.1
Figure 11-13 illustrates this problem. It has no good solution at the moment. One workaround is the undocumented kinit -A switch, which causes kinit to request a ticket with no addresses in it at all. This trick decreases security, because a stolen ticket cache can then easily be used from anywhere, but it gets around the problem.Trying Kerberos V5 authentication. Kerberos V5: failure on credentials (Incorrect net address).
However, this won't work. To log in, Sam needs a service ticket for host/bulwark@ENGINEERING. Only a KDC for the ENGINEERING realm can issue such a ticket, but an ENGINEERING KDC won't know the principal sam@SALES . In general, an ENGINEERING host has no way of authenticating a principal from the SALES realm. It looks as if Sam will need a principal in the ENGINEERING domain as well, but this poor solution violates the whole idea of having separate realms. It's also cumbersome, since Sam would have to do another kinit each time he wants to access resources in a different realm. The solution to this problem is called cross-realm authentication. First, both realms must be described in the /etc/krb5.conf files on all machines in both realms; Kerberos knows only those realms listed in the configuration file. Then the administrators of the two realms establish a shared secret key between them, called a cross-realm key. The key is realized as a common key for two specially named principals, one in each realm. The key has a direction, and its existence allows one KDC to issue a TGT for the other realm; the other KDC can verify that this TGT was issued by its trusted peer realm using the shared key. With one cross-realm key in place, authentication in one realm provides a verifiable identity in the other realm as well. If the trust is symmetric -- that is, if each realm should trust the other -- then two cross-realm keys are needed, one for each direction.bulwark:~erin/.k5login: erin@ENGINEERING sam@SALES
Note that Sam doesn't have a second principal now, sam@ENGINEERING. Rather, an ENGINEERING KDC can now verify that Sam was authenticated as sam@SALES by a SALES KDC and can therefore use the principal sam@SALES in authorization decisions. When Sam tries to log into bulwark using SSH, Kerberos notices that the target machine is in a different realm from Sam's principal and automatically uses the appropriate cross-realm key to obtain another TGT for him in the ENGINEERING realm. Kerberos then uses that to obtain a service ticket authenticating sam@SALES to host/bulwark@ENGINEERING. sshd on bulwark reads Erin's ~/.k5login file, sees that sam@SALES is allowed access, and permits the login. That's the basic idea. However, when SSH enters the picture, cross-realm authentication can fail due to a confusing catch. Suppose Sam uses bulwark so often that he's given an account there. The sysadmin puts "sam@SALES" into bulwark:~sam/.k5login, so that Sam can log in there with his SALES credentials. But, it doesn't work. Even with everything set up correctly so that cross-realm kerberized telnet works, SSH Kerberos authentication still fails for him. Even more mysteriously, every other form of authentication starts failing as well. Sam had public-key authentication set up and working before, and you'd expect it to try Kerberos, fail, then try public-key and succeed. But all the public-key attempts fail, too. Sam won't get much of a hint of what the problem is unless password authentication is turned on, and SSH eventually tries it:
Hierarchical Realms in Kerberos-5
For a large number of realms, the system as described quickly becomes unwieldy. If you want cross-realm trust between all of them, you must manually establish cross-realm keys for each pair of realms. Kerberos-5 supports hierarchical realms to address this problem. A realm name containing dots, such as ENGINEERING.BIGCORP.COM, implies the (possible) existence of realms BIGCORP.COM and COM. When attempting cross-realm authentication from SALES.BIGCORP.COM to ENGINEERING.BIGCORP.COM, if Kerberos doesn't find a direct cross-realm key, it attempts to navigate up and then down the realm hierarchy, following a chain of cross-realm relations to the target realm. That is, if there are cross-realm keys from SALES.BIGCORP.COM to BIGCORP.COM, and from BIGCORP.COM to ENGINEERING.BIGCORP.COM, the cross-realm authentication from SALES to ENGINEERING succeeds without needing an explicit cross-realm setup between them. This allows for scalable, complete, cross-realm relationships among a large collection of realms.
That last prompt doesn't look right at all: "sam@SALES@bulwark"? There's another hint from sshd -d:[sam@sales sam]$ ssh -v bulwark ... Trying Kerberos V5 authentication. Kerberos V5 authentication failed. Connection to authentication agent opened. Trying RSA authentication via agent with 'Sam's personal key' Server refused our key. Trying RSA authentication via agent with 'Sam's work key' Server refused our key. Doing password authentication. sam@SALES@bulwarks's password:
SSH is mistakenly using the principal name as if it were the account name -- as if Sam had typed, ssh -l sam@SALES bulwark. Of course, there's no account named "sam@SALES"; there's one named "sam ". And in fact, the quick fix for this problem is for Sam to specify his username explicitly, with ssh -l sam bulwark, even though this seems redundant. The reason for this odd problem is a Kerberos-5 feature that SSH employs, called anameConnection attempt for sam@SALES from sales
must translate to the account res on some systems, but rsilverman on others. The Kerberos-5 designers thought it would be good if Kerberos could automate handling this problem itself, and so they included the anameres@REALM
to "user" if REALM is the host's REALM. However, Sam is doing cross-realm authentication, and so the two realms are different: his principal isuser@REALM
, but the server's realm is ENGINEERING. So the anamesam@SALES
These rules cause the anamebulwark:/etc/krb5.conf: ... [realms] ENGINEERING = { kdc = kerberos.engineering.bigcorp.com admin_server = kerberos.engineering.bigcorp.com default_domain = engineering.bigcorp.com auth_to_local = RULE:[1:$1] auth_to_local = RULE:[2:$1] auth_to_local = DEFAULT }
and a klist on the remote host shows the forwarded TGT. In order to use TGT forwarding, you must compile SSH with the switch -- enable-kerberos-tgt-passing. You must also request a forwardable TGT with kinit -f ; otherwise, you see:Trying Kerberos V5 TGT passing. Kerberos V5 TGT passing was successful.
Kerberos V5 krb5_fwd_tgt_creds failure (KDC can't fulfill requested option)
WARNING: Don't use Kerberos authentication in SSH1 versions earlier than 1.2.28.This bug was fixed by SSH Communications Security in Version 1.2.28 in response to our bug report. Note that this problem occurs if SSH1 is compiled with Kerberos support, even if Kerberos authentication isn't in use for the session at hand. The OpenSSH Kerberos-4 code has never had this bug.
$ mkdir /var/krb5kdc
[libdefaults] ticket_lifetime = 600 default_realm = FOO default_tkt_enctypes = des-cbc-crc default_tgs_enctypes = des-cbc-crc [realms] FOO = { kdc = shag.carpet.net admin_server = shag.carpet.net default_domain = carpet.net } [domain_realm] .carpet.net = FOO carpet.net = FOO [logging] kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmin.log default = FILE:/var/log/krb5lib.log Install a file /var/krb5kdc/kdc.conf like this: [kdcdefaults] kdc_ports = 88,750 [realms] FOO = { database_name = /var/krb5kdc/principal admin_keytab = /var/krb5kdc/kadm5.keytab acl_file = /var/krb5kdc/kadm5.acl dict_file = /var/krb5kdc/kadm5.dict key_stash_file = /var/krb5kdc/.k5.FOO kadmind_port = 749 max_life = 10h 0m 0s max_renewable_life = 7d 0h 0m 0s master_key_type = des-cbc-crc supported_enctypes = des-cbc-crc:normal des-cbc-crc:v4 }
This creates the KDC principal database in /var/krb5kdc. You are prompted for the KDC master key, a password the KDC needs to operate. The key is stored in /var/krb5kdc/.k5.FOO, which allows the KDC software to start without human intervention but which is obviously not wise unless the KDC machine is extremely well protected.$ kdb5_util create
$ kadmin.local This program modifies the principal database. Issue the following kadmin commands: kadmin.local: ktadd -k /var/krb5kdc/kadm5.keytab kadmin/admin kadmin/changepw Entry for principal kadmin/admin with kvno 4, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/var/krb5kdc/kadm5.keytab. Entry for principal kadmin/changepw with kvno 4, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/var/krb5kdc/kadm5.keytab. kadmin.local: add_principal -randkey host/shag.carpet.net WARNING: no policy specified for host/shag.carpet.net@FOO; defaulting to no policy Principal "host/shag.carpet.net@FOO" created. kadmin.local: ktadd -k /etc/krb5.keytab host/shag.carpet.net Entry for principal host/shag.carpet.net with kvno 3, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab. kadmin.local: add_principal fred WARNING: no policy specified for fred@FOO; defaulting to no policy Enter password for principal "fred@FOO": ******** Re-enter password for principal "fred@FOO": ******** Principal "fred@FOO" created. kadmin.local: quit
[143]Principals in Kerberos-4 also include a name, optional instance, and realm, but are written name.instance@REALM instead of name/instance@REALM as in Kerberos-5.Access control for an account is via the file ~/.klogin. With Kerberos-4, it isn't necessary to include the account's default principal in ~/.klogin if that file exists; the default principal always has access. Table 11-1 summarizes the salient differences between Kerberos-4 and Kerberos-5 with respect to SSH.
The KDC satisfies v4 requests for rcmd.hostname@REALM tickets, using the key of the corresponding v5 host/hostname@REALM principal, so you don't need to create separate "rcmd/hostname" principals in your v5 KDC. Since v4-only servers still need the principal key, you need to create a v4 version of the key file ( /etc/srvtab) with that key; you can do this with the v5 program kutil to read in an existing krb5.keytab and write out a v4 srvtab. Direct cross-realm authentication also automatically works using existing cross-realm keys; however, Kerberos-4 doesn't support hierarchical realms. Using the Kerberos-5 credentials conversion service, you can even avoid having to do a separate v4 kinit. On the KDC, the separate server program krb524d must be running. Then, after doing a v5 kinit, the user simply runs the program krb524init. This obtains a v4 TGT using the v5 one, which you can verify with the v4 klist command. Note that OpenSSH and SSH1 can't interoperate using Kerberos authentication. They use the same SSH protocol messages in each case but implicitly expect encapsulated Kerberos tickets of the appropriate Kerberos version. You can't use Kerberos-5 v4 compatibility mode to overcome this limitation. We hope OpenSSH will eventually add Kerberos-5 support. Also note that Kerberos-4 doesn't have an analog to the Kerberos-5 kinit -A switch. We don't know of any way to overcome the Kerberos/NAT problem using Kerberos-4. [Section 11.4.4.2, "Kerberos and NAT "] We have heard, however, that the Transarc AFS KDC ignores IP addresses in tickets, thus avoiding the problem./etc/krb.conf: FOO shag.carpet.net /etc/krb.realms: .carpet.net FOO
![]() | ![]() | ![]() |
11.3. Pine, IMAP, and SSH | ![]() | 11.5. Connecting Through a GatewayHost |
Copyright © 2002 O'Reilly & Associates. All rights reserved.