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 decrypted client long-term key chosen according to the request
186      * enctype list, or NULL if no matching key was found.  The returned
187      * pointer is an alias and should not be freed.  If invoked from
188      * return_padata, the result will be the same as the encrypting_key
189      * parameter if it is not NULL, and will therefore reflect the modified
190      * reply key if a return_padata handler has replaced the reply key.
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 } *krb5_kdcpreauth_callbacks;
261 
262 /* Optional: preauth plugin initialization function. */
263 typedef krb5_error_code
264 (*krb5_kdcpreauth_init_fn)(krb5_context context,
265                            krb5_kdcpreauth_moddata *moddata_out,
266                            const char **realmnames);
267 
268 /* Optional: preauth plugin cleanup function. */
269 typedef void
270 (*krb5_kdcpreauth_fini_fn)(krb5_context context,
271                            krb5_kdcpreauth_moddata moddata);
272 
273 /*
274  * Optional: return the flags which the KDC should use for this module.  This
275  * is a callback instead of a static value because the module may or may not
276  * wish to count itself as a hardware preauthentication module (in other words,
277  * the flags may be affected by the configuration, for example if a site
278  * administrator can force a particular preauthentication type to be supported
279  * using only hardware).  This function is called for each entry entry in the
280  * server_pa_type_list.
281  */
282 typedef int
283 (*krb5_kdcpreauth_flags_fn)(krb5_context context, krb5_preauthtype pa_type);
284 
285 /*
286  * Responder for krb5_kdcpreauth_edata_fn.  If invoked with a non-zero code, pa
287  * will be ignored and the padata type will not be included in the hint list.
288  * If invoked with a zero code and a null pa value, the padata type will be
289  * included in the list with an empty value.  If invoked with a zero code and a
290  * non-null pa value, pa will be included in the hint list and will later be
291  * freed by the KDC.
292  */
293 typedef void
294 (*krb5_kdcpreauth_edata_respond_fn)(void *arg, krb5_error_code code,
295                                     krb5_pa_data *pa);
296 
297 /*
298  * Optional: provide pa_data to send to the client as part of the "you need to
299  * use preauthentication" error.  The implementation must invoke the respond
300  * when complete, whether successful or not, either before returning or
301  * asynchronously using the verto context returned by cb->event_context().
302  *
303  * This function is not allowed to create a modreq object because we have no
304  * guarantee that the client will ever make a follow-up request, or that it
305  * will hit this KDC if it does.
306  */
307 typedef void
308 (*krb5_kdcpreauth_edata_fn)(krb5_context context, krb5_kdc_req *request,
309                             krb5_kdcpreauth_callbacks cb,
310                             krb5_kdcpreauth_rock rock,
311                             krb5_kdcpreauth_moddata moddata,
312                             krb5_preauthtype pa_type,
313                             krb5_kdcpreauth_edata_respond_fn respond,
314                             void *arg);
315 
316 /*
317  * Responder for krb5_kdcpreauth_verify_fn.  Invoke with the arg parameter
318  * supplied to verify, the error code (0 for success), an optional module
319  * request state object to be consumed by return_fn or free_modreq_fn, optional
320  * e_data to be passed to the caller if code is nonzero, and optional
321  * authorization data to be included in the ticket.  In non-FAST replies,
322  * e_data will be encoded as typed-data if the module sets the PA_TYPED_E_DATA
323  * flag, and as pa-data otherwise.  e_data and authz_data will be freed by the
324  * KDC.
325  */
326 typedef void
327 (*krb5_kdcpreauth_verify_respond_fn)(void *arg, krb5_error_code code,
328                                      krb5_kdcpreauth_modreq modreq,
329                                      krb5_pa_data **e_data,
330                                      krb5_authdata **authz_data);
331 
332 /*
333  * Optional: verify preauthentication data sent by the client, setting the
334  * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
335  * field as appropriate.  The implementation must invoke the respond function
336  * when complete, whether successful or not, either before returning or
337  * asynchronously using the verto context returned by cb->event_context().
338  */
339 typedef void
340 (*krb5_kdcpreauth_verify_fn)(krb5_context context,
341                              krb5_data *req_pkt, krb5_kdc_req *request,
342                              krb5_enc_tkt_part *enc_tkt_reply,
343                              krb5_pa_data *data,
344                              krb5_kdcpreauth_callbacks cb,
345                              krb5_kdcpreauth_rock rock,
346                              krb5_kdcpreauth_moddata moddata,
347                              krb5_kdcpreauth_verify_respond_fn respond,
348                              void *arg);
349 
350 /*
351  * Optional: generate preauthentication response data to send to the client as
352  * part of the AS-REP.  If it needs to override the key which is used to
353  * encrypt the response, it can do so.
354  */
355 typedef krb5_error_code
356 (*krb5_kdcpreauth_return_fn)(krb5_context context,
357                              krb5_pa_data *padata,
358                              krb5_data *req_pkt,
359                              krb5_kdc_req *request,
360                              krb5_kdc_rep *reply,
361                              krb5_keyblock *encrypting_key,
362                              krb5_pa_data **send_pa_out,
363                              krb5_kdcpreauth_callbacks cb,
364                              krb5_kdcpreauth_rock rock,
365                              krb5_kdcpreauth_moddata moddata,
366                              krb5_kdcpreauth_modreq modreq);
367 
368 /* Optional: free a per-request context. */
369 typedef void
370 (*krb5_kdcpreauth_free_modreq_fn)(krb5_context,
371                                   krb5_kdcpreauth_moddata moddata,
372                                   krb5_kdcpreauth_modreq modreq);
373 
374 /* Optional: invoked after init_fn to provide the module with a pointer to the
375  * verto main loop. */
376 typedef krb5_error_code
377 (*krb5_kdcpreauth_loop_fn)(krb5_context context,
378                            krb5_kdcpreauth_moddata moddata,
379                            struct verto_ctx *ctx);
380 
381 typedef struct krb5_kdcpreauth_vtable_st {
382     /* Mandatory: name of module. */
383     char *name;
384 
385     /* Mandatory: pointer to zero-terminated list of pa_types which this module
386      * can provide services for. */
387     krb5_preauthtype *pa_type_list;
388 
389     krb5_kdcpreauth_init_fn init;
390     krb5_kdcpreauth_fini_fn fini;
391     krb5_kdcpreauth_flags_fn flags;
392     krb5_kdcpreauth_edata_fn edata;
393     krb5_kdcpreauth_verify_fn verify;
394     krb5_kdcpreauth_return_fn return_padata;
395     krb5_kdcpreauth_free_modreq_fn free_modreq;
396     /* Minor 1 ends here. */
397 
398     krb5_kdcpreauth_loop_fn loop;
399     /* Minor 2 ends here. */
400 } *krb5_kdcpreauth_vtable;
401 
402 #endif /* KRB5_KDCPREAUTH_PLUGIN_H */
403