1178825Sdfr@c $Id: programming.texi 22071 2007-11-14 20:04:50Z lha $
278527Sassar
3178825Sdfr@node Programming with Kerberos, Migration, Windows 2000 compatability, Top
478527Sassar@chapter Programming with Kerberos
578527Sassar
678527SassarFirst you need to know how the Kerberos model works, go read the
778527Sassarintroduction text (@pxref{What is Kerberos?}).
878527Sassar
978527Sassar@menu
1078527Sassar* Kerberos 5 API Overview::     
11178825Sdfr* Walkthrough of a sample Kerberos 5 client::  
1278527Sassar* Validating a password in a server application::  
13178825Sdfr* API differences to MIT Kerberos::  
14178825Sdfr* File formats::
1578527Sassar@end menu
1678527Sassar
17178825Sdfr@node Kerberos 5 API Overview, Walkthrough of a sample Kerberos 5 client, Programming with Kerberos, Programming with Kerberos
1878527Sassar@section Kerberos 5 API Overview
1978527Sassar
20178825SdfrAll functions are documented in manual pages.  This section tries to
21178825Sdfrgive an overview of the major components used in Kerberos library, and
22178825Sdfrpoint to where to look for a specific function.
2378527Sassar
2478527Sassar@subsection Kerberos context
2578527Sassar
2678527SassarA kerberos context (@code{krb5_context}) holds all per thread state. All global variables that
27178825Sdfrare context specific are stored in this structure, including default
28178825Sdfrencryption types, credential cache (for example, a ticket file), and default realms.
2978527Sassar
3078527SassarSee the manual pages for @manpage{krb5_context,3} and
3178527Sassar@manpage{krb5_init_context,3}.
3278527Sassar
33178825Sdfr@subsection Kerberos authentication context
3478527Sassar
3578527SassarKerberos authentication context (@code{krb5_auth_context}) holds all
3678527Sassarcontext related to an authenticated connection, in a similar way to the
3778527Sassarkerberos context that holds the context for the thread or process.
3878527Sassar
3978527SassarThe @code{krb5_auth_context} is used by various functions that are
4078527Sassardirectly related to authentication between the server/client. Example of
4178527Sassardata that this structure contains are various flags, addresses of client
4278527Sassarand server, port numbers, keyblocks (and subkeys), sequence numbers,
4378527Sassarreplay cache, and checksum types.
4478527Sassar
4578527SassarSee the manual page for @manpage{krb5_auth_context,3}.
4678527Sassar
47178825Sdfr@subsection Kerberos principal
48178825Sdfr
49178825SdfrThe Kerberos principal is the structure that identifies a user or
50178825Sdfrservice in Kerberos. The structure that holds the principal is the
51178825Sdfr@code{krb5_principal}. There are function to extract the realm and
52178825Sdfrelements of the principal, but most applications have no reason to
53178825Sdfrinspect the content of the structure.
54178825Sdfr
55178825SdfrThe are several ways to create a principal (with different degree of
56178825Sdfrportability), and one way to free it.
57178825Sdfr
58178825SdfrSee manual page for @manpage{krb5_principal,3} for more information
59178825Sdfrabout the functions.
60178825Sdfr
61178825Sdfr@subsection Credential cache
62178825Sdfr
63178825SdfrA credential cache holds the tickets for a user. A given user can have
64178825Sdfrseveral credential caches, one for each realm where the user have the
65178825Sdfrinitial tickets (the first krbtgt).
66178825Sdfr
67178825SdfrThe credential cache data can be stored internally in different way, each of them for
68178825Sdfrdifferent proposes.  File credential (FILE) caches and processes based
69178825Sdfr(KCM) caches are for permanent storage. While memory caches (MEMORY)
70178825Sdfrare local caches to the local process.
71178825Sdfr
72178825SdfrCaches are opened with @manpage{krb5_cc_resolve,3} or created with
73178825Sdfr@manpage{krb5_cc_gen_unique,3}.
74178825Sdfr
75178825SdfrIf the cache needs to be opened again (using
76178825Sdfr@manpage{krb5_cc_resolve,3}) @manpage{krb5_cc_close,3} will close the
77178825Sdfrhandle, but not the remove the cache. @manpage{krb5_cc_destroy,3} will
78178825Sdfrzero out the cache, remove the cache so it can no longer be
79178825Sdfrreferenced.
80178825Sdfr
81178825SdfrSee also manual page for @manpage{krb5_ccache,3}
82178825Sdfr
83178825Sdfr@subsection Kerberos errors
84178825Sdfr
85178825SdfrKerberos errors are based on the com_err library.  All error codes are
86178825Sdfr32-bit signed numbers, the first 24 bits define what subsystem the
87178825Sdfrerror originates from, and last 8 bits are 255 error codes within the
88178825Sdfrlibrary.  Each error code have fixed string associated with it.  For
89178825Sdfrexample, the error-code -1765328383 have the symbolic name
90178825SdfrKRB5KDC_ERR_NAME_EXP, and associated error string ``Client's entry in
91178825Sdfrdatabase has expired''.
92178825Sdfr
93178825SdfrThis is a great improvement compared to just getting one of the unix
94178825Sdfrerror-codes back.  However, Heimdal have an extention to pass back
95178825Sdfrcustomised errors messages.  Instead of getting ``Key table entry not
96178825Sdfrfound'', the user might back ``failed to find
97178825Sdfrhost/host.example.com@@EXAMLE.COM(kvno 3) in keytab /etc/krb5.keytab
98178825Sdfr(des-cbc-crc)''.  This improves the chance that the user find the
99178825Sdfrcause of the error so you should use the customised error message
100178825Sdfrwhenever it's available.
101178825Sdfr
102178825SdfrSee also manual page for @manpage{krb5_get_error_string,3} and
103178825Sdfr@manpage{krb5_get_err_text,3}.
104178825Sdfr
105120945Snectar@subsection Keytab management
10678527Sassar
10778527SassarA keytab is a storage for locally stored keys. Heimdal includes keytab
10878527Sassarsupport for Kerberos 5 keytabs, Kerberos 4 srvtab, AFS-KeyFile's,
10978527Sassarand for storing keys in memory.
11078527Sassar
111178825SdfrKeytabs are used for servers and long-running services.
112178825Sdfr
11378527SassarSee also manual page for @manpage{krb5_keytab,3}
11478527Sassar
115178825Sdfr@subsection Kerberos crypto
11678527Sassar
117178825SdfrHeimdal includes a implementation of the Kerberos crypto framework,
118178825Sdfrall crypto operations.
119178825Sdfr
120178825SdfrSee also manual page for @manpage{krb5_crypto_init,3},
121178825Sdfr@manpage{krb5_keyblock,3}, @manpage{krb5_create_checksum,3}, 
122178825Sdfrand @manpage{krb5_encrypt,3}.
123178825Sdfr
124178825Sdfr@node Walkthrough of a sample Kerberos 5 client, Validating a password in a server application, Kerberos 5 API Overview, Programming with Kerberos
125178825Sdfr@section Walkthrough of a sample Kerberos 5 client
126178825Sdfr
12778527SassarThis example contains parts of a sample TCP Kerberos 5 clients, if you
12878527Sassarwant a real working client, please look in @file{appl/test} directory in
12978527Sassarthe Heimdal distribution.
13078527Sassar
13178527SassarAll Kerberos error-codes that are returned from kerberos functions in
13278527Sassarthis program are passed to @code{krb5_err}, that will print a
13378527Sassardescriptive text of the error code and exit. Graphical programs can
134178825Sdfrconvert error-code to a human readable error-string with the
13578527Sassar@manpage{krb5_get_err_text,3} function.
13678527Sassar
13778527SassarNote that you should not use any Kerberos function before
13878527Sassar@code{krb5_init_context()} have completed successfully. That is the
139178825Sdfrreason @code{err()} is used when @code{krb5_init_context()} fails.
14078527Sassar
141178825SdfrFirst the client needs to call @code{krb5_init_context} to initialise
14278527Sassarthe Kerberos 5 library. This is only needed once per thread
14378527Sassarin the program. If the function returns a non-zero value it indicates
144178825Sdfrthat either the Kerberos implementation is failing or it's disabled on
14578527Sassarthis host.
14678527Sassar
14778527Sassar@example
14878527Sassar#include <krb5.h>
14978527Sassar
15078527Sassarint
15178527Sassarmain(int argc, char **argv)
15278527Sassar@{
15378527Sassar        krb5_context context;
15478527Sassar
15578527Sassar        if (krb5_context(&context))
15678527Sassar                errx (1, "krb5_context");
15778527Sassar@end example
15878527Sassar
15978527SassarNow the client wants to connect to the host at the other end. The
16078527Sassarpreferred way of doing this is using @manpage{getaddrinfo,3} (for
16178527Sassaroperating system that have this function implemented), since getaddrinfo
16278527Sassaris neutral to the address type and can use any protocol that is available.
16378527Sassar
16478527Sassar@example
16578527Sassar        struct addrinfo *ai, *a;
16678527Sassar        struct addrinfo hints;
16778527Sassar        int error;
16878527Sassar
16978527Sassar        memset (&hints, 0, sizeof(hints));
17078527Sassar        hints.ai_socktype = SOCK_STREAM;
17178527Sassar        hints.ai_protocol = IPPROTO_TCP;
17278527Sassar
17378527Sassar        error = getaddrinfo (hostname, "pop3", &hints, &ai);
17478527Sassar        if (error)
17578527Sassar                errx (1, "%s: %s", hostname, gai_strerror(error));
17678527Sassar
17778527Sassar        for (a = ai; a != NULL; a = a->ai_next) @{
17878527Sassar                int s;
17978527Sassar
18078527Sassar                s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
18178527Sassar                if (s < 0)
18278527Sassar                        continue;
18378527Sassar                if (connect (s, a->ai_addr, a->ai_addrlen) < 0) @{
18478527Sassar                        warn ("connect(%s)", hostname);
18578527Sassar                            close (s);
18678527Sassar                            continue;
18778527Sassar                @}
18878527Sassar                freeaddrinfo (ai);
18978527Sassar                ai = NULL;
19078527Sassar        @}
19178527Sassar        if (ai) @{
19278527Sassar                    freeaddrinfo (ai);
19378527Sassar                    errx ("failed to contact %s", hostname);
19478527Sassar        @}
19578527Sassar@end example
19678527Sassar
19778527SassarBefore authenticating, an authentication context needs to be
19878527Sassarcreated. This context keeps all information for one (to be) authenticated
19978527Sassarconnection (see @manpage{krb5_auth_context,3}).
20078527Sassar
20178527Sassar@example
20278527Sassar        status = krb5_auth_con_init (context, &auth_context);
20378527Sassar        if (status)
20478527Sassar                krb5_err (context, 1, status, "krb5_auth_con_init");
20578527Sassar@end example
20678527Sassar
20778527SassarFor setting the address in the authentication there is a help function
208178825Sdfr@code{krb5_auth_con_setaddrs_from_fd} that does everything that is needed
20978527Sassarwhen given a connected file descriptor to the socket.
21078527Sassar
21178527Sassar@example
21278527Sassar        status = krb5_auth_con_setaddrs_from_fd (context,
21378527Sassar                                                 auth_context,
21478527Sassar                                                 &sock);
21578527Sassar        if (status)
21678527Sassar                krb5_err (context, 1, status, 
21778527Sassar                          "krb5_auth_con_setaddrs_from_fd");
21878527Sassar@end example
21978527Sassar
22078527SassarThe next step is to build a server principal for the service we want
22178527Sassarto connect to. (See also @manpage{krb5_sname_to_principal,3}.)
22278527Sassar
22378527Sassar@example
22478527Sassar        status = krb5_sname_to_principal (context,
22578527Sassar                                          hostname,
22678527Sassar                                          service,
22778527Sassar                                          KRB5_NT_SRV_HST,
22878527Sassar                                          &server);
22978527Sassar        if (status)
23078527Sassar                krb5_err (context, 1, status, "krb5_sname_to_principal");
23178527Sassar@end example
23278527Sassar
23378527SassarThe client principal is not passed to @manpage{krb5_sendauth,3}
23478527Sassarfunction, this causes the @code{krb5_sendauth} function to try to figure it
23578527Sassarout itself.
23678527Sassar
23778527SassarThe server program is using the function @manpage{krb5_recvauth,3} to
23878527Sassarreceive the Kerberos 5 authenticator.
23978527Sassar
240178825SdfrIn this case, mutual authentication will be tried. That means that the server
241178825Sdfrwill authenticate to the client. Using mutual authentication
24278527Sassaris good since it enables the user to verify that they are talking to the
24378527Sassarright server (a server that knows the key).
24478527Sassar
24578527SassarIf you are using a non-blocking socket you will need to do all work of
24678527Sassar@code{krb5_sendauth} yourself. Basically you need to send over the
24778527Sassarauthenticator from @manpage{krb5_mk_req,3} and, in case of mutual
24878527Sassarauthentication, verifying the result from the server with
24978527Sassar@manpage{krb5_rd_rep,3}.
25078527Sassar
25178527Sassar@example
25278527Sassar        status = krb5_sendauth (context,
25378527Sassar                                &auth_context,
25478527Sassar                                &sock,
25578527Sassar                                VERSION,
25678527Sassar                                NULL,
25778527Sassar                                server,
25878527Sassar                                AP_OPTS_MUTUAL_REQUIRED,
25978527Sassar                                NULL,
26078527Sassar                                NULL,
26178527Sassar                                NULL,
26278527Sassar                                NULL,
26378527Sassar                                NULL,
26478527Sassar                                NULL);
26578527Sassar        if (status)
26678527Sassar                krb5_err (context, 1, status, "krb5_sendauth");
26778527Sassar@end example
26878527Sassar
26978527SassarOnce authentication has been performed, it is time to send some
27078527Sassardata. First we create a krb5_data structure, then we sign it with
27178527Sassar@manpage{krb5_mk_safe,3} using the @code{auth_context} that contains the
27278527Sassarsession-key that was exchanged in the
27378527Sassar@manpage{krb5_sendauth,3}/@manpage{krb5_recvauth,3} authentication
27478527Sassarsequence.
27578527Sassar
27678527Sassar@example
27778527Sassar        data.data   = "hej";
27878527Sassar        data.length = 3;
27978527Sassar
28078527Sassar        krb5_data_zero (&packet);
28178527Sassar
28278527Sassar        status = krb5_mk_safe (context,
28378527Sassar                               auth_context,
28478527Sassar                               &data,
28578527Sassar                               &packet,
28678527Sassar                               NULL);
28778527Sassar        if (status)
28878527Sassar                krb5_err (context, 1, status, "krb5_mk_safe");
28978527Sassar@end example
29078527Sassar
29178527SassarAnd send it over the network.
29278527Sassar
29378527Sassar@example
29478527Sassar        len = packet.length;
29578527Sassar        net_len = htonl(len);
29678527Sassar
29778527Sassar        if (krb5_net_write (context, &sock, &net_len, 4) != 4)
29878527Sassar                err (1, "krb5_net_write");
29978527Sassar        if (krb5_net_write (context, &sock, packet.data, len) != len)
30078527Sassar                err (1, "krb5_net_write");
30178527Sassar@end example
30278527Sassar
30378527SassarTo send encrypted (and signed) data @manpage{krb5_mk_priv,3} should be
30478527Sassarused instead. @manpage{krb5_mk_priv,3} works the same way as
30578527Sassar@manpage{krb5_mk_safe,3}, with the exception that it encrypts the data
30678527Sassarin addition to signing it.
30778527Sassar
30878527Sassar@example
30978527Sassar        data.data   = "hemligt";
31078527Sassar        data.length = 7;
31178527Sassar
31278527Sassar        krb5_data_free (&packet);
31378527Sassar
31478527Sassar        status = krb5_mk_priv (context,
31578527Sassar                               auth_context,
31678527Sassar                               &data,
31778527Sassar                               &packet,
31878527Sassar                               NULL);
31978527Sassar        if (status)
32078527Sassar                krb5_err (context, 1, status, "krb5_mk_priv");
32178527Sassar@end example
32278527Sassar
32378527SassarAnd send it over the network.
32478527Sassar
32578527Sassar@example
32678527Sassar        len = packet.length;
32778527Sassar        net_len = htonl(len);
32878527Sassar
32978527Sassar        if (krb5_net_write (context, &sock, &net_len, 4) != 4)
33078527Sassar                err (1, "krb5_net_write");
33178527Sassar        if (krb5_net_write (context, &sock, packet.data, len) != len)
33278527Sassar                err (1, "krb5_net_write");
33378527Sassar
33478527Sassar@end example
33578527Sassar
33678527SassarThe server is using @manpage{krb5_rd_safe,3} and
33778527Sassar@manpage{krb5_rd_priv,3} to verify the signature and decrypt the packet.
33878527Sassar
339178825Sdfr@node Validating a password in a server application, API differences to MIT Kerberos, Walkthrough of a sample Kerberos 5 client, Programming with Kerberos
34078527Sassar@section Validating a password in an application
34178527Sassar
34278527SassarSee the manual page for @manpage{krb5_verify_user,3}.
34378527Sassar
344178825Sdfr@node API differences to MIT Kerberos, File formats, Validating a password in a server application, Programming with Kerberos
345178825Sdfr@section API differences to MIT Kerberos
346178825Sdfr
347178825SdfrThis section is somewhat disorganised, but so far there is no overall
348178825Sdfrstructure to the differences, though some of the have their root in
349178825Sdfrthat Heimdal uses an ASN.1 compiler and MIT doesn't.
350178825Sdfr
351178825Sdfr@subsection Principal and realms
352178825Sdfr
353178825SdfrHeimdal stores the realm as a @code{krb5_realm}, that is a @code{char *}.
354178825SdfrMIT Kerberos uses a @code{krb5_data} to store a realm.
355178825Sdfr
356178825SdfrIn Heimdal @code{krb5_principal} doesn't contain the component
357178825Sdfr@code{name_type}; it's instead stored in component
358178825Sdfr@code{name.name_type}. To get and set the nametype in Heimdal, use
359178825Sdfr@manpage{krb5_principal_get_type,3} and
360178825Sdfr@manpage{krb5_principal_set_type,3}.
361178825Sdfr
362178825SdfrFor more information about principal and realms, see
363178825Sdfr@manpage{krb5_principal,3}.
364178825Sdfr
365178825Sdfr@subsection Error messages
366178825Sdfr
367178825SdfrTo get the error string, Heimdal uses
368178825Sdfr@manpage{krb5_get_error_string,3} or, if @code{NULL} is returned,
369178825Sdfr@manpage{krb5_get_err_text,3}. This is to return custom error messages
370178825Sdfr(like ``Can't find host/datan.example.com@@EXAMPLE.COM in
371178825Sdfr/etc/krb5.conf.'' instead of a ``Key table entry not found'' that
372178825Sdfr@manpage{error_message,3} returns.
373178825Sdfr
374178825SdfrHeimdal uses a threadsafe(r) version of the com_err interface; the
375178825Sdfrglobal @code{com_err} table isn't initialised.  Then
376178825Sdfr@manpage{error_message,3} returns quite a boring error string (just
377178825Sdfrthe error code itself).
378178825Sdfr
379178825Sdfr
380178825Sdfr@c @node Why you should use GSS-API for new applications, Walkthrough of a sample GSS-API client, Validating a password in a server application, Programming with Kerberos
38178527Sassar@c @section Why you should use GSS-API for new applications
38278527Sassar@c 
38378527Sassar@c SSPI, bah, bah, microsoft, bah, bah, almost GSS-API.
38478527Sassar@c 
38578527Sassar@c It would also be possible for other mechanisms then Kerberos, but that
38678527Sassar@c doesn't exist any other GSS-API implementations today.
38778527Sassar@c 
388178825Sdfr@c @node Walkthrough of a sample GSS-API client, , Why you should use GSS-API for new applications, Programming with Kerberos
389178825Sdfr@c @section Walkthrough of a sample GSS-API client
39078527Sassar@c 
39178527Sassar@c Write about how gssapi_clent.c works.
392178825Sdfr
393178825Sdfr@node File formats,  , API differences to MIT Kerberos, Programming with Kerberos
394178825Sdfr@section File formats
395178825Sdfr
396178825SdfrThis section documents the diffrent file formats that are used in
397178825SdfrHeimdal and other Kerberos implementations.
398178825Sdfr
399178825Sdfr@subsection keytab
400178825Sdfr
401178825SdfrThe keytab binary format is not a standard format. The format has
402178825Sdfrevolved and may continue to. It is however understood by several
403178825SdfrKerberos implementations including Heimdal, MIT, Sun's Java ktab and
404178825Sdfrare created by the ktpass.exe utility from Windows. So it has
405178825Sdfrestablished itself as the defacto format for storing Kerberos keys.
406178825Sdfr
407178825SdfrThe following C-like structure definitions illustrate the MIT keytab
408178825Sdfrfile format. All values are in network byte order. All text is ASCII.
409178825Sdfr
410178825Sdfr@example
411178825Sdfr  keytab @{
412178825Sdfr      uint16_t file_format_version;                    /* 0x502 */
413178825Sdfr      keytab_entry entries[*];
414178825Sdfr  @};
415178825Sdfr
416178825Sdfr  keytab_entry @{
417178825Sdfr      int32_t size;
418178825Sdfr      uint16_t num_components;   /* subtract 1 if version 0x501 */
419178825Sdfr      counted_octet_string realm;
420178825Sdfr      counted_octet_string components[num_components];
421178825Sdfr      uint32_t name_type;       /* not present if version 0x501 */
422178825Sdfr      uint32_t timestamp;
423178825Sdfr      uint8_t vno8;
424178825Sdfr      keyblock key;
425178825Sdfr      uint32_t vno; /* only present if >= 4 bytes left in entry */
426178825Sdfr  @};
427178825Sdfr
428178825Sdfr  counted_octet_string @{
429178825Sdfr      uint16_t length;
430178825Sdfr      uint8_t data[length];
431178825Sdfr  @};
432178825Sdfr
433178825Sdfr  keyblock @{
434178825Sdfr      uint16_t type;
435178825Sdfr      counted_octet_string;
436178825Sdfr  @};
437178825Sdfr@end example
438178825Sdfr
439178825SdfrAll numbers are stored in network byteorder (big endian) format.
440178825Sdfr
441178825SdfrThe keytab file format begins with the 16 bit file_format_version which
442178825Sdfrat the time this document was authored is 0x502. The format of older
443178825Sdfrkeytabs is described at the end of this document.
444178825Sdfr
445178825SdfrThe file_format_version is immediately followed by an array of
446178825Sdfrkeytab_entry structures which are prefixed with a 32 bit size indicating
447178825Sdfrthe number of bytes that follow in the entry. Note that the size should be
448178825Sdfrevaluated as signed. This is because a negative value indicates that the
449178825Sdfrentry is in fact empty (e.g. it has been deleted) and that the negative
450178825Sdfrvalue of that negative value (which is of course a positive value) is
451178825Sdfrthe offset to the next keytab_entry. Based on these size values alone
452178825Sdfrthe entire keytab file can be traversed.
453178825Sdfr
454178825SdfrThe size is followed by a 16 bit num_components field indicating the
455178825Sdfrnumber of counted_octet_string components in the components array.
456178825Sdfr
457178825SdfrThe num_components field is followed by a counted_octet_string
458178825Sdfrrepresenting the realm of the principal.
459178825Sdfr
460178825SdfrA counted_octet_string is simply an array of bytes prefixed with a 16
461178825Sdfrbit length. For the realm and name components, the counted_octet_string
462178825Sdfrbytes are ASCII encoded text with no zero terminator.
463178825Sdfr
464178825SdfrFollowing the realm is the components array that represents the name of
465178825Sdfrthe principal. The text of these components may be joined with slashs
466178825Sdfrto construct the typical SPN representation. For example, the service
467178825Sdfrprincipal HTTP/www.foo.net@@FOO.NET would consist of name components
468178825Sdfr"HTTP" followed by "www.foo.net".
469178825Sdfr
470178825SdfrFollowing the components array is the 32 bit name_type (e.g. 1 is
471178825SdfrKRB5_NT_PRINCIPAL, 2 is KRB5_NT_SRV_INST, 5 is KRB5_NT_UID, etc). In
472178825Sdfrpractice the name_type is almost certainly 1 meaning KRB5_NT_PRINCIPAL.
473178825Sdfr
474178825SdfrThe 32 bit timestamp indicates the time the key was established for that
475178825Sdfrprincipal. The value represents the number of seconds since Jan 1, 1970.
476178825Sdfr
477178825SdfrThe 8 bit vno8 field is the version number of the key. This value is
478178825Sdfroverridden by the 32 bit vno field if it is present. The vno8 field is
479178825Sdfrfilled with the lower 8 bits of the 32 bit protocol kvno field.
480178825Sdfr
481178825SdfrThe keyblock structure consists of a 16 bit value indicating the
482178825Sdfrencryption type and is a counted_octet_string containing the key.  The
483178825Sdfrencryption type is the same as the Kerberos standard (e.g. 3 is
484178825Sdfrdes-cbc-md5, 23 is arcfour-hmac-md5, etc).
485178825Sdfr
486178825SdfrThe last field of the keytab_entry structure is optional. If the size of
487178825Sdfrthe keytab_entry indicates that there are at least 4 bytes remaining,
488178825Sdfra 32 bit value representing the key version number is present. This
489178825Sdfrvalue supersedes the 8 bit vno8 value preceeding the keyblock.
490178825Sdfr
491178825SdfrOlder keytabs with a file_format_version of 0x501 are different in
492178825Sdfrthree ways:
493178825Sdfr
494178825Sdfr@table @asis
495178825Sdfr@item All integers are in host byte order [1].
496178825Sdfr@item The num_components field is 1 too large (i.e. after decoding, decrement by 1).
497178825Sdfr@item The 32 bit name_type field is not present.
498178825Sdfr@end table
499178825Sdfr
500178825Sdfr[1] The file_format_version field should really be treated as two
501178825Sdfrseparate 8 bit quantities representing the major and minor version
502178825Sdfrnumber respectively.
503178825Sdfr
504178825Sdfr@subsection Heimdal database dump file
505178825Sdfr
506178825SdfrFormat of the Heimdal text dump file as of Heimdal 0.6.3:
507178825Sdfr
508178825SdfrEach line in the dump file is one entry in the database.
509178825Sdfr
510178825SdfrEach field of a line is separated by one or more spaces, with the
511178825Sdfrexception of fields consisting of principals containing spaces, where
512178825Sdfrspace can be quoted with \ and \ is quoted by \.
513178825Sdfr
514178825SdfrFields and their types are:
515178825Sdfr
516178825Sdfr@example
517178825Sdfr	Quoted princial (quote character is \) [string]
518178825Sdfr	Keys [keys]
519178825Sdfr	Created by [event]
520178825Sdfr	Modified by [event optional]
521178825Sdfr	Valid start time [time optional]
522178825Sdfr	Valid end time [time optional]
523178825Sdfr	Password end valid time [time optional]
524178825Sdfr	Max lifetime of ticket [time optional]
525178825Sdfr	Max renew time of ticket [integer optional]
526178825Sdfr	Flags [hdb flags]
527178825Sdfr	Generation number [generation optional]
528178825Sdfr	Extensions [extentions optional]
529178825Sdfr@end example
530178825Sdfr
531178825SdfrFields following these silently are ignored.
532178825Sdfr
533178825SdfrAll optional fields will be skipped if they fail to parse (or comprise
534178825Sdfrthe optional field marker of "-", w/o quotes).
535178825Sdfr
536178825SdfrExample:
537178825Sdfr
538178825Sdfr@example
539178825Sdfrfred@@EXAMPLE.COM 27:1:16:e8b4c8fc7e60b9e641dcf4cff3f08a701d982a2f89ba373733d26ca59ba6c789666f6b8bfcf169412bb1e5dceb9b33cda29f3412:-:1:3:4498a933881178c744f4232172dcd774c64e81fa6d05ecdf643a7e390624a0ebf3c7407a:-:1:2:b01934b13eb795d76f3a80717d469639b4da0cfb644161340ef44fdeb375e54d684dbb85:-:1:1:ea8e16d8078bf60c781da90f508d4deccba70595258b9d31888d33987cd31af0c9cced2e:- 20020415130120:admin@@EXAMPLE.COM 20041221112428:fred@@EXAMPLE.COM - - - 86400 604800 126 20020415130120:793707:28 -
540178825Sdfr@end example
541178825Sdfr
542178825SdfrEncoding of types are as follows:
543178825Sdfr
544178825Sdfr@table @asis
545178825Sdfr@item keys
546178825Sdfr
547178825Sdfr@example
548178825Sdfrkvno:[masterkvno:keytype:keydata:salt]@{zero or more separated by :@}
549178825Sdfr@end example
550178825Sdfr
551178825Sdfrkvno is the key version number.
552178825Sdfr
553178825Sdfrkeydata is hex-encoded
554178825Sdfr
555178825Sdfrmasterkvno is the kvno of the database master key.  If this field is
556178825Sdfrempty, the kadmin load and merge operations will encrypt the key data
557178825Sdfrwith the master key if there is one.  Otherwise the key data will be
558178825Sdfrimported asis.
559178825Sdfr
560178825Sdfrsalt is encoded as "-" (no/default salt) or
561178825Sdfr
562178825Sdfr@example
563178825Sdfrsalt-type /
564178825Sdfrsalt-type / "string"
565178825Sdfrsalt-type / hex-encoded-data
566178825Sdfr@end example
567178825Sdfr
568178825Sdfrkeytype is the protocol enctype number; see enum ENCTYPE in
569178825Sdfrinclude/krb5_asn1.h for values.
570178825Sdfr
571178825SdfrExample:
572178825Sdfr@example
573178825Sdfr27:1:16:e8b4c8fc7e60b9e641dcf4cff3f08a701d982a2f89ba373733d26ca59ba6c789666f6b8bfcf169412bb1e5dceb9b33cda29f3412:-:1:3:4498a933881178c744f4232172dcd774c64e81fa6d05ecdf643a7e390624a0ebf3c7407a:-:1:2:b01934b13eb795d76f3a80717d469639b4da0cfb644161340ef44fdeb375e54d684dbb85:-:1:1:ea8e16d8078bf60c781da90f508d4deccba70595258b9d31888d33987cd31af0c9cced2e:-
574178825Sdfr@end example
575178825Sdfr
576178825Sdfr
577178825Sdfr@example
578178825Sdfrkvno=27,@{key: masterkvno=1,keytype=des3-cbc-sha1,keydata=..., default salt@}...
579178825Sdfr@end example
580178825Sdfr
581178825Sdfr@item time
582178825Sdfr	
583178825SdfrFormat of the time is: YYYYmmddHHMMSS, corresponding to strftime
584178825Sdfrformat "%Y%m%d%k%M%S".
585178825Sdfr
586178825SdfrTime is expressed in UTC.
587178825Sdfr
588178825SdfrTime can be optional (using -), when the time 0 is used.
589178825Sdfr
590178825SdfrExample:
591178825Sdfr
592178825Sdfr@example
593178825Sdfr20041221112428
594178825Sdfr@end example
595178825Sdfr
596178825Sdfr@item event
597178825Sdfr
598178825Sdfr@example
599178825Sdfr	time:principal
600178825Sdfr@end example
601178825Sdfr
602178825Sdfrtime is as given in format time
603178825Sdfr
604178825Sdfrprincipal is a string.  Not quoting it may not work in earlier
605178825Sdfrversions of Heimdal.
606178825Sdfr
607178825SdfrExample:
608178825Sdfr@example
609178825Sdfr20041221112428:bloggs@@EXAMPLE.COM
610178825Sdfr@end example
611178825Sdfr
612178825Sdfr@item hdb flags
613178825Sdfr
614178825SdfrInteger encoding of HDB flags, see HDBFlags in lib/hdb/hdb.asn1. Each
615178825Sdfrbit in the integer is the same as the bit in the specification.
616178825Sdfr
617178825Sdfr@item generation:
618178825Sdfr
619178825Sdfr@example
620178825Sdfrtime:usec:gen
621178825Sdfr@end example
622178825Sdfr
623178825Sdfr
624178825Sdfrusec is a the microsecond, integer.
625178825Sdfrgen is generation number, integer.
626178825Sdfr
627178825SdfrThe generation can be defaulted (using '-') or the empty string
628178825Sdfr
629178825Sdfr@item extensions:
630178825Sdfr
631178825Sdfr@example
632178825Sdfrfirst-hex-encoded-HDB-Extension[:second-...]
633178825Sdfr@end example
634178825Sdfr
635178825SdfrHDB-extension is encoded the DER encoded HDB-Extension from
636178825Sdfrlib/hdb/hdb.asn1. Consumers HDB extensions should be aware that
637178825Sdfrunknown entires needs to be preserved even thought the ASN.1 data
638178825Sdfrcontent might be unknown. There is a critical flag in the data to show
639178825Sdfrto the KDC that the entry MUST be understod if the entry is to be
640178825Sdfrused.
641178825Sdfr
642178825Sdfr@end table
643