Next: Key as initialization vector, Previous: Telnet encryption with AES-CCM, Up: Protocol Extensions [Contents][Index]
This appendix describes the KCMDV0.2 protocol used in versions of
inetutils patched for shishi. The KCMD protocol was developed by
the MIT Kerberos team for the kerberized rsh
and
rlogin
programs.
The differences between rlogin
and rsh
are explained below, as are differences between protocol versions v0.1
and v0.2. Both remain in use resons of compatibility.
It is possible that some parts of this document are not in conformity with the original KCMD protocol, because there is no official specification of it. However, it seems that shishi’s implementation is compatible with MIT’s protocol.
Warning: If you are seriously considering using Kerberized
rsh
or rlogin
, instead of more robust remote
access protocols, such as SSH, you may first want to explore
http://www.cs.berkeley.edu/~hildrum/kerberos/ or the full paper
at http://www.cs.berkeley.edu/~hildrum/043.pdf.
Initially the client establishs a TCP connection to the server. Default ports are 543 (‘klogin’), 544 (‘kshell’), and 2105 (‘eklogin’). Here ‘eklogin’ is the same as ‘klogin’, but with encryption. There is no longer a separate ‘ekshell’ port, because encrypted and normal connection now use the same port ‘kshell’.
Normally ‘kshell’ needs a second connection for stderr
.
The client should send a null terminated string containing an ascii
encoding of the port number to be used for this second connection.
Since ‘klogin’ and ‘eklogin’ do not use a second connection
for stderr
, the client just sends an additional null byte
to the server, which can be thought of as an empty string.
Contrary to classic rsh
and rlogin
, the server
need not check if the client’s port lies in the range 0-1023.
When a connection is being established, the first thing to do is to indicate that Kerberos authentication is desired. The client will send a string to indicate it will use Kerberos 5. Let us say “length-string” of strl, and mean the couple
(length of the string strl, null-terminated string strl).
when strl itself is given.
The string length is encoded as an int32
(32-bit integer)
in MSB order, i.e., network byte order.
So the client first sends an authentication message,
the length-string of
KRB5_SENDAUTH_V1.0
After that, the client must tell which version of the protocol it uses by sending a version message, consisting of a second length-string. This time based on
KCMDV0.2
or on “KCMDV0.1”, for the older version.
If the client’s indentification is acceptable, the server will respond
with a null byte (0x00
).
Otherwise, if the authentication message was incorrect, then the server
responds with the single byte 0x01
, while if the protocol version
message was unacceptable, then the response is a single 0x02
.
When the client is indentified, Kerberos authentication can begin. The client must send an AP-REQ to the server; an AP-REQ authenticator must contain a subkey (only for KCMDV0.2) and a checksum. The authenticator checksum is calculated from the following string.
"serverport":"terminaltype""remoteusername"
Observe the mandatory colon, serving as a delimiter to the terminal type. Here remoteusername is whatever identity the client desires to use at the remote end. The simple example
543:linux/38400user
demonstrates that the terminal type expects a terminfo name and a speed as decimal number.
Once the AP-REQ has been updated with the checksum, it is ready for
transmission to the server.
Its length (as int32
) is first sent in network order (MSB),
followed by the DER encoded AP-REQ itself.
If all is acceptable, the server reponds with an int32
of
value null.
(In MSB order, but as it is null, order is irrelevant!).
The KCMD protocol uses mutual authentication, so the server must
also send an AP-REP back:
(int32-length in MSB of DER encoded AP-REP) (DER encoded AP-REP)
Now server and client are provisionally authenticated.
The client next sends three different null terminated strings, without length :
rlogin
or command for rsh
An example for rsh
:
"rname\0" "cat /usr/local/etc/shishi.conf" "lname\0"
The server must next verify that the checksum delivered in the AP-REQ authenticator is correct, by computing a new hash like the client has previously done.
The server must also verify that the requesting principal (found in AP-REQ) has the right to log in to the remote user account. In the ‘basic’ authorization, this is done by checking whether the remote user name is identical to the principal’s name. The alternative is ‘k5login’ mode, which is discussed in kerberos authorization.
If all is correct, the server sends a null byte, i.e., an empty string, or else an error message string (null terminated). The remote client reads the first byte. If it is equal to zero, authentication is successful and the user is logged in at the remote host. In any other case, the client has the error message available, as sent by the server, to help the user understand the failure.
In the rlogin
protocol, when authentication completes,
the server can optionally send a message asking for terminal window
size suitable for the user.
The client can respond, but it is not obliged to do so.
Under KCMDV0.1, the server sends a single byte, an urgent TCP message
(MSG_OOB
) :
TIOCPKT_WINDOW = 0x80
With KCMDV0.2, the server does not send an urgent message at all, but writes five bytes to the socket :
'\377', '\377', 'o', 'o', TIOCPKT_WINDOW
If encryption is enabled (‘eklogin’) the server must send those five bytes in encrypted form.
The client answers alike in both protocol versions :
'\377', '\377', 's', 's', "struct winsize"
The winsize structure is filled in with the settings from the client’s terminal. With encryption enabled, this answer must be sent encrypted.
The legacy exchange supported by rsh
and rlogin
continues from this point onwards.
Encryption mode is always used when connecting via the port ‘eklogin’. The port ‘kshell’ also supports encryption. Previously, there was a specific port ‘ekshell’ for that purpose, a use which is now extinct. Instead, whenever an encrypted exchange is desired via the port ‘kshell’, client must prefix the string “-x ” to the command string, when it is sent inbetween the remote user name and the local user name. In contrast, when the client computes the checksum for the AP-REQ authenticator, the string “-x ” must not be included.
Encryption porcedure under version KCMDV0.2 differs from that in the older protocol version. Under version KCMDV0.1, the ticket session key is put to use as encryption key, and only standard Kerberos encryption functions are usable. Thus it supports only ‘des-cbc-crc’, ‘des-cbc-md4’, ‘des-cbc-md5’, and does not allow use of initialisation vectors.
As an example of encryption/decryption calls, the following Kerberos function prototype should be used :
kerberos_encrypt (key, keyusage, in, out) (or kerberos_decrypt)
To contrast, KCMDV0.2 can be used with all Kerberos encryption modes,
i.e., ‘des’, ‘3des’, ‘aes’, ‘arcfour’,
and it uses an AP-REQ authenticator subkey. In opposition to KCMDV0.1,
initialisation vectors are used.
All encryption and descryption must be made using a cryptographic context.
A typical coding example updates the context with an iv
,
then executes an encryption call :
kerberos_init(ctx, iv, key, keyusage) kerberos_encrypt (ctx, in, out)
For both protocols, default keyusage identity allowing ‘des-cbc-md5’, ‘des-cbc-md4’, ‘des-cbc-crc’, and ‘des3-cbc-sha1’ (the latter applicable only to KCMDV0.2) is identical :
keyusage = 1026
KCMDV0.2 encryption modes, other than the four named above, specify distinct values for keyusage, unique to each encryption/decryption mode.
In conclusion, ‘eklogin’ uses a single socket. It encrypts data “output 1” prior to sending, and it decrypts “input 1” received data.
‘kshell’ uses two sockets: one for transmitting data,
and one for a side channel carrying stderr
.
Thus there are four streams available :
transmit : input 1 output 1 stderr : input 2 output 2
There is a key usage set for each mode. The values of each keyusage must be compatible between client and server side.
An example with ‘klogin’, shows the client’s “input 1” key usage to be identical to the server’s “output 1” usage.
I/O | Client | Server |
input 1 | 1028 | 1030 |
output 1 | 1030 | 1028 |
input 2 | 1032 | 1034 |
output 2 | 1034 | 1032 |
The stated key usages are for AES and ARCFOUR modes.
KCMDV0.2 uses an IV (initialisation vector) with AES. Like for key usage, the client IV must correspond to the server IV. The IV size is equal to the blocksize of the chosen key type. All bytes of IV must be initialised too :
I/O | Client | Server |
input 1 | 0 | 1 |
output 1 | 1 | 0 |
input 2 | 2 | 3 |
output 2 | 3 | 2 |
ARCFOUR mode does not use an IV. However, like mentioned before, a context must be used to keep the updating the sbox.
A normal message for ‘klogin’ or ‘kshell’ is set up like this :
(int32-length of message in MSB order) (message)
In encrypted mode, the format is only slightly different :
(int32-length of unencrypted message in MSB order) (encrypted message)
Under KCMDV0.2, the encrypted message is create like this :
encrypt ( (int32-length of message in MSB order) (message) )
A check on message size can be made in second version of the protocol.
This part only gives possible ways to extend the KCMD protocol. They should not be understood as some kind of “must have” in a future KCMD implementation.
Extensions to KCMV0.2 can be imagined. For example, ‘kshell’ assumes there are no files of names like “-x *”. I think the same thing can be assumed of terminal names for ‘klogin’. So the client could add “-x ” to the terminal type it transmits to the server, in order to indicate the desire to use encryption.
Under this provision, there need only be one port shared by ‘klogin’ and ‘eklogin’, namely the IANA defined port number 543.
Before encryption begins, ‘kshell’ passes the intended commands in the clear through the network. This could be considered insecure, once the user has decided to use encryption. It is not really a problem with ‘klogin’, because it just tells which terminal type to target.
One could imagine, when the client intends to use encrypted mode, that the client side initially transmits a mundane “-x” and nothing else to either of ‘klogin’ and ‘kshell’, in place of either a command or a terminal type, respectively. Once encryption is in place, the client could send terminal type or command in a second, now encrypted exchange. The server could respond with a single null byte, saying that all is well, or respond with an error message, which already enjoys the added benefit of being encrypted.
This short part describes how MIT/Heimdal versions of Kerberos 5 check authorization of any user seeking to log in to a remote machine.
The authorization stage begins by testing whether the file .k5login exists in the home directory of the remote user. If this file does not exist, then a valid authorization demands that the remote user’s name must be the same as the name of the principal contained in the request AP-REQ. (This is the legacy ‘basic’ authorization.) Else, if the file is present, the serve first verifies that the remote user, or root, is the owner of .k5login, then goes on to verify that the file is not readable by group, nor by world. If either fails, then the check fails entirely.
If all is good so far, then each line of that file is examined, and each name read in is compared to the principal. If the principal is found listed somewhere in .k5login, then authorization is successful. In the contrary case, the user is not admitted to the remote host as the requested remote user, a name that could have been derived to be the very same as in the principal itself.
So someone, “user1” say, can remotely log in to the account of “user2”, if the file .k5login is present in the home directory of “user2”, and it is owned by “user2” or by root, and at the same time the name “user1” is listed in this file.
Next: Key as initialization vector, Previous: Telnet encryption with AES-CCM, Up: Protocol Extensions [Contents][Index]