1 
2 /*
3  * <krb5/preauth_plugin.h>
4  *
5  * Copyright (c) 2006 Red Hat, Inc.
6  * Portions copyright (c) 2006 Massachusetts Institute of Technology
7  * All Rights Reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  *  * Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *  * Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *  * Neither the name of Red Hat, Inc., nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Preauthentication plugin definitions for Kerberos 5.
35  */
36 
37 #ifndef KRB5_PREAUTH_PLUGIN_H_INCLUDED
38 #define KRB5_PREAUTH_PLUGIN_H_INCLUDED
39 #include <krb5.h>
40 
41 /*
42  * While arguments of these types are passed-in, for the most part a preauth
43  * module can treat them as opaque.  If we need keying data, we can ask for
44  * it directly.
45  */
46 struct _krb5_db_entry_new;
47 struct _krb5_key_data;
48 struct _krb5_preauth_client_rock;
49 
50 /*
51  * Preauth mechanism property flags, unified from previous definitions in the
52  * KDC and libkrb5 sources.
53  */
54 
55 /* Provides a real answer which we can send back to the KDC (client-only).  The
56  * client assumes that one real answer will be enough. */
57 #define PA_REAL		0x00000001
58 
59 /* Doesn't provide a real answer, but must be given a chance to run before any
60  * REAL mechanism callbacks (client-only). */
61 #define PA_INFO		0x00000002
62 
63 /* Causes the KDC to include this mechanism in a list of supported preauth
64  * types if the user's DB entry flags the user as requiring hardware-based
65  * preauthentication (server-only). */
66 #define PA_HARDWARE	0x00000004
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 preauthentication,
70  * and to fail preauthentication if we can't verify the client data.  The
71  * flipside of PA_SUFFICIENT (server-only). */
72 #define PA_REQUIRED	0x00000008
73 
74 /* Causes the KDC to include this mechanism in a list of supported preauth
75  * types if the user's DB entry flags the user as requiring preauthentication,
76  * and to mark preauthentication as successful if we can verify the client
77  * data.  The flipside of PA_REQUIRED (server-only). */
78 #define PA_SUFFICIENT	0x00000010
79 
80 /* Marks this preauthentication mechanism as one which changes the key which is
81  * used for encrypting the response to the client.  Modules which have this
82  * flag have their server_return_proc called before modules which do not, and
83  * are passed over if a previously-called module has modified the encrypting
84  * key (server-only). */
85 #define PA_REPLACES_KEY	0x00000020
86 
87 /* Causes the KDC to check with this preauthentication module even if the
88  * client has no entry in the realm database.  If the module returns a success
89  * code, continue processing and assume that its return_padata callback will
90  * supply us with a key for encrypting the AS reply (server-only). */
91 /* #define PA_VIRTUAL	(0x00000040 | PA_REPLACES_KEY) */
92 
93 /* Not really a padata type, so don't include it in any list of preauth types
94  * which gets sent over the wire. */
95 #define PA_PSEUDO	0x00000080
96 
97 
98 /***************************************************************************
99  *
100  * Client-side preauthentication plugin interface definition.
101  *
102  ***************************************************************************/
103 
104 /*
105  * A callback which will obtain the user's long-term AS key by prompting the
106  * user for the password, then salting it properly, and so on.  For the moment,
107  * it's identical to the get_as_key callback used inside of libkrb5, but we
108  * define a new typedef here instead of making the existing one public to
109  * isolate ourselves from potential future changes.
110  */
111 typedef krb5_error_code
112 (*preauth_get_as_key_proc)(krb5_context,
113 			   krb5_principal,
114 			   krb5_enctype,
115 			   krb5_prompter_fct,
116 			   void *prompter_data,
117 			   krb5_data *salt,
118 			   krb5_data *s2kparams,
119 			   krb5_keyblock *as_key,
120 			   void *gak_data);
121 
122 /*
123  * A client module's callback functions are allowed to request various
124  * information to enable it to process a request.
125  */
126 enum krb5plugin_preauth_client_request_type {
127     /* The returned krb5_data item holds the enctype used to encrypt the
128      * encrypted portion of the AS_REP packet. */
129     krb5plugin_preauth_client_get_etype = 1,
130     /* Free the data returned from krb5plugin_preauth_client_req_get_etype */
131     krb5plugin_preauth_client_free_etype = 2
132 };
133 typedef krb5_error_code
134 (*preauth_get_client_data_proc)(krb5_context,
135 				struct _krb5_preauth_client_rock *,
136 				krb5_int32 request_type,
137 				krb5_data **);
138 
139 /* Per-plugin initialization/cleanup.  The init function is called
140  * by libkrb5 when the plugin is loaded, and the fini function is
141  * called before the plugin is unloaded.  Both are optional and
142  * may be called multiple times in case the plugin is used in
143  * multiple contexts.  The returned context lives the lifetime of
144  * the krb5_context */
145 typedef krb5_error_code
146 (*preauth_client_plugin_init_proc)(krb5_context context,
147 				   void **plugin_context);
148 typedef void
149 (*preauth_client_plugin_fini_proc)(krb5_context context,
150 				   void *plugin_context);
151 
152 /* A callback which returns flags indicating if the module is a "real" or
153  * an "info" mechanism, and so on.  This function is called for each entry
154  * in the client_pa_type_list. */
155 typedef int
156 (*preauth_client_get_flags_proc)(krb5_context context,
157 				 krb5_preauthtype pa_type);
158 
159 /* Per-request initialization/cleanup.  The request_init function is
160  * called when beginning to process a get_init_creds request and the
161  * request_fini function is called when processing of the request is
162  * complete.  This is optional.  It may be called multiple times in
163  * the lifetime of a krb5_context. */
164 typedef void
165 (*preauth_client_request_init_proc)(krb5_context context,
166 				    void *plugin_context,
167 				    void **request_context);
168 typedef void
169 (*preauth_client_request_fini_proc)(krb5_context context,
170 				    void *plugin_context,
171 				    void *request_context);
172 
173 /* Client function which processes server-supplied data in pa_data,
174  * returns created data in out_pa_data, storing any of its own state in
175  * client_context if data for the associated preauthentication type is
176  * needed.  It is also called after the AS-REP is received if the AS-REP
177  * includes preauthentication data of the associated type.
178  * NOTE! the encoded_previous_request will be NULL the first time this
179  * function is called, because it is expected to only ever contain the data
180  * obtained from a previous call to this function. */
181 typedef krb5_error_code
182 (*preauth_client_process_proc)(krb5_context context,
183 			       void *plugin_context,
184 			       void *request_context,
185 			       krb5_get_init_creds_opt *opt,
186 			       preauth_get_client_data_proc get_data_proc,
187 			       struct _krb5_preauth_client_rock *rock,
188 			       krb5_kdc_req *request,
189 			       krb5_data *encoded_request_body,
190 			       krb5_data *encoded_previous_request,
191 			       krb5_pa_data *pa_data,
192 			       krb5_prompter_fct prompter,
193 			       void *prompter_data,
194 			       preauth_get_as_key_proc gak_fct,
195 			       void *gak_data,
196 			       krb5_data *salt,
197 			       krb5_data *s2kparams,
198 			       krb5_keyblock *as_key,
199 			       krb5_pa_data ***out_pa_data);
200 
201 /* Client function which can attempt to use e-data in the error response to
202  * try to recover from the given error.  If this function is not NULL, and
203  * it stores data in out_pa_data which is different data from the contents
204  * of in_pa_data, then the client library will retransmit the request. */
205 typedef krb5_error_code
206 (*preauth_client_tryagain_proc)(krb5_context context,
207 				void *plugin_context,
208 				void *request_context,
209 				krb5_get_init_creds_opt *opt,
210 				preauth_get_client_data_proc get_data_proc,
211 				struct _krb5_preauth_client_rock *rock,
212 				krb5_kdc_req *request,
213 				krb5_data *encoded_request_body,
214 				krb5_data *encoded_previous_request,
215 				krb5_pa_data *in_pa_data,
216 				krb5_error *error,
217 				krb5_prompter_fct prompter,
218 				void *prompter_data,
219 				preauth_get_as_key_proc gak_fct,
220 				void *gak_data,
221 				krb5_data *salt,
222 				krb5_data *s2kparams,
223 				krb5_keyblock *as_key,
224 				krb5_pa_data ***out_pa_data);
225 
226 /*
227  * Client function which receives krb5_get_init_creds_opt information.
228  * The attr and value information supplied should be copied locally by
229  * the module if it wishes to reference it after returning from this call.
230  */
231 typedef krb5_error_code
232 (*preauth_client_supply_gic_opts_proc)(krb5_context context,
233 				       void *plugin_context,
234 				       krb5_get_init_creds_opt *opt,
235 				       const char *attr,
236 				       const char *value);
237 
238 /*
239  * The function table / structure which a preauth client module must export as
240  * "preauthentication_client_0".  If the interfaces work correctly, future
241  * versions of the table will add either more callbacks or more arguments to
242  * callbacks, and in both cases we'll be able to wrap the v0 functions.
243  */
244 typedef struct krb5plugin_preauth_client_ftable_v1 {
245     /* Not-usually-visible name. */
246     char *name;
247 
248     /* Pointer to zero-terminated list of pa_types which this module can
249      * provide services for. */
250     krb5_preauthtype *pa_type_list;
251 
252     /* Pointer to zero-terminated list of enc_types which this module claims
253      * to add support for. */
254     krb5_enctype *enctype_list;
255 
256     /* Per-plugin initialization/cleanup.  The init function is called
257      * by libkrb5 when the plugin is loaded, and the fini function is
258      * called before the plugin is unloaded.  Both are optional and
259      * may be called multiple times in case the plugin is used in
260      * multiple contexts.  The returned context lives the lifetime of
261      * the krb5_context */
262     preauth_client_plugin_init_proc init;
263     preauth_client_plugin_fini_proc fini;
264 
265     /* A callback which returns flags indicating if the module is a "real" or
266      * an "info" mechanism, and so on.  This function is called for each entry
267      * in the client_pa_type_list. */
268     preauth_client_get_flags_proc flags;
269 
270     /* Per-request initialization/cleanup.  The request_init function is
271      * called when beginning to process a get_init_creds request and the
272      * request_fini function is called when processing of the request is
273      * complete.  This is optional.  It may be called multiple times in
274      * the lifetime of a krb5_context. */
275     preauth_client_request_init_proc request_init;
276     preauth_client_request_fini_proc request_fini;
277 
278     /* Client function which processes server-supplied data in pa_data,
279      * returns created data in out_pa_data, storing any of its own state in
280      * client_context if data for the associated preauthentication type is
281      * needed.  It is also called after the AS-REP is received if the AS-REP
282      * includes preauthentication data of the associated type.
283      * NOTE! the encoded_previous_request will be NULL the first time this
284      * function is called, because it is expected to only ever contain the data
285      * obtained from a previous call to this function. */
286     preauth_client_process_proc process;
287 
288     /* Client function which can attempt to use e-data in the error response to
289      * try to recover from the given error.  If this function is not NULL, and
290      * it stores data in out_pa_data which is different data from the contents
291      * of in_pa_data, then the client library will retransmit the request. */
292     preauth_client_tryagain_proc tryagain;
293 
294     /*
295      * Client function which receives krb5_get_init_creds_opt information.
296      * The attr and value information supplied should be copied locally by
297      * the module if it wishes to reference it after returning from this call.
298      */
299     preauth_client_supply_gic_opts_proc gic_opts;
300 
301 } krb5plugin_preauth_client_ftable_v1;
302 
303 
304 /***************************************************************************
305  *
306  * Server-side preauthentication plugin interface definition.
307  *
308  ***************************************************************************/
309 
310 /*
311  * A server module's callback functions are allowed to request specific types
312  * of information about the given client or server record or request, even
313  * though the database records themselves are opaque to the module.
314  */
315 enum krb5plugin_preauth_entry_request_type {
316     /* The returned krb5_data item holds a DER-encoded X.509 certificate. */
317     krb5plugin_preauth_entry_request_certificate = 1,
318     /* The returned krb5_data_item holds a krb5_deltat. */
319     krb5plugin_preauth_entry_max_time_skew = 2,
320     /* The returned krb5_data_item holds an array of krb5_keyblock structures,
321      * terminated by an entry with key type = 0.
322      * Each keyblock should have its contents freed in turn, and then the data
323      * item itself should be freed. */
324     krb5plugin_preauth_keys = 3,
325     /* The returned krb5_data_item holds the request structure, re-encoded
326      * using DER.  Unless the client implementation is the same as the server
327      * implementation, there's a good chance that the result will not match
328      * what the client sent, so don't go creating any fatal errors if it
329      * doesn't match up. */
330     krb5plugin_preauth_request_body = 4
331 };
332 
333 typedef krb5_error_code
334 (*preauth_get_entry_data_proc)(krb5_context,
335 			       krb5_kdc_req *,
336 			       struct _krb5_db_entry_new *,
337 			       krb5_int32 request_type,
338 			       krb5_data **);
339 
340 /* Preauth plugin initialization function */
341 typedef krb5_error_code
342 (*preauth_server_init_proc)(krb5_context context,
343 			    void **plugin_context,
344 			    const char** realmnames);
345 
346 /* Preauth plugin cleanup function */
347 typedef void
348 (*preauth_server_fini_proc)(krb5_context context, void *plugin_context);
349 
350 /* Return the flags which the KDC should use for this module.  This is a
351  * callback instead of a static value because the module may or may not
352  * wish to count itself as a hardware preauthentication module (in other
353  * words, the flags may be affected by the configuration, for example if a
354  * site administrator can force a particular preauthentication type to be
355  * supported using only hardware).  This function is called for each entry
356  * entry in the server_pa_type_list. */
357 typedef int
358 (*preauth_server_flags_proc)(krb5_context context, krb5_preauthtype patype);
359 
360 /* Get preauthentication data to send to the client as part of the "you
361  * need to use preauthentication" error.  The module doesn't need to
362  * actually provide data if the protocol doesn't require it, but it should
363  * return either zero or non-zero to control whether its padata type is
364  * included in the list which is sent back to the client.  Is not allowed
365  * to create a context because we have no guarantee that the client will
366  * ever call again (or that it will hit this server if it does), in which
367  * case a context might otherwise hang around forever. */
368 typedef krb5_error_code
369 (*preauth_server_edata_proc)(krb5_context,
370 			     krb5_kdc_req *request,
371 			     struct _krb5_db_entry_new *client,
372 			     struct _krb5_db_entry_new *server,
373 			     preauth_get_entry_data_proc,
374 			     void *pa_module_context,
375 			     krb5_pa_data *data);
376 
377 /* Verify preauthentication data sent by the client, setting the
378  * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
379  * field as appropriate, and returning nonzero on failure.  Can create
380  * context data for consumption by the return_proc or freepa_proc below. */
381 typedef krb5_error_code
382 (*preauth_server_verify_proc)(krb5_context context,
383 			      struct _krb5_db_entry_new *client,
384 			      krb5_data *req_pkt,
385 			      krb5_kdc_req *request,
386 			      krb5_enc_tkt_part *enc_tkt_reply,
387 			      krb5_pa_data *data,
388 			      preauth_get_entry_data_proc,
389 			      void *pa_module_context,
390 			      void **pa_request_context,
391 			      krb5_data **e_data,
392 			      krb5_authdata ***authz_data);
393 
394 /* Generate preauthentication response data to send to the client as part
395  * of the AS-REP.  If it needs to override the key which is used to encrypt
396  * the response, it can do so.  The module is expected (but not required,
397  * if a preauth_server_free_reqcontext_proc is also provided) to free any
398  * context data it saved in "pa_request_context". */
399 typedef krb5_error_code
400 (*preauth_server_return_proc)(krb5_context context,
401 			      krb5_pa_data * padata,
402 			      struct _krb5_db_entry_new *client,
403 			      krb5_data *req_pkt,
404 			      krb5_kdc_req *request,
405 			      krb5_kdc_rep *reply,
406 			      struct _krb5_key_data *client_keys,
407 			      krb5_keyblock *encrypting_key,
408 			      krb5_pa_data **send_pa,
409 			      preauth_get_entry_data_proc,
410 			      void *pa_module_context,
411 			      void **pa_request_context);
412 
413 /* Free up the server-side per-request context, in cases where
414  * server_return_proc() didn't or for whatever reason was not called.
415  * Can be NULL. */
416 typedef krb5_error_code
417 (*preauth_server_free_reqcontext_proc)(krb5_context,
418 				       void *pa_module_context,
419 				       void **request_pa_context);
420 
421 /*
422  * The function table / structure which a preauth server module must export as
423  * "preauthentication_server_0".  NOTE: replace "0" with "1" for the type and
424  * variable names if this gets picked up by upstream.  If the interfaces work
425  * correctly, future versions of the table will add either more callbacks or
426  * more arguments to callbacks, and in both cases we'll be able to wrap the v0
427  * functions.
428  */
429 typedef struct krb5plugin_preauth_server_ftable_v1 {
430     /* Not-usually-visible name. */
431     char *name;
432 
433     /* Pointer to zero-terminated list of pa_types which this module can
434      * provide services for. */
435     krb5_preauthtype *pa_type_list;
436 
437     /* Per-plugin initialization/cleanup.  The init function is called by the
438      * KDC when the plugin is loaded, and the fini function is called before
439      * the plugin is unloaded.  Both are optional. */
440     preauth_server_init_proc init_proc;
441     preauth_server_fini_proc fini_proc;
442 
443     /* Return the flags which the KDC should use for this module.  This is a
444      * callback instead of a static value because the module may or may not
445      * wish to count itself as a hardware preauthentication module (in other
446      * words, the flags may be affected by the configuration, for example if a
447      * site administrator can force a particular preauthentication type to be
448      * supported using only hardware).  This function is called for each entry
449      * entry in the server_pa_type_list. */
450     preauth_server_flags_proc flags_proc;
451 
452     /* Get preauthentication data to send to the client as part of the "you
453      * need to use preauthentication" error.  The module doesn't need to
454      * actually provide data if the protocol doesn't require it, but it should
455      * return either zero or non-zero to control whether its padata type is
456      * included in the list which is sent back to the client.  Is not allowed
457      * to create a context because we have no guarantee that the client will
458      * ever call again (or that it will hit this server if it does), in which
459      * case a context might otherwise hang around forever. */
460     preauth_server_edata_proc edata_proc;
461 
462     /* Verify preauthentication data sent by the client, setting the
463      * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
464      * field as appropriate, and returning nonzero on failure.  Can create
465      * context data for consumption by the return_proc or freepa_proc below. */
466     preauth_server_verify_proc verify_proc;
467 
468     /* Generate preauthentication response data to send to the client as part
469      * of the AS-REP.  If it needs to override the key which is used to encrypt
470      * the response, it can do so.  The module is expected (but not required,
471      * if a freepa_proc is also provided) to free any context data it saved in
472      * "request_pa_context". */
473     preauth_server_return_proc return_proc;
474 
475     /* Free up the server-side per-request context, in cases where
476      * server_return_proc() didn't or for whatever reason was not called.
477      * Can be NULL. */
478     preauth_server_free_reqcontext_proc freepa_reqcontext_proc;
479 
480 } krb5plugin_preauth_server_ftable_v1;
481 
482 
483 /*
484  * This function allows a preauth plugin to obtain preauth
485  * options.  The preauth_data returned from this function
486  * should be freed by calling krb5_get_init_creds_opt_free_pa().
487  *
488  * The 'opt' pointer supplied to this function must have been
489  * obtained using krb5_get_init_creds_opt_alloc()
490  */
491 krb5_error_code KRB5_CALLCONV
492 krb5_get_init_creds_opt_get_pa
493 		(krb5_context context,
494 		krb5_get_init_creds_opt *opt,
495 		int *num_preauth_data,
496 		krb5_gic_opt_pa_data **preauth_data);
497 
498 /*
499  * This function frees the preauth_data that was returned by
500  * krb5_get_init_creds_opt_get_pa().
501  */
502 void KRB5_CALLCONV
503 krb5_get_init_creds_opt_free_pa
504 		(krb5_context context,
505 		 int num_preauth_data,
506 		 krb5_gic_opt_pa_data *preauth_data);
507 
508 #endif /* KRB5_PREAUTH_PLUGIN_H_INCLUDED */
509