1krb5_introduction(3)      Heimdal Kerberos 5 library      krb5_introduction(3)
2
3
4

NAME

6       krb5_introduction - Introduction to the Kerberos 5 API
7
8

Kerberos 5 API Overview

10       All functions are documented in manual pages. This section tries to
11       give an overview of the major components used in Kerberos library, and
12       point to where to look for a specific function.
13
14   Kerberos context
15       A kerberos context (krb5_context) holds all per thread state. All
16       global variables that are context specific are stored in this
17       structure, including default encryption types, credential cache (for
18       example, a ticket file), and default realms.
19
20       The internals of the structure should never be accessed directly,
21       functions exist for extracting information.
22
23       See the manual page for krb5_init_context() how to create a context and
24       module Heimdal Kerberos 5 library for more information about the
25       functions.
26
27   Kerberos authentication context
28       Kerberos authentication context (krb5_auth_context) holds all context
29       related to an authenticated connection, in a similar way to the
30       kerberos context that holds the context for the thread or process.
31
32       The krb5_auth_context is used by various functions that are directly
33       related to authentication between the server/client. Example of data
34       that this structure contains are various flags, addresses of client and
35       server, port numbers, keyblocks (and subkeys), sequence numbers, replay
36       cache, and checksum types.
37
38   Kerberos principal
39       The Kerberos principal is the structure that identifies a user or
40       service in Kerberos. The structure that holds the principal is the
41       krb5_principal. There are function to extract the realm and elements of
42       the principal, but most applications have no reason to inspect the
43       content of the structure.
44
45       The are several ways to create a principal (with different degree of
46       portability), and one way to free it.
47
48       See also the page The principal handing functions. for more information
49       and also module Heimdal Kerberos 5 principal functions.
50
51   Credential cache
52       A credential cache holds the tickets for a user. A given user can have
53       several credential caches, one for each realm where the user have the
54       initial tickets (the first krbtgt).
55
56       The credential cache data can be stored internally in different way,
57       each of them for different proposes. File credential (FILE) caches and
58       processes based (KCM) caches are for permanent storage. While memory
59       caches (MEMORY) are local caches to the local process.
60
61       Caches are opened with krb5_cc_resolve() or created with
62       krb5_cc_new_unique().
63
64       If the cache needs to be opened again (using krb5_cc_resolve())
65       krb5_cc_close() will close the handle, but not the remove the cache.
66       krb5_cc_destroy() will zero out the cache, remove the cache so it can
67       no longer be referenced.
68
69       See also The credential cache functions and Heimdal Kerberos 5
70       credential cache functions .
71
72   Kerberos errors
73       Kerberos errors are based on the com_err library. All error codes are
74       32-bit signed numbers, the first 24 bits define what subsystem the
75       error originates from, and last 8 bits are 255 error codes within the
76       library. Each error code have fixed string associated with it. For
77       example, the error-code -1765328383 have the symbolic name
78       KRB5KDC_ERR_NAME_EXP, and associated error string ``Client's entry in
79       database has expired''.
80
81       This is a great improvement compared to just getting one of the unix
82       error-codes back. However, Heimdal have an extention to pass back
83       customised errors messages. Instead of getting Key table entry not
84       found'', the user might backfailed to find
85       host/host.example.com@EXAMLE.COM(kvno 3) in keytab /etc/krb5.keytab
86       (des-cbc-crc)''. This improves the chance that the user find the cause
87       of the error so you should use the customised error message whenever
88       it's available.
89
90       See also module Heimdal Kerberos 5 error reporting functions .
91
92   Keytab management
93       A keytab is a storage for locally stored keys. Heimdal includes keytab
94       support for Kerberos 5 keytabs, Kerberos 4 srvtab, AFS-KeyFile's, and
95       for storing keys in memory.
96
97       Keytabs are used for servers and long-running services.
98
99       See also The keytab handing functions and Heimdal Kerberos 5 keytab
100       handling functions .
101
102   Kerberos crypto
103       Heimdal includes a implementation of the Kerberos crypto framework, all
104       crypto operations. To create a crypto context call krb5_crypto_init().
105
106       See also module Heimdal Kerberos 5 cryptography functions .
107

