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