From: Greg Hudson Date: Fri, 17 Jun 2011 13:44:33 +0000 (+0000) Subject: Convert preauth_plugin.h to new plugin framework X-Git-Tag: krb5-1.10-alpha1~402 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=6099f525eb64772557927760d8a7ff1e75f79ff7;p=krb5.git Convert preauth_plugin.h to new plugin framework The preauth plugin interface was introduced in 1.6 but was never made a public API. In preparation for making it public in 1.10, convert it to use the new plugin framework. This will require changes to any existing preauth plugins. A number of symbols were renamed for namespace cleanliness, and abstract types were introduced for module data and module per-request data for better type safety. On the consumer end (preauth2.c and kdc_preauth.c), this is a pretty rough conversion. Eventually we should create proper consumer APIs with module handles, and the flat lists of preauth types should hold pointers to module handles rather than copies of the vtables. The built-in preauth type handlers should then be converted to built-in module providers linked into the consumer code (as should encrypted challenge, since it has no external dependencies). None of this will impact the provider API for preauth plugins, so it can wait. ticket: 6921 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24970 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 86ec114b0..76993f397 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -809,48 +809,11 @@ error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE) * expanded in the future as new types of requests are defined which * may require other things to be passed through. */ struct krb5int_fast_request_state; -typedef struct _krb5_preauth_client_rock { - krb5_magic magic; +struct krb5_clpreauth_rock_st { + krb5_magic magic; krb5_enctype *etype; struct krb5int_fast_request_state *fast_state; -} krb5_preauth_client_rock; - -/* This structure lets us keep track of all of the modules which are loaded, - * turning the list of modules and their lists of implemented preauth types - * into a single list which we can walk easily. */ -typedef struct _krb5_preauth_context { - int n_modules; - struct _krb5_preauth_context_module { - /* Which of the possibly more than one preauth types which the - * module supports we're using at this point in the list. */ - krb5_preauthtype pa_type; - /* Encryption types which the client claims to support -- we - * copy them directly into the krb5_kdc_req structure during - * krb5_preauth_prepare_request(). */ - krb5_enctype *enctypes; - /* The plugin's per-plugin context and a function to clear it. */ - void *plugin_context; - preauth_client_plugin_fini_proc client_fini; - /* The module's table, and some of its members, copied here for - * convenience when we populated the list. */ - struct krb5plugin_preauth_client_ftable_v1 *ftable; - const char *name; - int flags, use_count; - preauth_client_process_proc client_process; - preauth_client_tryagain_proc client_tryagain; - preauth_client_supply_gic_opts_proc client_supply_gic_opts; - preauth_client_request_init_proc client_req_init; - preauth_client_request_fini_proc client_req_fini; - /* The per-request context which the client_req_init() function - * might allocate, which we'll need to clean up later by - * calling the client_req_fini() function. */ - void *request_context; - /* A pointer to the request_context pointer. All modules within - * a plugin will point at the request_context of the first - * module within the plugin. */ - void **request_context_pp; - } *modules; -} krb5_preauth_context; +}; typedef struct _krb5_pa_enc_ts { krb5_timestamp patimestamp; @@ -1121,7 +1084,7 @@ krb5_do_preauth(krb5_context context, krb5_kdc_req *request, krb5_data *s2kparams, krb5_enctype *etype, krb5_keyblock *as_key, krb5_prompter_fct prompter, void *prompter_data, krb5_gic_get_as_key_fct gak_fct, - void *gak_data, krb5_preauth_client_rock *get_data_rock, + void *gak_data, krb5_clpreauth_rock preauth_rock, krb5_gic_opt_ext *opte); krb5_error_code KRB5_CALLCONV @@ -1134,7 +1097,7 @@ krb5_do_preauth_tryagain(krb5_context context, krb5_kdc_req *request, krb5_enctype *etype, krb5_keyblock *as_key, krb5_prompter_fct prompter, void *prompter_data, krb5_gic_get_as_key_fct gak_fct, void *gak_data, - krb5_preauth_client_rock *get_data_rock, + krb5_clpreauth_rock preauth_rock, krb5_gic_opt_ext *opte); void KRB5_CALLCONV krb5_init_preauth_context(krb5_context); @@ -1411,9 +1374,11 @@ struct plugin_interface { /* A list of plugin interface IDs. Make sure to increment * PLUGIN_NUM_INTERFACES when a new interface is added. */ -#define PLUGIN_INTERFACE_PWQUAL 0 -#define PLUGIN_INTERFACE_KADM5_HOOK 1 -#define PLUGIN_NUM_INTERFACES 2 +#define PLUGIN_INTERFACE_PWQUAL 0 +#define PLUGIN_INTERFACE_KADM5_HOOK 1 +#define PLUGIN_INTERFACE_CLPREAUTH 2 +#define PLUGIN_INTERFACE_KDCPREAUTH 3 +#define PLUGIN_NUM_INTERFACES 4 /* Retrieve the plugin module of type interface_id and name modname, * storing the result into module. */ @@ -1452,6 +1417,7 @@ k5_plugin_free_context(krb5_context context); struct _kdb5_dal_handle; /* private, in kdb5.h */ typedef struct _kdb5_dal_handle kdb5_dal_handle; struct _kdb_log_context; +typedef struct krb5_preauth_context_st krb5_preauth_context; struct _krb5_context { krb5_magic magic; krb5_enctype *in_tkt_etypes; @@ -1490,7 +1456,6 @@ struct _krb5_context { void (**locate_fptrs)(void); /* preauth module stuff */ - struct plugin_dir_handle preauth_plugins; krb5_preauth_context *preauth_context; /* error detail info */ diff --git a/src/include/krb5/preauth_plugin.h b/src/include/krb5/preauth_plugin.h index 21140cb45..2ddacdabb 100644 --- a/src/include/krb5/preauth_plugin.h +++ b/src/include/krb5/preauth_plugin.h @@ -1,7 +1,7 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * Copyright (c) 2006 Red Hat, Inc. - * Portions copyright (c) 2006 Massachusetts Institute of Technology + * Portions copyright (c) 2006, 2011 Massachusetts Institute of Technology * All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,20 +30,50 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Preauthentication plugin definitions for Kerberos 5 */ +/* + * Declarations for preauth plugin module implementors. + * + * This header defines two preauth interfaces, clpreauth and kdcpreauth. A + * shared object can implement both interfaces or it can implement just one. + * + * + * The clpreauth interface has a single supported major version, which is + * 1. Major version 1 has a current minor version of 1. clpreauth modules + * should define a function named clpreauth__initvt, matching + * the signature: + * + * krb5_error_code + * clpreauth_modname_initvt(krb5_context context, int maj_ver, + * int min_ver, krb5_plugin_vtable vtable); + * + * The kdcpreauth interface has a single supported major version, which is 1. + * Major version 1 has a current minor version of 1. kdcpreauth modules should + * define a function named kdcpreauth__initvt, matching the + * signature: + * + * krb5_error_code + * kdcpreauth_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * For both interfaces, the initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for the interface and maj_ver: + * clpreauth, maj_ver == 1: Cast to krb5_clpreauth_vtable + * kdcpreauth, maj_ver == 1: Cast to krb5_kdcpreauth_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ #ifndef KRB5_PREAUTH_PLUGIN_H_INCLUDED #define KRB5_PREAUTH_PLUGIN_H_INCLUDED #include - -/* - * 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; +#include /* * Preauth mechanism property flags, unified from previous definitions in the @@ -58,444 +88,390 @@ struct _krb5_preauth_client_rock; * REAL mechanism callbacks (client-only). */ #define PA_INFO 0x00000002 -/* Causes the KDC to include this mechanism in a list of supported preauth +/* + * 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). */ + * preauthentication (KDC-only). + */ #define PA_HARDWARE 0x00000004 -/* Causes the KDC to include this mechanism in a list of supported preauth +/* + * 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). */ + * flipside of PA_SUFFICIENT (KDC-only). + */ #define PA_REQUIRED 0x00000008 -/* Causes the KDC to include this mechanism in a list of supported preauth +/* + * 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). */ + * data. The flipside of PA_REQUIRED (KDC-only). + */ #define PA_SUFFICIENT 0x00000010 -/* Marks this preauthentication mechanism as one which changes the key which is +/* + * 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). */ + * flag have their server_return_fn called before modules which do not, and are + * passed over if a previously-called module has modified the encrypting key + * (KDC-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. */ +/* + * 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. - * - ***************************************************************************/ +/* + * clpreauth plugin interface definition. + */ + +/* Abstract type for a client request information handle. */ +typedef struct krb5_clpreauth_rock_st *krb5_clpreauth_rock; + +/* Abstract types for module data and per-request module data. */ +typedef struct krb5_clpreauth_moddata_st *krb5_clpreauth_moddata; +typedef struct krb5_clpreauth_modreq_st *krb5_clpreauth_modreq; /* - * 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. + * Provided by krb5: 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); +(*krb5_clpreauth_get_as_key_fn)(krb5_context context, + krb5_principal princ, + krb5_enctype enctype, + krb5_prompter_fct prompter, + 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. + * Provided by krb5: 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 expected to be used to encrypt the - * encrypted portion of the AS_REP packet. When handling a - * PREAUTH_REQUIRED error, this typically comes from etype-info2. - * When handling an AS reply, it is initialized from the AS reply itself.*/ - krb5plugin_preauth_client_get_etype = 1, - /* Free the data returned from krb5plugin_preauth_client_req_get_etype */ - krb5plugin_preauth_client_free_etype = 2, - /* The returned krb5_data contains the FAST armor key in a - * krb5_keyblock. Returns success with a NULL data item in the - * krb5_data if the client library supports FAST but is not using it.*/ - krb5plugin_preauth_client_fast_armor = 3, - /* Frees return from KRB5PLUGIN_PREAUTH_CLIENT_FAST_ARMOR. It is - * acceptable to set data to NULL and free the keyblock using - * krb5_free_keyblock; in that case, this frees the krb5_data - * only.*/ - krb5plugin_preauth_client_free_fast_armor = 4 +enum krb5_clpreauth_request_type { + /* + * The returned krb5_data item holds the enctype expected to be used to + * encrypt the encrypted portion of the AS_REP packet. When handling a + * PREAUTH_REQUIRED error, this typically comes from etype-info2. When + * handling an AS reply, it is initialized from the AS reply itself. + */ + krb5_clpreauth_get_etype = 1, + + /* Free the data returned from krb5plugin_clpreauth_req_get_etype */ + krb5_clpreauth_free_etype = 2, + + /* + * The returned krb5_data contains the FAST armor key in a krb5_keyblock. + * Returns success with a NULL data item in the krb5_data if the client + * library supports FAST but is not using it. + */ + krb5_clpreauth_fast_armor = 3, + + /* + * Frees return from KRB5PLUGIN_CLPREAUTH_FAST_ARMOR. It is + * acceptable to set data->data to NULL and free the keyblock using + * krb5_free_keyblock; in that case, this frees the krb5_data only. + */ + krb5_clpreauth_free_fast_armor = 4 }; 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 */ +(*krb5_clpreauth_get_data_fn)(krb5_context context, + krb5_clpreauth_rock rock, + krb5_int32 request_type, krb5_data **data); + +/* + * Optional: 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. These 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); +(*krb5_clpreauth_init_fn)(krb5_context context, + krb5_clpreauth_moddata *moddata_out); typedef void -(*preauth_client_plugin_fini_proc)(krb5_context context, - void *plugin_context); +(*krb5_clpreauth_fini_fn)(krb5_context context, + krb5_clpreauth_moddata moddata); -/* 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. */ +/* + * Mandatory: Return 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); +(*krb5_clpreauth_get_flags_fn)(krb5_context context, krb5_preauthtype pa_type); -/* Per-request initialization/cleanup. The request_init function is +/* + * Optional: 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. */ + * 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); +(*krb5_clpreauth_request_init_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq *modreq_out); 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. */ +(*krb5_clpreauth_request_fini_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq); + +/* + * Mandatory: process server-supplied data in pa_data and returns created data + * in out_pa_data. 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_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); +(*krb5_clpreauth_process_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, + krb5_clpreauth_get_data_fn get_data, + krb5_clpreauth_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, + krb5_clpreauth_get_as_key_fn 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. + * Optional: Attempt to use e-data in the error response to try to recover from + * the given error. If this function is provided, 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_supply_gic_opts_proc)(krb5_context context, - void *plugin_context, - krb5_get_init_creds_opt *opt, - const char *attr, - const char *value); +(*krb5_clpreauth_tryagain_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, + krb5_clpreauth_get_data_fn get_data, + krb5_clpreauth_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, + krb5_clpreauth_get_as_key_fn gak_fct, + void *gak_data, + krb5_data *salt, krb5_data *s2kparams, + krb5_keyblock *as_key, + krb5_pa_data ***out_pa_data); /* - * 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. + * Optional: receive krb5_get_init_creds_opt information. The attr and value + * information supplied should be copied into moddata by the module if it + * wishes to reference it after returning from this call. */ -typedef struct krb5plugin_preauth_client_ftable_v1 { - /* Not-usually-visible name. */ +typedef krb5_error_code +(*krb5_clpreauth_supply_gic_opts_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_get_init_creds_opt *opt, + const char *attr, const char *value); + +typedef struct krb5_clpreauth_vtable_st { + /* Mandatory: name of module. */ char *name; - /* Pointer to zero-terminated list of pa_types which this module can - * provide services for. */ + /* Mandatory: 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. */ + /* Optional: 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; + krb5_clpreauth_init_fn init; + krb5_clpreauth_fini_fn fini; + krb5_clpreauth_get_flags_fn flags; + krb5_clpreauth_request_init_fn request_init; + krb5_clpreauth_request_fini_fn request_fini; + krb5_clpreauth_process_fn process; + krb5_clpreauth_tryagain_fn tryagain; + krb5_clpreauth_supply_gic_opts_fn gic_opts; + /* Minor version 1 ends here. */ +} *krb5_clpreauth_vtable; - /* - * 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; +/* + * kdcpreauth plugin interface definition. + */ +/* While arguments of these types are passed in, they are opaque to kdcpreauth + * modules. */ +struct _krb5_db_entry_new; +struct _krb5_key_data; -/*************************************************************************** - * - * Server-side preauthentication plugin interface definition. - * - ***************************************************************************/ +/* Abstract type for module data and per-request module data. */ +typedef struct krb5_kdcpreauth_moddata_st *krb5_kdcpreauth_moddata; +typedef struct krb5_kdcpreauth_modreq_st *krb5_kdcpreauth_modreq; /* - * 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. + * Provided by krb5: a kdcpreauth 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 { +enum krb5_kdcpreauth_request_type { /* The returned krb5_data item holds a DER-encoded X.509 certificate. */ - krb5plugin_preauth_entry_request_certificate = 1, + krb5_kdcpreauth_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 + krb5_kdcpreauth_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. + */ + krb5_kdcpreauth_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, - /* The returned krb5_data contains a krb5_keyblock with the FAST - armor key. The data member is NULL if this method is not part - of a FAST tunnel */ - krb5plugin_preauth_fast_armor = 5, - /* Frees a fast armor key; it is acceptable to set data to NULL - and free the keyblock using krb5_free_keyblock; in that case, - this function simply frees the data*/ - krb5plugin_preauth_free_fast_armor = 6 + * what the client sent, so don't create any fatal errors if it doesn't + * match up. + */ + krb5_kdcpreauth_request_body = 4, + /* + * The returned krb5_data contains a krb5_keyblock with the FAST armor key. + * The data member is NULL if this method is not part of a FAST tunnel. + */ + krb5_kdcpreauth_fast_armor = 5, + /* + * Frees a fast armor key. It is acceptable to set data to NULL and free + * the keyblock using krb5_free_keyblock; in that case, this function + * simply frees the data. + */ + krb5_kdcpreauth_free_fast_armor = 6 }; - typedef krb5_error_code -(*preauth_get_entry_data_proc)(krb5_context, - krb5_kdc_req *, - struct _krb5_db_entry_new *, +(*krb5_kdcpreauth_get_data_fn)(krb5_context context, krb5_kdc_req *request, + struct _krb5_db_entry_new *entry, krb5_int32 request_type, krb5_data **); -/* Preauth plugin initialization function */ +/* Optional: preauth plugin initialization function. */ typedef krb5_error_code -(*preauth_server_init_proc)(krb5_context context, - void **plugin_context, - const char** realmnames); +(*krb5_kdcpreauth_init_fn)(krb5_context context, + krb5_kdcpreauth_moddata *moddata_out, + const char **realmnames); -/* Preauth plugin cleanup function */ +/* Optional: 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. */ +(*krb5_kdcpreauth_fini_fn)(krb5_context context, + krb5_kdcpreauth_moddata moddata); + +/* + * Optional: 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. */ +(*krb5_kdcpreauth_flags_fn)(krb5_context context, krb5_preauthtype patype); + +/* + * Optional: fill in pa_out->length and pa_out->contents with data to send to + * the client as part of the "you need to use preauthentication" error. If + * this function returns non-zero, the padata type will not be included in the + * list; if this function is not provided or returns zero without changing + * pa_out, the padata type will be included in the list with an empty value. + * This function 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); +(*krb5_kdcpreauth_edata_fn)(krb5_context context, krb5_kdc_req *request, + struct _krb5_db_entry_new *client, + struct _krb5_db_entry_new *server, + krb5_kdcpreauth_get_data_fn get_data, + krb5_kdcpreauth_moddata moddata, + krb5_pa_data *pa_out); -/* Verify preauthentication data sent by the client, setting the +/* + * Optional: 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. */ + * per-request module data for consumption by the return_fn or free_modreq_fn + * below. + */ typedef krb5_error_code -(*preauth_server_free_reqcontext_proc)(krb5_context, - void *pa_module_context, - void **request_pa_context); +(*krb5_kdcpreauth_verify_fn)(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, + krb5_kdcpreauth_get_data_fn get_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq *modreq_out, + krb5_data **e_data_out, + krb5_authdata ***authz_data_out); /* - * 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. + * Optional: 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. */ -typedef struct krb5plugin_preauth_server_ftable_v1 { - /* Not-usually-visible name. */ +typedef krb5_error_code +(*krb5_kdcpreauth_return_fn)(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_out, + krb5_kdcpreauth_get_data_fn, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq); + +/* Optional: free a per-request context. */ +typedef void +(*krb5_kdcpreauth_free_modreq_fn)(krb5_context, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq); + +typedef struct krb5_kdcpreauth_vtable_st { + /* Mandatory: name of module. */ char *name; - /* Pointer to zero-terminated list of pa_types which this module can - * provide services for. */ + /* Mandatory: 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; - + krb5_kdcpreauth_init_fn init; + krb5_kdcpreauth_fini_fn fini; + krb5_kdcpreauth_flags_fn flags; + krb5_kdcpreauth_edata_fn edata; + krb5_kdcpreauth_verify_fn verify; + krb5_kdcpreauth_return_fn return_padata; + krb5_kdcpreauth_free_modreq_fn free_modreq; +} *krb5_kdcpreauth_vtable; /* * This function allows a preauth plugin to obtain preauth @@ -503,7 +479,7 @@ typedef struct krb5plugin_preauth_server_ftable_v1 { * 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() + * obtained using krb5_get_init_creds_opt_alloc(). */ krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_get_pa(krb5_context context, diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index d4bef8933..87bccdb59 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -616,8 +616,7 @@ errout: /* fall through */ egress: - if (pa_context) - free_padata_context(kdc_context, &pa_context); + free_padata_context(kdc_context, pa_context); if (as_encrypting_key) krb5_free_keyblock(kdc_context, as_encrypting_key); if (errcode) diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index 8378e997d..d0a57b5fc 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -91,58 +91,45 @@ #include #include "../include/krb5/preauth_plugin.h" -#if TARGET_OS_MAC -static const char *objdirs[] = { KRB5_PLUGIN_BUNDLE_DIR, - LIBDIR "/krb5/plugins/preauth", - NULL }; /* should be a list */ -#else -static const char *objdirs[] = { LIBDIR "/krb5/plugins/preauth", NULL }; -#endif - -typedef struct _krb5_preauth_systems { +typedef struct preauth_system_st { const char *name; - int type; - int flags; - void *plugin_context; - preauth_server_init_proc init; - preauth_server_fini_proc fini; - preauth_server_edata_proc get_edata; - preauth_server_verify_proc verify_padata; - preauth_server_return_proc return_padata; - preauth_server_free_reqcontext_proc free_pa_reqctx; -} krb5_preauth_systems; + int type; + int flags; + krb5_kdcpreauth_moddata moddata; + krb5_kdcpreauth_init_fn init; + krb5_kdcpreauth_fini_fn fini; + krb5_kdcpreauth_edata_fn get_edata; + krb5_kdcpreauth_verify_fn verify_padata; + krb5_kdcpreauth_return_fn return_padata; + krb5_kdcpreauth_free_modreq_fn free_modreq; +} preauth_system; static krb5_error_code -verify_enc_timestamp (krb5_context, krb5_db_entry *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 get_entry_data, - void *pa_system_context, - void **pa_request_context, - krb5_data **e_data, - krb5_authdata ***authz_data); +verify_enc_timestamp(krb5_context, krb5_db_entry *client, krb5_data *req_pkt, + krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, + krb5_pa_data *data, + krb5_kdcpreauth_get_data_fn get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq *modreq_out, krb5_data **e_data, + krb5_authdata ***authz_data); static krb5_error_code -get_enc_ts(krb5_context, krb5_kdc_req *request, +get_enc_ts(krb5_context context, krb5_kdc_req *request, krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - krb5_pa_data *data); + krb5_kdcpreauth_get_data_fn get_entry_data, + krb5_kdcpreauth_moddata modata, krb5_pa_data *data); static krb5_error_code -get_etype_info(krb5_context, krb5_kdc_req *request, +get_etype_info(krb5_context context, krb5_kdc_req *request, krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - krb5_pa_data *data); + krb5_kdcpreauth_get_data_fn get_entry_data, + krb5_kdcpreauth_moddata moddata, krb5_pa_data *data); static krb5_error_code get_etype_info2(krb5_context context, krb5_kdc_req *request, krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - krb5_pa_data *pa_data); + krb5_kdcpreauth_get_data_fn get_entry_data, + krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data); static krb5_error_code etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, @@ -154,40 +141,31 @@ etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, int etype_info2); static krb5_error_code -return_etype_info(krb5_context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - void **pa_request_context); +return_etype_info(krb5_context, krb5_pa_data *padata, krb5_db_entry *client, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_kdc_rep *reply, krb5_key_data *client_key, + krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, + krb5_kdcpreauth_get_data_fn get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq); static krb5_error_code -return_etype_info2(krb5_context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - void **pa_request_context); +return_etype_info2(krb5_context, krb5_pa_data *padata, krb5_db_entry *client, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_kdc_rep *reply, krb5_key_data *client_key, + krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, + krb5_kdcpreauth_get_data_fn get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq); static krb5_error_code -return_pw_salt(krb5_context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, +return_pw_salt(krb5_context, krb5_pa_data *padata, krb5_db_entry *client, + krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - void **pa_request_context); + krb5_kdcpreauth_get_data_fn get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq); #if APPLE_PKINIT @@ -227,7 +205,7 @@ static krb5_error_code return_pkinit_response( void **pa_request_context); #endif /* APPLE_PKINIT */ -static krb5_preauth_systems static_preauth_systems[] = { +static preauth_system static_preauth_systems[] = { #if APPLE_PKINIT { "pkinit", @@ -239,7 +217,7 @@ static krb5_preauth_systems static_preauth_systems[] = { get_pkinit_edata, verify_pkinit_request, return_pkinit_response, - NULL /* free_pa_request_context */ + NULL /* free_modreq */ }, #endif /* APPLE_PKINIT */ { @@ -318,219 +296,168 @@ static krb5_preauth_systems static_preauth_systems[] = { return_server_referral }, #endif - { "[end]", -1,} }; -static krb5_preauth_systems *preauth_systems; -static int n_preauth_systems; -static struct plugin_dir_handle preauth_plugins; +#define NUM_STATIC_PREAUTH_SYSTEMS (sizeof(static_preauth_systems) / \ + sizeof(*static_preauth_systems)) -/* Open plugin directories for preauth modules. */ -static krb5_error_code -open_preauth_plugin_dirs(krb5_context ctx) +static preauth_system *preauth_systems; +static size_t n_preauth_systems; + +/* Get all available kdcpreauth vtables and a count of preauth types they + * support. Return an empty list on failure. */ +static void +get_plugin_vtables(krb5_context context, + struct krb5_kdcpreauth_vtable_st **vtables_out, + size_t *n_tables_out, size_t *n_systems_out) { - static const char *path[] = { - KRB5_CONF_LIBDEFAULTS, KRB5_CONF_PREAUTH_MODULE_DIR, NULL, - }; - char **profpath = NULL; - const char **dirs; - krb5_error_code ret; + krb5_plugin_initvt_fn *plugins = NULL, *pl; + struct krb5_kdcpreauth_vtable_st *vtables; + size_t count, n_tables, n_systems, i; + + *vtables_out = NULL; + *n_tables_out = *n_systems_out = 0; + + /* Auto-register pkinit and encrypted challenge if possible. */ + k5_plugin_register_dyn(context, PLUGIN_INTERFACE_KDCPREAUTH, "pkinit", + "preauth"); + k5_plugin_register_dyn(context, PLUGIN_INTERFACE_KDCPREAUTH, + "encrypted_challenge", "preauth"); - ret = profile_get_values(ctx->profile, path, &profpath); - if (ret != 0 && ret != PROF_NO_RELATION) - return ret; - dirs = (profpath != NULL) ? (const char **) profpath : objdirs; - ret = krb5int_open_plugin_dirs(dirs, NULL, &preauth_plugins, &ctx->err); - profile_free_list(profpath); - return ret; + if (k5_plugin_load_all(context, PLUGIN_INTERFACE_KDCPREAUTH, &plugins)) + return; + for (count = 0; plugins[count]; count++); + vtables = calloc(count + 1, sizeof(*vtables)); + if (vtables == NULL) + goto cleanup; + for (pl = plugins, n_tables = 0; *pl != NULL; pl++) { + if ((*pl)(context, 1, 1, (krb5_plugin_vtable)&vtables[n_tables]) == 0) + n_tables++; + } + for (i = 0, n_systems = 0; i < n_tables; i++) { + for (count = 0; vtables[i].pa_type_list[count] > 0; count++); + n_systems += count; + } + *vtables_out = vtables; + *n_tables_out = n_tables; + *n_systems_out = n_systems; + +cleanup: + k5_plugin_free_modules(context, plugins); } -krb5_error_code -load_preauth_plugins(krb5_context context) +/* Make a list of realm names. The caller should free the list container but + * not the list elements (which are aliases into kdc_realmlist). */ +static krb5_error_code +get_realm_names(const char ***list_out) { - void **preauth_plugins_ftables; - struct krb5plugin_preauth_server_ftable_v1 *ftable; - size_t module_count, i, j, k; - void *plugin_context; - preauth_server_init_proc server_init_proc = NULL; - char **kdc_realm_names = NULL; - - /* Attempt to load all of the preauth plugins we can find. */ - PLUGIN_DIR_INIT(&preauth_plugins); - if (PLUGIN_DIR_OPEN(&preauth_plugins) == 0) { - if (open_preauth_plugin_dirs(context) != 0) - return KRB5_PLUGIN_NO_HANDLE; - } - - /* Get the method tables provided by the loaded plugins. */ - preauth_plugins_ftables = NULL; - if (krb5int_get_plugin_dir_data(&preauth_plugins, - "preauthentication_server_1", - &preauth_plugins_ftables, &context->err) != 0) { - return KRB5_PLUGIN_NO_HANDLE; - } - - /* Count the valid modules. */ - module_count = sizeof(static_preauth_systems) - / sizeof(static_preauth_systems[0]); - if (preauth_plugins_ftables != NULL) { - for (i = 0; preauth_plugins_ftables[i] != NULL; i++) { - ftable = preauth_plugins_ftables[i]; - if ((ftable->flags_proc == NULL) && - (ftable->edata_proc == NULL) && - (ftable->verify_proc == NULL) && - (ftable->return_proc == NULL)) { - continue; - } - for (j = 0; - ftable->pa_type_list != NULL && - ftable->pa_type_list[j] > 0; - j++) { - module_count++; - } - } - } + const char **list; + int i; - /* Build the complete list of supported preauthentication options, and - * leave room for a terminator entry. */ - preauth_systems = malloc(sizeof(krb5_preauth_systems) * (module_count + 1)); - if (preauth_systems == NULL) { - krb5int_free_plugin_dir_data(preauth_plugins_ftables); + list = calloc(kdc_numrealms + 1, sizeof(*list)); + if (list == NULL) return ENOMEM; - } + for (i = 0; i < kdc_numrealms; i++) + list[i] = kdc_realmlist[i]->realm_name; + list[i] = NULL; + *list_out = list; + return 0; +} - /* Build a list of the names of the supported realms for this KDC. - * The list of names is terminated with a NULL. */ - kdc_realm_names = malloc(sizeof(char *) * (kdc_numrealms + 1)); - if (kdc_realm_names == NULL) { - krb5int_free_plugin_dir_data(preauth_plugins_ftables); - return ENOMEM; - } - for (i = 0; i < (size_t)kdc_numrealms; i++) { - kdc_realm_names[i] = kdc_realmlist[i]->realm_name; - } - kdc_realm_names[i] = NULL; +void +load_preauth_plugins(krb5_context context) +{ + krb5_error_code ret; + struct krb5_kdcpreauth_vtable_st *vtables = NULL, *vt; + size_t n_systems, n_tables, i, j; + krb5_kdcpreauth_moddata moddata; + const char **realm_names = NULL, *emsg; + preauth_system *sys; + + /* Get all available kdcpreauth vtables. */ + get_plugin_vtables(context, &vtables, &n_tables, &n_systems); + + /* Allocate the list of static and plugin preauth systems. */ + n_systems += NUM_STATIC_PREAUTH_SYSTEMS; + preauth_systems = calloc(n_systems + 1, sizeof(preauth_system)); + if (preauth_systems == NULL) + goto cleanup; - /* Add the locally-supplied mechanisms to the dynamic list first. */ - for (i = 0, k = 0; - i < sizeof(static_preauth_systems) / sizeof(static_preauth_systems[0]); - i++) { - if (static_preauth_systems[i].type == -1) - break; - preauth_systems[k] = static_preauth_systems[i]; - /* Try to initialize the preauth system. If it fails, we'll remove it - * from the list of systems we'll be using. */ - plugin_context = NULL; - server_init_proc = static_preauth_systems[i].init; - if ((server_init_proc != NULL) && - ((*server_init_proc)(context, &plugin_context, - (const char **)kdc_realm_names) != 0)) { - memset(&preauth_systems[k], 0, sizeof(preauth_systems[k])); - continue; - } - preauth_systems[k].plugin_context = plugin_context; - k++; - } - - /* Now add the dynamically-loaded mechanisms to the list. */ - if (preauth_plugins_ftables != NULL) { - for (i = 0; preauth_plugins_ftables[i] != NULL; i++) { - ftable = preauth_plugins_ftables[i]; - if ((ftable->flags_proc == NULL) && - (ftable->edata_proc == NULL) && - (ftable->verify_proc == NULL) && - (ftable->return_proc == NULL)) { + if (get_realm_names(&realm_names)) + goto cleanup; + + /* Add the static system to the list first. No static systems require + * initialization, so just make a direct copy. */ + memcpy(preauth_systems, static_preauth_systems, + sizeof(static_preauth_systems)); + + /* Add the dynamically-loaded mechanisms to the list. */ + n_systems = NUM_STATIC_PREAUTH_SYSTEMS; + for (i = 0; i < n_tables; i++) { + /* Try to initialize this module. */ + vt = &vtables[i]; + moddata = NULL; + if (vt->init) { + ret = vt->init(context, &moddata, realm_names); + if (ret) { + emsg = krb5_get_error_message(context, ret); + krb5_klog_syslog(LOG_ERR, _("preauth %s failed to " + "initialize: %s"), vt->name, emsg); + krb5_free_error_message(context, emsg); continue; } - plugin_context = NULL; - for (j = 0; - ftable->pa_type_list != NULL && - ftable->pa_type_list[j] > 0; - j++) { - /* Try to initialize the plugin. If it fails, we'll remove it - * from the list of modules we'll be using. */ - if (j == 0) { - server_init_proc = ftable->init_proc; - if (server_init_proc != NULL) { - krb5_error_code initerr; - initerr = (*server_init_proc)(context, &plugin_context, - (const char **)kdc_realm_names); - if (initerr) { - const char *emsg; - emsg = krb5_get_error_message(context, initerr); - krb5_klog_syslog(LOG_ERR, _("preauth %s failed to " - "initialize: %s"), - ftable->name, emsg); - krb5_free_error_message(context, emsg); - memset(&preauth_systems[k], 0, - sizeof(preauth_systems[k])); - - break; /* skip all modules in this plugin */ - } - } - } - preauth_systems[k].name = ftable->name; - preauth_systems[k].type = ftable->pa_type_list[j]; - if (ftable->flags_proc != NULL) - preauth_systems[k].flags = ftable->flags_proc(context, - preauth_systems[k].type); - else - preauth_systems[k].flags = 0; - preauth_systems[k].plugin_context = plugin_context; - preauth_systems[k].init = server_init_proc; - /* Only call fini once for each plugin */ - if (j == 0) - preauth_systems[k].fini = ftable->fini_proc; - else - preauth_systems[k].fini = NULL; - preauth_systems[k].get_edata = ftable->edata_proc; - preauth_systems[k].verify_padata = ftable->verify_proc; - preauth_systems[k].return_padata = ftable->return_proc; - preauth_systems[k].free_pa_reqctx = - ftable->freepa_reqcontext_proc; - k++; - } } - krb5int_free_plugin_dir_data(preauth_plugins_ftables); + /* Add this module to the systems list once for each pa type. */ + for (j = 0; vt->pa_type_list[j] > 0; j++) { + sys = &preauth_systems[n_systems]; + sys->name = vt->name; + sys->type = vt->pa_type_list[j]; + sys->flags = (vt->flags) ? vt->flags(context, sys->type) : 0; + sys->moddata = moddata; + sys->init = vt->init; + /* Only call fini once for each plugin. */ + sys->fini = (j == 0) ? vt->fini : NULL; + sys->get_edata = vt->edata; + sys->verify_padata = vt->verify; + sys->return_padata = vt->return_padata; + sys->free_modreq = vt->free_modreq; + n_systems++; + } } - free(kdc_realm_names); - n_preauth_systems = k; + n_preauth_systems = n_systems; /* Add the end-of-list marker. */ - preauth_systems[k].name = "[end]"; - preauth_systems[k].type = -1; - return 0; + preauth_systems[n_systems].name = "[end]"; + preauth_systems[n_systems].type = -1; + +cleanup: + free(vtables); + free(realm_names); } -krb5_error_code +void unload_preauth_plugins(krb5_context context) { - int i; - if (preauth_systems != NULL) { - for (i = 0; i < n_preauth_systems; i++) { - if (preauth_systems[i].fini != NULL) { - (*preauth_systems[i].fini)(context, - preauth_systems[i].plugin_context); - } - memset(&preauth_systems[i], 0, sizeof(preauth_systems[i])); - } - free(preauth_systems); - preauth_systems = NULL; - n_preauth_systems = 0; - krb5int_close_plugin_dirs(&preauth_plugins); + size_t i; + + for (i = 0; i < n_preauth_systems; i++) { + if (preauth_systems[i].fini) + preauth_systems[i].fini(context, preauth_systems[i].moddata); } - return 0; + free(preauth_systems); + preauth_systems = NULL; + n_preauth_systems = 0; } /* - * The make_padata_context() function creates a space for storing any context - * information which will be needed by return_padata() later. Each preauth - * type gets a context storage location of its own. + * The make_padata_context() function creates a space for storing any + * request-specific module data which will be needed by return_padata() later. + * Each preauth type gets a storage location of its own. */ struct request_pa_context { int n_contexts; struct { - krb5_preauth_systems *pa_system; - void *pa_context; + preauth_system *pa_system; + krb5_kdcpreauth_modreq modreq; } *contexts; }; @@ -556,7 +483,7 @@ make_padata_context(krb5_context context, void **padata_context) for (i = 0; i < ret->n_contexts; i++) { ret->contexts[i].pa_system = &preauth_systems[i]; - ret->contexts[i].pa_context = NULL; + ret->contexts[i].modreq = NULL; } *padata_context = ret; @@ -569,35 +496,25 @@ make_padata_context(krb5_context context, void **padata_context) * which the check_padata() function created but which weren't already cleaned * up by return_padata(). */ -krb5_error_code -free_padata_context(krb5_context kcontext, void **padata_context) +void +free_padata_context(krb5_context kcontext, void *padata_context) { - struct request_pa_context *context; - krb5_preauth_systems *preauth_system; - void **pctx, *mctx; + struct request_pa_context *context = padata_context; + preauth_system *sys; int i; - if (padata_context == NULL) - return 0; - - context = *padata_context; - + if (context == NULL) + return; for (i = 0; i < context->n_contexts; i++) { - if (context->contexts[i].pa_context != NULL) { - preauth_system = context->contexts[i].pa_system; - mctx = preauth_system->plugin_context; - if (preauth_system->free_pa_reqctx != NULL) { - pctx = &context->contexts[i].pa_context; - (*preauth_system->free_pa_reqctx)(kcontext, mctx, pctx); - } - context->contexts[i].pa_context = NULL; - } + sys = context->contexts[i].pa_system; + if (!sys->free_modreq || !context->contexts[i].modreq) + continue; + sys->free_modreq(kcontext, sys->moddata, context->contexts[i].modreq); + context->contexts[i].modreq = NULL; } free(context->contexts); free(context); - - return 0; } /* Retrieve a specified tl_data item from the given entry, and return its @@ -637,10 +554,8 @@ get_entry_tl_data(krb5_context context, krb5_db_entry *entry, * modules. */ static krb5_error_code -get_entry_data(krb5_context context, - krb5_kdc_req *request, krb5_db_entry *entry, - krb5_int32 type, - krb5_data **result) +get_entry_data(krb5_context context, krb5_kdc_req *request, + krb5_db_entry *entry, krb5_int32 type, krb5_data **result) { int i, k; krb5_data *ret; @@ -651,11 +566,11 @@ get_entry_data(krb5_context context, struct kdc_request_state *state = request->kdc_state; switch (type) { - case krb5plugin_preauth_entry_request_certificate: + case krb5_kdcpreauth_request_certificate: return get_entry_tl_data(context, entry, KRB5_TL_USER_CERTIFICATE, result); break; - case krb5plugin_preauth_entry_max_time_skew: + case krb5_kdcpreauth_max_time_skew: ret = malloc(sizeof(krb5_data)); if (ret == NULL) return ENOMEM; @@ -670,7 +585,7 @@ get_entry_data(krb5_context context, *result = ret; return 0; break; - case krb5plugin_preauth_keys: + case krb5_kdcpreauth_keys: ret = malloc(sizeof(krb5_data)); if (ret == NULL) return ENOMEM; @@ -705,7 +620,7 @@ get_entry_data(krb5_context context, free(ret); } break; - case krb5plugin_preauth_request_body: + case krb5_kdcpreauth_request_body: ret = NULL; encode_krb5_kdc_req_body(request, &ret); if (ret != NULL) { @@ -714,7 +629,7 @@ get_entry_data(krb5_context context, } return ASN1_PARSE_ERROR; break; - case krb5plugin_preauth_fast_armor: + case krb5_kdcpreauth_fast_armor: ret = calloc(1, sizeof(krb5_data)); if (ret == NULL) return ENOMEM; @@ -731,7 +646,7 @@ get_entry_data(krb5_context context, } free(ret); return error; - case krb5plugin_preauth_free_fast_armor: + case krb5_kdcpreauth_free_fast_armor: if ((*result)->data) { keys = (krb5_keyblock *) (*result)->data; krb5_free_keyblock(context, keys); @@ -745,9 +660,9 @@ get_entry_data(krb5_context context, } static krb5_error_code -find_pa_system(int type, krb5_preauth_systems **preauth) +find_pa_system(int type, preauth_system **preauth) { - krb5_preauth_systems *ap; + preauth_system *ap; ap = preauth_systems ? preauth_systems : static_preauth_systems; while ((ap->type != -1) && (ap->type != type)) @@ -758,21 +673,20 @@ find_pa_system(int type, krb5_preauth_systems **preauth) return 0; } +/* Find a pointer to the request-specific module data for pa_sys. */ static krb5_error_code -find_pa_context(krb5_preauth_systems *pa_sys, - struct request_pa_context *context, - void ***pa_context) +find_modreq(preauth_system *pa_sys, struct request_pa_context *context, + krb5_kdcpreauth_modreq **modreq_out) { int i; - *pa_context = 0; - + *modreq_out = NULL; if (context == NULL) return KRB5KRB_ERR_GENERIC; for (i = 0; i < context->n_contexts; i++) { if (context->contexts[i].pa_system == pa_sys) { - *pa_context = &context->contexts[i].pa_context; + *modreq_out = &context->contexts[i].modreq; return 0; } } @@ -797,7 +711,7 @@ pa_list_includes(krb5_pa_data **pa_data, krb5_preauthtype pa_type) static void sort_pa_order(krb5_context context, krb5_kdc_req *request, int *pa_order) { - int i, j, k, n_repliers, n_key_replacers; + size_t i, j, k, n_repliers, n_key_replacers; /* First, set up the default order. */ i = 0; @@ -909,7 +823,7 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_db_entry *client, krb5_db_entry *server, krb5_data *e_data) { int hw_only; - krb5_preauth_systems *ap; + preauth_system *ap; krb5_pa_data **pa_data, **pa; krb5_data *edat; krb5_error_code retval; @@ -937,8 +851,8 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_db_entry *client, (*pa)->magic = KV5M_PA_DATA; (*pa)->pa_type = ap->type; if (ap->get_edata) { - retval = (ap->get_edata)(kdc_context, request, client, server, - get_entry_data, ap->plugin_context, *pa); + retval = ap->get_edata(kdc_context, request, client, server, + get_entry_data, ap->moddata, *pa); if (retval) { /* just failed on this type, continue */ free(*pa); @@ -1033,8 +947,8 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, { krb5_error_code retval = 0; krb5_pa_data **padata; - krb5_preauth_systems *pa_sys; - void **pa_context; + preauth_system *pa_sys; + krb5_kdcpreauth_modreq *modreq_ptr; krb5_data *pa_e_data = NULL, *tmp_e_data = NULL; int pa_ok = 0, pa_found = 0; krb5_error_code saved_retval = 0; @@ -1058,7 +972,7 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, #endif if (find_pa_system((*padata)->pa_type, &pa_sys)) continue; - if (find_pa_context(pa_sys, *padata_context, &pa_context)) + if (find_modreq(pa_sys, *padata_context, &modreq_ptr)) continue; #ifdef DEBUG krb5_klog_syslog (LOG_DEBUG, ".. pa_type %s", pa_sys->name); @@ -1068,8 +982,9 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, pa_found++; retval = pa_sys->verify_padata(context, client, req_pkt, request, enc_tkt_reply, *padata, - get_entry_data, pa_sys->plugin_context, - pa_context, &tmp_e_data, &tmp_authz_data); + get_entry_data, pa_sys->moddata, + modreq_ptr, &tmp_e_data, + &tmp_authz_data); if (retval) { emsg = krb5_get_error_message (context, retval); krb5_klog_syslog (LOG_INFO, "preauth (%s) verify failure: %s", @@ -1211,11 +1126,11 @@ return_padata(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, krb5_pa_data ** send_pa; krb5_pa_data * pa = 0; krb5_pa_data null_item; - krb5_preauth_systems * ap; + preauth_system * ap; int * pa_order; int * pa_type; int size = 0; - void ** pa_context; + krb5_kdcpreauth_modreq *modreq_ptr; krb5_boolean key_modified; krb5_keyblock original_key; if ((!*padata_context) && @@ -1265,7 +1180,7 @@ return_padata(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, continue; if (ap->return_padata == 0) continue; - if (find_pa_context(ap, *padata_context, &pa_context)) + if (find_modreq(ap, *padata_context, &modreq_ptr)) continue; pa = &null_item; null_item.pa_type = ap->type; @@ -1280,8 +1195,8 @@ return_padata(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, if ((retval = ap->return_padata(context, pa, client, req_pkt, request, reply, client_key, encrypting_key, send_pa, - get_entry_data, ap->plugin_context, - pa_context))) { + get_entry_data, ap->moddata, + *modreq_ptr))) { goto cleanup; } @@ -1320,9 +1235,8 @@ request_contains_enctype(krb5_context context, const krb5_kdc_req *request, static krb5_error_code get_enc_ts(krb5_context context, krb5_kdc_req *request, krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data_proc, - void *pa_system_context, - krb5_pa_data *data) + krb5_kdcpreauth_get_data_fn get_entry_data_proc, + krb5_kdcpreauth_moddata moddata, krb5_pa_data *data) { struct kdc_request_state *state = request->kdc_state; if (state->armor_key) @@ -1333,12 +1247,11 @@ get_enc_ts(krb5_context context, krb5_kdc_req *request, static krb5_error_code verify_enc_timestamp(krb5_context context, krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, - krb5_pa_data *pa, - preauth_get_entry_data_proc ets_get_entry_data, - void *pa_system_context, - void **pa_request_context, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa, + krb5_kdcpreauth_get_data_fn ets_get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq *modreq_out, krb5_data **e_data, krb5_authdata ***authz_data) { @@ -1580,9 +1493,8 @@ cleanup: static krb5_error_code get_etype_info(krb5_context context, krb5_kdc_req *request, krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc etype_get_entry_data, - void *pa_system_context, - krb5_pa_data *pa_data) + krb5_kdcpreauth_get_data_fn etype_get_entry_data, + krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data) { int i; for (i=0; i < request->nktypes; i++) { @@ -1597,9 +1509,8 @@ get_etype_info(krb5_context context, krb5_kdc_req *request, static krb5_error_code get_etype_info2(krb5_context context, krb5_kdc_req *request, krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc etype_get_entry_data, - void *pa_system_context, - krb5_pa_data *pa_data) + krb5_kdcpreauth_get_data_fn etype_get_entry_data, + krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data) { return etype_info_helper( context, request, client, server, pa_data, 1); } @@ -1689,9 +1600,9 @@ return_etype_info2(krb5_context context, krb5_pa_data * padata, krb5_key_data *client_key, krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - preauth_get_entry_data_proc etype_get_entry_data, - void *pa_system_context, - void **pa_request_context) + krb5_kdcpreauth_get_data_fn etype_get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) { return etype_info_as_rep_helper(context, padata, client, request, reply, client_key, encrypting_key, send_pa, 1); @@ -1706,9 +1617,9 @@ return_etype_info(krb5_context context, krb5_pa_data * padata, krb5_key_data *client_key, krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - preauth_get_entry_data_proc etypeget_entry_data, - void *pa_system_context, - void **pa_request_context) + krb5_kdcpreauth_get_data_fn etypeget_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) { return etype_info_as_rep_helper(context, padata, client, request, reply, client_key, encrypting_key, send_pa, 0); @@ -1716,12 +1627,13 @@ return_etype_info(krb5_context context, krb5_pa_data * padata, static krb5_error_code return_pw_salt(krb5_context context, krb5_pa_data *in_padata, - krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request, - krb5_kdc_rep *reply, krb5_key_data *client_key, - krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - preauth_get_entry_data_proc etype_get_entry_data, - void *pa_system_context, - void **pa_request_context) + krb5_db_entry *client, krb5_data *req_pkt, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa, + krb5_kdcpreauth_get_data_fn etype_get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) { krb5_error_code retval; krb5_pa_data * padata; diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 2f85b0274..20e8ac46d 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -170,9 +170,9 @@ get_preauth_hint_list (krb5_kdc_req * request, krb5_db_entry *client, krb5_db_entry *server, krb5_data *e_data); -krb5_error_code +void load_preauth_plugins(krb5_context context); -krb5_error_code +void unload_preauth_plugins(krb5_context context); krb5_error_code @@ -189,8 +189,8 @@ return_padata (krb5_context context, krb5_db_entry *client, krb5_key_data *client_key, krb5_keyblock *encrypting_key, void **padata_context); -krb5_error_code -free_padata_context (krb5_context context, void **padata_context); +void +free_padata_context(krb5_context context, void *padata_context); krb5_pa_data * find_pa_data (krb5_pa_data **padata, krb5_preauthtype pa_type); diff --git a/src/lib/krb5/krb/copy_ctx.c b/src/lib/krb5/krb/copy_ctx.c index c52472119..9d2c3e491 100644 --- a/src/lib/krb5/krb/copy_ctx.c +++ b/src/lib/krb5/krb/copy_ctx.c @@ -79,9 +79,6 @@ krb5_copy_context(krb5_context ctx, krb5_context *nctx_out) nctx->prompt_types = NULL; nctx->os_context.default_ccname = NULL; - memset(&nctx->preauth_plugins, 0, sizeof(nctx->preauth_plugins)); - nctx->preauth_context = NULL; - memset(&nctx->libkrb5_plugins, 0, sizeof(nctx->libkrb5_plugins)); nctx->vtbl = NULL; nctx->locate_fptrs = NULL; diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index fc00e21d7..2968bd7ba 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -705,7 +705,7 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx, code = krb5int_fast_make_state(context, &ctx->fast_state); if (code != 0) goto cleanup; - ctx->get_data_rock.fast_state = ctx->fast_state; + ctx->preauth_rock.fast_state = ctx->fast_state; krb5_preauth_request_context_init(context); if (ctx->encoded_request_body) { krb5_free_data(context, ctx->encoded_request_body); @@ -837,8 +837,8 @@ krb5_init_creds_init(krb5_context context, opte = ctx->opte; - ctx->get_data_rock.magic = CLIENT_ROCK_MAGIC; - ctx->get_data_rock.etype = &ctx->etype; + ctx->preauth_rock.magic = CLIENT_ROCK_MAGIC; + ctx->preauth_rock.etype = &ctx->etype; /* Initialise request parameters as per krb5_get_init_creds() */ ctx->request->kdc_options = context->kdc_default_options; @@ -1116,7 +1116,7 @@ init_creds_step_request(krb5_context context, ctx->prompter_data, ctx->gak_fct, ctx->gak_data, - &ctx->get_data_rock, + &ctx->preauth_rock, ctx->opte); if (code != 0) goto cleanup; @@ -1141,7 +1141,7 @@ init_creds_step_request(krb5_context context, ctx->prompter_data, ctx->gak_fct, ctx->gak_data, - &ctx->get_data_rock, + &ctx->preauth_rock, ctx->opte); } else { /* No preauth supplied, so can't query the plugins. */ @@ -1373,7 +1373,7 @@ init_creds_step_reply(krb5_context context, ctx->prompter_data, ctx->gak_fct, ctx->gak_data, - &ctx->get_data_rock, + &ctx->preauth_rock, ctx->opte); if (code != 0) goto cleanup; diff --git a/src/lib/krb5/krb/gic_opt_set_pa.c b/src/lib/krb5/krb/gic_opt_set_pa.c index a60cc3b2f..1e79c4232 100644 --- a/src/lib/krb5/krb/gic_opt_set_pa.c +++ b/src/lib/krb5/krb/gic_opt_set_pa.c @@ -97,50 +97,3 @@ krb5_get_init_creds_opt_set_pa(krb5_context context, retval = krb5_preauth_supply_preauth_data(context, opte, attr, value); return retval; } - -/* - * Give all the preauth plugins a look at the preauth option which - * has just been set - */ -krb5_error_code -krb5_preauth_supply_preauth_data(krb5_context context, - krb5_gic_opt_ext *opte, - const char *attr, - const char *value) -{ - krb5_error_code retval = 0; - int i; - void *pctx; - const char *emsg = NULL; - - if (context->preauth_context == NULL) - krb5_init_preauth_context(context); - if (context->preauth_context == NULL) { - retval = EINVAL; - krb5int_set_error(&context->err, retval, - _("Unable to initialize preauth context")); - return retval; - } - - /* - * Go down the list of preauth modules, and supply them with the - * attribute/value pair. - */ - for (i = 0; i < context->preauth_context->n_modules; i++) { - if (context->preauth_context->modules[i].client_supply_gic_opts == NULL) - continue; - pctx = context->preauth_context->modules[i].plugin_context; - retval = (*context->preauth_context->modules[i].client_supply_gic_opts) - (context, pctx, - (krb5_get_init_creds_opt *)opte, attr, value); - if (retval) { - emsg = krb5_get_error_message(context, retval); - krb5int_set_error(&context->err, retval, - _("Preauth plugin %s: %s"), - context->preauth_context->modules[i].name, emsg); - krb5_free_error_message(context, emsg); - break; - } - } - return retval; -} diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h index 6a762982c..de43163d8 100644 --- a/src/lib/krb5/krb/init_creds_ctx.h +++ b/src/lib/krb5/krb/init_creds_ctx.h @@ -29,7 +29,7 @@ struct _krb5_init_creds_context { krb5_data s2kparams; krb5_keyblock as_key; krb5_enctype etype; - krb5_preauth_client_rock get_data_rock; + struct krb5_clpreauth_rock_st preauth_rock; krb5_boolean enc_pa_rep_permitted; krb5_boolean have_restarted; krb5_boolean sent_nontrivial_preauth; diff --git a/src/lib/krb5/krb/plugin.c b/src/lib/krb5/krb/plugin.c index a9d6b06a7..6f164e0a6 100644 --- a/src/lib/krb5/krb/plugin.c +++ b/src/lib/krb5/krb/plugin.c @@ -28,7 +28,9 @@ const char *interface_names[PLUGIN_NUM_INTERFACES] = { "pwqual", - "kadm5_hook" + "kadm5_hook", + "clpreauth", + "kdcpreauth" }; /* Return the context's interface structure for id, or NULL if invalid. */ diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index 82b422eac..ef866b1a2 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -44,13 +44,41 @@ #include #endif -#if TARGET_OS_MAC -static const char *objdirs[] = { KRB5_PLUGIN_BUNDLE_DIR, - LIBDIR "/krb5/plugins/preauth", - NULL }; -#else -static const char *objdirs[] = { LIBDIR "/krb5/plugins/preauth", NULL }; -#endif +/* This structure lets us keep track of all of the modules which are loaded, + * turning the list of modules and their lists of implemented preauth types + * into a single list which we can walk easily. */ +struct krb5_preauth_context_st { + int n_modules; + struct krb5_preauth_context_module_st { + /* Which of the possibly more than one preauth types which the + * module supports we're using at this point in the list. */ + krb5_preauthtype pa_type; + /* Encryption types which the client claims to support -- we + * copy them directly into the krb5_kdc_req structure during + * krb5_preauth_prepare_request(). */ + krb5_enctype *enctypes; + /* The plugin's module data and a function to clear it. */ + krb5_clpreauth_moddata moddata; + krb5_clpreauth_fini_fn client_fini; + /* The module's table, and some of its members, copied here for + * convenience when we populated the list. */ + const char *name; + int flags, use_count; + krb5_clpreauth_process_fn client_process; + krb5_clpreauth_tryagain_fn client_tryagain; + krb5_clpreauth_supply_gic_opts_fn client_supply_gic_opts; + krb5_clpreauth_request_init_fn client_req_init; + krb5_clpreauth_request_fini_fn client_req_fini; + /* The per-request context which the client_req_init() function + * might allocate, which we'll need to clean up later by + * calling the client_req_fini() function. */ + krb5_clpreauth_modreq modreq; + /* A pointer to the request_context pointer. All modules within + * a plugin will point at the request_context of the first + * module within the plugin. */ + krb5_clpreauth_modreq *modreq_p; + } *modules; +}; typedef krb5_error_code (*pa_function)(krb5_context, krb5_kdc_req *request, @@ -70,27 +98,6 @@ typedef struct _pa_types_t { int flags; } pa_types_t; -/* Open plugin directories for preauth modules. */ -static krb5_error_code -open_preauth_plugin_dirs(krb5_context ctx) -{ - static const char *path[] = { - KRB5_CONF_LIBDEFAULTS, KRB5_CONF_PREAUTH_MODULE_DIR, NULL, - }; - char **profpath = NULL; - const char **dirs; - krb5_error_code ret; - - ret = profile_get_values(ctx->profile, path, &profpath); - if (ret != 0 && ret != PROF_NO_RELATION) - return ret; - dirs = (profpath != NULL) ? (const char **) profpath : objdirs; - ret = krb5int_open_plugin_dirs(dirs, NULL, &ctx->preauth_plugins, - &ctx->err); - profile_free_list(profpath); - return ret; -} - /* Create the per-krb5_context context. This means loading the modules * if we haven't done that yet (applications which never obtain initial * credentials should never hit this routine), breaking up the module's @@ -99,101 +106,88 @@ open_preauth_plugin_dirs(krb5_context ctx) void KRB5_CALLCONV krb5_init_preauth_context(krb5_context kcontext) { - int n_modules, n_tables, i, j, k; - void **tables; - struct krb5plugin_preauth_client_ftable_v1 *table; + int n_tables, n_modules, i, count; + krb5_plugin_initvt_fn *plugins = NULL, *pl; + struct krb5_clpreauth_vtable_st *vtables = NULL, *vt; + struct krb5_preauth_context_module_st *mod; krb5_preauth_context *context = NULL; - void *plugin_context; - krb5_preauthtype pa_type; - void **rcpp; + krb5_clpreauth_moddata moddata; + krb5_preauthtype pa_type, *pat; + krb5_boolean first; + krb5_clpreauth_modreq *rcpp; /* Only do this once for each krb5_context */ if (kcontext->preauth_context != NULL) return; - /* load the plugins for the current context */ - if (PLUGIN_DIR_OPEN(&kcontext->preauth_plugins) == 0) { - if (open_preauth_plugin_dirs(kcontext) != 0) - return; - } + /* Auto-register pkinit and encrypted challenge if possible. */ + k5_plugin_register_dyn(kcontext, PLUGIN_INTERFACE_CLPREAUTH, "pkinit", + "preauth"); + k5_plugin_register_dyn(kcontext, PLUGIN_INTERFACE_CLPREAUTH, + "encrypted_challenge", "preauth"); - /* pull out the module function tables for all of the modules */ - tables = NULL; - if (krb5int_get_plugin_dir_data(&kcontext->preauth_plugins, - "preauthentication_client_1", - &tables, - &kcontext->err) != 0) { - return; - } - if (tables == NULL) { + /* Get all available clpreauth vtables. */ + if (k5_plugin_load_all(kcontext, PLUGIN_INTERFACE_CLPREAUTH, &plugins)) return; + for (count = 0; plugins[count] != NULL; count++); + vtables = calloc(count, sizeof(*vtables)); + if (vtables == NULL) + goto cleanup; + for (pl = plugins, n_tables = 0; *pl != NULL; pl++) { + if ((*pl)(kcontext, 1, 1, (krb5_plugin_vtable)&vtables[n_tables]) == 0) + n_tables++; } - /* count how many modules we ended up loading, and how many preauth - * types we may claim to support as a result */ + /* Count how many modules we ended up loading, and how many preauth + * types we may claim to support as a result. */ n_modules = 0; - for (n_tables = 0; - (tables != NULL) && (tables[n_tables] != NULL); - n_tables++) { - table = tables[n_tables]; - if ((table->pa_type_list != NULL) && (table->process != NULL)) { - for (j = 0; table->pa_type_list[j] > 0; j++) { - n_modules++; - } - } + for (i = 0; i < n_tables; i++) { + for (count = 0; vtables[i].pa_type_list[count] > 0; count++); + n_modules += count; } - /* allocate the space we need */ + /* Allocate the space we need. */ context = malloc(sizeof(*context)); - if (context == NULL) { - krb5int_free_plugin_dir_data(tables); - return; - } - context->modules = calloc(n_modules, sizeof(context->modules[0])); - if (context->modules == NULL) { - krb5int_free_plugin_dir_data(tables); - free(context); - return; - } - context->n_modules = n_modules; + if (context == NULL) + goto cleanup; + context->modules = calloc(n_modules, sizeof(*context->modules)); + if (context->modules == NULL) + goto cleanup; /* fill in the structure */ - k = 0; + n_modules = 0; for (i = 0; i < n_tables; i++) { - table = tables[i]; - if ((table->pa_type_list != NULL) && (table->process != NULL)) { - plugin_context = NULL; - if ((table->init != NULL) && - ((*table->init)(kcontext, &plugin_context) != 0)) { + vt = &vtables[i]; + if ((vt->pa_type_list != NULL) && (vt->process != NULL)) { + moddata = NULL; + if (vt->init != NULL && vt->init(kcontext, &moddata) != 0) { #ifdef DEBUG - fprintf (stderr, "init err, skipping module \"%s\"\n", - table->name); + fprintf(stderr, "init err, skipping module \"%s\"\n", + vt->name); #endif continue; } rcpp = NULL; - for (j = 0; table->pa_type_list[j] > 0; j++) { - pa_type = table->pa_type_list[j]; - context->modules[k].pa_type = pa_type; - context->modules[k].enctypes = table->enctype_list; - context->modules[k].plugin_context = plugin_context; + for (pat = vt->pa_type_list, first = TRUE; *pat > 0; + pat++, first = FALSE) { + pa_type = *pat; + mod = &context->modules[n_modules]; + mod->pa_type = pa_type; + mod->enctypes = vt->enctype_list; + mod->moddata = moddata; /* Only call client_fini once per plugin */ - if (j == 0) - context->modules[k].client_fini = table->fini; - else - context->modules[k].client_fini = NULL; - context->modules[k].ftable = table; - context->modules[k].name = table->name; - context->modules[k].flags = (*table->flags)(kcontext, pa_type); - context->modules[k].use_count = 0; - context->modules[k].client_process = table->process; - context->modules[k].client_tryagain = table->tryagain; - if (j == 0) - context->modules[k].client_supply_gic_opts = table->gic_opts; + if (first) + mod->client_fini = vt->fini; else - context->modules[k].client_supply_gic_opts = NULL; - context->modules[k].request_context = NULL; + mod->client_fini = NULL; + mod->name = vt->name; + mod->flags = (*vt->flags)(kcontext, pa_type); + mod->use_count = 0; + mod->client_process = vt->process; + mod->client_tryagain = vt->tryagain; + mod->client_supply_gic_opts = first ? vt->gic_opts : NULL; + mod->modreq = NULL; /* * Only call request_init and request_fini once per plugin. * Only the first module within each plugin will ever @@ -202,29 +196,35 @@ krb5_init_preauth_context(krb5_context kcontext) * to that entry's request_context. That way all the * modules within the plugin share the same request_context */ - if (j == 0) { - context->modules[k].client_req_init = table->request_init; - context->modules[k].client_req_fini = table->request_fini; - rcpp = &context->modules[k].request_context; + if (first) { + mod->client_req_init = vt->request_init; + mod->client_req_fini = vt->request_fini; + rcpp = &mod->modreq; } else { - context->modules[k].client_req_init = NULL; - context->modules[k].client_req_fini = NULL; + mod->client_req_init = NULL; + mod->client_req_fini = NULL; } - context->modules[k].request_context_pp = rcpp; + mod->modreq_p = rcpp; #ifdef DEBUG - fprintf (stderr, "init module \"%s\", pa_type %d, flag %d\n", - context->modules[k].name, - context->modules[k].pa_type, - context->modules[k].flags); + fprintf(stderr, "init module \"%s\", pa_type %d, flag %d\n", + mod->name, mod->pa_type, mod->flags); #endif - k++; + n_modules++; } } } - krb5int_free_plugin_dir_data(tables); + context->n_modules = n_modules; - /* return the result */ + /* Place the constructed preauth context into the krb5 context. */ kcontext->preauth_context = context; + context = NULL; + +cleanup: + if (context) + free(context->modules); + free(context); + k5_plugin_free_modules(kcontext, plugins); + free(vtables); } /* Zero the use counts for the modules herein. Usually used before we @@ -249,23 +249,19 @@ void KRB5_CALLCONV krb5_free_preauth_context(krb5_context context) { int i; - void *pctx; - if (context && context->preauth_context != NULL) { - for (i = 0; i < context->preauth_context->n_modules; i++) { - pctx = context->preauth_context->modules[i].plugin_context; - if (context->preauth_context->modules[i].client_fini != NULL) { - (*context->preauth_context->modules[i].client_fini)(context, pctx); - } - memset(&context->preauth_context->modules[i], 0, - sizeof(context->preauth_context->modules[i])); - } - if (context->preauth_context->modules != NULL) { - free(context->preauth_context->modules); - context->preauth_context->modules = NULL; - } - free(context->preauth_context); - context->preauth_context = NULL; - } + struct krb5_preauth_context_module_st *mod; + + if (context == NULL || context->preauth_context == NULL) + return; + for (i = 0; i < context->preauth_context->n_modules; i++) { + mod = &context->preauth_context->modules[i]; + if (mod->client_fini != NULL) + mod->client_fini(context, mod->moddata); + zap(mod, sizeof(*mod)); + } + free(context->preauth_context->modules); + free(context->preauth_context); + context->preauth_context = NULL; } /* Initialize the per-AS-REQ context. This means calling the client_req_init @@ -274,19 +270,16 @@ void KRB5_CALLCONV krb5_preauth_request_context_init(krb5_context context) { int i; - void *rctx, *pctx; + struct krb5_preauth_context_module_st *mod; - /* Limit this to only one attempt per context? */ if (context->preauth_context == NULL) krb5_init_preauth_context(context); - if (context->preauth_context != NULL) { - for (i = 0; i < context->preauth_context->n_modules; i++) { - pctx = context->preauth_context->modules[i].plugin_context; - if (context->preauth_context->modules[i].client_req_init != NULL) { - rctx = context->preauth_context->modules[i].request_context_pp; - (*context->preauth_context->modules[i].client_req_init) (context, pctx, rctx); - } - } + if (context->preauth_context == NULL) + return; + for (i = 0; i < context->preauth_context->n_modules; i++) { + mod = &context->preauth_context->modules[i]; + if (mod->client_req_init != NULL) + mod->client_req_init(context, mod->moddata, mod->modreq_p); } } @@ -296,17 +289,16 @@ void KRB5_CALLCONV krb5_preauth_request_context_fini(krb5_context context) { int i; - void *rctx, *pctx; - if (context->preauth_context != NULL) { - for (i = 0; i < context->preauth_context->n_modules; i++) { - pctx = context->preauth_context->modules[i].plugin_context; - rctx = context->preauth_context->modules[i].request_context; - if (rctx != NULL) { - if (context->preauth_context->modules[i].client_req_fini != NULL) { - (*context->preauth_context->modules[i].client_req_fini)(context, pctx, rctx); - } - context->preauth_context->modules[i].request_context = NULL; - } + struct krb5_preauth_context_module_st *mod; + + if (context->preauth_context == NULL) + return; + for (i = 0; i < context->preauth_context->n_modules; i++) { + mod = &context->preauth_context->modules[i]; + if (mod->modreq != NULL) { + if (mod->client_req_fini != NULL) + mod->client_req_fini(context, mod->moddata, mod->modreq); + mod->modreq = NULL; } } } @@ -390,10 +382,8 @@ grow_pa_list(krb5_pa_data ***out_pa_list, int *out_pa_list_size, */ static krb5_error_code -client_data_proc(krb5_context kcontext, - krb5_preauth_client_rock *rock, - krb5_int32 request_type, - krb5_data **retdata) +client_data_proc(krb5_context kcontext, krb5_clpreauth_rock rock, + krb5_int32 request_type, krb5_data **retdata) { krb5_data *ret; krb5_error_code retval; @@ -405,7 +395,7 @@ client_data_proc(krb5_context kcontext, return EINVAL; switch (request_type) { - case krb5plugin_preauth_client_get_etype: + case krb5_clpreauth_get_etype: { krb5_enctype *eptr; ret = malloc(sizeof(krb5_data)); @@ -424,7 +414,7 @@ client_data_proc(krb5_context kcontext, return 0; } break; - case krb5plugin_preauth_client_free_etype: + case krb5_clpreauth_free_etype: ret = *retdata; if (ret == NULL) return 0; @@ -433,7 +423,7 @@ client_data_proc(krb5_context kcontext, free(ret); return 0; break; - case krb5plugin_preauth_client_fast_armor: { + case krb5_clpreauth_fast_armor: { krb5_keyblock *key = NULL; ret = calloc(1, sizeof(krb5_data)); if (ret == NULL) @@ -455,7 +445,7 @@ client_data_proc(krb5_context kcontext, free(ret); return retval; } - case krb5plugin_preauth_client_free_fast_armor: + case krb5_clpreauth_free_fast_armor: ret = *retdata; if (ret) { if (ret->data) @@ -508,11 +498,11 @@ run_preauth_plugins(krb5_context kcontext, krb5_pa_data *in_padata, krb5_prompter_fct prompter, void *prompter_data, - preauth_get_as_key_proc gak_fct, + krb5_clpreauth_get_as_key_fn gak_fct, krb5_data *salt, krb5_data *s2kparams, void *gak_data, - krb5_preauth_client_rock *get_data_rock, + krb5_clpreauth_rock preauth_rock, krb5_keyblock *as_key, krb5_pa_data ***out_pa_list, int *out_pa_list_size, @@ -523,7 +513,7 @@ run_preauth_plugins(krb5_context kcontext, int i; krb5_pa_data **out_pa_data; krb5_error_code ret; - struct _krb5_preauth_context_module *module; + struct krb5_preauth_context_module_st *module; if (kcontext->preauth_context == NULL) { return ENOENT; @@ -551,19 +541,14 @@ run_preauth_plugins(krb5_context kcontext, fprintf(stderr, "using module \"%s\" (%d), flags = %d\n", module->name, module->pa_type, module->flags); #endif - ret = module->client_process(kcontext, - module->plugin_context, - *module->request_context_pp, + ret = module->client_process(kcontext, module->moddata, + *module->modreq_p, (krb5_get_init_creds_opt *)opte, - client_data_proc, - get_data_rock, - request, - encoded_request_body, - encoded_previous_request, - in_padata, - prompter, prompter_data, - gak_fct, gak_data, salt, s2kparams, - as_key, + client_data_proc, preauth_rock, + request, encoded_request_body, + encoded_previous_request, in_padata, + prompter, prompter_data, gak_fct, + gak_data, salt, s2kparams, as_key, &out_pa_data); TRACE_PREAUTH_PROCESS(kcontext, module->name, module->pa_type, module->flags, ret); @@ -1517,13 +1502,13 @@ krb5_do_preauth_tryagain(krb5_context kcontext, krb5_keyblock *as_key, krb5_prompter_fct prompter, void *prompter_data, krb5_gic_get_as_key_fct gak_fct, void *gak_data, - krb5_preauth_client_rock *get_data_rock, + krb5_clpreauth_rock preauth_rock, krb5_gic_opt_ext *opte) { krb5_error_code ret; krb5_pa_data **out_padata; krb5_preauth_context *context; - struct _krb5_preauth_context_module *module; + struct krb5_preauth_context_module_st *module; int i, j; int out_pa_list_size = 0; @@ -1548,12 +1533,11 @@ krb5_do_preauth_tryagain(krb5_context kcontext, if (module->client_tryagain == NULL) { continue; } - if ((*module->client_tryagain)(kcontext, - module->plugin_context, - *module->request_context_pp, + if ((*module->client_tryagain)(kcontext, module->moddata, + *module->modreq_p, (krb5_get_init_creds_opt *)opte, client_data_proc, - get_data_rock, + preauth_rock, request, encoded_request_body, encoded_previous_request, @@ -1589,8 +1573,7 @@ krb5_do_preauth(krb5_context context, krb5_keyblock *as_key, krb5_prompter_fct prompter, void *prompter_data, krb5_gic_get_as_key_fct gak_fct, void *gak_data, - krb5_preauth_client_rock *get_data_rock, - krb5_gic_opt_ext *opte) + krb5_clpreauth_rock preauth_rock, krb5_gic_opt_ext *opte) { unsigned int h; int i, j, out_pa_list_size; @@ -1769,7 +1752,7 @@ krb5_do_preauth(krb5_context context, gak_fct, salt, s2kparams, gak_data, - get_data_rock, + preauth_rock, as_key, &out_pa_list, &out_pa_list_size, @@ -1803,3 +1786,47 @@ cleanup: krb5_free_etype_info(context, etype_info); return (ret); } + +/* + * Give all the preauth plugins a look at the preauth option which + * has just been set + */ +krb5_error_code +krb5_preauth_supply_preauth_data(krb5_context context, krb5_gic_opt_ext *opte, + const char *attr, const char *value) +{ + krb5_error_code retval = 0; + int i; + struct krb5_preauth_context_module_st *mod; + const char *emsg = NULL; + + if (context->preauth_context == NULL) + krb5_init_preauth_context(context); + if (context->preauth_context == NULL) { + retval = EINVAL; + krb5_set_error_message(context, retval, + _("Unable to initialize preauth context")); + return retval; + } + + /* + * Go down the list of preauth modules, and supply them with the + * attribute/value pair. + */ + for (i = 0; i < context->preauth_context->n_modules; i++) { + mod = &context->preauth_context->modules[i]; + if (mod->client_supply_gic_opts == NULL) + continue; + retval = mod->client_supply_gic_opts(context, mod->moddata, + (krb5_get_init_creds_opt *)opte, + attr, value); + if (retval) { + emsg = krb5_get_error_message(context, retval); + krb5_set_error_message(context, retval, _("Preauth plugin %s: %s"), + mod->name, emsg); + krb5_free_error_message(context, emsg); + break; + } + } + return retval; +} diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index b531b70b5..edc4b1fc5 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -114,6 +114,7 @@ k5_plugin_free_modules k5_plugin_load k5_plugin_load_all k5_plugin_register +k5_plugin_register_dyn krb524_convert_creds_kdc krb524_init_ets krb5_425_conv_principal diff --git a/src/lib/krb5/os/init_os_ctx.c b/src/lib/krb5/os/init_os_ctx.c index 6cb9b1680..9387cf872 100644 --- a/src/lib/krb5/os/init_os_ctx.c +++ b/src/lib/krb5/os/init_os_ctx.c @@ -376,7 +376,6 @@ krb5_os_init_context(krb5_context ctx, krb5_boolean kdc) ctx->vtbl = 0; PLUGIN_DIR_INIT(&ctx->libkrb5_plugins); - PLUGIN_DIR_INIT(&ctx->preauth_plugins); ctx->preauth_context = NULL; retval = os_init_paths(ctx, kdc); @@ -477,7 +476,6 @@ krb5_os_free_context(krb5_context ctx) krb5_free_preauth_context(ctx); ctx->preauth_context = NULL; } - krb5int_close_plugin_dirs (&ctx->preauth_plugins); krb5int_close_plugin_dirs (&ctx->libkrb5_plugins); #ifdef _WIN32 diff --git a/src/plugins/preauth/cksum_body/cksum_body.exports b/src/plugins/preauth/cksum_body/cksum_body.exports index 98e96c399..df335ca64 100644 --- a/src/plugins/preauth/cksum_body/cksum_body.exports +++ b/src/plugins/preauth/cksum_body/cksum_body.exports @@ -1,2 +1,2 @@ -preauthentication_client_1 -preauthentication_server_1 +clpreauth_cksum_body_initvt +kdcpreauth_cksum_body_initvt diff --git a/src/plugins/preauth/cksum_body/cksum_body_main.c b/src/plugins/preauth/cksum_body/cksum_body_main.c index 2759045b0..e79b84a12 100644 --- a/src/plugins/preauth/cksum_body/cksum_body_main.c +++ b/src/plugins/preauth/cksum_body/cksum_body_main.c @@ -80,18 +80,18 @@ client_get_flags(krb5_context kcontext, krb5_preauthtype pa_type) static krb5_error_code client_process(krb5_context kcontext, - void *client_plugin_context, - void *client_request_context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, - preauth_get_client_data_proc client_get_data_proc, - struct _krb5_preauth_client_rock *rock, + krb5_clpreauth_get_data_fn client_get_data_proc, + krb5_clpreauth_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, + krb5_clpreauth_get_as_key_fn gak_fct, void *gak_data, krb5_data *salt, krb5_data *s2kparams, krb5_keyblock *as_key, @@ -229,7 +229,7 @@ client_process(krb5_context kcontext, static krb5_error_code client_gic_opt(krb5_context kcontext, - void *plugin_context, + krb5_clpreauth_moddata moddata, krb5_get_init_creds_opt *opt, const char *attr, const char *value) @@ -243,7 +243,8 @@ client_gic_opt(krb5_context kcontext, /* Initialize and tear down the server-side module, and do stat tracking. */ static krb5_error_code -server_init(krb5_context kcontext, void **module_context, const char **realmnames) +server_init(krb5_context kcontext, krb5_kdcpreauth_moddata *moddata_out, + const char **realmnames) { struct server_stats *stats; stats = malloc(sizeof(struct server_stats)); @@ -251,14 +252,14 @@ server_init(krb5_context kcontext, void **module_context, const char **realmname return ENOMEM; stats->successes = 0; stats->failures = 0; - *module_context = stats; + *moddata_out = (krb5_kdcpreauth_moddata)stats; return 0; } static void -server_fini(krb5_context kcontext, void *module_context) +server_fini(krb5_context kcontext, krb5_kdcpreauth_moddata moddata) { struct server_stats *stats; - stats = module_context; + stats = (struct server_stats *)moddata; if (stats != NULL) { #ifdef DEBUG fprintf(stderr, "Total: %d clients failed, %d succeeded.\n", @@ -275,8 +276,8 @@ server_get_edata(krb5_context kcontext, krb5_kdc_req *request, struct _krb5_db_entry_new *client, struct _krb5_db_entry_new *server, - preauth_get_entry_data_proc server_get_entry_data, - void *pa_module_context, + krb5_kdcpreauth_get_data_fn server_get_entry_data, + krb5_kdcpreauth_moddata moddata, krb5_pa_data *data) { krb5_data *key_data; @@ -287,7 +288,7 @@ server_get_edata(krb5_context kcontext, /* Retrieve the client's keys. */ key_data = NULL; if ((*server_get_entry_data)(kcontext, request, client, - krb5plugin_preauth_keys, &key_data) != 0) { + krb5_kdcpreauth_keys, &key_data) != 0) { #ifdef DEBUG fprintf(stderr, "Error retrieving client keys.\n"); #endif @@ -335,9 +336,9 @@ server_verify(krb5_context kcontext, krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, - preauth_get_entry_data_proc server_get_entry_data, - void *pa_module_context, - void **pa_request_context, + krb5_kdcpreauth_get_data_fn server_get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq *modreq_out, krb5_data **e_data, krb5_authdata ***authz_data) { @@ -356,7 +357,7 @@ server_verify(krb5_context kcontext, test_svr_req_ctx *svr_req_ctx; krb5_authdata **my_authz_data = NULL; - stats = pa_module_context; + stats = (struct server_stats *)moddata; #ifdef DEBUG fprintf(stderr, "cksum_body: server_verify\n"); @@ -392,7 +393,7 @@ server_verify(krb5_context kcontext, /* Pull up the client's keys. */ key_data = NULL; if ((*server_get_entry_data)(kcontext, request, client, - krb5plugin_preauth_keys, &key_data) != 0) { + krb5_kdcpreauth_keys, &key_data) != 0) { #ifdef DEBUG fprintf(stderr, "Error retrieving client keys.\n"); #endif @@ -449,7 +450,7 @@ server_verify(krb5_context kcontext, * will probably work if it's us on both ends, though. */ req_body = NULL; if ((*server_get_entry_data)(kcontext, request, client, - krb5plugin_preauth_request_body, + krb5_kdcpreauth_request_body, &req_body) != 0) { krb5_free_keyblock(kcontext, key); stats->failures++; @@ -572,7 +573,7 @@ server_verify(krb5_context kcontext, svr_req_ctx); #endif } - *pa_request_context = svr_req_ctx; + *modreq_out = (krb5_kdcpreauth_modreq)svr_req_ctx; /* Note that preauthentication succeeded. */ enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; @@ -591,9 +592,9 @@ server_return(krb5_context kcontext, struct _krb5_key_data *client_key, krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - preauth_get_entry_data_proc server_get_entry_data, - void *pa_module_context, - void **pa_request_context) + krb5_kdcpreauth_get_data_fn server_get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) { /* We don't need to send data back on the return trip. */ *send_pa = NULL; @@ -601,34 +602,32 @@ server_return(krb5_context kcontext, } /* Test server request context freeing */ -static krb5_error_code -server_free_reqctx(krb5_context kcontext, - void *pa_module_context, - void **pa_request_context) +static void +server_free_modreq(krb5_context kcontext, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) { test_svr_req_ctx *svr_req_ctx; #ifdef DEBUG - fprintf(stderr, "server_free_reqctx: entered!\n"); + fprintf(stderr, "server_free_modreq: entered!\n"); #endif - if (pa_request_context == NULL) - return 0; + if (modreq == NULL) + return; - svr_req_ctx = *pa_request_context; + svr_req_ctx = (test_svr_req_ctx *)modreq; if (svr_req_ctx == NULL) - return 0; + return; if (svr_req_ctx->value1 != 111111 || svr_req_ctx->value2 != 222222) { - fprintf(stderr, "server_free_reqctx: got invalid req context " + fprintf(stderr, "server_free_modreq: got invalid req context " "at %p with values %d and %d\n", svr_req_ctx, svr_req_ctx->value1, svr_req_ctx->value2); - return EINVAL; + return; } #ifdef DEBUG - fprintf(stderr, "server_free_reqctx: freeing context at %p\n", svr_req_ctx); + fprintf(stderr, "server_free_modreq: freeing context at %p\n", svr_req_ctx); #endif free(svr_req_ctx); - *pa_request_context = NULL; - return 0; } static int @@ -644,28 +643,47 @@ static krb5_preauthtype supported_server_pa_types[] = { KRB5_PADATA_CKSUM_BODY_REQ, 0, }; -struct krb5plugin_preauth_client_ftable_v1 preauthentication_client_1 = { - "cksum_body", /* name */ - &supported_client_pa_types[0], /* pa_type_list */ - NULL, /* enctype_list */ - NULL, /* plugin init function */ - NULL, /* plugin fini function */ - client_get_flags, /* get flags function */ - NULL, /* request init function */ - NULL, /* request fini function */ - client_process, /* process function */ - NULL, /* try_again function */ - client_gic_opt /* get init creds opt function */ -}; +krb5_error_code +clpreauth_cksum_body_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); +krb5_error_code +kdcpreauth_cksum_body_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); -struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = { - "cksum_body", - &supported_server_pa_types[0], - server_init, - server_fini, - server_get_flags, - server_get_edata, - server_verify, - server_return, - server_free_reqctx -}; +krb5_error_code +clpreauth_cksum_body_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "cksum_body"; + vt->pa_type_list = supported_client_pa_types; + vt->flags = client_get_flags; + vt->process = client_process; + vt->gic_opts = client_gic_opt; + return 0; +} + +krb5_error_code +kdcpreauth_cksum_body_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != -1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "cksum_body"; + vt->pa_type_list = supported_server_pa_types; + vt->init = server_init; + vt->fini = server_fini; + vt->flags = server_get_flags; + vt->edata = server_get_edata; + vt->verify = server_verify; + vt->return_padata = server_return; + vt->free_modreq = server_free_modreq; + return 0; +} diff --git a/src/plugins/preauth/encrypted_challenge/encrypted_challenge.exports b/src/plugins/preauth/encrypted_challenge/encrypted_challenge.exports index 98e96c399..651dcea1c 100644 --- a/src/plugins/preauth/encrypted_challenge/encrypted_challenge.exports +++ b/src/plugins/preauth/encrypted_challenge/encrypted_challenge.exports @@ -1,2 +1,2 @@ -preauthentication_client_1 -preauthentication_server_1 +clpreauth_encrypted_challenge_initvt +kdcpreauth_encrypted_challenge_initvt diff --git a/src/plugins/preauth/encrypted_challenge/encrypted_challenge_main.c b/src/plugins/preauth/encrypted_challenge/encrypted_challenge_main.c index 833385c63..58a659246 100644 --- a/src/plugins/preauth/encrypted_challenge/encrypted_challenge_main.c +++ b/src/plugins/preauth/encrypted_challenge/encrypted_challenge_main.c @@ -41,14 +41,14 @@ preauth_flags(krb5_context context, krb5_preauthtype pa_type) } static krb5_error_code -process_preauth(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, +process_preauth(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_get_data_fn get_data_proc, + krb5_clpreauth_rock rock, krb5_kdc_req *request, krb5_data *encoded_request_body, krb5_data *encoded_previous_request, krb5_pa_data *padata, krb5_prompter_fct prompter, void *prompter_data, - preauth_get_as_key_proc gak_fct, void *gak_data, + krb5_clpreauth_get_as_key_fn gak_fct, void *gak_data, krb5_data *salt, krb5_data *s2kparams, krb5_keyblock *as_key, krb5_pa_data ***out_padata) { @@ -63,7 +63,8 @@ process_preauth(krb5_context context, void *plugin_context, retval = fast_get_armor_key(context, get_data_proc, rock, &armor_key); if (retval || armor_key == NULL) return 0; - retval = get_data_proc(context, rock, krb5plugin_preauth_client_get_etype, &etype_data); + retval = get_data_proc(context, rock, krb5_clpreauth_get_etype, + &etype_data); if (retval == 0) { enctype = *((krb5_enctype *)etype_data->data); if (as_key->length == 0 ||as_key->enctype != enctype) @@ -163,8 +164,7 @@ process_preauth(krb5_context context, void *plugin_context, if (armor_key) krb5_free_keyblock(context, armor_key); if (etype_data != NULL) - get_data_proc(context, rock, krb5plugin_preauth_client_free_etype, - &etype_data); + get_data_proc(context, rock, krb5_clpreauth_free_etype, &etype_data); return retval; } @@ -173,12 +173,13 @@ static krb5_error_code kdc_include_padata(krb5_context context, krb5_kdc_req *request, struct _krb5_db_entry_new *client, struct _krb5_db_entry_new *server, - preauth_get_entry_data_proc get_entry_proc, - void *pa_module_context, krb5_pa_data *data) + krb5_kdcpreauth_get_data_fn get_data_proc, + krb5_kdcpreauth_moddata moddata, krb5_pa_data *data) { krb5_error_code retval = 0; krb5_keyblock *armor_key = NULL; - retval = fast_kdc_get_armor_key(context, get_entry_proc, request, client, &armor_key); + retval = fast_kdc_get_armor_key(context, get_data_proc, request, client, + &armor_key); if (retval) return retval; if (armor_key == 0) @@ -191,8 +192,9 @@ static krb5_error_code kdc_verify_preauth(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 get_entry_proc, - void *pa_module_context, void **pa_request_context, + krb5_kdcpreauth_get_data_fn get_entry_proc, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq *modreq_out, krb5_data **e_data, krb5_authdata ***authz_data) { krb5_error_code retval = 0; @@ -205,6 +207,7 @@ kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client, krb5_keyblock *client_keys = NULL; krb5_data *client_data = NULL; krb5_keyblock *challenge_key = NULL; + krb5_keyblock *kdc_challenge_key; int i = 0; plain.data = NULL; @@ -228,7 +231,7 @@ kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client, } if (retval == 0) retval = get_entry_proc(context, request, client, - krb5plugin_preauth_keys, &client_data); + krb5_kdcpreauth_keys, &client_data); if (retval == 0) { client_keys = (krb5_keyblock *) client_data->data; for (i = 0; client_keys[i].enctype&& (retval == 0); i++ ) { @@ -273,9 +276,10 @@ kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client, * considered this a success, so the return value is ignored. */ fast_kdc_replace_reply_key(context, get_entry_proc, request); - krb5_c_fx_cf2_simple(context, armor_key, "kdcchallengearmor", - &client_keys[i], "challengelongterm", - (krb5_keyblock **) pa_request_context); + if (krb5_c_fx_cf2_simple(context, armor_key, "kdcchallengearmor", + &client_keys[i], "challengelongterm", + &kdc_challenge_key) == 0) + *modreq_out = (krb5_kdcpreauth_modreq)kdc_challenge_key; } else { /*skew*/ retval = KRB5KRB_AP_ERR_SKEW; } @@ -302,11 +306,12 @@ kdc_return_preauth(krb5_context context, krb5_pa_data *padata, 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 get_entry_proc, - void *pa_module_context, void **pa_request_context) + krb5_kdcpreauth_get_data_fn get_entry_proc, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) { krb5_error_code retval = 0; - krb5_keyblock *challenge_key = *pa_request_context; + krb5_keyblock *challenge_key = (krb5_keyblock *)modreq; krb5_pa_enc_ts ts; krb5_data *plain = NULL; krb5_enc_data enc; @@ -318,8 +323,6 @@ kdc_return_preauth(krb5_context context, krb5_pa_data *padata, return 0; if (challenge_key == NULL) return 0; - * pa_request_context = NULL; /*this function will free the - * challenge key*/ enc.ciphertext.data = NULL; /* In case of error pass through */ retval = krb5_us_timeofday(context, &ts.patimestamp, &ts.pausec); @@ -355,37 +358,45 @@ kdc_return_preauth(krb5_context context, krb5_pa_data *padata, return retval; } -static int -kdc_preauth_flags(krb5_context context, krb5_preauthtype patype) +krb5_preauthtype supported_pa_types[] = { + KRB5_PADATA_ENCRYPTED_CHALLENGE, 0}; + +krb5_error_code +kdcpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); +krb5_error_code +clpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +krb5_error_code +kdcpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) { + krb5_kdcpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "encrypted_challenge"; + vt->pa_type_list = supported_pa_types; + vt->edata = kdc_include_padata; + vt->verify = kdc_verify_preauth; + vt->return_padata = kdc_return_preauth; return 0; } -krb5_preauthtype supported_pa_types[] = { - KRB5_PADATA_ENCRYPTED_CHALLENGE, 0}; - -struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = { - "Encrypted challenge", - &supported_pa_types[0], - NULL, - NULL, - kdc_preauth_flags, - kdc_include_padata, - kdc_verify_preauth, - kdc_return_preauth, - NULL -}; +krb5_error_code +clpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; -struct krb5plugin_preauth_client_ftable_v1 preauthentication_client_1 = { - "Encrypted Challenge", /* name */ - &supported_pa_types[0], /* pa_type_list */ - NULL, /* enctype_list */ - NULL, /* plugin init function */ - NULL, /* plugin fini function */ - preauth_flags, /* get flags function */ - NULL, /* request init function */ - NULL, /* request fini function */ - process_preauth, /* process function */ - NULL, /* try_again function */ - NULL /* get init creds opt function */ -}; + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "encrypted_challenge"; + vt->pa_type_list = supported_pa_types; + vt->flags = preauth_flags; + vt->process = process_preauth; + return 0; +} diff --git a/src/plugins/preauth/fast_factor.h b/src/plugins/preauth/fast_factor.h index 52f4fa2e8..f585bc22c 100644 --- a/src/plugins/preauth/fast_factor.h +++ b/src/plugins/preauth/fast_factor.h @@ -5,38 +5,36 @@ * Returns failure if the client library does not support FAST. */ static inline krb5_error_code -fast_get_armor_key(krb5_context context, preauth_get_client_data_proc get_data, - struct _krb5_preauth_client_rock *rock, - krb5_keyblock **armor_key) +fast_get_armor_key(krb5_context context, krb5_clpreauth_get_data_fn get_data, + krb5_clpreauth_rock rock, krb5_keyblock **armor_key) { krb5_error_code retval = 0; krb5_data *data; - retval = get_data(context, rock, krb5plugin_preauth_client_fast_armor, &data); + retval = get_data(context, rock, krb5_clpreauth_fast_armor, &data); if (retval == 0) { *armor_key = (krb5_keyblock *) data->data; data->data = NULL; - get_data(context, rock, krb5plugin_preauth_client_free_fast_armor, - &data); + get_data(context, rock, krb5_clpreauth_free_fast_armor, &data); } return retval; } static inline krb5_error_code fast_kdc_get_armor_key(krb5_context context, - preauth_get_entry_data_proc get_entry, + krb5_kdcpreauth_get_data_fn get_entry, krb5_kdc_req *request, struct _krb5_db_entry_new *client, krb5_keyblock **armor_key) { krb5_error_code retval; krb5_data *data; - retval = get_entry(context, request, client, krb5plugin_preauth_fast_armor, + retval = get_entry(context, request, client, krb5_kdcpreauth_fast_armor, &data); if (retval == 0) { *armor_key = (krb5_keyblock *) data->data; data->data = NULL; get_entry(context, request, client, - krb5plugin_preauth_free_fast_armor, &data); + krb5_kdcpreauth_free_fast_armor, &data); } return retval; } @@ -45,7 +43,7 @@ fast_kdc_get_armor_key(krb5_context context, static inline krb5_error_code fast_kdc_replace_reply_key(krb5_context context, - preauth_get_entry_data_proc get_data, + krb5_kdcpreauth_get_data_fn get_data, krb5_kdc_req *request) { return 0; @@ -53,8 +51,8 @@ fast_kdc_replace_reply_key(krb5_context context, static inline krb5_error_code fast_set_kdc_verified(krb5_context context, - preauth_get_client_data_proc get_data, - struct _krb5_preauth_client_rock *rock) + krb5_clpreauth_get_data_fn get_data, + krb5_clpreauth_rock rock) { return 0; } diff --git a/src/plugins/preauth/pkinit/pkinit.exports b/src/plugins/preauth/pkinit/pkinit.exports index 98e96c399..e77fa3ef0 100644 --- a/src/plugins/preauth/pkinit/pkinit.exports +++ b/src/plugins/preauth/pkinit/pkinit.exports @@ -1,2 +1,2 @@ -preauthentication_client_1 -preauthentication_server_1 +clpreauth_pkinit_initvt +kdcpreauth_pkinit_initvt diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c index 6888c1b07..cf95bd57b 100644 --- a/src/plugins/preauth/pkinit/pkinit_clnt.c +++ b/src/plugins/preauth/pkinit/pkinit_clnt.c @@ -71,7 +71,8 @@ pkinit_as_rep_parse(krb5_context context, pkinit_context plgctx, krb5_kdc_req *request, const krb5_data *as_rep, krb5_keyblock *key_block, krb5_enctype etype, krb5_data *); -static void pkinit_client_plugin_fini(krb5_context context, void *blob); +static void pkinit_client_plugin_fini(krb5_context context, + krb5_clpreauth_moddata moddata); static krb5_error_code pa_pkinit_gen_req(krb5_context context, @@ -975,31 +976,25 @@ pkinit_client_profile(krb5_context context, } static krb5_error_code -pkinit_client_process(krb5_context context, - void *plugin_context, - void *request_context, +pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *gic_opt, - preauth_get_client_data_proc get_data_proc, - struct _krb5_preauth_client_rock *rock, - krb5_kdc_req *request, + krb5_clpreauth_get_data_fn get_data_proc, + krb5_clpreauth_rock rock, krb5_kdc_req *request, krb5_data *encoded_request_body, krb5_data *encoded_previous_request, krb5_pa_data *in_padata, - 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_padata) + krb5_prompter_fct prompter, void *prompter_data, + krb5_clpreauth_get_as_key_fn gak_fct, void *gak_data, + krb5_data *salt, krb5_data *s2kparams, + krb5_keyblock *as_key, krb5_pa_data ***out_padata) { krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; krb5_enctype enctype = -1; krb5_data *cdata = NULL; int processing_request = 0; - pkinit_context plgctx = (pkinit_context)plugin_context; - pkinit_req_context reqctx = (pkinit_req_context)request_context; + pkinit_context plgctx = (pkinit_context)moddata; + pkinit_req_context reqctx = (pkinit_req_context)modreq; krb5_keyblock *armor_key = NULL; pkiDebug("pkinit_client_process %p %p %p %p\n", @@ -1061,16 +1056,15 @@ pkinit_client_process(krb5_context context, /* * Get the enctype of the reply. */ - retval = (*get_data_proc)(context, rock, - krb5plugin_preauth_client_get_etype, &cdata); + retval = (*get_data_proc)(context, rock, krb5_clpreauth_get_etype, + &cdata); if (retval) { pkiDebug("get_data_proc returned %d (%s)\n", retval, error_message(retval)); return retval; } enctype = *((krb5_enctype *)cdata->data); - (*get_data_proc)(context, rock, - krb5plugin_preauth_client_free_etype, &cdata); + (*get_data_proc)(context, rock, krb5_clpreauth_free_etype, &cdata); retval = pa_pkinit_parse_rep(context, plgctx, reqctx, request, in_padata, enctype, as_key, encoded_previous_request); @@ -1082,29 +1076,22 @@ pkinit_client_process(krb5_context context, } static krb5_error_code -pkinit_client_tryagain(krb5_context context, - void *plugin_context, - void *request_context, +pkinit_client_tryagain(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *gic_opt, - preauth_get_client_data_proc get_data_proc, - struct _krb5_preauth_client_rock *rock, - krb5_kdc_req *request, + krb5_clpreauth_get_data_fn get_data_proc, + krb5_clpreauth_rock rock, krb5_kdc_req *request, krb5_data *encoded_request_body, krb5_data *encoded_previous_request, - krb5_pa_data *in_padata, - krb5_error *err_reply, - 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_padata) + krb5_pa_data *in_padata, krb5_error *err_reply, + krb5_prompter_fct prompter, void *prompter_data, + krb5_clpreauth_get_as_key_fn gak_fct, void *gak_data, + krb5_data *salt, krb5_data *s2kparams, + krb5_keyblock *as_key, krb5_pa_data ***out_padata) { krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; - pkinit_context plgctx = (pkinit_context)plugin_context; - pkinit_req_context reqctx = (pkinit_req_context)request_context; + pkinit_context plgctx = (pkinit_context)moddata; + pkinit_req_context reqctx = (pkinit_req_context)modreq; krb5_typed_data **typed_data = NULL; krb5_data scratch; krb5_external_principal_identifier **krb5_trusted_certifiers = NULL; @@ -1202,14 +1189,14 @@ static krb5_preauthtype supported_client_pa_types[] = { static void pkinit_client_req_init(krb5_context context, - void *plugin_context, - void **request_context) + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq *modreq_out) { krb5_error_code retval = ENOMEM; pkinit_req_context reqctx = NULL; - pkinit_context plgctx = plugin_context; + pkinit_context plgctx = (pkinit_context)moddata; - *request_context = NULL; + *modreq_out = NULL; reqctx = malloc(sizeof(*reqctx)); if (reqctx == NULL) @@ -1244,7 +1231,7 @@ pkinit_client_req_init(krb5_context context, if (retval) goto cleanup; - *request_context = (void *) reqctx; + *modreq_out = (krb5_clpreauth_modreq)reqctx; pkiDebug("%s: returning reqctx at %p\n", __FUNCTION__, reqctx); cleanup: @@ -1264,11 +1251,10 @@ cleanup: } static void -pkinit_client_req_fini(krb5_context context, - void *plugin_context, - void *request_context) +pkinit_client_req_fini(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq) { - pkinit_req_context reqctx = request_context; + pkinit_req_context reqctx = (pkinit_req_context)modreq; pkiDebug("%s: received reqctx at %p\n", __FUNCTION__, reqctx); if (reqctx == NULL) @@ -1295,7 +1281,8 @@ pkinit_client_req_fini(krb5_context context, } static int -pkinit_client_plugin_init(krb5_context context, void **blob) +pkinit_client_plugin_init(krb5_context context, + krb5_clpreauth_moddata *moddata_out) { krb5_error_code retval = ENOMEM; pkinit_context ctx = NULL; @@ -1325,21 +1312,21 @@ pkinit_client_plugin_init(krb5_context context, void **blob) if (retval) goto errout; - *blob = ctx; + *moddata_out = (krb5_clpreauth_moddata)ctx; pkiDebug("%s: returning plgctx at %p\n", __FUNCTION__, ctx); errout: if (retval) - pkinit_client_plugin_fini(context, ctx); + pkinit_client_plugin_fini(context, (krb5_clpreauth_moddata)ctx); return retval; } static void -pkinit_client_plugin_fini(krb5_context context, void *blob) +pkinit_client_plugin_fini(krb5_context context, krb5_clpreauth_moddata moddata) { - pkinit_context ctx = blob; + pkinit_context ctx = (pkinit_context)moddata; if (ctx == NULL || ctx->magic != PKINIT_CTX_MAGIC) { pkiDebug("pkinit_lib_fini: got bad plgctx (%p)!\n", ctx); @@ -1425,14 +1412,13 @@ handle_gic_opt(krb5_context context, } static krb5_error_code -pkinit_client_gic_opt(krb5_context context, - void *plugin_context, +pkinit_client_gic_opt(krb5_context context, krb5_clpreauth_moddata moddata, krb5_get_init_creds_opt *gic_opt, const char *attr, const char *value) { krb5_error_code retval; - pkinit_context plgctx = plugin_context; + pkinit_context plgctx = (pkinit_context)moddata; pkiDebug("(pkinit) received '%s' = '%s'\n", attr, value); retval = handle_gic_opt(context, plgctx, attr, value); @@ -1442,20 +1428,28 @@ pkinit_client_gic_opt(krb5_context context, return 0; } -/* Only necessary for static plugin linking support. */ -#include "k5-plugin.h" - -struct krb5plugin_preauth_client_ftable_v1 -PLUGIN_SYMBOL_NAME(krb5_preauth, preauthentication_client_1) = { - "pkinit", /* name */ - supported_client_pa_types, /* pa_type_list */ - NULL, /* enctype_list */ - pkinit_client_plugin_init, /* (*init) */ - pkinit_client_plugin_fini, /* (*fini) */ - pkinit_client_get_flags, /* (*flags) */ - pkinit_client_req_init, /* (*client_req_init) */ - pkinit_client_req_fini, /* (*client_req_fini) */ - pkinit_client_process, /* (*process) */ - pkinit_client_tryagain, /* (*tryagain) */ - pkinit_client_gic_opt /* (*gic_opt) */ -}; +krb5_error_code +clpreauth_pkinit_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +clpreauth_pkinit_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "pkinit"; + vt->pa_type_list = supported_client_pa_types; + vt->init = pkinit_client_plugin_init; + vt->fini = pkinit_client_plugin_fini; + vt->flags = pkinit_client_get_flags; + vt->request_init = pkinit_client_req_init; + vt->request_fini = pkinit_client_req_fini; + vt->process = pkinit_client_process; + vt->tryagain = pkinit_client_tryagain; + vt->gic_opts = pkinit_client_gic_opt; + return 0; +} diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c index 2a33e9331..d87d57031 100644 --- a/src/plugins/preauth/pkinit/pkinit_srv.c +++ b/src/plugins/preauth/pkinit/pkinit_srv.c @@ -50,10 +50,12 @@ pkinit_server_plugin_fini_realm(krb5_context context, pkinit_kdc_context plgctx); static void -pkinit_server_plugin_fini(krb5_context context, void *blob); +pkinit_server_plugin_fini(krb5_context context, + krb5_kdcpreauth_moddata moddata); static pkinit_kdc_context -pkinit_find_realm_context(krb5_context context, void *pa_plugin_context, +pkinit_find_realm_context(krb5_context context, + krb5_kdcpreauth_moddata moddata, krb5_principal princ); static krb5_error_code @@ -97,12 +99,12 @@ cleanup: static krb5_error_code pkinit_server_get_edata(krb5_context context, - krb5_kdc_req * request, - struct _krb5_db_entry_new * client, - struct _krb5_db_entry_new * server, - preauth_get_entry_data_proc server_get_entry_data, - void *pa_plugin_context, - krb5_pa_data * data) + krb5_kdc_req *request, + struct _krb5_db_entry_new *client, + struct _krb5_db_entry_new *server, + krb5_kdcpreauth_get_data_fn server_get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_pa_data *data) { krb5_error_code retval = 0; pkinit_kdc_context plgctx = NULL; @@ -123,8 +125,7 @@ pkinit_server_get_edata(krb5_context context, * If we don't have a realm context for the given realm, * don't tell the client that we support pkinit! */ - plgctx = pkinit_find_realm_context(context, pa_plugin_context, - request->server); + plgctx = pkinit_find_realm_context(context, moddata, request->server); if (plgctx == NULL) retval = EINVAL; @@ -292,9 +293,9 @@ pkinit_server_verify_padata(krb5_context context, krb5_kdc_req * request, krb5_enc_tkt_part * enc_tkt_reply, krb5_pa_data * data, - preauth_get_entry_data_proc server_get_entry_data, - void *pa_plugin_context, - void **pa_request_context, + krb5_kdcpreauth_get_data_fn server_get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq *modreq_out, krb5_data **e_data, krb5_authdata ***authz_data) { @@ -328,11 +329,10 @@ pkinit_server_verify_padata(krb5_context context, return EINVAL; } - if (pa_plugin_context == NULL || e_data == NULL) + if (moddata == NULL || e_data == NULL) return EINVAL; - plgctx = pkinit_find_realm_context(context, pa_plugin_context, - request->server); + plgctx = pkinit_find_realm_context(context, moddata, request->server); if (plgctx == NULL) return 0; @@ -562,7 +562,7 @@ pkinit_server_verify_padata(krb5_context context, } /* remember to set the PREAUTH flag in the reply */ enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; - *pa_request_context = reqctx; + *modreq_out = (krb5_kdcpreauth_modreq)reqctx; reqctx = NULL; cleanup: @@ -668,9 +668,9 @@ pkinit_server_return_padata(krb5_context context, struct _krb5_key_data * client_key, krb5_keyblock * encrypting_key, krb5_pa_data ** send_pa, - preauth_get_entry_data_proc server_get_entry_data, - void *pa_plugin_context, - void **pa_request_context) + krb5_kdcpreauth_get_data_fn server_get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) { krb5_error_code retval = 0; krb5_data scratch = {0, 0, NULL}; @@ -708,20 +708,19 @@ pkinit_server_return_padata(krb5_context context, if (padata->length <= 0 || padata->contents == NULL) return 0; - if (pa_request_context == NULL || *pa_request_context == NULL) { + if (modreq == NULL) { pkiDebug("missing request context \n"); return EINVAL; } - plgctx = pkinit_find_realm_context(context, pa_plugin_context, - request->server); + plgctx = pkinit_find_realm_context(context, moddata, request->server); if (plgctx == NULL) { pkiDebug("Unable to locate correct realm context\n"); return ENOENT; } pkiDebug("pkinit_return_padata: entered!\n"); - reqctx = (pkinit_kdc_req_context)*pa_request_context; + reqctx = (pkinit_kdc_req_context)modreq; if (encrypting_key->contents) { free(encrypting_key->contents); @@ -1169,13 +1168,14 @@ errout: } static pkinit_kdc_context -pkinit_find_realm_context(krb5_context context, void *pa_plugin_context, +pkinit_find_realm_context(krb5_context context, + krb5_kdcpreauth_moddata moddata, krb5_principal princ) { int i; - pkinit_kdc_context *realm_contexts = pa_plugin_context; + pkinit_kdc_context *realm_contexts = (pkinit_kdc_context *)moddata; - if (pa_plugin_context == NULL) + if (moddata == NULL) return NULL; for (i = 0; realm_contexts[i] != NULL; i++) { @@ -1254,7 +1254,8 @@ errout: } static int -pkinit_server_plugin_init(krb5_context context, void **blob, +pkinit_server_plugin_init(krb5_context context, + krb5_kdcpreauth_moddata *moddata_out, const char **realmnames) { krb5_error_code retval = ENOMEM; @@ -1289,13 +1290,15 @@ pkinit_server_plugin_init(krb5_context context, void **blob, goto errout; } - *blob = realm_contexts; + *moddata_out = (krb5_kdcpreauth_moddata)realm_contexts; retval = 0; pkiDebug("%s: returning context at %p\n", __FUNCTION__, realm_contexts); errout: - if (retval) - pkinit_server_plugin_fini(context, realm_contexts); + if (retval) { + pkinit_server_plugin_fini(context, + (krb5_kdcpreauth_moddata)realm_contexts); + } return retval; } @@ -1316,9 +1319,10 @@ pkinit_server_plugin_fini_realm(krb5_context context, pkinit_kdc_context plgctx) } static void -pkinit_server_plugin_fini(krb5_context context, void *blob) +pkinit_server_plugin_fini(krb5_context context, + krb5_kdcpreauth_moddata moddata) { - pkinit_kdc_context *realm_contexts = blob; + pkinit_kdc_context *realm_contexts = (pkinit_kdc_context *)moddata; int i; if (realm_contexts == NULL) @@ -1379,18 +1383,26 @@ pkinit_fini_kdc_req_context(krb5_context context, void *ctx) free(reqctx); } -/* Only necessary for static plugin linking support. */ -#include "k5-plugin.h" - -struct krb5plugin_preauth_server_ftable_v1 -PLUGIN_SYMBOL_NAME(krb5_pkinit, preauthentication_server_1) = { - "pkinit", /* name */ - supported_server_pa_types, /* pa_type_list */ - pkinit_server_plugin_init, /* (*init_proc) */ - pkinit_server_plugin_fini, /* (*fini_proc) */ - pkinit_server_get_flags, /* (*flags_proc) */ - pkinit_server_get_edata, /* (*edata_proc) */ - pkinit_server_verify_padata,/* (*verify_proc) */ - pkinit_server_return_padata,/* (*return_proc) */ - NULL, /* (*freepa_reqcontext_proc) */ -}; +krb5_error_code +kdcpreauth_pkinit_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +kdcpreauth_pkinit_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "pkinit"; + vt->pa_type_list = supported_server_pa_types; + vt->init = pkinit_server_plugin_init; + vt->fini = pkinit_server_plugin_fini; + vt->flags = pkinit_server_get_flags; + vt->edata = pkinit_server_get_edata; + vt->verify = pkinit_server_verify_padata; + vt->return_padata = pkinit_server_return_padata; + return 0; +} diff --git a/src/plugins/preauth/securid_sam2/securid_sam2_main.c b/src/plugins/preauth/securid_sam2/securid_sam2_main.c index 49b497ef0..6bc65e85e 100644 --- a/src/plugins/preauth/securid_sam2/securid_sam2_main.c +++ b/src/plugins/preauth/securid_sam2/securid_sam2_main.c @@ -116,8 +116,8 @@ static krb5_error_code kdc_include_padata(krb5_context context, krb5_kdc_req *request, struct _krb5_db_entry_new *client, struct _krb5_db_entry_new *server, - preauth_get_entry_data_proc get_entry_proc, - void *pa_module_context, krb5_pa_data *pa_data) + krb5_kdcpreauth_get_data_fn get_entry_proc, + krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data) { krb5_error_code retval; krb5_data *client_keys_data = NULL; @@ -138,7 +138,7 @@ kdc_include_padata(krb5_context context, krb5_kdc_req *request, if (retval) return retval; retval = get_entry_proc(context, request, client, - krb5plugin_preauth_keys, &client_keys_data); + krb5_kdcpreauth_keys, &client_keys_data); if (retval) goto cleanup; client_key = (krb5_keyblock *) client_keys_data->data; @@ -206,8 +206,9 @@ static krb5_error_code kdc_verify_preauth(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 *pa_data, - preauth_get_entry_data_proc get_entry_proc, - void *pa_module_context, void **opaque, + krb5_kdcpreauth_get_data_fn get_entry_proc, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq *modreq_out, krb5_data **e_data, krb5_authdata ***authz_data) { krb5_error_code retval, saved_retval = 0; @@ -294,14 +295,23 @@ kdc_preauth_flags(krb5_context context, krb5_preauthtype patype) krb5_preauthtype supported_pa_types[] = { KRB5_PADATA_SAM_RESPONSE_2, 0}; -struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = { - "SAM2", - &supported_pa_types[0], - NULL, - NULL, - kdc_preauth_flags, - kdc_include_padata, - kdc_verify_preauth, - NULL, - NULL -}; +krb5_error_code +kdcpreauth_securid_sam2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +kdcpreauth_securid_sam2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "securid_sam2"; + vt->pa_type_list = supported_pa_types; + vt->flags = kdc_preauth_flags; + vt->edata = kdc_include_padata; + vt->verify = kdc_verify_preauth; + return 0; +} diff --git a/src/plugins/preauth/wpse/wpse.exports b/src/plugins/preauth/wpse/wpse.exports index 98e96c399..4cc48a883 100644 --- a/src/plugins/preauth/wpse/wpse.exports +++ b/src/plugins/preauth/wpse/wpse.exports @@ -1,2 +1,2 @@ -preauthentication_client_1 -preauthentication_server_1 +clpreauth_wpse_initvt +kdcpreauth_wpse_initvt diff --git a/src/plugins/preauth/wpse/wpse_main.c b/src/plugins/preauth/wpse/wpse_main.c index 14e994d42..866286c1b 100644 --- a/src/plugins/preauth/wpse/wpse_main.c +++ b/src/plugins/preauth/wpse/wpse_main.c @@ -59,7 +59,7 @@ client_get_flags(krb5_context kcontext, krb5_preauthtype pa_type) } static krb5_error_code -client_init(krb5_context kcontext, void **ctx) +client_init(krb5_context kcontext, krb5_clpreauth_moddata *moddata_out) { int *pctx; @@ -67,16 +67,16 @@ client_init(krb5_context kcontext, void **ctx) if (pctx == NULL) return ENOMEM; *pctx = 0; - *ctx = pctx; + *moddata_out = (krb5_clpreauth_moddata)pctx; return 0; } static void -client_fini(krb5_context kcontext, void *ctx) +client_fini(krb5_context kcontext, krb5_clpreauth_moddata moddata) { int *pctx; - pctx = ctx; + pctx = (int *)moddata; if (pctx) { #ifdef DEBUG fprintf(stderr, "wpse module called total of %d times\n", *pctx); @@ -87,18 +87,18 @@ client_fini(krb5_context kcontext, void *ctx) static krb5_error_code client_process(krb5_context kcontext, - void *plugin_context, - void *request_context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, - preauth_get_client_data_proc client_get_data_proc, - struct _krb5_preauth_client_rock *rock, + krb5_clpreauth_get_data_fn client_get_data_proc, + krb5_clpreauth_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, + krb5_clpreauth_get_as_key_fn gak_fct, void *gak_data, krb5_data *salt, krb5_data *s2kparams, krb5_keyblock *as_key, @@ -115,7 +115,7 @@ client_process(krb5_context kcontext, pa_data->length, pa_data->pa_type); #endif - pctx = plugin_context; + pctx = (int *)moddata; if (pctx) { (*pctx)++; } @@ -176,11 +176,12 @@ typedef struct _wpse_req_ctx } wpse_req_ctx; static void -client_req_init(krb5_context kcontext, void *plugin_context, void **req_context_p) +client_req_init(krb5_context kcontext, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq *modreq_out) { wpse_req_ctx *ctx; - *req_context_p = NULL; + *modreq_out = NULL; /* Allocate a request context. Useful for verifying that we do in fact * do per-request cleanup. */ @@ -190,13 +191,14 @@ client_req_init(krb5_context kcontext, void *plugin_context, void **req_context_ ctx->magic = WPSE_MAGIC; ctx->value = 0xc0dec0de; - *req_context_p = ctx; + *modreq_out = (krb5_clpreauth_modreq)ctx; } static void -client_req_cleanup(krb5_context kcontext, void *plugin_context, void *req_context) +client_req_cleanup(krb5_context kcontext, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq) { - wpse_req_ctx *ctx = (wpse_req_ctx *)req_context; + wpse_req_ctx *ctx = (wpse_req_ctx *)modreq; if (ctx) { #ifdef DEBUG @@ -217,7 +219,7 @@ client_req_cleanup(krb5_context kcontext, void *plugin_context, void *req_contex static krb5_error_code client_gic_opt(krb5_context kcontext, - void *plugin_context, + krb5_clpreauth_moddata moddata, krb5_get_init_creds_opt *opt, const char *attr, const char *value) @@ -231,15 +233,12 @@ client_gic_opt(krb5_context kcontext, /* Free state. */ -static krb5_error_code -server_free_pa_request_context(krb5_context kcontext, void *plugin_context, - void **request_context) +static void +server_free_modreq(krb5_context kcontext, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) { - if (*request_context != NULL) { - free(*request_context); - *request_context = NULL; - } - return 0; + free(modreq); } /* Obtain and return any preauthentication data (which is destined for the @@ -249,8 +248,8 @@ server_get_edata(krb5_context kcontext, krb5_kdc_req *request, struct _krb5_db_entry_new *client, struct _krb5_db_entry_new *server, - preauth_get_entry_data_proc server_get_entry_data, - void *pa_module_context, + krb5_kdcpreauth_get_data_fn server_get_entry_data, + krb5_kdcpreauth_moddata moddata, krb5_pa_data *data) { /* Return zero bytes of data. */ @@ -267,9 +266,9 @@ server_verify(krb5_context kcontext, krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, - preauth_get_entry_data_proc server_get_entry_data, - void *pa_module_context, - void **pa_request_context, + krb5_kdcpreauth_get_data_fn server_get_entry_data, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq *modreq_out, krb5_data **e_data, krb5_authdata ***authz_data) { @@ -292,8 +291,7 @@ server_verify(krb5_context kcontext, enc_tkt_reply->flags |= TKT_FLG_HW_AUTH; /* Allocate a context. Useful for verifying that we do in fact do * per-request cleanup. */ - if (*pa_request_context == NULL) - *pa_request_context = malloc(4); + *modreq_out = malloc(4); /* * Return some junk authorization data just to exercise the @@ -373,9 +371,8 @@ server_return(krb5_context kcontext, struct _krb5_key_data *client_key, krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - preauth_get_entry_data_proc server_get_entry_data, - void *pa_module_context, - void **pa_request_context) + krb5_kdcpreauth_get_data_fn server_get_entry_data, + krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq) { /* This module does a couple of dumb things. It tags its reply with * the same type as the initial challenge (expecting the client to sort @@ -447,28 +444,49 @@ server_get_flags(krb5_context kcontext, krb5_preauthtype pa_type) static krb5_preauthtype supported_client_pa_types[] = {KRB5_PADATA_WPSE_REQ, 0}; static krb5_preauthtype supported_server_pa_types[] = {KRB5_PADATA_WPSE_REQ, 0}; -struct krb5plugin_preauth_client_ftable_v1 preauthentication_client_1 = { - "wpse", /* name */ - &supported_client_pa_types[0], /* pa_type_list */ - NULL, /* enctype_list */ - client_init, /* plugin init function */ - client_fini, /* plugin fini function */ - client_get_flags, /* get flags function */ - client_req_init, /* request init function */ - client_req_cleanup, /* request fini function */ - client_process, /* process function */ - NULL, /* try_again function */ - client_gic_opt /* get init creds opts function */ -}; - -struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = { - "wpse", - &supported_server_pa_types[0], - NULL, - NULL, - server_get_flags, - server_get_edata, - server_verify, - server_return, - server_free_pa_request_context, -}; +krb5_error_code +clpreauth_wpse_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); +krb5_error_code +kdcpreauth_wpse_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +krb5_error_code +clpreauth_wpse_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "wpse"; + vt->pa_type_list = supported_client_pa_types; + vt->init = client_init; + vt->fini = client_fini; + vt->flags = client_get_flags; + vt->request_init = client_req_init; + vt->request_fini = client_req_cleanup; + vt->process = client_process; + vt->gic_opts = client_gic_opt; + return 0; +} + +krb5_error_code +kdcpreauth_wpse_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != -1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "wpse"; + vt->pa_type_list = supported_server_pa_types; + vt->flags = server_get_flags; + vt->edata = server_get_edata; + vt->verify = server_verify; + vt->return_padata = server_return; + vt->free_modreq = server_free_modreq; + return 0; +} diff --git a/src/tests/dejagnu/Makefile.in b/src/tests/dejagnu/Makefile.in index 85c7ab9d1..ffdfbd617 100644 --- a/src/tests/dejagnu/Makefile.in +++ b/src/tests/dejagnu/Makefile.in @@ -41,6 +41,6 @@ site.exp: runenv.vals Makefile echo "set runvarlist [list `cat runenv.vals | tr '\n' ' '`]" | \ sed -e 's%=\.%='`pwd`'/.%g' > site.exp echo "set KRB5_DB_MODULE_DIR {$(KRB5_DB_MODULE_DIR)}" >> site.exp - echo "set KRB5_PA_MODULE_DIR {$(KRB5_PA_MODULE_DIR)}" >> site.exp + echo "set MODULE_DIR {$(MODULE_DIR)}" >> site.exp echo "set PRIOCNTL_HACK @PRIOCNTL_HACK@" >> site.exp diff --git a/src/tests/dejagnu/config/default.exp b/src/tests/dejagnu/config/default.exp index cbe460031..3a997e58d 100644 --- a/src/tests/dejagnu/config/default.exp +++ b/src/tests/dejagnu/config/default.exp @@ -918,7 +918,7 @@ proc setup_krb5_conf { {type client} } { global mode global portbase global KRB5_DB_MODULE_DIR - global KRB5_PA_MODULE_DIR + global MODULE_DIR global srcdir set pkinit_certs [findfile "[pwd]/$srcdir/pkinit-certs" "[pwd]/$srcdir/pkinit-certs" "$srcdir/pkinit-certs"] @@ -950,7 +950,7 @@ proc setup_krb5_conf { {type client} } { if { $mode == "tcp" } { puts $conffile " udp_preference_limit = 1" } - puts $conffile " preauth_module_dir = $tmppwd/../../../util/fakedest$KRB5_PA_MODULE_DIR" + puts $conffile " plugin_base_dir = $tmppwd/../../../util/fakedest$MODULE_DIR" puts $conffile "" puts $conffile "\[realms\]" puts $conffile " $REALMNAME = \{" diff --git a/src/tests/dejagnu/krb-standalone/standalone.exp b/src/tests/dejagnu/krb-standalone/standalone.exp index dbaf95dbd..03a5d52e0 100644 --- a/src/tests/dejagnu/krb-standalone/standalone.exp +++ b/src/tests/dejagnu/krb-standalone/standalone.exp @@ -139,7 +139,7 @@ proc doit { } { global portbase global mode global tmppwd - global KRB5_PA_MODULE_DIR + global MODULE_DIR setup_kerberos_env kdc @@ -235,7 +235,7 @@ proc doit { } { } # If we have anonymous then test it - if [file exists "$tmppwd/../../../util/fakedest$KRB5_PA_MODULE_DIR/pkinit.so" ] { + if [file exists "$tmppwd/../../../util/fakedest$MODULE_DIR/preauth/pkinit.so" ] { kinit_anonymous "WELLKNOWN/ANONYMOUS" } diff --git a/src/util/k5test.py b/src/util/k5test.py index 4a54ba6db..89551dde5 100644 --- a/src/util/k5test.py +++ b/src/util/k5test.py @@ -915,7 +915,7 @@ _default_krb5_conf = { 'libdefaults' : { 'default_realm' : '$realm', 'dns_lookup_kdc' : 'false', - 'preauth_module_dir' : '$plugins/preauth' + 'plugin_base_dir' : '$plugins' }, 'realms' : { '$realm' : {