xref: /freebsd/crypto/heimdal/lib/krb5/doxygen.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1c19800e8SDoug Rabson /*
2*ae771770SStanislav Sedov  * Copyright (c) 2007-2008 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson  * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson  * All rights reserved.
5c19800e8SDoug Rabson  *
6c19800e8SDoug Rabson  * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson  * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson  * are met:
9c19800e8SDoug Rabson  *
10c19800e8SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson  *
13c19800e8SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson  *    documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson  *
17c19800e8SDoug Rabson  * 3. Neither the name of the Institute nor the names of its contributors
18c19800e8SDoug Rabson  *    may be used to endorse or promote products derived from this software
19c19800e8SDoug Rabson  *    without specific prior written permission.
20c19800e8SDoug Rabson  *
21c19800e8SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22c19800e8SDoug Rabson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c19800e8SDoug Rabson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25c19800e8SDoug Rabson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c19800e8SDoug Rabson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c19800e8SDoug Rabson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c19800e8SDoug Rabson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c19800e8SDoug Rabson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c19800e8SDoug Rabson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c19800e8SDoug Rabson  * SUCH DAMAGE.
32c19800e8SDoug Rabson  */
33c19800e8SDoug Rabson 
34c19800e8SDoug Rabson #include "krb5_locl.h"
35c19800e8SDoug Rabson 
36c19800e8SDoug Rabson /**
37c19800e8SDoug Rabson  *
38c19800e8SDoug Rabson  */
39c19800e8SDoug Rabson 
40*ae771770SStanislav Sedov /*! @mainpage Heimdal Kerberos 5 library
41c19800e8SDoug Rabson  *
42*ae771770SStanislav Sedov  * @section intro Introduction
43c19800e8SDoug Rabson  *
44c19800e8SDoug Rabson  * Heimdal libkrb5 library is a implementation of the Kerberos
45c19800e8SDoug Rabson  * protocol.
46c19800e8SDoug Rabson  *
47c19800e8SDoug Rabson  * Kerberos is a system for authenticating users and services on a
48c19800e8SDoug Rabson  * network.  It is built upon the assumption that the network is
49c19800e8SDoug Rabson  * ``unsafe''.  For example, data sent over the network can be
50c19800e8SDoug Rabson  * eavesdropped and altered, and addresses can also be faked.
51c19800e8SDoug Rabson  * Therefore they cannot be used for authentication purposes.
52c19800e8SDoug Rabson  *
53*ae771770SStanislav Sedov  *
54*ae771770SStanislav Sedov  * - @ref krb5_introduction
55*ae771770SStanislav Sedov  * - @ref krb5_principal_intro
56*ae771770SStanislav Sedov  * - @ref krb5_ccache_intro
57*ae771770SStanislav Sedov  * - @ref krb5_keytab_intro
58*ae771770SStanislav Sedov  *
59*ae771770SStanislav Sedov  * If you want to know more about the file formats that is used by
60*ae771770SStanislav Sedov  * Heimdal, please see: @ref krb5_fileformats
61*ae771770SStanislav Sedov  *
62*ae771770SStanislav Sedov  * The project web page: http://www.h5l.org/
63c19800e8SDoug Rabson  *
64c19800e8SDoug Rabson  */
65c19800e8SDoug Rabson 
66c19800e8SDoug Rabson /** @defgroup krb5 Heimdal Kerberos 5 library */
67c19800e8SDoug Rabson /** @defgroup krb5_address Heimdal Kerberos 5 address functions */
68*ae771770SStanislav Sedov /** @defgroup krb5_principal Heimdal Kerberos 5 principal functions */
69c19800e8SDoug Rabson /** @defgroup krb5_ccache Heimdal Kerberos 5 credential cache functions */
70*ae771770SStanislav Sedov /** @defgroup krb5_crypto Heimdal Kerberos 5 cryptography functions */
71c19800e8SDoug Rabson /** @defgroup krb5_credential Heimdal Kerberos 5 credential handing functions */
72c19800e8SDoug Rabson /** @defgroup krb5_deprecated Heimdal Kerberos 5 deprecated functions */
73c19800e8SDoug Rabson /** @defgroup krb5_digest Heimdal Kerberos 5 digest service */
74c19800e8SDoug Rabson /** @defgroup krb5_error Heimdal Kerberos 5 error reporting functions */
75*ae771770SStanislav Sedov /** @defgroup krb5_keytab Heimdal Kerberos 5 keytab handling functions */
76*ae771770SStanislav Sedov /** @defgroup krb5_ticket Heimdal Kerberos 5 ticket functions */
77*ae771770SStanislav Sedov /** @defgroup krb5_pac Heimdal Kerberos 5 PAC handling functions */
78c19800e8SDoug Rabson /** @defgroup krb5_v4compat Heimdal Kerberos 4 compatiblity functions */
79*ae771770SStanislav Sedov /** @defgroup krb5_storage Heimdal Kerberos 5 storage functions */
80c19800e8SDoug Rabson /** @defgroup krb5_support Heimdal Kerberos 5 support functions */
81*ae771770SStanislav Sedov /** @defgroup krb5_auth Heimdal Kerberos 5 authentication functions */
82*ae771770SStanislav Sedov 
83*ae771770SStanislav Sedov 
84*ae771770SStanislav Sedov /**
85*ae771770SStanislav Sedov  * @page krb5_introduction Introduction to the Kerberos 5 API
86*ae771770SStanislav Sedov  * @section api_overview Kerberos 5 API Overview
87*ae771770SStanislav Sedov  *
88*ae771770SStanislav Sedov  * All functions are documented in manual pages.  This section tries
89*ae771770SStanislav Sedov  * to give an overview of the major components used in Kerberos
90*ae771770SStanislav Sedov  * library, and point to where to look for a specific function.
91*ae771770SStanislav Sedov  *
92*ae771770SStanislav Sedov  * @subsection intro_krb5_context Kerberos context
93*ae771770SStanislav Sedov  *
94*ae771770SStanislav Sedov  * A kerberos context (krb5_context) holds all per thread state. All
95*ae771770SStanislav Sedov  * global variables that are context specific are stored in this
96*ae771770SStanislav Sedov  * structure, including default encryption types, credential cache
97*ae771770SStanislav Sedov  * (for example, a ticket file), and default realms.
98*ae771770SStanislav Sedov  *
99*ae771770SStanislav Sedov  * The internals of the structure should never be accessed directly,
100*ae771770SStanislav Sedov  * functions exist for extracting information.
101*ae771770SStanislav Sedov  *
102*ae771770SStanislav Sedov  * See the manual page for krb5_init_context() how to create a context
103*ae771770SStanislav Sedov  * and module @ref krb5 for more information about the functions.
104*ae771770SStanislav Sedov  *
105*ae771770SStanislav Sedov  * @subsection intro_krb5_auth_context Kerberos authentication context
106*ae771770SStanislav Sedov  *
107*ae771770SStanislav Sedov  * Kerberos authentication context (krb5_auth_context) holds all
108*ae771770SStanislav Sedov  * context related to an authenticated connection, in a similar way to
109*ae771770SStanislav Sedov  * the kerberos context that holds the context for the thread or
110*ae771770SStanislav Sedov  * process.
111*ae771770SStanislav Sedov  *
112*ae771770SStanislav Sedov  * The krb5_auth_context is used by various functions that are
113*ae771770SStanislav Sedov  * directly related to authentication between the
114*ae771770SStanislav Sedov  * server/client. Example of data that this structure contains are
115*ae771770SStanislav Sedov  * various flags, addresses of client and server, port numbers,
116*ae771770SStanislav Sedov  * keyblocks (and subkeys), sequence numbers, replay cache, and
117*ae771770SStanislav Sedov  * checksum types.
118*ae771770SStanislav Sedov  *
119*ae771770SStanislav Sedov  * @subsection intro_krb5_principal Kerberos principal
120*ae771770SStanislav Sedov  *
121*ae771770SStanislav Sedov  * The Kerberos principal is the structure that identifies a user or
122*ae771770SStanislav Sedov  * service in Kerberos. The structure that holds the principal is the
123*ae771770SStanislav Sedov  * krb5_principal. There are function to extract the realm and
124*ae771770SStanislav Sedov  * elements of the principal, but most applications have no reason to
125*ae771770SStanislav Sedov  * inspect the content of the structure.
126*ae771770SStanislav Sedov  *
127*ae771770SStanislav Sedov  * The are several ways to create a principal (with different degree of
128*ae771770SStanislav Sedov  * portability), and one way to free it.
129*ae771770SStanislav Sedov  *
130*ae771770SStanislav Sedov  * See also the page @ref krb5_principal_intro for more information and also
131*ae771770SStanislav Sedov  * module @ref krb5_principal.
132*ae771770SStanislav Sedov  *
133*ae771770SStanislav Sedov  * @subsection intro_krb5_ccache Credential cache
134*ae771770SStanislav Sedov  *
135*ae771770SStanislav Sedov  * A credential cache holds the tickets for a user. A given user can
136*ae771770SStanislav Sedov  * have several credential caches, one for each realm where the user
137*ae771770SStanislav Sedov  * have the initial tickets (the first krbtgt).
138*ae771770SStanislav Sedov  *
139*ae771770SStanislav Sedov  * The credential cache data can be stored internally in different
140*ae771770SStanislav Sedov  * way, each of them for different proposes.  File credential (FILE)
141*ae771770SStanislav Sedov  * caches and processes based (KCM) caches are for permanent
142*ae771770SStanislav Sedov  * storage. While memory caches (MEMORY) are local caches to the local
143*ae771770SStanislav Sedov  * process.
144*ae771770SStanislav Sedov  *
145*ae771770SStanislav Sedov  * Caches are opened with krb5_cc_resolve() or created with
146*ae771770SStanislav Sedov  * krb5_cc_new_unique().
147*ae771770SStanislav Sedov  *
148*ae771770SStanislav Sedov  * If the cache needs to be opened again (using krb5_cc_resolve())
149*ae771770SStanislav Sedov  * krb5_cc_close() will close the handle, but not the remove the
150*ae771770SStanislav Sedov  * cache. krb5_cc_destroy() will zero out the cache, remove the cache
151*ae771770SStanislav Sedov  * so it can no longer be referenced.
152*ae771770SStanislav Sedov  *
153*ae771770SStanislav Sedov  * See also @ref krb5_ccache_intro and @ref krb5_ccache .
154*ae771770SStanislav Sedov  *
155*ae771770SStanislav Sedov  * @subsection intro_krb5_error_code Kerberos errors
156*ae771770SStanislav Sedov  *
157*ae771770SStanislav Sedov  * Kerberos errors are based on the com_err library.  All error codes are
158*ae771770SStanislav Sedov  * 32-bit signed numbers, the first 24 bits define what subsystem the
159*ae771770SStanislav Sedov  * error originates from, and last 8 bits are 255 error codes within the
160*ae771770SStanislav Sedov  * library.  Each error code have fixed string associated with it.  For
161*ae771770SStanislav Sedov  * example, the error-code -1765328383 have the symbolic name
162*ae771770SStanislav Sedov  * KRB5KDC_ERR_NAME_EXP, and associated error string ``Client's entry in
163*ae771770SStanislav Sedov  * database has expired''.
164*ae771770SStanislav Sedov  *
165*ae771770SStanislav Sedov  * This is a great improvement compared to just getting one of the unix
166*ae771770SStanislav Sedov  * error-codes back.  However, Heimdal have an extention to pass back
167*ae771770SStanislav Sedov  * customised errors messages.  Instead of getting ``Key table entry not
168*ae771770SStanislav Sedov  * found'', the user might back ``failed to find
169*ae771770SStanislav Sedov  * host/host.example.com\@EXAMLE.COM(kvno 3) in keytab /etc/krb5.keytab
170*ae771770SStanislav Sedov  * (des-cbc-crc)''.  This improves the chance that the user find the
171*ae771770SStanislav Sedov  * cause of the error so you should use the customised error message
172*ae771770SStanislav Sedov  * whenever it's available.
173*ae771770SStanislav Sedov  *
174*ae771770SStanislav Sedov  * See also module @ref krb5_error .
175*ae771770SStanislav Sedov  *
176*ae771770SStanislav Sedov  *
177*ae771770SStanislav Sedov  * @subsection intro_krb5_keytab Keytab management
178*ae771770SStanislav Sedov  *
179*ae771770SStanislav Sedov  * A keytab is a storage for locally stored keys. Heimdal includes keytab
180*ae771770SStanislav Sedov  * support for Kerberos 5 keytabs, Kerberos 4 srvtab, AFS-KeyFile's,
181*ae771770SStanislav Sedov  * and for storing keys in memory.
182*ae771770SStanislav Sedov  *
183*ae771770SStanislav Sedov  * Keytabs are used for servers and long-running services.
184*ae771770SStanislav Sedov  *
185*ae771770SStanislav Sedov  * See also @ref krb5_keytab_intro and @ref krb5_keytab .
186*ae771770SStanislav Sedov  *
187*ae771770SStanislav Sedov  * @subsection intro_krb5_crypto Kerberos crypto
188*ae771770SStanislav Sedov  *
189*ae771770SStanislav Sedov  * Heimdal includes a implementation of the Kerberos crypto framework,
190*ae771770SStanislav Sedov  * all crypto operations. To create a crypto context call krb5_crypto_init().
191*ae771770SStanislav Sedov  *
192*ae771770SStanislav Sedov  * See also module @ref krb5_crypto .
193*ae771770SStanislav Sedov  *
194*ae771770SStanislav Sedov  * @section kerberos5_client Walkthrough of a sample Kerberos 5 client
195*ae771770SStanislav Sedov  *
196*ae771770SStanislav Sedov  * This example contains parts of a sample TCP Kerberos 5 clients, if you
197*ae771770SStanislav Sedov  * want a real working client, please look in appl/test directory in
198*ae771770SStanislav Sedov  * the Heimdal distribution.
199*ae771770SStanislav Sedov  *
200*ae771770SStanislav Sedov  * All Kerberos error-codes that are returned from kerberos functions in
201*ae771770SStanislav Sedov  * this program are passed to krb5_err, that will print a
202*ae771770SStanislav Sedov  * descriptive text of the error code and exit. Graphical programs can
203*ae771770SStanislav Sedov  * convert error-code to a human readable error-string with the
204*ae771770SStanislav Sedov  * krb5_get_error_message() function.
205*ae771770SStanislav Sedov  *
206*ae771770SStanislav Sedov  * Note that you should not use any Kerberos function before
207*ae771770SStanislav Sedov  * krb5_init_context() have completed successfully. That is the
208*ae771770SStanislav Sedov  * reason err() is used when krb5_init_context() fails.
209*ae771770SStanislav Sedov  *
210*ae771770SStanislav Sedov  * First the client needs to call krb5_init_context to initialise
211*ae771770SStanislav Sedov  * the Kerberos 5 library. This is only needed once per thread
212*ae771770SStanislav Sedov  * in the program. If the function returns a non-zero value it indicates
213*ae771770SStanislav Sedov  * that either the Kerberos implementation is failing or it's disabled on
214*ae771770SStanislav Sedov  * this host.
215*ae771770SStanislav Sedov  *
216*ae771770SStanislav Sedov  * @code
217*ae771770SStanislav Sedov  * #include <krb5.h>
218*ae771770SStanislav Sedov  *
219*ae771770SStanislav Sedov  * int
220*ae771770SStanislav Sedov  * main(int argc, char **argv)
221*ae771770SStanislav Sedov  * {
222*ae771770SStanislav Sedov  *         krb5_context context;
223*ae771770SStanislav Sedov  *
224*ae771770SStanislav Sedov  *         if (krb5_init_context(&context))
225*ae771770SStanislav Sedov  *                 errx (1, "krb5_context");
226*ae771770SStanislav Sedov  * @endcode
227*ae771770SStanislav Sedov  *
228*ae771770SStanislav Sedov  * Now the client wants to connect to the host at the other end. The
229*ae771770SStanislav Sedov  * preferred way of doing this is using getaddrinfo (for
230*ae771770SStanislav Sedov  * operating system that have this function implemented), since getaddrinfo
231*ae771770SStanislav Sedov  * is neutral to the address type and can use any protocol that is available.
232*ae771770SStanislav Sedov  *
233*ae771770SStanislav Sedov  * @code
234*ae771770SStanislav Sedov  *         struct addrinfo *ai, *a;
235*ae771770SStanislav Sedov  *         struct addrinfo hints;
236*ae771770SStanislav Sedov  *         int error;
237*ae771770SStanislav Sedov  *
238*ae771770SStanislav Sedov  *         memset (&hints, 0, sizeof(hints));
239*ae771770SStanislav Sedov  *         hints.ai_socktype = SOCK_STREAM;
240*ae771770SStanislav Sedov  *         hints.ai_protocol = IPPROTO_TCP;
241*ae771770SStanislav Sedov  *
242*ae771770SStanislav Sedov  *         error = getaddrinfo (hostname, "pop3", &hints, &ai);
243*ae771770SStanislav Sedov  *         if (error)
244*ae771770SStanislav Sedov  *                 errx (1, "%s: %s", hostname, gai_strerror(error));
245*ae771770SStanislav Sedov  *
246*ae771770SStanislav Sedov  *         for (a = ai; a != NULL; a = a->ai_next) {
247*ae771770SStanislav Sedov  *                 int s;
248*ae771770SStanislav Sedov  *
249*ae771770SStanislav Sedov  *                 s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
250*ae771770SStanislav Sedov  *                 if (s < 0)
251*ae771770SStanislav Sedov  *                         continue;
252*ae771770SStanislav Sedov  *                 if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
253*ae771770SStanislav Sedov  *                         warn ("connect(%s)", hostname);
254*ae771770SStanislav Sedov  *                             close (s);
255*ae771770SStanislav Sedov  *                             continue;
256*ae771770SStanislav Sedov  *                 }
257*ae771770SStanislav Sedov  *                 freeaddrinfo (ai);
258*ae771770SStanislav Sedov  *                 ai = NULL;
259*ae771770SStanislav Sedov  *         }
260*ae771770SStanislav Sedov  *         if (ai) {
261*ae771770SStanislav Sedov  *                     freeaddrinfo (ai);
262*ae771770SStanislav Sedov  *                     errx ("failed to contact %s", hostname);
263*ae771770SStanislav Sedov  *         }
264*ae771770SStanislav Sedov  * @endcode
265*ae771770SStanislav Sedov  *
266*ae771770SStanislav Sedov  * Before authenticating, an authentication context needs to be
267*ae771770SStanislav Sedov  * created. This context keeps all information for one (to be) authenticated
268*ae771770SStanislav Sedov  * connection (see krb5_auth_context).
269*ae771770SStanislav Sedov  *
270*ae771770SStanislav Sedov  * @code
271*ae771770SStanislav Sedov  *         status = krb5_auth_con_init (context, &auth_context);
272*ae771770SStanislav Sedov  *         if (status)
273*ae771770SStanislav Sedov  *                 krb5_err (context, 1, status, "krb5_auth_con_init");
274*ae771770SStanislav Sedov  * @endcode
275*ae771770SStanislav Sedov  *
276*ae771770SStanislav Sedov  * For setting the address in the authentication there is a help function
277*ae771770SStanislav Sedov  * krb5_auth_con_setaddrs_from_fd() that does everything that is needed
278*ae771770SStanislav Sedov  * when given a connected file descriptor to the socket.
279*ae771770SStanislav Sedov  *
280*ae771770SStanislav Sedov  * @code
281*ae771770SStanislav Sedov  *         status = krb5_auth_con_setaddrs_from_fd (context,
282*ae771770SStanislav Sedov  *                                                  auth_context,
283*ae771770SStanislav Sedov  *                                                  &sock);
284*ae771770SStanislav Sedov  *         if (status)
285*ae771770SStanislav Sedov  *                 krb5_err (context, 1, status,
286*ae771770SStanislav Sedov  *                           "krb5_auth_con_setaddrs_from_fd");
287*ae771770SStanislav Sedov  * @endcode
288*ae771770SStanislav Sedov  *
289*ae771770SStanislav Sedov  * The next step is to build a server principal for the service we want
290*ae771770SStanislav Sedov  * to connect to. (See also krb5_sname_to_principal().)
291*ae771770SStanislav Sedov  *
292*ae771770SStanislav Sedov  * @code
293*ae771770SStanislav Sedov  *         status = krb5_sname_to_principal (context,
294*ae771770SStanislav Sedov  *                                           hostname,
295*ae771770SStanislav Sedov  *                                           service,
296*ae771770SStanislav Sedov  *                                           KRB5_NT_SRV_HST,
297*ae771770SStanislav Sedov  *                                           &server);
298*ae771770SStanislav Sedov  *         if (status)
299*ae771770SStanislav Sedov  *                 krb5_err (context, 1, status, "krb5_sname_to_principal");
300*ae771770SStanislav Sedov  * @endcode
301*ae771770SStanislav Sedov  *
302*ae771770SStanislav Sedov  * The client principal is not passed to krb5_sendauth()
303*ae771770SStanislav Sedov  * function, this causes the krb5_sendauth() function to try to figure it
304*ae771770SStanislav Sedov  * out itself.
305*ae771770SStanislav Sedov  *
306*ae771770SStanislav Sedov  * The server program is using the function krb5_recvauth() to
307*ae771770SStanislav Sedov  * receive the Kerberos 5 authenticator.
308*ae771770SStanislav Sedov  *
309*ae771770SStanislav Sedov  * In this case, mutual authentication will be tried. That means that the server
310*ae771770SStanislav Sedov  * will authenticate to the client. Using mutual authentication
311*ae771770SStanislav Sedov  * is good since it enables the user to verify that they are talking to the
312*ae771770SStanislav Sedov  * right server (a server that knows the key).
313*ae771770SStanislav Sedov  *
314*ae771770SStanislav Sedov  * If you are using a non-blocking socket you will need to do all work of
315*ae771770SStanislav Sedov  * krb5_sendauth() yourself. Basically you need to send over the
316*ae771770SStanislav Sedov  * authenticator from krb5_mk_req() and, in case of mutual
317*ae771770SStanislav Sedov  * authentication, verifying the result from the server with
318*ae771770SStanislav Sedov  * krb5_rd_rep().
319*ae771770SStanislav Sedov  *
320*ae771770SStanislav Sedov  * @code
321*ae771770SStanislav Sedov  *         status = krb5_sendauth (context,
322*ae771770SStanislav Sedov  *                                 &auth_context,
323*ae771770SStanislav Sedov  *                                 &sock,
324*ae771770SStanislav Sedov  *                                 VERSION,
325*ae771770SStanislav Sedov  *                                 NULL,
326*ae771770SStanislav Sedov  *                                 server,
327*ae771770SStanislav Sedov  *                                 AP_OPTS_MUTUAL_REQUIRED,
328*ae771770SStanislav Sedov  *                                 NULL,
329*ae771770SStanislav Sedov  *                                 NULL,
330*ae771770SStanislav Sedov  *                                 NULL,
331*ae771770SStanislav Sedov  *                                 NULL,
332*ae771770SStanislav Sedov  *                                 NULL,
333*ae771770SStanislav Sedov  *                                 NULL);
334*ae771770SStanislav Sedov  *         if (status)
335*ae771770SStanislav Sedov  *                 krb5_err (context, 1, status, "krb5_sendauth");
336*ae771770SStanislav Sedov  * @endcode
337*ae771770SStanislav Sedov  *
338*ae771770SStanislav Sedov  * Once authentication has been performed, it is time to send some
339*ae771770SStanislav Sedov  * data. First we create a krb5_data structure, then we sign it with
340*ae771770SStanislav Sedov  * krb5_mk_safe() using the auth_context that contains the
341*ae771770SStanislav Sedov  * session-key that was exchanged in the
342*ae771770SStanislav Sedov  * krb5_sendauth()/krb5_recvauth() authentication
343*ae771770SStanislav Sedov  * sequence.
344*ae771770SStanislav Sedov  *
345*ae771770SStanislav Sedov  * @code
346*ae771770SStanislav Sedov  *         data.data   = "hej";
347*ae771770SStanislav Sedov  *         data.length = 3;
348*ae771770SStanislav Sedov  *
349*ae771770SStanislav Sedov  *         krb5_data_zero (&packet);
350*ae771770SStanislav Sedov  *
351*ae771770SStanislav Sedov  *         status = krb5_mk_safe (context,
352*ae771770SStanislav Sedov  *                                auth_context,
353*ae771770SStanislav Sedov  *                                &data,
354*ae771770SStanislav Sedov  *                                &packet,
355*ae771770SStanislav Sedov  *                                NULL);
356*ae771770SStanislav Sedov  *         if (status)
357*ae771770SStanislav Sedov  *                 krb5_err (context, 1, status, "krb5_mk_safe");
358*ae771770SStanislav Sedov  * @endcode
359*ae771770SStanislav Sedov  *
360*ae771770SStanislav Sedov  * And send it over the network.
361*ae771770SStanislav Sedov  *
362*ae771770SStanislav Sedov  * @code
363*ae771770SStanislav Sedov  *         len = packet.length;
364*ae771770SStanislav Sedov  *         net_len = htonl(len);
365*ae771770SStanislav Sedov  *
366*ae771770SStanislav Sedov  *         if (krb5_net_write (context, &sock, &net_len, 4) != 4)
367*ae771770SStanislav Sedov  *                 err (1, "krb5_net_write");
368*ae771770SStanislav Sedov  *         if (krb5_net_write (context, &sock, packet.data, len) != len)
369*ae771770SStanislav Sedov  *                 err (1, "krb5_net_write");
370*ae771770SStanislav Sedov  * @endcode
371*ae771770SStanislav Sedov  *
372*ae771770SStanislav Sedov  * To send encrypted (and signed) data krb5_mk_priv() should be
373*ae771770SStanislav Sedov  * used instead. krb5_mk_priv() works the same way as
374*ae771770SStanislav Sedov  * krb5_mk_safe(), with the exception that it encrypts the data
375*ae771770SStanislav Sedov  * in addition to signing it.
376*ae771770SStanislav Sedov  *
377*ae771770SStanislav Sedov  * @code
378*ae771770SStanislav Sedov  *         data.data   = "hemligt";
379*ae771770SStanislav Sedov  *         data.length = 7;
380*ae771770SStanislav Sedov  *
381*ae771770SStanislav Sedov  *         krb5_data_free (&packet);
382*ae771770SStanislav Sedov  *
383*ae771770SStanislav Sedov  *         status = krb5_mk_priv (context,
384*ae771770SStanislav Sedov  *                                auth_context,
385*ae771770SStanislav Sedov  *                                &data,
386*ae771770SStanislav Sedov  *                                &packet,
387*ae771770SStanislav Sedov  *                                NULL);
388*ae771770SStanislav Sedov  *         if (status)
389*ae771770SStanislav Sedov  *                 krb5_err (context, 1, status, "krb5_mk_priv");
390*ae771770SStanislav Sedov  * @endcode
391*ae771770SStanislav Sedov  *
392*ae771770SStanislav Sedov  * And send it over the network.
393*ae771770SStanislav Sedov  *
394*ae771770SStanislav Sedov  * @code
395*ae771770SStanislav Sedov  *         len = packet.length;
396*ae771770SStanislav Sedov  *         net_len = htonl(len);
397*ae771770SStanislav Sedov  *
398*ae771770SStanislav Sedov  *         if (krb5_net_write (context, &sock, &net_len, 4) != 4)
399*ae771770SStanislav Sedov  *                 err (1, "krb5_net_write");
400*ae771770SStanislav Sedov  *         if (krb5_net_write (context, &sock, packet.data, len) != len)
401*ae771770SStanislav Sedov  *                 err (1, "krb5_net_write");
402*ae771770SStanislav Sedov  *
403*ae771770SStanislav Sedov  * @endcode
404*ae771770SStanislav Sedov  *
405*ae771770SStanislav Sedov  * The server is using krb5_rd_safe() and
406*ae771770SStanislav Sedov  * krb5_rd_priv() to verify the signature and decrypt the packet.
407*ae771770SStanislav Sedov  *
408*ae771770SStanislav Sedov  * @section intro_krb5_verify_user Validating a password in an application
409*ae771770SStanislav Sedov  *
410*ae771770SStanislav Sedov  * See the manual page for krb5_verify_user().
411*ae771770SStanislav Sedov  *
412*ae771770SStanislav Sedov  * @section mit_differences API differences to MIT Kerberos
413*ae771770SStanislav Sedov  *
414*ae771770SStanislav Sedov  * This section is somewhat disorganised, but so far there is no overall
415*ae771770SStanislav Sedov  * structure to the differences, though some of the have their root in
416*ae771770SStanislav Sedov  * that Heimdal uses an ASN.1 compiler and MIT doesn't.
417*ae771770SStanislav Sedov  *
418*ae771770SStanislav Sedov  * @subsection mit_krb5_principal Principal and realms
419*ae771770SStanislav Sedov  *
420*ae771770SStanislav Sedov  * Heimdal stores the realm as a krb5_realm, that is a char *.
421*ae771770SStanislav Sedov  * MIT Kerberos uses a krb5_data to store a realm.
422*ae771770SStanislav Sedov  *
423*ae771770SStanislav Sedov  * In Heimdal krb5_principal doesn't contain the component
424*ae771770SStanislav Sedov  * name_type; it's instead stored in component
425*ae771770SStanislav Sedov  * name.name_type. To get and set the nametype in Heimdal, use
426*ae771770SStanislav Sedov  * krb5_principal_get_type() and
427*ae771770SStanislav Sedov  * krb5_principal_set_type().
428*ae771770SStanislav Sedov  *
429*ae771770SStanislav Sedov  * For more information about principal and realms, see
430*ae771770SStanislav Sedov  * krb5_principal.
431*ae771770SStanislav Sedov  *
432*ae771770SStanislav Sedov  * @subsection mit_krb5_error_code Error messages
433*ae771770SStanislav Sedov  *
434*ae771770SStanislav Sedov  * To get the error string, Heimdal uses
435*ae771770SStanislav Sedov  * krb5_get_error_message(). This is to return custom error messages
436*ae771770SStanislav Sedov  * (like ``Can't find host/datan.example.com\@CODE.COM in
437*ae771770SStanislav Sedov  * /etc/krb5.conf.'' instead of a ``Key table entry not found'' that
438*ae771770SStanislav Sedov  * error_message returns.
439*ae771770SStanislav Sedov  *
440*ae771770SStanislav Sedov  * Heimdal uses a threadsafe(r) version of the com_err interface; the
441*ae771770SStanislav Sedov  * global com_err table isn't initialised.  Then
442*ae771770SStanislav Sedov  * error_message returns quite a boring error string (just
443*ae771770SStanislav Sedov  * the error code itself).
444*ae771770SStanislav Sedov  *
445*ae771770SStanislav Sedov  *
446*ae771770SStanislav Sedov  */
447*ae771770SStanislav Sedov 
448*ae771770SStanislav Sedov /**
449*ae771770SStanislav Sedov  *
450*ae771770SStanislav Sedov  *
451*ae771770SStanislav Sedov  * @page krb5_fileformats File formats
452*ae771770SStanislav Sedov  *
453*ae771770SStanislav Sedov  * @section fileformats File formats
454*ae771770SStanislav Sedov  *
455*ae771770SStanislav Sedov  * This section documents the diffrent file formats that are used in
456*ae771770SStanislav Sedov  * Heimdal and other Kerberos implementations.
457*ae771770SStanislav Sedov  *
458*ae771770SStanislav Sedov  * @subsection file_keytab keytab
459*ae771770SStanislav Sedov  *
460*ae771770SStanislav Sedov  * The keytab binary format is not a standard format. The format has
461*ae771770SStanislav Sedov  * evolved and may continue to. It is however understood by several
462*ae771770SStanislav Sedov  * Kerberos implementations including Heimdal, MIT, Sun's Java ktab and
463*ae771770SStanislav Sedov  * are created by the ktpass.exe utility from Windows. So it has
464*ae771770SStanislav Sedov  * established itself as the defacto format for storing Kerberos keys.
465*ae771770SStanislav Sedov  *
466*ae771770SStanislav Sedov  * The following C-like structure definitions illustrate the MIT keytab
467*ae771770SStanislav Sedov  * file format. All values are in network byte order. All text is ASCII.
468*ae771770SStanislav Sedov  *
469*ae771770SStanislav Sedov  * @code
470*ae771770SStanislav Sedov  *   keytab {
471*ae771770SStanislav Sedov  *       uint16_t file_format_version;                    # 0x502
472*ae771770SStanislav Sedov  *       keytab_entry entries[*];
473*ae771770SStanislav Sedov  *   };
474*ae771770SStanislav Sedov  *
475*ae771770SStanislav Sedov  *   keytab_entry {
476*ae771770SStanislav Sedov  *       int32_t size;
477*ae771770SStanislav Sedov  *       uint16_t num_components;   # subtract 1 if version 0x501
478*ae771770SStanislav Sedov  *       counted_octet_string realm;
479*ae771770SStanislav Sedov  *       counted_octet_string components[num_components];
480*ae771770SStanislav Sedov  *       uint32_t name_type;       # not present if version 0x501
481*ae771770SStanislav Sedov  *       uint32_t timestamp;
482*ae771770SStanislav Sedov  *       uint8_t vno8;
483*ae771770SStanislav Sedov  *       keyblock key;
484*ae771770SStanislav Sedov  *       uint32_t vno; #only present if >= 4 bytes left in entry
485*ae771770SStanislav Sedov  *       uint32_t flags; #only present if >= 4 bytes left in entry
486*ae771770SStanislav Sedov  *   };
487*ae771770SStanislav Sedov  *
488*ae771770SStanislav Sedov  *   counted_octet_string {
489*ae771770SStanislav Sedov  *       uint16_t length;
490*ae771770SStanislav Sedov  *       uint8_t data[length];
491*ae771770SStanislav Sedov  *   };
492*ae771770SStanislav Sedov  *
493*ae771770SStanislav Sedov  *   keyblock {
494*ae771770SStanislav Sedov  *       uint16_t type;
495*ae771770SStanislav Sedov  *       counted_octet_string;
496*ae771770SStanislav Sedov  *   };
497*ae771770SStanislav Sedov  * @endcode
498*ae771770SStanislav Sedov  *
499*ae771770SStanislav Sedov  * All numbers are stored in network byteorder (big endian) format.
500*ae771770SStanislav Sedov  *
501*ae771770SStanislav Sedov  * The keytab file format begins with the 16 bit file_format_version which
502*ae771770SStanislav Sedov  * at the time this document was authored is 0x502. The format of older
503*ae771770SStanislav Sedov  * keytabs is described at the end of this document.
504*ae771770SStanislav Sedov  *
505*ae771770SStanislav Sedov  * The file_format_version is immediately followed by an array of
506*ae771770SStanislav Sedov  * keytab_entry structures which are prefixed with a 32 bit size indicating
507*ae771770SStanislav Sedov  * the number of bytes that follow in the entry. Note that the size should be
508*ae771770SStanislav Sedov  * evaluated as signed. This is because a negative value indicates that the
509*ae771770SStanislav Sedov  * entry is in fact empty (e.g. it has been deleted) and that the negative
510*ae771770SStanislav Sedov  * value of that negative value (which is of course a positive value) is
511*ae771770SStanislav Sedov  * the offset to the next keytab_entry. Based on these size values alone
512*ae771770SStanislav Sedov  * the entire keytab file can be traversed.
513*ae771770SStanislav Sedov  *
514*ae771770SStanislav Sedov  * The size is followed by a 16 bit num_components field indicating the
515*ae771770SStanislav Sedov  * number of counted_octet_string components in the components array.
516*ae771770SStanislav Sedov  *
517*ae771770SStanislav Sedov  * The num_components field is followed by a counted_octet_string
518*ae771770SStanislav Sedov  * representing the realm of the principal.
519*ae771770SStanislav Sedov  *
520*ae771770SStanislav Sedov  * A counted_octet_string is simply an array of bytes prefixed with a 16
521*ae771770SStanislav Sedov  * bit length. For the realm and name components, the counted_octet_string
522*ae771770SStanislav Sedov  * bytes are ASCII encoded text with no zero terminator.
523*ae771770SStanislav Sedov  *
524*ae771770SStanislav Sedov  * Following the realm is the components array that represents the name of
525*ae771770SStanislav Sedov  * the principal. The text of these components may be joined with slashs
526*ae771770SStanislav Sedov  * to construct the typical SPN representation. For example, the service
527*ae771770SStanislav Sedov  * principal HTTP/www.foo.net\@FOO.NET would consist of name components
528*ae771770SStanislav Sedov  * "HTTP" followed by "www.foo.net".
529*ae771770SStanislav Sedov  *
530*ae771770SStanislav Sedov  * Following the components array is the 32 bit name_type (e.g. 1 is
531*ae771770SStanislav Sedov  * KRB5_NT_PRINCIPAL, 2 is KRB5_NT_SRV_INST, 5 is KRB5_NT_UID, etc). In
532*ae771770SStanislav Sedov  * practice the name_type is almost certainly 1 meaning KRB5_NT_PRINCIPAL.
533*ae771770SStanislav Sedov  *
534*ae771770SStanislav Sedov  * The 32 bit timestamp indicates the time the key was established for that
535*ae771770SStanislav Sedov  * principal. The value represents the number of seconds since Jan 1, 1970.
536*ae771770SStanislav Sedov  *
537*ae771770SStanislav Sedov  * The 8 bit vno8 field is the version number of the key. This value is
538*ae771770SStanislav Sedov  * overridden by the 32 bit vno field if it is present. The vno8 field is
539*ae771770SStanislav Sedov  * filled with the lower 8 bits of the 32 bit protocol kvno field.
540*ae771770SStanislav Sedov  *
541*ae771770SStanislav Sedov  * The keyblock structure consists of a 16 bit value indicating the
542*ae771770SStanislav Sedov  * encryption type and is a counted_octet_string containing the key.  The
543*ae771770SStanislav Sedov  * encryption type is the same as the Kerberos standard (e.g. 3 is
544*ae771770SStanislav Sedov  * des-cbc-md5, 23 is arcfour-hmac-md5, etc).
545*ae771770SStanislav Sedov  *
546*ae771770SStanislav Sedov  * The last field of the keytab_entry structure is optional. If the size of
547*ae771770SStanislav Sedov  * the keytab_entry indicates that there are at least 4 bytes remaining,
548*ae771770SStanislav Sedov  * a 32 bit value representing the key version number is present. This
549*ae771770SStanislav Sedov  * value supersedes the 8 bit vno8 value preceeding the keyblock.
550*ae771770SStanislav Sedov  *
551*ae771770SStanislav Sedov  * Older keytabs with a file_format_version of 0x501 are different in
552*ae771770SStanislav Sedov  * three ways:
553*ae771770SStanislav Sedov  *
554*ae771770SStanislav Sedov  * - All integers are in host byte order [1].
555*ae771770SStanislav Sedov  * - The num_components field is 1 too large (i.e. after decoding, decrement by 1).
556*ae771770SStanislav Sedov  * - The 32 bit name_type field is not present.
557*ae771770SStanislav Sedov  *
558*ae771770SStanislav Sedov  * [1] The file_format_version field should really be treated as two
559*ae771770SStanislav Sedov  * separate 8 bit quantities representing the major and minor version
560*ae771770SStanislav Sedov  * number respectively.
561*ae771770SStanislav Sedov  *
562*ae771770SStanislav Sedov  * @subsection file_hdb_dump Heimdal database dump file
563*ae771770SStanislav Sedov  *
564*ae771770SStanislav Sedov  * Format of the Heimdal text dump file as of Heimdal 0.6.3:
565*ae771770SStanislav Sedov  *
566*ae771770SStanislav Sedov  * Each line in the dump file is one entry in the database.
567*ae771770SStanislav Sedov  *
568*ae771770SStanislav Sedov  * Each field of a line is separated by one or more spaces, with the
569*ae771770SStanislav Sedov  * exception of fields consisting of principals containing spaces, where
570*ae771770SStanislav Sedov  * space can be quoted with \ and \ is quoted by \.
571*ae771770SStanislav Sedov  *
572*ae771770SStanislav Sedov  * Fields and their types are:
573*ae771770SStanislav Sedov  *
574*ae771770SStanislav Sedov  * @code
575*ae771770SStanislav Sedov  * 	Quoted princial (quote character is \) [string]
576*ae771770SStanislav Sedov  * 	Keys [keys]
577*ae771770SStanislav Sedov  * 	Created by [event]
578*ae771770SStanislav Sedov  * 	Modified by [event optional]
579*ae771770SStanislav Sedov  * 	Valid start time [time optional]
580*ae771770SStanislav Sedov  * 	Valid end time [time optional]
581*ae771770SStanislav Sedov  * 	Password end valid time [time optional]
582*ae771770SStanislav Sedov  * 	Max lifetime of ticket [time optional]
583*ae771770SStanislav Sedov  * 	Max renew time of ticket [integer optional]
584*ae771770SStanislav Sedov  * 	Flags [hdb flags]
585*ae771770SStanislav Sedov  * 	Generation number [generation optional]
586*ae771770SStanislav Sedov  * 	Extensions [extentions optional]
587*ae771770SStanislav Sedov  * @endcode
588*ae771770SStanislav Sedov  *
589*ae771770SStanislav Sedov  * Fields following these silently are ignored.
590*ae771770SStanislav Sedov  *
591*ae771770SStanislav Sedov  * All optional fields will be skipped if they fail to parse (or comprise
592*ae771770SStanislav Sedov  * the optional field marker of "-", w/o quotes).
593*ae771770SStanislav Sedov  *
594*ae771770SStanislav Sedov  * Example:
595*ae771770SStanislav Sedov  *
596*ae771770SStanislav Sedov  * @code
597*ae771770SStanislav Sedov  * 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 -
598*ae771770SStanislav Sedov  * @endcode
599*ae771770SStanislav Sedov  *
600*ae771770SStanislav Sedov  * Encoding of types are as follows:
601*ae771770SStanislav Sedov  *
602*ae771770SStanislav Sedov  * - keys
603*ae771770SStanislav Sedov  *
604*ae771770SStanislav Sedov  * @code
605*ae771770SStanislav Sedov  * kvno:[masterkvno:keytype:keydata:salt]{zero or more separated by :}
606*ae771770SStanislav Sedov  * @endcode
607*ae771770SStanislav Sedov  *
608*ae771770SStanislav Sedov  * kvno is the key version number.
609*ae771770SStanislav Sedov  *
610*ae771770SStanislav Sedov  * keydata is hex-encoded
611*ae771770SStanislav Sedov  *
612*ae771770SStanislav Sedov  * masterkvno is the kvno of the database master key.  If this field is
613*ae771770SStanislav Sedov  * empty, the kadmin load and merge operations will encrypt the key data
614*ae771770SStanislav Sedov  * with the master key if there is one.  Otherwise the key data will be
615*ae771770SStanislav Sedov  * imported asis.
616*ae771770SStanislav Sedov  *
617*ae771770SStanislav Sedov  * salt is encoded as "-" (no/default salt) or
618*ae771770SStanislav Sedov  *
619*ae771770SStanislav Sedov  * @code
620*ae771770SStanislav Sedov  * salt-type /
621*ae771770SStanislav Sedov  * salt-type / "string"
622*ae771770SStanislav Sedov  * salt-type / hex-encoded-data
623*ae771770SStanislav Sedov  * @endcode
624*ae771770SStanislav Sedov  *
625*ae771770SStanislav Sedov  * keytype is the protocol enctype number; see enum ENCTYPE in
626*ae771770SStanislav Sedov  * include/krb5_asn1.h for values.
627*ae771770SStanislav Sedov  *
628*ae771770SStanislav Sedov  * Example:
629*ae771770SStanislav Sedov  * @code
630*ae771770SStanislav Sedov  * 27:1:16:e8b4c8fc7e60b9e641dcf4cff3f08a701d982a2f89ba373733d26ca59ba6c789666f6b8bfcf169412bb1e5dceb9b33cda29f3412:-:1:3:4498a933881178c744f4232172dcd774c64e81fa6d05ecdf643a7e390624a0ebf3c7407a:-:1:2:b01934b13eb795d76f3a80717d469639b4da0cfb644161340ef44fdeb375e54d684dbb85:-:1:1:ea8e16d8078bf60c781da90f508d4deccba70595258b9d31888d33987cd31af0c9cced2e:-
631*ae771770SStanislav Sedov  * @endcode
632*ae771770SStanislav Sedov  *
633*ae771770SStanislav Sedov  *
634*ae771770SStanislav Sedov  * @code
635*ae771770SStanislav Sedov  * kvno=27,{key: masterkvno=1,keytype=des3-cbc-sha1,keydata=..., default salt}...
636*ae771770SStanislav Sedov  * @endcode
637*ae771770SStanislav Sedov  *
638*ae771770SStanislav Sedov  * - time
639*ae771770SStanislav Sedov  *
640*ae771770SStanislav Sedov  * Format of the time is: YYYYmmddHHMMSS, corresponding to strftime
641*ae771770SStanislav Sedov  * format "%Y%m%d%k%M%S".
642*ae771770SStanislav Sedov  *
643*ae771770SStanislav Sedov  * Time is expressed in UTC.
644*ae771770SStanislav Sedov  *
645*ae771770SStanislav Sedov  * Time can be optional (using -), when the time 0 is used.
646*ae771770SStanislav Sedov  *
647*ae771770SStanislav Sedov  * Example:
648*ae771770SStanislav Sedov  *
649*ae771770SStanislav Sedov  * @code
650*ae771770SStanislav Sedov  * 20041221112428
651*ae771770SStanislav Sedov  * @endcode
652*ae771770SStanislav Sedov  *
653*ae771770SStanislav Sedov  * - event
654*ae771770SStanislav Sedov  *
655*ae771770SStanislav Sedov  * @code
656*ae771770SStanislav Sedov  * 	time:principal
657*ae771770SStanislav Sedov  * @endcode
658*ae771770SStanislav Sedov  *
659*ae771770SStanislav Sedov  * time is as given in format time
660*ae771770SStanislav Sedov  *
661*ae771770SStanislav Sedov  * principal is a string.  Not quoting it may not work in earlier
662*ae771770SStanislav Sedov  * versions of Heimdal.
663*ae771770SStanislav Sedov  *
664*ae771770SStanislav Sedov  * Example:
665*ae771770SStanislav Sedov  * @code
666*ae771770SStanislav Sedov  * 20041221112428:bloggs\@CODE.COM
667*ae771770SStanislav Sedov  * @endcode
668*ae771770SStanislav Sedov  *
669*ae771770SStanislav Sedov  * - hdb flags
670*ae771770SStanislav Sedov  *
671*ae771770SStanislav Sedov  * Integer encoding of HDB flags, see HDBFlags in lib/hdb/hdb.asn1. Each
672*ae771770SStanislav Sedov  * bit in the integer is the same as the bit in the specification.
673*ae771770SStanislav Sedov  *
674*ae771770SStanislav Sedov  * - generation:
675*ae771770SStanislav Sedov  *
676*ae771770SStanislav Sedov  * @code
677*ae771770SStanislav Sedov  * time:usec:gen
678*ae771770SStanislav Sedov  * @endcode
679*ae771770SStanislav Sedov  *
680*ae771770SStanislav Sedov  *
681*ae771770SStanislav Sedov  * usec is a the microsecond, integer.
682*ae771770SStanislav Sedov  * gen is generation number, integer.
683*ae771770SStanislav Sedov  *
684*ae771770SStanislav Sedov  * The generation can be defaulted (using '-') or the empty string
685*ae771770SStanislav Sedov  *
686*ae771770SStanislav Sedov  * - extensions:
687*ae771770SStanislav Sedov  *
688*ae771770SStanislav Sedov  * @code
689*ae771770SStanislav Sedov  * first-hex-encoded-HDB-Extension[:second-...]
690*ae771770SStanislav Sedov  * @endcode
691*ae771770SStanislav Sedov  *
692*ae771770SStanislav Sedov  * HDB-extension is encoded the DER encoded HDB-Extension from
693*ae771770SStanislav Sedov  * lib/hdb/hdb.asn1. Consumers HDB extensions should be aware that
694*ae771770SStanislav Sedov  * unknown entires needs to be preserved even thought the ASN.1 data
695*ae771770SStanislav Sedov  * content might be unknown. There is a critical flag in the data to show
696*ae771770SStanislav Sedov  * to the KDC that the entry MUST be understod if the entry is to be
697*ae771770SStanislav Sedov  * used.
698*ae771770SStanislav Sedov  *
699*ae771770SStanislav Sedov  *
700*ae771770SStanislav Sedov  */
701