Walkthrough of a sample Kerberos 5 client

109       This example contains parts of a sample TCP Kerberos 5 clients, if you
110       want a real working client, please look in appl/test directory in the
111       Heimdal distribution.
112
113       All Kerberos error-codes that are returned from kerberos functions in
114       this program are passed to krb5_err, that will print a descriptive text
115       of the error code and exit. Graphical programs can convert error-code
116       to a human readable error-string with the krb5_get_error_message()
117       function.
118
119       Note that you should not use any Kerberos function before
120       krb5_init_context() have completed successfully. That is the reason
121       err() is used when krb5_init_context() fails.
122
123       First the client needs to call krb5_init_context to initialise the
124       Kerberos 5 library. This is only needed once per thread in the program.
125       If the function returns a non-zero value it indicates that either the
126       Kerberos implementation is failing or it's disabled on this host.
127
128       #include <krb5.h>
129
130       int
131       main(int argc, char **argv)
132       {
133               krb5_context context;
134
135               if (krb5_init_context(&context))
136                       errx (1, "krb5_context");
137
138       Now the client wants to connect to the host at the other end. The
139       preferred way of doing this is using getaddrinfo (for operating system
140       that have this function implemented), since getaddrinfo is neutral to
141       the address type and can use any protocol that is available.
142
143       struct addrinfo *ai, *a;
144       struct addrinfo hints;
145       int error;
146
147       memset (&hints, 0, sizeof(hints));
148       hints.ai_socktype = SOCK_STREAM;
149       hints.ai_protocol = IPPROTO_TCP;
150
151       error = getaddrinfo (hostname, "pop3", &hints, &ai);
152       if (error)
153               errx (1, "%s: %s", hostname, gai_strerror(error));
154
155       for (a = ai; a != NULL; a = a->ai_next) {
156               int s;
157
158               s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
159               if (s < 0)
160                       continue;
161               if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
162                       warn ("connect(%s)", hostname);
163                           close (s);
164                           continue;
165               }
166               freeaddrinfo (ai);
167               ai = NULL;
168       }
169       if (ai) {
170                   freeaddrinfo (ai);
171                   errx ("failed to contact %s", hostname);
172       }
173
174       Before authenticating, an authentication context needs to be created.
175       This context keeps all information for one (to be) authenticated
176       connection (see krb5_auth_context).
177
178       status = krb5_auth_con_init (context, &auth_context);
179       if (status)
180               krb5_err (context, 1, status, "krb5_auth_con_init");
181
182       For setting the address in the authentication there is a help function
183       krb5_auth_con_setaddrs_from_fd() that does everything that is needed
184       when given a connected file descriptor to the socket.
185
186       status = krb5_auth_con_setaddrs_from_fd (context,
187                                                auth_context,
188                                                &sock);
189       if (status)
190               krb5_err (context, 1, status,
191                         "krb5_auth_con_setaddrs_from_fd");
192
193       The next step is to build a server principal for the service we want to
194       connect to. (See also krb5_sname_to_principal().)
195
196       status = krb5_sname_to_principal (context,
197                                         hostname,
198                                         service,
199                                         KRB5_NT_SRV_HST,
200                                         &server);
201       if (status)
202               krb5_err (context, 1, status, "krb5_sname_to_principal");
203
204       The client principal is not passed to krb5_sendauth() function, this
205       causes the krb5_sendauth() function to try to figure it out itself.
206
207       The server program is using the function krb5_recvauth() to receive the
208       Kerberos 5 authenticator.
209
210       In this case, mutual authentication will be tried. That means that the
211       server will authenticate to the client. Using mutual authentication is
212       required to avoid man-in-the-middle attacks, since it enables the user
213       to verify that they are talking to the right server (a server that
214       knows the key).
215
216       If you are using a non-blocking socket you will need to do all work of
217       krb5_sendauth() yourself. Basically you need to send over the
218       authenticator from krb5_mk_req() and, in case of mutual authentication,
219       verifying the result from the server with krb5_rd_rep().
220
221       status = krb5_sendauth (context,
222                               &auth_context,
223                               &sock,
224                               VERSION,
225                               NULL,
226                               server,
227                               AP_OPTS_MUTUAL_REQUIRED,
228                               NULL,
229                               NULL,
230                               NULL,
231                               NULL,
232                               NULL,
233                               NULL);
234       if (status)
235               krb5_err (context, 1, status, "krb5_sendauth");
236
237       Once authentication has been performed, it is time to send some data.
238       First we create a krb5_data structure, then we sign it with
239       krb5_mk_safe() using the auth_context that contains the session-key
240       that was exchanged in the krb5_sendauth()/krb5_recvauth()
241       authentication sequence.
242
243       data.data   = "hej";
244       data.length = 3;
245
246       krb5_data_zero (&packet);
247
248       status = krb5_mk_safe (context,
249                              auth_context,
250                              &data,
251                              &packet,
252                              NULL);
253       if (status)
254               krb5_err (context, 1, status, "krb5_mk_safe");
255
256       And send it over the network.
257
258       len = packet.length;
259       net_len = htonl(len);
260
261       if (krb5_net_write (context, &sock, &net_len, 4) != 4)
262               err (1, "krb5_net_write");
263       if (krb5_net_write (context, &sock, packet.data, len) != len)
264               err (1, "krb5_net_write");
265
266       To send encrypted (and signed) data krb5_mk_priv() should be used
267       instead. krb5_mk_priv() works the same way as krb5_mk_safe(), with the
268       exception that it encrypts the data in addition to signing it.
269
270       data.data   = "hemligt";
271       data.length = 7;
272
273       krb5_data_free (&packet);
274
275       status = krb5_mk_priv (context,
276                              auth_context,
277                              &data,
278                              &packet,
279                              NULL);
280       if (status)
281               krb5_err (context, 1, status, "krb5_mk_priv");
282
283       And send it over the network.
284
285       len = packet.length;
286       net_len = htonl(len);
287
288       if (krb5_net_write (context, &sock, &net_len, 4) != 4)
289               err (1, "krb5_net_write");
290       if (krb5_net_write (context, &sock, packet.data, len) != len)
291               err (1, "krb5_net_write");
292
293       The server is using krb5_rd_safe() and krb5_rd_priv() to verify the
294       signature and decrypt the packet.
295

