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