/*
* <krb5/preauth_plugin.h>
*
* Copyright (c) 2006 Red Hat, Inc.
* Portions copyright (c) 2006 Massachusetts Institute of Technology
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Red Hat, Inc., nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Preauthentication plugin definitions for Kerberos 5.
*/
#ifndef KRB5_PREAUTH_PLUGIN_H_INCLUDED
#define KRB5_PREAUTH_PLUGIN_H_INCLUDED
#include <krb5.h>
/*
* While arguments of these types are passed-in, for the most part a preauth
* module can treat them as opaque. If we need keying data, we can ask for
* it directly.
*/
struct _krb5_db_entry_new;
struct _krb5_key_data;
struct _krb5_preauth_client_rock;
/*
* Preauth mechanism property flags, unified from previous definitions in the
* KDC and libkrb5 sources.
*/
/* Provides a real answer which we can send back to the KDC (client-only). The
* client assumes that one real answer will be enough. */
#define PA_REAL 0x00000001
/* Doesn't provide a real answer, but must be given a chance to run before any
* REAL mechanism callbacks (client-only). */
#define PA_INFO 0x00000002
/* Causes the KDC to include this mechanism in a list of supported preauth
* types if the user's DB entry flags the user as requiring hardware-based
* preauthentication (server-only). */
#define PA_HARDWARE 0x00000004
/* Causes the KDC to include this mechanism in a list of supported preauth
* types if the user's DB entry flags the user as requiring preauthentication,
* and to fail preauthentication if we can't verify the client data. The
* flipside of PA_SUFFICIENT (server-only). */
#define PA_REQUIRED 0x00000008
/* Causes the KDC to include this mechanism in a list of supported preauth
* types if the user's DB entry flags the user as requiring preauthentication,
* and to mark preauthentication as successful if we can verify the client
* data. The flipside of PA_REQUIRED (server-only). */
#define PA_SUFFICIENT 0x00000010
/* Marks this preauthentication mechanism as one which changes the key which is
* used for encrypting the response to the client. Modules which have this
* flag have their server_return_proc called before modules which do not, and
* are passed over if a previously-called module has modified the encrypting
* key (server-only). */
#define PA_REPLACES_KEY 0x00000020
/* Causes the KDC to check with this preauthentication module even if the
* client has no entry in the realm database. If the module returns a success
* code, continue processing and assume that its return_padata callback will
* supply us with a key for encrypting the AS reply (server-only). */
/* #define PA_VIRTUAL (0x00000040 | PA_REPLACES_KEY) */
/* Not really a padata type, so don't include it in any list of preauth types
* which gets sent over the wire. */
#define PA_PSEUDO 0x00000080
/***************************************************************************
*
* Client-side preauthentication plugin interface definition.
*
***************************************************************************/
/*
* A callback which will obtain the user's long-term AS key by prompting the
* user for the password, then salting it properly, and so on. For the moment,
* it's identical to the get_as_key callback used inside of libkrb5, but we
* define a new typedef here instead of making the existing one public to
* isolate ourselves from potential future changes.
*/
typedef krb5_error_code
(*preauth_get_as_key_proc)(krb5_context,
krb5_principal,
krb5_enctype,
krb5_prompter_fct,
void *prompter_data,
krb5_data *salt,
krb5_data *s2kparams,
krb5_keyblock *as_key,
void *gak_data);
/*
* A client module's callback functions are allowed to request various
* information to enable it to process a request.
*/
enum krb5plugin_preauth_client_request_type {
/* The returned krb5_data item holds the enctype used to encrypt the
* encrypted portion of the AS_REP packet. */
krb5plugin_preauth_client_get_etype = 1,
/* Free the data returned from krb5plugin_preauth_client_req_get_etype */
krb5plugin_preauth_client_free_etype = 2
};
typedef krb5_error_code
(*preauth_get_client_data_proc)(krb5_context,
struct _krb5_preauth_client_rock *,
krb5_int32 request_type,
krb5_data **);
/* Per-plugin initialization/cleanup. The init function is called
* by libkrb5 when the plugin is loaded, and the fini function is
* called before the plugin is unloaded. Both are optional and
* may be called multiple times in case the plugin is used in
* multiple contexts. The returned context lives the lifetime of
* the krb5_context */
typedef krb5_error_code
(*preauth_client_plugin_init_proc)(krb5_context context,
void **plugin_context);
typedef void
(*preauth_client_plugin_fini_proc)(krb5_context context,
void *plugin_context);
/* A callback which returns flags indicating if the module is a "real" or
* an "info" mechanism, and so on. This function is called for each entry
* in the client_pa_type_list. */
typedef int
(*preauth_client_get_flags_proc)(krb5_context context,
krb5_preauthtype pa_type);
/* Per-request initialization/cleanup. The request_init function is
* called when beginning to process a get_init_creds request and the
* request_fini function is called when processing of the request is
* complete. This is optional. It may be called multiple times in
* the lifetime of a krb5_context. */
typedef void
(*preauth_client_request_init_proc)(krb5_context context,
void *plugin_context,
void **request_context);
typedef void
(*preauth_client_request_fini_proc)(krb5_context context,
void *plugin_context,
void *request_context);
/* Client function which processes server-supplied data in pa_data,
* returns created data in out_pa_data, storing any of its own state in
* client_context if data for the associated preauthentication type is
* needed. It is also called after the AS-REP is received if the AS-REP
* includes preauthentication data of the associated type.
* NOTE! the encoded_previous_request will be NULL the first time this
* function is called, because it is expected to only ever contain the data
* obtained from a previous call to this function. */
typedef krb5_error_code
(*preauth_client_process_proc)(krb5_context context,
void *plugin_context,
void *request_context,
krb5_get_init_creds_opt *opt,
preauth_get_client_data_proc get_data_proc,
struct _krb5_preauth_client_rock *rock,
krb5_kdc_req *request,
krb5_data *encoded_request_body,
krb5_data *encoded_previous_request,
krb5_pa_data *pa_data,
krb5_prompter_fct prompter,
void *prompter_data,
preauth_get_as_key_proc gak_fct,
void *gak_data,
krb5_data *salt,
krb5_data *s2kparams,
krb5_keyblock *as_key,
krb5_pa_data ***out_pa_data);
/* Client function which can attempt to use e-data in the error response to
* try to recover from the given error. If this function is not NULL, and
* it stores data in out_pa_data which is different data from the contents
* of in_pa_data, then the client library will retransmit the request. */
typedef krb5_error_code
(*preauth_client_tryagain_proc)(krb5_context context,
void *plugin_context,
void *request_context,
krb5_get_init_creds_opt *opt,
preauth_get_client_data_proc get_data_proc,
struct _krb5_preauth_client_rock *rock,
krb5_kdc_req *request,
krb5_data *encoded_request_body,
krb5_data *encoded_previous_request,
krb5_pa_data *in_pa_data,
krb5_error *error,
krb5_prompter_fct prompter,
void *prompter_data,
preauth_get_as_key_proc gak_fct,
void *gak_data,
krb5_data *salt,
krb5_data *s2kparams,
krb5_keyblock *as_key,
krb5_pa_data ***out_pa_data);
/*
* Client function which receives krb5_get_init_creds_opt information.
* The attr and value information supplied should be copied locally by
* the module if it wishes to reference it after returning from this call.
*/
typedef krb5_error_code
(*preauth_client_supply_gic_opts_proc)(krb5_context context,
void *plugin_context,
krb5_get_init_creds_opt *opt,
const char *attr,
const char *value);
/*
* The function table / structure which a preauth client module must export as
* "preauthentication_client_0". If the interfaces work correctly, future
* versions of the table will add either more callbacks or more arguments to
* callbacks, and in both cases we'll be able to wrap the v0 functions.
*/
typedef struct krb5plugin_preauth_client_ftable_v1 {
/* Not-usually-visible name. */
char *name;
/* Pointer to zero-terminated list of pa_types which this module can
* provide services for. */
krb5_preauthtype *pa_type_list;
/* Pointer to zero-terminated list of enc_types which this module claims
* to add support for. */
krb5_enctype *enctype_list;
/* Per-plugin initialization/cleanup. The init function is called
* by libkrb5 when the plugin is loaded, and the fini function is
* called before the plugin is unloaded. Both are optional and
* may be called multiple times in case the plugin is used in
* multiple contexts. The returned context lives the lifetime of
* the krb5_context */
preauth_client_plugin_init_proc init;
preauth_client_plugin_fini_proc fini;
/* A callback which returns flags indicating if the module is a "real" or
* an "info" mechanism, and so on. This function is called for each entry
* in the client_pa_type_list. */
preauth_client_get_flags_proc flags;
/* Per-request initialization/cleanup. The request_init function is
* called when beginning to process a get_init_creds request and the
* request_fini function is called when processing of the request is
* complete. This is optional. It may be called multiple times in
* the lifetime of a krb5_context. */
preauth_client_request_init_proc request_init;
preauth_client_request_fini_proc request_fini;
/* Client function which processes server-supplied data in pa_data,
* returns created data in out_pa_data, storing any of its own state in
* client_context if data for the associated preauthentication type is
* needed. It is also called after the AS-REP is received if the AS-REP
* includes preauthentication data of the associated type.
* NOTE! the encoded_previous_request will be NULL the first time this
* function is called, because it is expected to only ever contain the data
* obtained from a previous call to this function. */
preauth_client_process_proc process;
/* Client function which can attempt to use e-data in the error response to
* try to recover from the given error. If this function is not NULL, and
* it stores data in out_pa_data which is different data from the contents
* of in_pa_data, then the client library will retransmit the request. */
preauth_client_tryagain_proc tryagain;
/*
* Client function which receives krb5_get_init_creds_opt information.
* The attr and value information supplied should be copied locally by
* the module if it wishes to reference it after returning from this call.
*/
preauth_client_supply_gic_opts_proc gic_opts;
} krb5plugin_preauth_client_ftable_v1;
/***************************************************************************
*
* Server-side preauthentication plugin interface definition.
*
***************************************************************************/
/*
* A server module's callback functions are allowed to request specific types
* of information about the given client or server record or request, even
* though the database records themselves are opaque to the module.
*/
enum krb5plugin_preauth_entry_request_type {
/* The returned krb5_data item holds a DER-encoded X.509 certificate. */
krb5plugin_preauth_entry_request_certificate = 1,
/* The returned krb5_data_item holds a krb5_deltat. */
krb5plugin_preauth_entry_max_time_skew = 2,
/* The returned krb5_data_item holds an array of krb5_keyblock structures,
* terminated by an entry with key type = 0.
* Each keyblock should have its contents freed in turn, and then the data
* item itself should be freed. */
krb5plugin_preauth_keys = 3,
/* The returned krb5_data_item holds the request structure, re-encoded
* using DER. Unless the client implementation is the same as the server
* implementation, there's a good chance that the result will not match
* what the client sent, so don't go creating any fatal errors if it
* doesn't match up. */
krb5plugin_preauth_request_body = 4
};
typedef krb5_error_code
(*preauth_get_entry_data_proc)(krb5_context,
krb5_kdc_req *,
struct _krb5_db_entry_new *,
krb5_int32 request_type,
krb5_data **);
/* Preauth plugin initialization function */
typedef krb5_error_code
(*preauth_server_init_proc)(krb5_context context,
void **plugin_context,
const char** realmnames);
/* Preauth plugin cleanup function */
typedef void
(*preauth_server_fini_proc)(krb5_context context, void *plugin_context);
/* Return the flags which the KDC should use for this module. This is a
* callback instead of a static value because the module may or may not
* wish to count itself as a hardware preauthentication module (in other
* words, the flags may be affected by the configuration, for example if a
* site administrator can force a particular preauthentication type to be
* supported using only hardware). This function is called for each entry
* entry in the server_pa_type_list. */
typedef int
(*preauth_server_flags_proc)(krb5_context context, krb5_preauthtype patype);
/* Get preauthentication data to send to the client as part of the "you
* need to use preauthentication" error. The module doesn't need to
* actually provide data if the protocol doesn't require it, but it should
* return either zero or non-zero to control whether its padata type is
* included in the list which is sent back to the client. Is not allowed
* to create a context because we have no guarantee that the client will
* ever call again (or that it will hit this server if it does), in which
* case a context might otherwise hang around forever. */
typedef krb5_error_code
(*preauth_server_edata_proc)(krb5_context,
krb5_kdc_req *request,
struct _krb5_db_entry_new *client,
struct _krb5_db_entry_new *server,
preauth_get_entry_data_proc,
void *pa_module_context,
krb5_pa_data *data);
/* Verify preauthentication data sent by the client, setting the
* TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
* field as appropriate, and returning nonzero on failure. Can create
* context data for consumption by the return_proc or freepa_proc below. */
typedef krb5_error_code
(*preauth_server_verify_proc)(krb5_context context,
struct _krb5_db_entry_new *client,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_enc_tkt_part *enc_tkt_reply,
krb5_pa_data *data,
preauth_get_entry_data_proc,
void *pa_module_context,
void **pa_request_context,
krb5_data **e_data,
krb5_authdata ***authz_data);
/* Generate preauthentication response data to send to the client as part
* of the AS-REP. If it needs to override the key which is used to encrypt
* the response, it can do so. The module is expected (but not required,
* if a preauth_server_free_reqcontext_proc is also provided) to free any
* context data it saved in "pa_request_context". */
typedef krb5_error_code
(*preauth_server_return_proc)(krb5_context context,
krb5_pa_data * padata,
struct _krb5_db_entry_new *client,
krb5_data *req_pkt,
krb5_kdc_req *request,
krb5_kdc_rep *reply,
struct _krb5_key_data *client_keys,
krb5_keyblock *encrypting_key,
krb5_pa_data **send_pa,
preauth_get_entry_data_proc,
void *pa_module_context,
void **pa_request_context);
/* Free up the server-side per-request context, in cases where
* server_return_proc() didn't or for whatever reason was not called.
* Can be NULL. */
typedef krb5_error_code
(*preauth_server_free_reqcontext_proc)(krb5_context,
void *pa_module_context,
void **request_pa_context);
/*
* The function table / structure which a preauth server module must export as
* "preauthentication_server_0". NOTE: replace "0" with "1" for the type and
* variable names if this gets picked up by upstream. If the interfaces work
* correctly, future versions of the table will add either more callbacks or
* more arguments to callbacks, and in both cases we'll be able to wrap the v0
* functions.
*/
typedef struct krb5plugin_preauth_server_ftable_v1 {
/* Not-usually-visible name. */
char *name;
/* Pointer to zero-terminated list of pa_types which this module can
* provide services for. */
krb5_preauthtype *pa_type_list;
/* Per-plugin initialization/cleanup. The init function is called by the
* KDC when the plugin is loaded, and the fini function is called before
* the plugin is unloaded. Both are optional. */
preauth_server_init_proc init_proc;
preauth_server_fini_proc fini_proc;
/* Return the flags which the KDC should use for this module. This is a
* callback instead of a static value because the module may or may not
* wish to count itself as a hardware preauthentication module (in other
* words, the flags may be affected by the configuration, for example if a
* site administrator can force a particular preauthentication type to be
* supported using only hardware). This function is called for each entry
* entry in the server_pa_type_list. */
preauth_server_flags_proc flags_proc;
/* Get preauthentication data to send to the client as part of the "you
* need to use preauthentication" error. The module doesn't need to
* actually provide data if the protocol doesn't require it, but it should
* return either zero or non-zero to control whether its padata type is
* included in the list which is sent back to the client. Is not allowed
* to create a context because we have no guarantee that the client will
* ever call again (or that it will hit this server if it does), in which
* case a context might otherwise hang around forever. */
preauth_server_edata_proc edata_proc;
/* Verify preauthentication data sent by the client, setting the
* TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
* field as appropriate, and returning nonzero on failure. Can create
* context data for consumption by the return_proc or freepa_proc below. */
preauth_server_verify_proc verify_proc;
/* Generate preauthentication response data to send to the client as part
* of the AS-REP. If it needs to override the key which is used to encrypt
* the response, it can do so. The module is expected (but not required,
* if a freepa_proc is also provided) to free any context data it saved in
* "request_pa_context". */
preauth_server_return_proc return_proc;
/* Free up the server-side per-request context, in cases where
* server_return_proc() didn't or for whatever reason was not called.
* Can be NULL. */
preauth_server_free_reqcontext_proc freepa_reqcontext_proc;
} krb5plugin_preauth_server_ftable_v1;
/*
* This function allows a preauth plugin to obtain preauth
* options. The preauth_data returned from this function
* should be freed by calling krb5_get_init_creds_opt_free_pa().
*
* The 'opt' pointer supplied to this function must have been
* obtained using krb5_get_init_creds_opt_alloc()
*/
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_get_pa
(krb5_context context,
krb5_get_init_creds_opt *opt,
int *num_preauth_data,
krb5_gic_opt_pa_data **preauth_data);
/*
* This function frees the preauth_data that was returned by
* krb5_get_init_creds_opt_get_pa().
*/
void KRB5_CALLCONV
krb5_get_init_creds_opt_free_pa
(krb5_context context,
int num_preauth_data,
krb5_gic_opt_pa_data *preauth_data);
#endif /* KRB5_PREAUTH_PLUGIN_H_INCLUDED */