Validating a password in an application

297       See the manual page for krb5_verify_user().
298

API differences to MIT Kerberos

300       This section is somewhat disorganised, but so far there is no overall
301       structure to the differences, though some of the have their root in
302       that Heimdal uses an ASN.1 compiler and MIT doesn't.
303
304   Principal and realms
305       Heimdal stores the realm as a krb5_realm, that is a char *. MIT
306       Kerberos uses a krb5_data to store a realm.
307
308       In Heimdal krb5_principal doesn't contain the component name_type; it's
309       instead stored in component name.name_type. To get and set the nametype
310       in Heimdal, use krb5_principal_get_type() and
311       krb5_principal_set_type().
312
313       For more information about principal and realms, see krb5_principal.
314
315   Error messages
316       To get the error string, Heimdal uses krb5_get_error_message(). This is
317       to return custom error messages (like Can't find
318       host/datan.example.com\@CODE.COM in /etc/krb5.conf.'' instead of aKey
319       table entry not found'' that error_message returns.
320
321       Heimdal uses a threadsafe(r) version of the com_err interface; the
322       global com_err table isn't initialised. Then error_message returns
323       quite a boring error string (just the error code itself).
324
325
326
327Version 7.8.0                   Tue Nov 15 2022           krb5_introduction(3)
Impressum