1178825Sdfr/*
2233294Sstas * Copyright (c) 2007-2008 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
20178825Sdfr *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34178825Sdfr#include "krb5_locl.h"
35178825Sdfr
36178825Sdfr/**
37233294Sstas *
38178825Sdfr */
39178825Sdfr
40233294Sstas/*! @mainpage Heimdal Kerberos 5 library
41178825Sdfr *
42233294Sstas * @section intro Introduction
43178825Sdfr *
44178825Sdfr * Heimdal libkrb5 library is a implementation of the Kerberos
45178825Sdfr * protocol.
46233294Sstas *
47178825Sdfr * Kerberos is a system for authenticating users and services on a
48178825Sdfr * network.  It is built upon the assumption that the network is
49178825Sdfr * ``unsafe''.  For example, data sent over the network can be
50178825Sdfr * eavesdropped and altered, and addresses can also be faked.
51178825Sdfr * Therefore they cannot be used for authentication purposes.
52178825Sdfr *
53178825Sdfr *
54233294Sstas * - @ref krb5_introduction
55233294Sstas * - @ref krb5_principal_intro
56233294Sstas * - @ref krb5_ccache_intro
57233294Sstas * - @ref krb5_keytab_intro
58233294Sstas *
59233294Sstas * If you want to know more about the file formats that is used by
60233294Sstas * Heimdal, please see: @ref krb5_fileformats
61233294Sstas *
62233294Sstas * The project web page: http://www.h5l.org/
63233294Sstas *
64178825Sdfr */
65178825Sdfr
66178825Sdfr/** @defgroup krb5 Heimdal Kerberos 5 library */
67178825Sdfr/** @defgroup krb5_address Heimdal Kerberos 5 address functions */
68233294Sstas/** @defgroup krb5_principal Heimdal Kerberos 5 principal functions */
69178825Sdfr/** @defgroup krb5_ccache Heimdal Kerberos 5 credential cache functions */
70233294Sstas/** @defgroup krb5_crypto Heimdal Kerberos 5 cryptography functions */
71178825Sdfr/** @defgroup krb5_credential Heimdal Kerberos 5 credential handing functions */
72178825Sdfr/** @defgroup krb5_deprecated Heimdal Kerberos 5 deprecated functions */
73178825Sdfr/** @defgroup krb5_digest Heimdal Kerberos 5 digest service */
74178825Sdfr/** @defgroup krb5_error Heimdal Kerberos 5 error reporting functions */
75233294Sstas/** @defgroup krb5_keytab Heimdal Kerberos 5 keytab handling functions */
76233294Sstas/** @defgroup krb5_ticket Heimdal Kerberos 5 ticket functions */
77233294Sstas/** @defgroup krb5_pac Heimdal Kerberos 5 PAC handling functions */
78178825Sdfr/** @defgroup krb5_v4compat Heimdal Kerberos 4 compatiblity functions */
79233294Sstas/** @defgroup krb5_storage Heimdal Kerberos 5 storage functions */
80178825Sdfr/** @defgroup krb5_support Heimdal Kerberos 5 support functions */
81233294Sstas/** @defgroup krb5_auth Heimdal Kerberos 5 authentication functions */
82233294Sstas
83233294Sstas
84233294Sstas/**
85233294Sstas * @page krb5_introduction Introduction to the Kerberos 5 API
86233294Sstas * @section api_overview Kerberos 5 API Overview
87233294Sstas *
88233294Sstas * All functions are documented in manual pages.  This section tries
89233294Sstas * to give an overview of the major components used in Kerberos
90233294Sstas * library, and point to where to look for a specific function.
91233294Sstas *
92233294Sstas * @subsection intro_krb5_context Kerberos context
93233294Sstas *
94233294Sstas * A kerberos context (krb5_context) holds all per thread state. All
95233294Sstas * global variables that are context specific are stored in this
96233294Sstas * structure, including default encryption types, credential cache
97233294Sstas * (for example, a ticket file), and default realms.
98233294Sstas *
99233294Sstas * The internals of the structure should never be accessed directly,
100233294Sstas * functions exist for extracting information.
101233294Sstas *
102233294Sstas * See the manual page for krb5_init_context() how to create a context
103233294Sstas * and module @ref krb5 for more information about the functions.
104233294Sstas *
105233294Sstas * @subsection intro_krb5_auth_context Kerberos authentication context
106233294Sstas *
107233294Sstas * Kerberos authentication context (krb5_auth_context) holds all
108233294Sstas * context related to an authenticated connection, in a similar way to
109233294Sstas * the kerberos context that holds the context for the thread or
110233294Sstas * process.
111233294Sstas *
112233294Sstas * The krb5_auth_context is used by various functions that are
113233294Sstas * directly related to authentication between the
114233294Sstas * server/client. Example of data that this structure contains are
115233294Sstas * various flags, addresses of client and server, port numbers,
116233294Sstas * keyblocks (and subkeys), sequence numbers, replay cache, and
117233294Sstas * checksum types.
118233294Sstas *
119233294Sstas * @subsection intro_krb5_principal Kerberos principal
120233294Sstas *
121233294Sstas * The Kerberos principal is the structure that identifies a user or
122233294Sstas * service in Kerberos. The structure that holds the principal is the
123233294Sstas * krb5_principal. There are function to extract the realm and
124233294Sstas * elements of the principal, but most applications have no reason to
125233294Sstas * inspect the content of the structure.
126233294Sstas *
127233294Sstas * The are several ways to create a principal (with different degree of
128233294Sstas * portability), and one way to free it.
129233294Sstas *
130233294Sstas * See also the page @ref krb5_principal_intro for more information and also
131233294Sstas * module @ref krb5_principal.
132233294Sstas *
133233294Sstas * @subsection intro_krb5_ccache Credential cache
134233294Sstas *
135233294Sstas * A credential cache holds the tickets for a user. A given user can
136233294Sstas * have several credential caches, one for each realm where the user
137233294Sstas * have the initial tickets (the first krbtgt).
138233294Sstas *
139233294Sstas * The credential cache data can be stored internally in different
140233294Sstas * way, each of them for different proposes.  File credential (FILE)
141233294Sstas * caches and processes based (KCM) caches are for permanent
142233294Sstas * storage. While memory caches (MEMORY) are local caches to the local
143233294Sstas * process.
144233294Sstas *
145233294Sstas * Caches are opened with krb5_cc_resolve() or created with
146233294Sstas * krb5_cc_new_unique().
147233294Sstas *
148233294Sstas * If the cache needs to be opened again (using krb5_cc_resolve())
149233294Sstas * krb5_cc_close() will close the handle, but not the remove the
150233294Sstas * cache. krb5_cc_destroy() will zero out the cache, remove the cache
151233294Sstas * so it can no longer be referenced.
152233294Sstas *
153233294Sstas * See also @ref krb5_ccache_intro and @ref krb5_ccache .
154233294Sstas *
155233294Sstas * @subsection intro_krb5_error_code Kerberos errors
156233294Sstas *
157233294Sstas * Kerberos errors are based on the com_err library.  All error codes are
158233294Sstas * 32-bit signed numbers, the first 24 bits define what subsystem the
159233294Sstas * error originates from, and last 8 bits are 255 error codes within the
160233294Sstas * library.  Each error code have fixed string associated with it.  For
161233294Sstas * example, the error-code -1765328383 have the symbolic name
162233294Sstas * KRB5KDC_ERR_NAME_EXP, and associated error string ``Client's entry in
163233294Sstas * database has expired''.
164233294Sstas *
165233294Sstas * This is a great improvement compared to just getting one of the unix
166233294Sstas * error-codes back.  However, Heimdal have an extention to pass back
167233294Sstas * customised errors messages.  Instead of getting ``Key table entry not
168233294Sstas * found'', the user might back ``failed to find
169233294Sstas * host/host.example.com\@EXAMLE.COM(kvno 3) in keytab /etc/krb5.keytab
170233294Sstas * (des-cbc-crc)''.  This improves the chance that the user find the
171233294Sstas * cause of the error so you should use the customised error message
172233294Sstas * whenever it's available.
173233294Sstas *
174233294Sstas * See also module @ref krb5_error .
175233294Sstas *
176233294Sstas *
177233294Sstas * @subsection intro_krb5_keytab Keytab management
178233294Sstas *
179233294Sstas * A keytab is a storage for locally stored keys. Heimdal includes keytab
180233294Sstas * support for Kerberos 5 keytabs, Kerberos 4 srvtab, AFS-KeyFile's,
181233294Sstas * and for storing keys in memory.
182233294Sstas *
183233294Sstas * Keytabs are used for servers and long-running services.
184233294Sstas *
185233294Sstas * See also @ref krb5_keytab_intro and @ref krb5_keytab .
186233294Sstas *
187233294Sstas * @subsection intro_krb5_crypto Kerberos crypto
188233294Sstas *
189233294Sstas * Heimdal includes a implementation of the Kerberos crypto framework,
190233294Sstas * all crypto operations. To create a crypto context call krb5_crypto_init().
191233294Sstas *
192233294Sstas * See also module @ref krb5_crypto .
193233294Sstas *
194233294Sstas * @section kerberos5_client Walkthrough of a sample Kerberos 5 client
195233294Sstas *
196233294Sstas * This example contains parts of a sample TCP Kerberos 5 clients, if you
197233294Sstas * want a real working client, please look in appl/test directory in
198233294Sstas * the Heimdal distribution.
199233294Sstas *
200233294Sstas * All Kerberos error-codes that are returned from kerberos functions in
201233294Sstas * this program are passed to krb5_err, that will print a
202233294Sstas * descriptive text of the error code and exit. Graphical programs can
203233294Sstas * convert error-code to a human readable error-string with the
204233294Sstas * krb5_get_error_message() function.
205233294Sstas *
206233294Sstas * Note that you should not use any Kerberos function before
207233294Sstas * krb5_init_context() have completed successfully. That is the
208233294Sstas * reason err() is used when krb5_init_context() fails.
209233294Sstas *
210233294Sstas * First the client needs to call krb5_init_context to initialise
211233294Sstas * the Kerberos 5 library. This is only needed once per thread
212233294Sstas * in the program. If the function returns a non-zero value it indicates
213233294Sstas * that either the Kerberos implementation is failing or it's disabled on
214233294Sstas * this host.
215233294Sstas *
216233294Sstas * @code
217233294Sstas * #include <krb5.h>
218233294Sstas *
219233294Sstas * int
220233294Sstas * main(int argc, char **argv)
221233294Sstas * {
222233294Sstas *         krb5_context context;
223233294Sstas *
224233294Sstas *         if (krb5_init_context(&context))
225233294Sstas *                 errx (1, "krb5_context");
226233294Sstas * @endcode
227233294Sstas *
228233294Sstas * Now the client wants to connect to the host at the other end. The
229233294Sstas * preferred way of doing this is using getaddrinfo (for
230233294Sstas * operating system that have this function implemented), since getaddrinfo
231233294Sstas * is neutral to the address type and can use any protocol that is available.
232233294Sstas *
233233294Sstas * @code
234233294Sstas *         struct addrinfo *ai, *a;
235233294Sstas *         struct addrinfo hints;
236233294Sstas *         int error;
237233294Sstas *
238233294Sstas *         memset (&hints, 0, sizeof(hints));
239233294Sstas *         hints.ai_socktype = SOCK_STREAM;
240233294Sstas *         hints.ai_protocol = IPPROTO_TCP;
241233294Sstas *
242233294Sstas *         error = getaddrinfo (hostname, "pop3", &hints, &ai);
243233294Sstas *         if (error)
244233294Sstas *                 errx (1, "%s: %s", hostname, gai_strerror(error));
245233294Sstas *
246233294Sstas *         for (a = ai; a != NULL; a = a->ai_next) {
247233294Sstas *                 int s;
248233294Sstas *
249233294Sstas *                 s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
250233294Sstas *                 if (s < 0)
251233294Sstas *                         continue;
252233294Sstas *                 if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
253233294Sstas *                         warn ("connect(%s)", hostname);
254233294Sstas *                             close (s);
255233294Sstas *                             continue;
256233294Sstas *                 }
257233294Sstas *                 freeaddrinfo (ai);
258233294Sstas *                 ai = NULL;
259233294Sstas *         }
260233294Sstas *         if (ai) {
261233294Sstas *                     freeaddrinfo (ai);
262233294Sstas *                     errx ("failed to contact %s", hostname);
263233294Sstas *         }
264233294Sstas * @endcode
265233294Sstas *
266233294Sstas * Before authenticating, an authentication context needs to be
267233294Sstas * created. This context keeps all information for one (to be) authenticated
268233294Sstas * connection (see krb5_auth_context).
269233294Sstas *
270233294Sstas * @code
271233294Sstas *         status = krb5_auth_con_init (context, &auth_context);
272233294Sstas *         if (status)
273233294Sstas *                 krb5_err (context, 1, status, "krb5_auth_con_init");
274233294Sstas * @endcode
275233294Sstas *
276233294Sstas * For setting the address in the authentication there is a help function
277233294Sstas * krb5_auth_con_setaddrs_from_fd() that does everything that is needed
278233294Sstas * when given a connected file descriptor to the socket.
279233294Sstas *
280233294Sstas * @code
281233294Sstas *         status = krb5_auth_con_setaddrs_from_fd (context,
282233294Sstas *                                                  auth_context,
283233294Sstas *                                                  &sock);
284233294Sstas *         if (status)
285233294Sstas *                 krb5_err (context, 1, status,
286233294Sstas *                           "krb5_auth_con_setaddrs_from_fd");
287233294Sstas * @endcode
288233294Sstas *
289233294Sstas * The next step is to build a server principal for the service we want
290233294Sstas * to connect to. (See also krb5_sname_to_principal().)
291233294Sstas *
292233294Sstas * @code
293233294Sstas *         status = krb5_sname_to_principal (context,
294233294Sstas *                                           hostname,
295233294Sstas *                                           service,
296233294Sstas *                                           KRB5_NT_SRV_HST,
297233294Sstas *                                           &server);
298233294Sstas *         if (status)
299233294Sstas *                 krb5_err (context, 1, status, "krb5_sname_to_principal");
300233294Sstas * @endcode
301233294Sstas *
302233294Sstas * The client principal is not passed to krb5_sendauth()
303233294Sstas * function, this causes the krb5_sendauth() function to try to figure it
304233294Sstas * out itself.
305233294Sstas *
306233294Sstas * The server program is using the function krb5_recvauth() to
307233294Sstas * receive the Kerberos 5 authenticator.
308233294Sstas *
309233294Sstas * In this case, mutual authentication will be tried. That means that the server
310233294Sstas * will authenticate to the client. Using mutual authentication
311233294Sstas * is good since it enables the user to verify that they are talking to the
312233294Sstas * right server (a server that knows the key).
313233294Sstas *
314233294Sstas * If you are using a non-blocking socket you will need to do all work of
315233294Sstas * krb5_sendauth() yourself. Basically you need to send over the
316233294Sstas * authenticator from krb5_mk_req() and, in case of mutual
317233294Sstas * authentication, verifying the result from the server with
318233294Sstas * krb5_rd_rep().
319233294Sstas *
320233294Sstas * @code
321233294Sstas *         status = krb5_sendauth (context,
322233294Sstas *                                 &auth_context,
323233294Sstas *                                 &sock,
324233294Sstas *                                 VERSION,
325233294Sstas *                                 NULL,
326233294Sstas *                                 server,
327233294Sstas *                                 AP_OPTS_MUTUAL_REQUIRED,
328233294Sstas *                                 NULL,
329233294Sstas *                                 NULL,
330233294Sstas *                                 NULL,
331233294Sstas *                                 NULL,
332233294Sstas *                                 NULL,
333233294Sstas *                                 NULL);
334233294Sstas *         if (status)
335233294Sstas *                 krb5_err (context, 1, status, "krb5_sendauth");
336233294Sstas * @endcode
337233294Sstas *
338233294Sstas * Once authentication has been performed, it is time to send some
339233294Sstas * data. First we create a krb5_data structure, then we sign it with
340233294Sstas * krb5_mk_safe() using the auth_context that contains the
341233294Sstas * session-key that was exchanged in the
342233294Sstas * krb5_sendauth()/krb5_recvauth() authentication
343233294Sstas * sequence.
344233294Sstas *
345233294Sstas * @code
346233294Sstas *         data.data   = "hej";
347233294Sstas *         data.length = 3;
348233294Sstas *
349233294Sstas *         krb5_data_zero (&packet);
350233294Sstas *
351233294Sstas *         status = krb5_mk_safe (context,
352233294Sstas *                                auth_context,
353233294Sstas *                                &data,
354233294Sstas *                                &packet,
355233294Sstas *                                NULL);
356233294Sstas *         if (status)
357233294Sstas *                 krb5_err (context, 1, status, "krb5_mk_safe");
358233294Sstas * @endcode
359233294Sstas *
360233294Sstas * And send it over the network.
361233294Sstas *
362233294Sstas * @code
363233294Sstas *         len = packet.length;
364233294Sstas *         net_len = htonl(len);
365233294Sstas *
366233294Sstas *         if (krb5_net_write (context, &sock, &net_len, 4) != 4)
367233294Sstas *                 err (1, "krb5_net_write");
368233294Sstas *         if (krb5_net_write (context, &sock, packet.data, len) != len)
369233294Sstas *                 err (1, "krb5_net_write");
370233294Sstas * @endcode
371233294Sstas *
372233294Sstas * To send encrypted (and signed) data krb5_mk_priv() should be
373233294Sstas * used instead. krb5_mk_priv() works the same way as
374233294Sstas * krb5_mk_safe(), with the exception that it encrypts the data
375233294Sstas * in addition to signing it.
376233294Sstas *
377233294Sstas * @code
378233294Sstas *         data.data   = "hemligt";
379233294Sstas *         data.length = 7;
380233294Sstas *
381233294Sstas *         krb5_data_free (&packet);
382233294Sstas *
383233294Sstas *         status = krb5_mk_priv (context,
384233294Sstas *                                auth_context,
385233294Sstas *                                &data,
386233294Sstas *                                &packet,
387233294Sstas *                                NULL);
388233294Sstas *         if (status)
389233294Sstas *                 krb5_err (context, 1, status, "krb5_mk_priv");
390233294Sstas * @endcode
391233294Sstas *
392233294Sstas * And send it over the network.
393233294Sstas *
394233294Sstas * @code
395233294Sstas *         len = packet.length;
396233294Sstas *         net_len = htonl(len);
397233294Sstas *
398233294Sstas *         if (krb5_net_write (context, &sock, &net_len, 4) != 4)
399233294Sstas *                 err (1, "krb5_net_write");
400233294Sstas *         if (krb5_net_write (context, &sock, packet.data, len) != len)
401233294Sstas *                 err (1, "krb5_net_write");
402233294Sstas *
403233294Sstas * @endcode
404233294Sstas *
405233294Sstas * The server is using krb5_rd_safe() and
406233294Sstas * krb5_rd_priv() to verify the signature and decrypt the packet.
407233294Sstas *
408233294Sstas * @section intro_krb5_verify_user Validating a password in an application
409233294Sstas *
410233294Sstas * See the manual page for krb5_verify_user().
411233294Sstas *
412233294Sstas * @section mit_differences API differences to MIT Kerberos
413233294Sstas *
414233294Sstas * This section is somewhat disorganised, but so far there is no overall
415233294Sstas * structure to the differences, though some of the have their root in
416233294Sstas * that Heimdal uses an ASN.1 compiler and MIT doesn't.
417233294Sstas *
418233294Sstas * @subsection mit_krb5_principal Principal and realms
419233294Sstas *
420233294Sstas * Heimdal stores the realm as a krb5_realm, that is a char *.
421233294Sstas * MIT Kerberos uses a krb5_data to store a realm.
422233294Sstas *
423233294Sstas * In Heimdal krb5_principal doesn't contain the component
424233294Sstas * name_type; it's instead stored in component
425233294Sstas * name.name_type. To get and set the nametype in Heimdal, use
426233294Sstas * krb5_principal_get_type() and
427233294Sstas * krb5_principal_set_type().
428233294Sstas *
429233294Sstas * For more information about principal and realms, see
430233294Sstas * krb5_principal.
431233294Sstas *
432233294Sstas * @subsection mit_krb5_error_code Error messages
433233294Sstas *
434233294Sstas * To get the error string, Heimdal uses
435233294Sstas * krb5_get_error_message(). This is to return custom error messages
436233294Sstas * (like ``Can't find host/datan.example.com\@CODE.COM in
437233294Sstas * /etc/krb5.conf.'' instead of a ``Key table entry not found'' that
438233294Sstas * error_message returns.
439233294Sstas *
440233294Sstas * Heimdal uses a threadsafe(r) version of the com_err interface; the
441233294Sstas * global com_err table isn't initialised.  Then
442233294Sstas * error_message returns quite a boring error string (just
443233294Sstas * the error code itself).
444233294Sstas *
445233294Sstas *
446233294Sstas */
447233294Sstas
448233294Sstas/**
449233294Sstas *
450233294Sstas *
451233294Sstas * @page krb5_fileformats File formats
452233294Sstas *
453233294Sstas * @section fileformats File formats
454233294Sstas *
455233294Sstas * This section documents the diffrent file formats that are used in
456233294Sstas * Heimdal and other Kerberos implementations.
457233294Sstas *
458233294Sstas * @subsection file_keytab keytab
459233294Sstas *
460233294Sstas * The keytab binary format is not a standard format. The format has
461233294Sstas * evolved and may continue to. It is however understood by several
462233294Sstas * Kerberos implementations including Heimdal, MIT, Sun's Java ktab and
463233294Sstas * are created by the ktpass.exe utility from Windows. So it has
464233294Sstas * established itself as the defacto format for storing Kerberos keys.
465233294Sstas *
466233294Sstas * The following C-like structure definitions illustrate the MIT keytab
467233294Sstas * file format. All values are in network byte order. All text is ASCII.
468233294Sstas *
469233294Sstas * @code
470233294Sstas *   keytab {
471233294Sstas *       uint16_t file_format_version;                    # 0x502
472233294Sstas *       keytab_entry entries[*];
473233294Sstas *   };
474233294Sstas *
475233294Sstas *   keytab_entry {
476233294Sstas *       int32_t size;
477233294Sstas *       uint16_t num_components;   # subtract 1 if version 0x501
478233294Sstas *       counted_octet_string realm;
479233294Sstas *       counted_octet_string components[num_components];
480233294Sstas *       uint32_t name_type;       # not present if version 0x501
481233294Sstas *       uint32_t timestamp;
482233294Sstas *       uint8_t vno8;
483233294Sstas *       keyblock key;
484233294Sstas *       uint32_t vno; #only present if >= 4 bytes left in entry
485233294Sstas *       uint32_t flags; #only present if >= 4 bytes left in entry
486233294Sstas *   };
487233294Sstas *
488233294Sstas *   counted_octet_string {
489233294Sstas *       uint16_t length;
490233294Sstas *       uint8_t data[length];
491233294Sstas *   };
492233294Sstas *
493233294Sstas *   keyblock {
494233294Sstas *       uint16_t type;
495233294Sstas *       counted_octet_string;
496233294Sstas *   };
497233294Sstas * @endcode
498233294Sstas *
499233294Sstas * All numbers are stored in network byteorder (big endian) format.
500233294Sstas *
501233294Sstas * The keytab file format begins with the 16 bit file_format_version which
502233294Sstas * at the time this document was authored is 0x502. The format of older
503233294Sstas * keytabs is described at the end of this document.
504233294Sstas *
505233294Sstas * The file_format_version is immediately followed by an array of
506233294Sstas * keytab_entry structures which are prefixed with a 32 bit size indicating
507233294Sstas * the number of bytes that follow in the entry. Note that the size should be
508233294Sstas * evaluated as signed. This is because a negative value indicates that the
509233294Sstas * entry is in fact empty (e.g. it has been deleted) and that the negative
510233294Sstas * value of that negative value (which is of course a positive value) is
511233294Sstas * the offset to the next keytab_entry. Based on these size values alone
512233294Sstas * the entire keytab file can be traversed.
513233294Sstas *
514233294Sstas * The size is followed by a 16 bit num_components field indicating the
515233294Sstas * number of counted_octet_string components in the components array.
516233294Sstas *
517233294Sstas * The num_components field is followed by a counted_octet_string
518233294Sstas * representing the realm of the principal.
519233294Sstas *
520233294Sstas * A counted_octet_string is simply an array of bytes prefixed with a 16
521233294Sstas * bit length. For the realm and name components, the counted_octet_string
522233294Sstas * bytes are ASCII encoded text with no zero terminator.
523233294Sstas *
524233294Sstas * Following the realm is the components array that represents the name of
525233294Sstas * the principal. The text of these components may be joined with slashs
526233294Sstas * to construct the typical SPN representation. For example, the service
527233294Sstas * principal HTTP/www.foo.net\@FOO.NET would consist of name components
528233294Sstas * "HTTP" followed by "www.foo.net".
529233294Sstas *
530233294Sstas * Following the components array is the 32 bit name_type (e.g. 1 is
531233294Sstas * KRB5_NT_PRINCIPAL, 2 is KRB5_NT_SRV_INST, 5 is KRB5_NT_UID, etc). In
532233294Sstas * practice the name_type is almost certainly 1 meaning KRB5_NT_PRINCIPAL.
533233294Sstas *
534233294Sstas * The 32 bit timestamp indicates the time the key was established for that
535233294Sstas * principal. The value represents the number of seconds since Jan 1, 1970.
536233294Sstas *
537233294Sstas * The 8 bit vno8 field is the version number of the key. This value is
538233294Sstas * overridden by the 32 bit vno field if it is present. The vno8 field is
539233294Sstas * filled with the lower 8 bits of the 32 bit protocol kvno field.
540233294Sstas *
541233294Sstas * The keyblock structure consists of a 16 bit value indicating the
542233294Sstas * encryption type and is a counted_octet_string containing the key.  The
543233294Sstas * encryption type is the same as the Kerberos standard (e.g. 3 is
544233294Sstas * des-cbc-md5, 23 is arcfour-hmac-md5, etc).
545233294Sstas *
546233294Sstas * The last field of the keytab_entry structure is optional. If the size of
547233294Sstas * the keytab_entry indicates that there are at least 4 bytes remaining,
548233294Sstas * a 32 bit value representing the key version number is present. This
549233294Sstas * value supersedes the 8 bit vno8 value preceeding the keyblock.
550233294Sstas *
551233294Sstas * Older keytabs with a file_format_version of 0x501 are different in
552233294Sstas * three ways:
553233294Sstas *
554233294Sstas * - All integers are in host byte order [1].
555233294Sstas * - The num_components field is 1 too large (i.e. after decoding, decrement by 1).
556233294Sstas * - The 32 bit name_type field is not present.
557233294Sstas *
558233294Sstas * [1] The file_format_version field should really be treated as two
559233294Sstas * separate 8 bit quantities representing the major and minor version
560233294Sstas * number respectively.
561233294Sstas *
562233294Sstas * @subsection file_hdb_dump Heimdal database dump file
563233294Sstas *
564233294Sstas * Format of the Heimdal text dump file as of Heimdal 0.6.3:
565233294Sstas *
566233294Sstas * Each line in the dump file is one entry in the database.
567233294Sstas *
568233294Sstas * Each field of a line is separated by one or more spaces, with the
569233294Sstas * exception of fields consisting of principals containing spaces, where
570233294Sstas * space can be quoted with \ and \ is quoted by \.
571233294Sstas *
572233294Sstas * Fields and their types are:
573233294Sstas *
574233294Sstas * @code
575233294Sstas * 	Quoted princial (quote character is \) [string]
576233294Sstas * 	Keys [keys]
577233294Sstas * 	Created by [event]
578233294Sstas * 	Modified by [event optional]
579233294Sstas * 	Valid start time [time optional]
580233294Sstas * 	Valid end time [time optional]
581233294Sstas * 	Password end valid time [time optional]
582233294Sstas * 	Max lifetime of ticket [time optional]
583233294Sstas * 	Max renew time of ticket [integer optional]
584233294Sstas * 	Flags [hdb flags]
585233294Sstas * 	Generation number [generation optional]
586233294Sstas * 	Extensions [extentions optional]
587233294Sstas * @endcode
588233294Sstas *
589233294Sstas * Fields following these silently are ignored.
590233294Sstas *
591233294Sstas * All optional fields will be skipped if they fail to parse (or comprise
592233294Sstas * the optional field marker of "-", w/o quotes).
593233294Sstas *
594233294Sstas * Example:
595233294Sstas *
596233294Sstas * @code
597233294Sstas * fred\@CODE.COM 27:1:16:e8b4c8fc7e60b9e641dcf4cff3f08a701d982a2f89ba373733d26ca59ba6c789666f6b8bfcf169412bb1e5dceb9b33cda29f3412:-:1:3:4498a933881178c744f4232172dcd774c64e81fa6d05ecdf643a7e390624a0ebf3c7407a:-:1:2:b01934b13eb795d76f3a80717d469639b4da0cfb644161340ef44fdeb375e54d684dbb85:-:1:1:ea8e16d8078bf60c781da90f508d4deccba70595258b9d31888d33987cd31af0c9cced2e:- 20020415130120:admin\@CODE.COM 20041221112428:fred\@CODE.COM - - - 86400 604800 126 20020415130120:793707:28 -
598233294Sstas * @endcode
599233294Sstas *
600233294Sstas * Encoding of types are as follows:
601233294Sstas *
602233294Sstas * - keys
603233294Sstas *
604233294Sstas * @code
605233294Sstas * kvno:[masterkvno:keytype:keydata:salt]{zero or more separated by :}
606233294Sstas * @endcode
607233294Sstas *
608233294Sstas * kvno is the key version number.
609233294Sstas *
610233294Sstas * keydata is hex-encoded
611233294Sstas *
612233294Sstas * masterkvno is the kvno of the database master key.  If this field is
613233294Sstas * empty, the kadmin load and merge operations will encrypt the key data
614233294Sstas * with the master key if there is one.  Otherwise the key data will be
615233294Sstas * imported asis.
616233294Sstas *
617233294Sstas * salt is encoded as "-" (no/default salt) or
618233294Sstas *
619233294Sstas * @code
620233294Sstas * salt-type /
621233294Sstas * salt-type / "string"
622233294Sstas * salt-type / hex-encoded-data
623233294Sstas * @endcode
624233294Sstas *
625233294Sstas * keytype is the protocol enctype number; see enum ENCTYPE in
626233294Sstas * include/krb5_asn1.h for values.
627233294Sstas *
628233294Sstas * Example:
629233294Sstas * @code
630233294Sstas * 27:1:16:e8b4c8fc7e60b9e641dcf4cff3f08a701d982a2f89ba373733d26ca59ba6c789666f6b8bfcf169412bb1e5dceb9b33cda29f3412:-:1:3:4498a933881178c744f4232172dcd774c64e81fa6d05ecdf643a7e390624a0ebf3c7407a:-:1:2:b01934b13eb795d76f3a80717d469639b4da0cfb644161340ef44fdeb375e54d684dbb85:-:1:1:ea8e16d8078bf60c781da90f508d4deccba70595258b9d31888d33987cd31af0c9cced2e:-
631233294Sstas * @endcode
632233294Sstas *
633233294Sstas *
634233294Sstas * @code
635233294Sstas * kvno=27,{key: masterkvno=1,keytype=des3-cbc-sha1,keydata=..., default salt}...
636233294Sstas * @endcode
637233294Sstas *
638233294Sstas * - time
639233294Sstas *
640233294Sstas * Format of the time is: YYYYmmddHHMMSS, corresponding to strftime
641233294Sstas * format "%Y%m%d%k%M%S".
642233294Sstas *
643233294Sstas * Time is expressed in UTC.
644233294Sstas *
645233294Sstas * Time can be optional (using -), when the time 0 is used.
646233294Sstas *
647233294Sstas * Example:
648233294Sstas *
649233294Sstas * @code
650233294Sstas * 20041221112428
651233294Sstas * @endcode
652233294Sstas *
653233294Sstas * - event
654233294Sstas *
655233294Sstas * @code
656233294Sstas * 	time:principal
657233294Sstas * @endcode
658233294Sstas *
659233294Sstas * time is as given in format time
660233294Sstas *
661233294Sstas * principal is a string.  Not quoting it may not work in earlier
662233294Sstas * versions of Heimdal.
663233294Sstas *
664233294Sstas * Example:
665233294Sstas * @code
666233294Sstas * 20041221112428:bloggs\@CODE.COM
667233294Sstas * @endcode
668233294Sstas *
669233294Sstas * - hdb flags
670233294Sstas *
671233294Sstas * Integer encoding of HDB flags, see HDBFlags in lib/hdb/hdb.asn1. Each
672233294Sstas * bit in the integer is the same as the bit in the specification.
673233294Sstas *
674233294Sstas * - generation:
675233294Sstas *
676233294Sstas * @code
677233294Sstas * time:usec:gen
678233294Sstas * @endcode
679233294Sstas *
680233294Sstas *
681233294Sstas * usec is a the microsecond, integer.
682233294Sstas * gen is generation number, integer.
683233294Sstas *
684233294Sstas * The generation can be defaulted (using '-') or the empty string
685233294Sstas *
686233294Sstas * - extensions:
687233294Sstas *
688233294Sstas * @code
689233294Sstas * first-hex-encoded-HDB-Extension[:second-...]
690233294Sstas * @endcode
691233294Sstas *
692233294Sstas * HDB-extension is encoded the DER encoded HDB-Extension from
693233294Sstas * lib/hdb/hdb.asn1. Consumers HDB extensions should be aware that
694233294Sstas * unknown entires needs to be preserved even thought the ASN.1 data
695233294Sstas * content might be unknown. There is a critical flag in the data to show
696233294Sstas * to the KDC that the entry MUST be understod if the entry is to be
697233294Sstas * used.
698233294Sstas *
699233294Sstas *
700233294Sstas */
701