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