xref: /freebsd/crypto/krb5/src/include/krb5/kdcpreauth_plugin.h (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * Copyright (c) 2006 Red Hat, Inc.
4  * Portions copyright (c) 2006, 2011 Massachusetts Institute of Technology
5  * All Rights Reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  *  * Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *  * Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *  * Neither the name of Red Hat, Inc., nor the names of its
17  *    contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Declarations for kdcpreauth plugin module implementors.
35  *
36  * The kdcpreauth interface has a single supported major version, which is 1.
37  * Major version 1 has a current minor version of 2.  kdcpreauth modules should
38  * define a function named kdcpreauth_<modulename>_initvt, matching the
39  * signature:
40  *
41  *   krb5_error_code
42  *   kdcpreauth_modname_initvt(krb5_context context, int maj_ver, int min_ver,
43  *                             krb5_plugin_vtable vtable);
44  *
45  * The initvt function should:
46  *
47  * - Check that the supplied maj_ver number is supported by the module, or
48  *   return KRB5_PLUGIN_VER_NOTSUPP if it is not.
49  *
50  * - Cast the vtable pointer as appropriate for the interface and maj_ver:
51  *     kdcpreauth, maj_ver == 1: Cast to krb5_kdcpreauth_vtable
52  *
53  * - Initialize the methods of the vtable, stopping as appropriate for the
54  *   supplied min_ver.  Optional methods may be left uninitialized.
55  *
56  * Memory for the vtable is allocated by the caller, not by the module.
57  */
58 
59 #ifndef KRB5_KDCPREAUTH_PLUGIN_H
60 #define KRB5_KDCPREAUTH_PLUGIN_H
61 
62 #include <krb5/krb5.h>
63 #include <krb5/plugin.h>
64 
65 /* kdcpreauth mechanism property flags */
66 
67 /*
68  * Causes the KDC to include this mechanism in a list of supported preauth
69  * types if the user's DB entry flags the user as requiring hardware-based
70  * preauthentication.
71  */
72 #define PA_HARDWARE     0x00000004
73 
74 /*
75  * Causes the KDC to include this mechanism in a list of supported preauth
76  * types if the user's DB entry flags the user as requiring preauthentication,
77  * and to fail preauthentication if we can't verify the client data.  The
78  * flipside of PA_SUFFICIENT.
79  */
80 #define PA_REQUIRED     0x00000008
81 
82 /*
83  * Causes the KDC to include this mechanism in a list of supported preauth
84  * types if the user's DB entry flags the user as requiring preauthentication,
85  * and to mark preauthentication as successful if we can verify the client
86  * data.  The flipside of PA_REQUIRED.
87  */
88 #define PA_SUFFICIENT   0x00000010
89 
90 /*
91  * Marks this preauthentication mechanism as one which changes the key which is
92  * used for encrypting the response to the client.  Modules which have this
93  * flag have their server_return_fn called before modules which do not, and are
94  * passed over if a previously-called module has modified the encrypting key.
95  */
96 #define PA_REPLACES_KEY 0x00000020
97 
98 /*
99  * Not really a padata type, so don't include it in any list of preauth types
100  * which gets sent over the wire.
101  */
102 #define PA_PSEUDO       0x00000080
103 
104 /*
105  * Indicates that e_data in non-FAST errors should be encoded as typed data
106  * instead of padata.
107  */
108 #define PA_TYPED_E_DATA 0x00000100
109 
110 /* Abstract type for a KDC callback data handle. */
111 typedef struct krb5_kdcpreauth_rock_st *krb5_kdcpreauth_rock;
112 
113 /* Abstract type for module data and per-request module data. */
114 typedef struct krb5_kdcpreauth_moddata_st *krb5_kdcpreauth_moddata;
115 typedef struct krb5_kdcpreauth_modreq_st *krb5_kdcpreauth_modreq;
116 
117 /* The verto context structure type (typedef is in verto.h; we want to avoid a
118  * header dependency for the moment). */
119 struct verto_ctx;
120 
121 /* Before using a callback after version 1, modules must check the vers
122  * field of the callback structure. */
123 typedef struct krb5_kdcpreauth_callbacks_st {
124     int vers;
125 
126     krb5_deltat (*max_time_skew)(krb5_context context,
127                                  krb5_kdcpreauth_rock rock);
128 
129     /*
130      * Get an array of krb5_keyblock structures containing the client keys
131      * matching the request enctypes, terminated by an entry with key type = 0.
132      * Returns ENOENT if no keys are available for the request enctypes.  Free
133      * the resulting object with the free_keys callback.
134      */
135     krb5_error_code (*client_keys)(krb5_context context,
136                                    krb5_kdcpreauth_rock rock,
137                                    krb5_keyblock **keys_out);
138 
139     /* Free the result of client_keys. */
140     void (*free_keys)(krb5_context context, krb5_kdcpreauth_rock rock,
141                       krb5_keyblock *keys);
142 
143     /*
144      * Get the encoded request body, which is sometimes needed for checksums.
145      * For a FAST request this is the encoded inner request body.  The returned
146      * pointer is an alias and should not be freed.
147      */
148     krb5_data *(*request_body)(krb5_context context,
149                                krb5_kdcpreauth_rock rock);
150 
151     /* Get a pointer to the FAST armor key, or NULL if the request did not use
152      * FAST.  The returned pointer is an alias and should not be freed. */
153     krb5_keyblock *(*fast_armor)(krb5_context context,
154                                  krb5_kdcpreauth_rock rock);
155 
156     /* Retrieve a string attribute from the client DB entry, or NULL if no such
157      * attribute is set.  Free the result with the free_string callback. */
158     krb5_error_code (*get_string)(krb5_context context,
159                                   krb5_kdcpreauth_rock rock, const char *key,
160                                   char **value_out);
161 
162     /* Free the result of get_string. */
163     void (*free_string)(krb5_context context, krb5_kdcpreauth_rock rock,
164                         char *string);
165 
166     /* Get a pointer to the client DB entry (returned as a void pointer to
167      * avoid a dependency on a libkdb5 type). */
168     void *(*client_entry)(krb5_context context, krb5_kdcpreauth_rock rock);
169 
170     /* Get a pointer to the verto context which should be used by an
171      * asynchronous edata or verify method. */
172     struct verto_ctx *(*event_context)(krb5_context context,
173                                        krb5_kdcpreauth_rock rock);
174 
175     /* End of version 1 kdcpreauth callbacks. */
176 
177     /* Return true if the client DB entry contains any keys matching the
178      * request enctypes. */
179     krb5_boolean (*have_client_keys)(krb5_context context,
180                                      krb5_kdcpreauth_rock rock);
181 
182     /* End of version 2 kdcpreauth callbacks. */
183 
184     /*
185      * Get the current reply key.  Initially the reply key is the decrypted
186      * client long-term key chosen according to the request enctype list, or
187      * NULL if no matching key was found.  The value may be changed by the
188      * replace_reply_key callback or a return_padata method modifying
189      * encrypting_key.  The returned pointer is an alias and should not be
190      * freed.
191      */
192     const krb5_keyblock *(*client_keyblock)(krb5_context context,
193                                             krb5_kdcpreauth_rock rock);
194 
195     /* Assert an authentication indicator in the AS-REP authdata.  Duplicate
196      * indicators will be ignored. */
197     krb5_error_code (*add_auth_indicator)(krb5_context context,
198                                           krb5_kdcpreauth_rock rock,
199                                           const char *indicator);
200 
201     /*
202      * Read a data value for pa_type from the request cookie, placing it in
203      * *out.  The value placed there is an alias and must not be freed.
204      * Returns true if a value for pa_type was retrieved, false if not.
205      */
206     krb5_boolean (*get_cookie)(krb5_context context, krb5_kdcpreauth_rock rock,
207                                krb5_preauthtype pa_type, krb5_data *out);
208 
209     /*
210      * Set a data value for pa_type to be sent in a secure cookie in the next
211      * error response.  If pa_type is already present, the value is ignored.
212      * If the preauth mechanism has different preauth types for requests and
213      * responses, use the request type.  Secure cookies are encrypted in a key
214      * known only to the KDCs, but can be replayed within a short time window
215      * for requests using the same client principal.
216      */
217     krb5_error_code (*set_cookie)(krb5_context context,
218                                   krb5_kdcpreauth_rock rock,
219                                   krb5_preauthtype pa_type,
220                                   const krb5_data *data);
221 
222     /* End of version 3 kdcpreauth callbacks. */
223 
224     /*
225      * Return true if princ matches the principal named in the request or the
226      * client principal (possibly canonicalized).  If princ does not match,
227      * attempt a database lookup of princ with aliases allowed and compare the
228      * result to the client principal, returning true if it matches.
229      * Otherwise, return false.
230      */
231     krb5_boolean (*match_client)(krb5_context context,
232                                  krb5_kdcpreauth_rock rock,
233                                  krb5_principal princ);
234 
235     /*
236      * Get an alias to the client DB entry principal (possibly canonicalized).
237      */
238     krb5_principal (*client_name)(krb5_context context,
239                                   krb5_kdcpreauth_rock rock);
240 
241     /* End of version 4 kdcpreauth callbacks. */
242 
243     /*
244      * Instruct the KDC to send a freshness token in the method data
245      * accompanying a PREAUTH_REQUIRED or PREAUTH_FAILED error, if the client
246      * indicated support for freshness tokens.  This callback should only be
247      * invoked from the edata method.
248      */
249     void (*send_freshness_token)(krb5_context context,
250                                  krb5_kdcpreauth_rock rock);
251 
252     /* Validate a freshness token sent by the client.  Return 0 on success,
253      * KRB5KDC_ERR_PREAUTH_EXPIRED on error. */
254     krb5_error_code (*check_freshness_token)(krb5_context context,
255                                              krb5_kdcpreauth_rock rock,
256                                              const krb5_data *token);
257 
258     /* End of version 5 kdcpreauth callbacks. */
259 
260     /*
261      * Replace the reply key with key.  If is_strengthen is true, key must be a
262      * derivative of the client long-term key.  This callback may be invoked
263      * from the verify or return_padata methods.  If it is invoked from the
264      * verify method, the new key will appear as the encrypting_key input to
265      * return_padata.
266      */
267     krb5_error_code (*replace_reply_key)(krb5_context context,
268                                          krb5_kdcpreauth_rock rock,
269                                          const krb5_keyblock *key,
270                                          krb5_boolean is_strengthen);
271 
272     /* End of version 6 kdcpreauth callbacks. */
273 
274 } *krb5_kdcpreauth_callbacks;
275 
276 /* Optional: preauth plugin initialization function. */
277 typedef krb5_error_code
278 (*krb5_kdcpreauth_init_fn)(krb5_context context,
279                            krb5_kdcpreauth_moddata *moddata_out,
280                            const char **realmnames);
281 
282 /* Optional: preauth plugin cleanup function. */
283 typedef void
284 (*krb5_kdcpreauth_fini_fn)(krb5_context context,
285                            krb5_kdcpreauth_moddata moddata);
286 
287 /*
288  * Optional: return the flags which the KDC should use for this module.  This
289  * is a callback instead of a static value because the module may or may not
290  * wish to count itself as a hardware preauthentication module (in other words,
291  * the flags may be affected by the configuration, for example if a site
292  * administrator can force a particular preauthentication type to be supported
293  * using only hardware).  This function is called for each entry entry in the
294  * server_pa_type_list.
295  */
296 typedef int
297 (*krb5_kdcpreauth_flags_fn)(krb5_context context, krb5_preauthtype pa_type);
298 
299 /*
300  * Responder for krb5_kdcpreauth_edata_fn.  If invoked with a non-zero code, pa
301  * will be ignored and the padata type will not be included in the hint list.
302  * If invoked with a zero code and a null pa value, the padata type will be
303  * included in the list with an empty value.  If invoked with a zero code and a
304  * non-null pa value, pa will be included in the hint list and will later be
305  * freed by the KDC.
306  */
307 typedef void
308 (*krb5_kdcpreauth_edata_respond_fn)(void *arg, krb5_error_code code,
309                                     krb5_pa_data *pa);
310 
311 /*
312  * Optional: provide pa_data to send to the client as part of the "you need to
313  * use preauthentication" error.  The implementation must invoke the respond
314  * when complete, whether successful or not, either before returning or
315  * asynchronously using the verto context returned by cb->event_context().
316  *
317  * This function is not allowed to create a modreq object because we have no
318  * guarantee that the client will ever make a follow-up request, or that it
319  * will hit this KDC if it does.
320  */
321 typedef void
322 (*krb5_kdcpreauth_edata_fn)(krb5_context context, krb5_kdc_req *request,
323                             krb5_kdcpreauth_callbacks cb,
324                             krb5_kdcpreauth_rock rock,
325                             krb5_kdcpreauth_moddata moddata,
326                             krb5_preauthtype pa_type,
327                             krb5_kdcpreauth_edata_respond_fn respond,
328                             void *arg);
329 
330 /*
331  * Responder for krb5_kdcpreauth_verify_fn.  Invoke with the arg parameter
332  * supplied to verify, the error code (0 for success), an optional module
333  * request state object to be consumed by return_fn or free_modreq_fn, optional
334  * e_data to be passed to the caller if code is nonzero, and optional
335  * authorization data to be included in the ticket.  In non-FAST replies,
336  * e_data will be encoded as typed-data if the module sets the PA_TYPED_E_DATA
337  * flag, and as pa-data otherwise.  e_data and authz_data will be freed by the
338  * KDC.
339  */
340 typedef void
341 (*krb5_kdcpreauth_verify_respond_fn)(void *arg, krb5_error_code code,
342                                      krb5_kdcpreauth_modreq modreq,
343                                      krb5_pa_data **e_data,
344                                      krb5_authdata **authz_data);
345 
346 /*
347  * Optional: verify preauthentication data sent by the client, setting the
348  * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
349  * field as appropriate.  The implementation must invoke the respond function
350  * when complete, whether successful or not, either before returning or
351  * asynchronously using the verto context returned by cb->event_context().
352  */
353 typedef void
354 (*krb5_kdcpreauth_verify_fn)(krb5_context context,
355                              krb5_data *req_pkt, krb5_kdc_req *request,
356                              krb5_enc_tkt_part *enc_tkt_reply,
357                              krb5_pa_data *data,
358                              krb5_kdcpreauth_callbacks cb,
359                              krb5_kdcpreauth_rock rock,
360                              krb5_kdcpreauth_moddata moddata,
361                              krb5_kdcpreauth_verify_respond_fn respond,
362                              void *arg);
363 
364 /*
365  * Optional: generate preauthentication response data to send to the client as
366  * part of the AS-REP.  If it needs to override the key which is used to
367  * encrypt the response, it can do so by modifying encrypting_key, but it is
368  * preferrable to use the replace_reply_key callback.
369  */
370 typedef krb5_error_code
371 (*krb5_kdcpreauth_return_fn)(krb5_context context,
372                              krb5_pa_data *padata,
373                              krb5_data *req_pkt,
374                              krb5_kdc_req *request,
375                              krb5_kdc_rep *reply,
376                              krb5_keyblock *encrypting_key,
377                              krb5_pa_data **send_pa_out,
378                              krb5_kdcpreauth_callbacks cb,
379                              krb5_kdcpreauth_rock rock,
380                              krb5_kdcpreauth_moddata moddata,
381                              krb5_kdcpreauth_modreq modreq);
382 
383 /* Optional: free a per-request context. */
384 typedef void
385 (*krb5_kdcpreauth_free_modreq_fn)(krb5_context,
386                                   krb5_kdcpreauth_moddata moddata,
387                                   krb5_kdcpreauth_modreq modreq);
388 
389 /* Optional: invoked after init_fn to provide the module with a pointer to the
390  * verto main loop. */
391 typedef krb5_error_code
392 (*krb5_kdcpreauth_loop_fn)(krb5_context context,
393                            krb5_kdcpreauth_moddata moddata,
394                            struct verto_ctx *ctx);
395 
396 typedef struct krb5_kdcpreauth_vtable_st {
397     /* Mandatory: name of module. */
398     const char *name;
399 
400     /* Mandatory: pointer to zero-terminated list of pa_types which this module
401      * can provide services for. */
402     krb5_preauthtype *pa_type_list;
403 
404     krb5_kdcpreauth_init_fn init;
405     krb5_kdcpreauth_fini_fn fini;
406     krb5_kdcpreauth_flags_fn flags;
407     krb5_kdcpreauth_edata_fn edata;
408     krb5_kdcpreauth_verify_fn verify;
409     krb5_kdcpreauth_return_fn return_padata;
410     krb5_kdcpreauth_free_modreq_fn free_modreq;
411     /* Minor 1 ends here. */
412 
413     krb5_kdcpreauth_loop_fn loop;
414     /* Minor 2 ends here. */
415 } *krb5_kdcpreauth_vtable;
416 
417 #endif /* KRB5_KDCPREAUTH_PLUGIN_H */
418