keytab - MIT Keytab Binary File Format Encoder / Decoder

Marcus Watts mdw at umich.edu
Wed May 3 01:32:55 EDT 2006


Michael B Allen <mba2000 at ioplex.com> writes:
...
> 1) What fields are in host byte order? It seems that everything is big
>    endian except the 16 bit vno and and 16 bit keyblock key type?

The IETF term you'd likely see here is "network byte order" = big-endian.
Everything is big-endian.  keytabs have exactly the same representation
on big-endian and little-endian machines (unlike, *cough*, key stash
files...).  vno is an 8-bit quantity, key type and length
are 16-bit big-endian quantities, and key length & contents you could
treat as a counted string.

> 2) What codeset are strings? Are they UTF-8 or locale dependant?

I'd guess UTF-8.  locale-dependant is almost certainly wrong.  There
was a lot of debate about this on the ietf kerberos list; I'm not
honestly sure where or if things got settled.  All the code I've seen
that looks at name components thinks of them as an ascii string and
pays no special attention to the high bit, that's at least consistent
with UTF-8.  Careful about validating UTF-8 strings if you process
keyblocks using counted string logic.

> 3) Are my assumptions about num_components correct: 1 for no service,
>    2 with service?

You should not make any assumptions in your keytab logic.  You might
have logic elsewhere that cares--hopefully buried way back in your
application logic, hopefully somewhere where you actually have need
to care about this like when constructing service names.

> 4) Have I missed anything?

Don't see anything else; but like any undocumented data structure
where the owners reserve the right to break things; there's
no guarantee.  If you're sharing keytabs with MIT application
logic that might write to the keytab, there's a bunch of logic
involving file locking & fsync that you might want to take
into account.

...
> the number of bytes that follow in the entry. Note that the size should be
> evaluated as signed. This is because a negative value indicates that the
> entry is in fact empty (e.g. it has been deleted) and that the negative
> value of that negative value (which is of course a positive value) is
> the offset to the next keytab_entry. Based on these size values alone
> the entire keytab file can be traversed.

negative sizes = deletion?  Wow, yup, somehow I missed or forgot that.

> 
> The size is followed by a 16 bit num_components field indicating the
> number of string components that follow minus one. In practice this value
> will be either 1 to indicate the realm and name follow or 2 to indicate
> the realm, service, and name follow. Each component is a counted_string.

Count 1 vs. 2 is k4-centric thinking.  It's a list of name components;
the count is whatever it is.  The keytab reading logic should neither
know nor care how many components or what they "mean".

...
> 
> Following the string components is the name_type. This value is usually
> 1 unless ... ?

MIT krb5.h sez:
KRB5_NT_UNKNOWN		0	/* Name type not known */
KRB5_NT_PRINCIPAL	1	/* users, etc. */
KRB5_NT_SRV_INST	2	/* service & other uniq inst (krbtgt) */
KRB5_NT_SRV_HST		3	/* service with hostname as instance */
KRB5_NT_SRV_XHST	4	/* service with host as components */
KRB5_NT_UID		5	/* unique id */
other types in various kerberos standards but not in MIT:
KRB_NT_X500_PRINCIPAL	6	/* X.500 encoded name RFC2253 */
KRB_NT_SMTP_NAME	7	/* SMTP mailbox address */
(what happened to 8, 9?)
KRB_NT_ENTERPRISE	10	/* enterprise name */

I'm not convinced you can see anything besides name type 1 = KRB5_NT_PRINCIPAL
in a keytab.

There is logic inside the MIT k5 library that does things
with some of the other name types, particularly KRB5_NT_SRV_HST.

...
> The 16 bit vno field is the version number of the key. This value may
> be overridden by the vno32 field described below.

The inline version is not little-endian, it is an 8 bit quantity.
That's where Jeff Altman gets his "less than a year" figure - 256 days
for a keytab that's updated once a day.  Apparently older logic that
updated keytabs didn't append the 4 byte quantity, it merely truncated
and stored inline.

So, one of the things you miss by not using the MIT .dll is the logic which
compares only the low order byte of a vno when the high order bits are
missing out of the keytab.  As an library designer using an undocmented
file format you can afford to do something MIT can't: you can tell
anybody who misses this feature "upgrade your kdc to mit 1.4X and make
another keytab."  Or even "it broke?  Send me a diff when you figure
out what should be done here."  Of course, you should probably try
using microsoft ktadd with a high kvno first to make sure they don't
do something inconvenient here.

> 
> The keyblock structure consists of a 16 bit value indicating the keytype
> (e.g. 3 is des-cbc-md5, 23 is arcfour-hmac-md5, 16 is des3-cbc-sha1,
> etc). This is followed by an 8 bit value indicating the length of the
> key data that follows.

These are 2 16-bit big-endian quantities.  You can treat the
keyblock length & contents as a counted string if you care.
In IETF network speak, that would be a "counted octet string".

> 
> The last field of the keytab_entry struction is optional. If the size of
> the keytab_entry indicates that there are bytes remaining a 32 bit value
> representing the key version number follows. This value superceeds the
> 16 bit value preceeding the keyblock.
(as per above the inline kvno was an 8 bit quantity).
...

				-Marcus Watts



More information about the Kerberos mailing list