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