* 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;
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
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);
/* 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. */
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;
void (**locate_fptrs)(void);
/* preauth module stuff */
- struct plugin_dir_handle preauth_plugins;
krb5_preauth_context *preauth_context;
/* error detail info */
/* -*- 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
* 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_<modulename>_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_<modulename>_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 <krb5/krb5.h>
-
-/*
- * While arguments of these types are passed-in, for the most part a preauth
- * module can treat them as opaque. If we need keying data, we can ask for
- * it directly.
- */
-struct _krb5_db_entry_new;
-struct _krb5_key_data;
-struct _krb5_preauth_client_rock;
+#include <krb5/plugin.h>
/*
* Preauth mechanism property flags, unified from previous definitions in the
* 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
* 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,
/* 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)
#include <assert.h>
#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,
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
void **pa_request_context);
#endif /* APPLE_PKINIT */
-static krb5_preauth_systems static_preauth_systems[] = {
+static preauth_system static_preauth_systems[] = {
#if APPLE_PKINIT
{
"pkinit",
get_pkinit_edata,
verify_pkinit_request,
return_pkinit_response,
- NULL /* free_pa_request_context */
+ NULL /* free_modreq */
},
#endif /* APPLE_PKINIT */
{
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;
};
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;
* 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
* 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;
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;
*result = ret;
return 0;
break;
- case krb5plugin_preauth_keys:
+ case krb5_kdcpreauth_keys:
ret = malloc(sizeof(krb5_data));
if (ret == NULL)
return ENOMEM;
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) {
}
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;
}
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);
}
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))
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;
}
}
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;
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;
(*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);
{
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;
#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);
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",
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) &&
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;
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;
}
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)
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)
{
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++) {
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);
}
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);
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);
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;
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
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);
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;
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);
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;
ctx->prompter_data,
ctx->gak_fct,
ctx->gak_data,
- &ctx->get_data_rock,
+ &ctx->preauth_rock,
ctx->opte);
if (code != 0)
goto cleanup;
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. */
ctx->prompter_data,
ctx->gak_fct,
ctx->gak_data,
- &ctx->get_data_rock,
+ &ctx->preauth_rock,
ctx->opte);
if (code != 0)
goto cleanup;
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;
-}
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;
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. */
#include <unistd.h>
#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,
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
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
* 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
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
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);
}
}
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;
}
}
}
*/
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;
return EINVAL;
switch (request_type) {
- case krb5plugin_preauth_client_get_etype:
+ case krb5_clpreauth_get_etype:
{
krb5_enctype *eptr;
ret = malloc(sizeof(krb5_data));
return 0;
}
break;
- case krb5plugin_preauth_client_free_etype:
+ case krb5_clpreauth_free_etype:
ret = *retdata;
if (ret == NULL)
return 0;
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)
free(ret);
return retval;
}
- case krb5plugin_preauth_client_free_fast_armor:
+ case krb5_clpreauth_free_fast_armor:
ret = *retdata;
if (ret) {
if (ret->data)
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,
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;
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);
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;
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,
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;
gak_fct,
salt, s2kparams,
gak_data,
- get_data_rock,
+ preauth_rock,
as_key,
&out_pa_list,
&out_pa_list_size,
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;
+}
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
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);
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
-preauthentication_client_1
-preauthentication_server_1
+clpreauth_cksum_body_initvt
+kdcpreauth_cksum_body_initvt
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,
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)
/* 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));
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",
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;
/* 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
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)
{
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");
/* 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
* 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++;
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;
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;
}
/* 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
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;
+}
-preauthentication_client_1
-preauthentication_server_1
+clpreauth_encrypted_challenge_initvt
+kdcpreauth_encrypted_challenge_initvt
}
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)
{
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)
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;
}
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)
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;
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;
}
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++ ) {
* 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;
}
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;
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);
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;
+}
* 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;
}
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;
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;
}
-preauthentication_client_1
-preauthentication_server_1
+clpreauth_pkinit_initvt
+kdcpreauth_pkinit_initvt
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,
}
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",
/*
* 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);
}
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;
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)
if (retval)
goto cleanup;
- *request_context = (void *) reqctx;
+ *modreq_out = (krb5_clpreauth_modreq)reqctx;
pkiDebug("%s: returning reqctx at %p\n", __FUNCTION__, reqctx);
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)
}
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;
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);
}
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);
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;
+}
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
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;
* 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;
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)
{
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;
}
/* 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:
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};
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);
}
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++) {
}
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;
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;
}
}
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)
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;
+}
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;
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;
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;
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;
+}
-preauthentication_client_1
-preauthentication_server_1
+clpreauth_wpse_initvt
+kdcpreauth_wpse_initvt
}
static krb5_error_code
-client_init(krb5_context kcontext, void **ctx)
+client_init(krb5_context kcontext, krb5_clpreauth_moddata *moddata_out)
{
int *pctx;
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);
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,
pa_data->length, pa_data->pa_type);
#endif
- pctx = plugin_context;
+ pctx = (int *)moddata;
if (pctx) {
(*pctx)++;
}
} 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. */
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
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)
/* 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
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. */
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)
{
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
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
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;
+}
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
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"]
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 = \{"
global portbase
global mode
global tmppwd
- global KRB5_PA_MODULE_DIR
+ global MODULE_DIR
setup_kerberos_env kdc
}
# 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"
}
'libdefaults' : {
'default_realm' : '$realm',
'dns_lookup_kdc' : 'false',
- 'preauth_module_dir' : '$plugins/preauth'
+ 'plugin_base_dir' : '$plugins'
},
'realms' : {
'$realm' : {