pull up r18754 from trunk
authorTom Yu <tlyu@mit.edu>
Wed, 8 Nov 2006 23:44:47 +0000 (23:44 +0000)
committerTom Yu <tlyu@mit.edu>
Wed, 8 Nov 2006 23:44:47 +0000 (23:44 +0000)
 r18754@cathode-dark-space:  coffman | 2006-11-01 17:40:30 -0500
 ticket: 4566
 ticket: 4567
 ticket: 4587
 Target_Version: 1.6
 Tags: pullup

 Modify the preath plugin interface so that a plugin's context is
 global to all the modules within a plugin.  Also, change the
 client-side interface so that the preauth plugin context (once
 created) lives the lifetime of a krb5_context.  This will allow
 future changes that can set plugin parameters.  The client side
 request context lives the lifetime of a call to krb5_get_init_creds().

 Make the sample preauth plugins buildable outside the source tree.

 Fix minor memory leak in sort_krb5_padata_sequence().

 Add a prototype for krb5_do_preauth_tryagain() and change the plugin
 interface.

 Incorporates fixes from Nalin Dahyabhai <nalin@redhat.com> for leaks
 of the function table pointers (rt #4566) and fix KDC crash (rt #4567)

ticket: 4566
ticket: 4567
ticket: 4587
version_fixed: 1.6

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@18777 dc483132-0cff-0310-8789-dd5450dbe970

src/include/k5-int.h
src/include/krb5/preauth_plugin.h
src/kdc/kdc_preauth.c
src/lib/krb5/krb/get_in_tkt.c
src/lib/krb5/krb/init_ctx.c
src/lib/krb5/krb/preauth2.c
src/lib/krb5/os/init_os_ctx.c
src/plugins/preauth/cksum_body/Makefile.in
src/plugins/preauth/cksum_body/cksum_body_main.c [moved from src/plugins/preauth/cksum_body/src/cksum_body.c with 94% similarity]
src/plugins/preauth/wpse/Makefile.in
src/plugins/preauth/wpse/wpse_main.c [moved from src/plugins/preauth/wpse/src/wpse.c with 81% similarity]

index f659e2e1e5f0d2b27c2dee2d66656449684122c2..884bd23c8a169b047e0520ac01cef182c7820046 100644 (file)
@@ -552,9 +552,6 @@ krb5int_locate_server (krb5_context, const krb5_data *realm,
 
 #endif /* KRB5_LIBOS_PROTO__ */
 
-#include <krb5/preauth_plugin.h>
-typedef struct _krb5_preauth_context krb5_preauth_context;
-
 /* new encryption provider api */
 
 struct krb5_enc_provider {
@@ -844,6 +841,71 @@ error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE)
 #ifndef KRB5_PREAUTH__
 #define KRB5_PREAUTH__
 
+#include <krb5/preauth_plugin.h>
+
+/* 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;
+       void (*client_fini)(krb5_context context, void *plugin_context);
+       /* The module's table, and some of its members, copied here for
+        * convenience when we populated the list. */
+       struct krb5plugin_preauth_client_ftable_v0 *ftable;
+       const char *name;
+       int flags, use_count;
+       krb5_error_code (*client_process)(krb5_context context,
+                                         void *plugin_context,
+                                         void *request_context,
+                                         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);
+       krb5_error_code (*client_tryagain)(krb5_context context,
+                                          void *plugin_context,
+                                          void *request_context,
+                                          krb5_kdc_req *request,
+                                          krb5_data *encoded_request_body,
+                                          krb5_data *encoded_previous_request,
+                                          krb5_pa_data *old_pa_data,
+                                          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 **new_pa_data);
+       void (*client_req_init)(krb5_context context, void *plugin_context,
+                              void **request_context);
+       void (*client_req_fini)(krb5_context context, void *plugin_context,
+                              void *request_context);
+       /* The per-pa_type context which the client_process() function
+        * might allocate, which we'll need to clean up later by
+        * calling the client_cleanup() function. */
+       void *request_context;
+    } *modules;
+} krb5_preauth_context;
+
 typedef struct _krb5_pa_enc_ts {
     krb5_timestamp     patimestamp;
     krb5_int32         pausec;
@@ -970,23 +1032,39 @@ void krb5int_populate_gic_opt (
     krb5_preauthtype *pre_auth_types, krb5_creds *creds);
 
 
-krb5_error_code krb5_do_preauth
-(krb5_context, krb5_preauth_context **, krb5_kdc_req *, krb5_data *,
-               krb5_data *, krb5_pa_data **, krb5_pa_data ***,
-               krb5_data *salt, krb5_data *s2kparams,
- krb5_enctype *,
-               krb5_keyblock *,
-               krb5_prompter_fct, void *,
-               krb5_gic_get_as_key_fct, void *);
+krb5_error_code KRB5_CALLCONV krb5_do_preauth
+       (krb5_context context,
+        krb5_kdc_req *request,
+        krb5_data *encoded_request_body,
+        krb5_data *encoded_previous_request,
+        krb5_pa_data **in_padata, krb5_pa_data ***out_padata,
+        krb5_data *salt, 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_error_code KRB5_CALLCONV krb5_do_preauth_tryagain
+       (krb5_context context,
+        krb5_kdc_req *request,
+        krb5_data *encoded_request_body,
+        krb5_data *encoded_previous_request,
+        krb5_pa_data **in_padata,
+        krb5_error *err_reply,
+        krb5_data *salt, 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);
 void KRB5_CALLCONV krb5_init_preauth_context
-       (krb5_context, krb5_preauth_context **);
+       (krb5_context);
+void KRB5_CALLCONV krb5_free_preauth_context
+       (krb5_context);
 void KRB5_CALLCONV krb5_clear_preauth_context_use_counts
-       (krb5_context, krb5_preauth_context *);
+       (krb5_context);
 void KRB5_CALLCONV krb5_preauth_prepare_request
-       (krb5_context, krb5_preauth_context **,
-        krb5_get_init_creds_opt *, krb5_kdc_req *);
-void KRB5_CALLCONV krb5_free_preauth_context
-       (krb5_context, krb5_preauth_context *);
+       (krb5_context, krb5_get_init_creds_opt *, krb5_kdc_req *);
+void KRB5_CALLCONV krb5_preauth_request_context_init
+       (krb5_context);
+void KRB5_CALLCONV krb5_preauth_request_context_fini
+       (krb5_context);
 
 void KRB5_CALLCONV krb5_free_sam_challenge
        (krb5_context, krb5_sam_challenge * );
@@ -1079,6 +1157,7 @@ struct _krb5_context {
 
     /* preauth module stuff */
     struct plugin_dir_handle preauth_plugins;
+    krb5_preauth_context *preauth_context;
 
     /* error detail info */
     struct errinfo err;
index 63600fead2e1eca0e71cb88c10b309fa1c79f2a9..d164192affb3567299eb7f64876c171c7b12b38f 100644 (file)
@@ -157,20 +157,27 @@ typedef struct krb5plugin_preauth_client_ftable_v0 {
      * to add support for. */
     krb5_enctype *enctype_list;
 
-    /* Per-module initialization/cleanup.  The init function is called
-     * by libkrb5 when the module is loaded, and the fini function is
-     * called before the module is unloaded.  Both are optional and
-     * may be called multiple times in case the module is used in
-     * multiple contexts.*/
-    krb5_error_code (*init)(krb5_context, krb5_preauthtype, void **);
-    void (*fini)(krb5_context, krb5_preauthtype, void *);
+    /* 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_error_code (*init)(krb5_context context, void **plugin_context);
+    void (*fini)(krb5_context context, void *plugin_context);
     /* A callback which returns flags indicating if the module is a "real" or
      * an "info" mechanism, and so on.  This function is called for each entry
      * in the client_pa_type_list. */
-    int (*flags)(krb5_context, krb5_preauthtype);
-    /* Clean up a client context.  Can be NULL. */
-    void (*cleanup)(krb5_context context, void *module_context,
+    int (*flags)(krb5_context context, krb5_preauthtype pa_type);
+    /* Per-request initialization/cleanup.  The request_init function is
+     * called when beginning to process a get_init_creds request and the
+     * request_fini function is called when processing of the request is
+     * complete.  This is optional.  It may be called multiple times in
+     * the lifetime of a krb5_context. */
+    void (*request_init)(krb5_context context, void *plugin_context,
                    void **request_context);
+    void (*request_fini)(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
@@ -180,8 +187,8 @@ typedef struct krb5plugin_preauth_client_ftable_v0 {
      * function is called, because it is expected to only ever contain the data
      * obtained from a previous call to this function. */
     krb5_error_code (*process)(krb5_context context,
-                              void *module_context,
-                              void **request_context,
+                              void *plugin_context,
+                              void *request_context,
                               krb5_kdc_req *request,
                               krb5_data *encoded_request_body,
                               krb5_data *encoded_previous_request,
@@ -189,8 +196,8 @@ typedef struct krb5plugin_preauth_client_ftable_v0 {
                               krb5_prompter_fct prompter,
                               void *prompter_data,
                               preauth_get_as_key_proc gak_fct,
-                              krb5_data *salt, krb5_data *s2kparams,
                               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
@@ -198,12 +205,19 @@ typedef struct krb5plugin_preauth_client_ftable_v0 {
      * 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_error_code (*tryagain)(krb5_context context,
-                               void *module_context,
-                               void **request_context,
+                               void *plugin_context,
+                               void *request_context,
                                krb5_kdc_req *request,
                                krb5_data *encoded_request_body,
-                               krb5_error *error,
+                               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);
 } krb5plugin_preauth_client_ftable_v0;
 
@@ -223,11 +237,11 @@ typedef struct krb5plugin_preauth_server_ftable_v0 {
      * provide services for. */
     krb5_preauthtype *pa_type_list;
 
-    /* Per-module initialization/cleanup.  The init function is called by the
-     * KDC when the module is loaded, and the fini function is called before
-     * the module is unloaded.  Both are optional. */
-    krb5_error_code (*init_proc)(krb5_context, krb5_preauthtype, void **);
-    void (*fini_proc)(krb5_context, krb5_preauthtype, void *);
+    /* 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. */
+    krb5_error_code (*init_proc)(krb5_context, void **);
+    void (*fini_proc)(krb5_context, void *);
     /* 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
index 16af527a64e39e293477b4abd1be1a0f815f546d..dfbb5fcc90a9cb6a98ed51ebfa9720632f2f9ee9 100644 (file)
@@ -109,15 +109,15 @@ typedef krb5_error_code (*freepa_proc)
     (krb5_context, void *pa_module_context, void **pa_request_context);
 
 typedef krb5_error_code (*init_proc)
-    (krb5_context, krb5_preauthtype, void **);
+    (krb5_context, void **);
 typedef void (*fini_proc)
-    (krb5_context, krb5_preauthtype, void *);
+    (krb5_context, void *);
 
 typedef struct _krb5_preauth_systems {
     const char *name;
     int                type;
     int                flags;
-    void       *pa_sys_context;
+    void       *plugin_context;
     init_proc   init;
     fini_proc   fini;
     edata_proc get_edata;
@@ -301,8 +301,7 @@ load_preauth_plugins(krb5_context context)
     void **preauth_plugins_ftables;
     struct krb5plugin_preauth_server_ftable_v0 *ftable;
     int module_count, i, j, k;
-    krb5_preauthtype pa_type;
-    void *pa_sys_context;
+    void *plugin_context;
     init_proc server_init_proc;
 
     memset(&err, 0, sizeof(err));
@@ -349,6 +348,7 @@ load_preauth_plugins(krb5_context context)
      * 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);
        return ENOMEM;
     }
 
@@ -361,15 +361,14 @@ load_preauth_plugins(krb5_context context)
        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. */
-       pa_sys_context = NULL;
-       pa_type = static_preauth_systems[i].type;
+       plugin_context = NULL;
        server_init_proc = static_preauth_systems[i].init;
        if ((server_init_proc != NULL) &&
-           ((*server_init_proc)(context, pa_type, &pa_sys_context) != 0)) {
+           ((*server_init_proc)(context, &plugin_context) != 0)) {
            memset(&preauth_systems[k], 0, sizeof(preauth_systems[k]));
            continue;
        }
-       preauth_systems[k].pa_sys_context = pa_sys_context;
+       preauth_systems[k].plugin_context = plugin_context;
        k++;
     }
 
@@ -383,28 +382,34 @@ load_preauth_plugins(krb5_context context)
                (ftable->return_proc == NULL)) {
                continue;
            }
+           plugin_context = NULL;
            for (j = 0;
                 ftable->pa_type_list != NULL &&
                 ftable->pa_type_list[j] > 0;
                 j++) {
-               /* Try to initialize the module.  If it fails, we'll remove it
+               /* Try to initialize the plugin.  If it fails, we'll remove it
                 * from the list of modules we'll be using. */
-               pa_sys_context = NULL;
-               server_init_proc = ftable->init_proc;
-               pa_type = ftable->pa_type_list[j];
-               if ((server_init_proc != NULL) &&
-                   ((*server_init_proc)(context, pa_type,
-                                        &pa_sys_context) != 0)) {
-                   memset(&preauth_systems[k], 0, sizeof(preauth_systems[k]));
-                   continue;
+               if (j == 0) {
+                   server_init_proc = ftable->init_proc;
+                   if ((server_init_proc != NULL) &&
+                       ((*server_init_proc)(context, &plugin_context) != 0)) {
+                       memset(&preauth_systems[k], 0, sizeof(preauth_systems[k]));
+                       continue;
+                   }
                }
                preauth_systems[k].name = ftable->name;
-               pa_type = ftable->pa_type_list[j];
-               preauth_systems[k].type = pa_type;
-               preauth_systems[k].flags = ftable->flags_proc(context, pa_type);
-               preauth_systems[k].pa_sys_context = pa_sys_context;
+               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;
-               preauth_systems[k].fini = ftable->fini_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;
@@ -413,6 +418,7 @@ load_preauth_plugins(krb5_context context)
                k++;
            }
        }
+       krb5int_free_plugin_dir_data(preauth_plugins_ftables);
     }
     n_preauth_systems = k;
     /* Add the end-of-list marker. */
@@ -429,8 +435,7 @@ unload_preauth_plugins(krb5_context context)
        for (i = 0; i < n_preauth_systems; i++) {
            if (preauth_systems[i].fini != NULL) {
                (*preauth_systems[i].fini)(context,
-                                          preauth_systems[i].type,
-                                          preauth_systems[i].pa_sys_context);
+                                          preauth_systems[i].plugin_context);
            }
            memset(&preauth_systems[i], 0, sizeof(preauth_systems[i]));
        }
@@ -506,7 +511,7 @@ free_padata_context(krb5_context kcontext, void **padata_context)
     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->pa_sys_context;
+           mctx = preauth_system->plugin_context;
            if (preauth_system->free_pa_request_context != NULL) {
                pctx = &context->contexts[i].pa_context;
                (*preauth_system->free_pa_request_context)(kcontext, mctx,
@@ -721,25 +726,28 @@ sort_pa_order(krb5_context context, krb5_kdc_req *request, int *pa_order)
         }
     }
 
-    /* Now sort just the modules which replace the key, placing those which
-     * handle the pa_data types provided by the client ahead of the others. */
-    for (i = 0; preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY; i++) {
-       continue;
-    }
-    n_key_replacers = i;
-    for (i = 0; i < n_key_replacers; i++) {
-       if (pa_list_includes(request->padata,
-                            preauth_systems[pa_order[i]].type))
+    if (request->padata != NULL) {
+       /* Now reorder the subset of modules which replace the key,
+        * bubbling those which handle pa_data types provided by the
+        * client ahead of the others. */
+       for (i = 0; preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY; i++) {
            continue;
-        for (j = i + 1; j < n_key_replacers; j++) {
+       }
+       n_key_replacers = i;
+       for (i = 0; i < n_key_replacers; i++) {
            if (pa_list_includes(request->padata,
-                                preauth_systems[pa_order[j]].type)) {
-                k = pa_order[j];
-               pa_order[j] = pa_order[i];
-               pa_order[i] = k;
-               break;
+                               preauth_systems[pa_order[i]].type))
+               continue;
+           for (j = i + 1; j < n_key_replacers; j++) {
+               if (pa_list_includes(request->padata,
+                                   preauth_systems[pa_order[j]].type)) {
+                   k = pa_order[j];
+                   pa_order[j] = pa_order[i];
+                   pa_order[i] = k;
+                   break;
+               }
            }
-        }
+       }
     }
 #ifdef DEBUG
     krb5_klog_syslog(LOG_DEBUG, "original preauth mechanism list:");
@@ -827,7 +835,7 @@ void get_preauth_hint_list(krb5_kdc_req *request, krb5_db_entry *client,
        (*pa)->pa_type = ap->type;
        if (ap->get_edata) {
          retval = (ap->get_edata)(kdc_context, request, client, server,
-                                  get_entry_data, ap->pa_sys_context, *pa);
+                                  get_entry_data, ap->plugin_context, *pa);
          if (retval) {
            /* just failed on this type, continue */
            free(*pa);
@@ -899,7 +907,7 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt,
        pa_found++;
        retval = pa_sys->verify_padata(context, client, req_pkt, request,
                                       enc_tkt_reply, *padata,
-                                      get_entry_data, pa_sys->pa_sys_context,
+                                      get_entry_data, pa_sys->plugin_context,
                                       pa_context);
        if (retval) {
            const char * emsg = krb5_get_error_message (context, retval);
@@ -1046,7 +1054,7 @@ return_padata(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt,
        }
        if ((retval = ap->return_padata(context, pa, client, req_pkt, request, reply,
                                        client_key, encrypting_key, send_pa,
-                                       get_entry_data, ap->pa_sys_context,
+                                       get_entry_data, ap->plugin_context,
                                        pa_context))) {
            goto cleanup;
        }
index 8d75c60c37608937bdb8e00815decead4260bc04..947984f62a897204a6894d211d50321ad64b42aa 100644 (file)
@@ -774,6 +774,7 @@ sort_krb5_padata_sequence(krb5_context context, krb5_data *realm,
     long l;
     char *q, *preauth_types = NULL;
     krb5_pa_data *tmp;
+    int need_free_string = 1;
 
     if ((padata == NULL) || (padata[0] == NULL)) {
        return 0;
@@ -784,6 +785,7 @@ sort_krb5_padata_sequence(krb5_context context, krb5_data *realm,
     if ((ret != 0) || (preauth_types == NULL)) {
        /* Try to use PKINIT first. */
        preauth_types = "17, 16, 15, 14";
+       need_free_string = 0;
     }
 
 #ifdef DEBUG
@@ -820,6 +822,8 @@ sort_krb5_padata_sequence(krb5_context context, krb5_data *realm,
            }
        }
     }
+    if (need_free_string)
+       free(preauth_types);
 
 #ifdef DEBUG
     fprintf (stderr, "preauth data types after sorting:");
@@ -861,7 +865,6 @@ krb5_get_init_creds(krb5_context context,
     krb5_kdc_rep *local_as_reply;
     krb5_timestamp time_now;
     krb5_enctype etype = 0;
-    krb5_preauth_context *preauth_context;
 
     /* initialize everything which will be freed at cleanup */
 
@@ -881,7 +884,6 @@ krb5_get_init_creds(krb5_context context,
 
        local_as_reply = 0;
 
-    preauth_context = NULL;
     err_reply = NULL;
 
     /*
@@ -1017,7 +1019,7 @@ krb5_get_init_creds(krb5_context context,
            goto cleanup;
     }
 
-    krb5_init_preauth_context(context, &preauth_context);
+    krb5_preauth_request_context_init(context);
 
     /* nonce is filled in by send_as_request if we don't take care of it */
 
@@ -1084,7 +1086,7 @@ krb5_get_init_creds(krb5_context context,
     request.nonce = (krb5_int32) time_now;
 
     /* give the preauth plugins a chance to prep the request body */
-    krb5_preauth_prepare_request(context, &preauth_context, options, &request);
+    krb5_preauth_prepare_request(context, options, &request);
     ret = encode_krb5_kdc_req_body(&request, &encoded_request_body);
     if (ret)
         goto cleanup;
@@ -1097,7 +1099,7 @@ krb5_get_init_creds(krb5_context context,
                krb5_free_pa_data(context, request.padata);
                request.padata = NULL;
            }
-           if ((ret = krb5_do_preauth(context, &preauth_context,
+           if ((ret = krb5_do_preauth(context,
                                       &request,
                                       encoded_request_body,
                                       encoded_previous_request,
@@ -1109,14 +1111,13 @@ krb5_get_init_creds(krb5_context context,
        } else {
            /* retrying after an error other than PREAUTH_NEEDED, using e-data
             * to figure out what to change */
-           if (krb5_do_preauth_tryagain(context, &preauth_context,
+           if (krb5_do_preauth_tryagain(context,
                                         &request,
                                         encoded_request_body,
                                         encoded_previous_request,
-                                        preauth_to_use, err_reply,
-                                        &request.padata,
-                                        &salt, &s2kparams,
-                                        &etype, &as_key,
+                                        preauth_to_use,
+                                        err_reply,
+                                        &salt, &s2kparams, &etype, &as_key,
                                         prompter, prompter_data,
                                         gak_fct, gak_data)) {
                /* couldn't come up with anything better */
@@ -1188,11 +1189,11 @@ krb5_get_init_creds(krb5_context context,
     }
 
     /* process any preauth data in the as_reply */
-    krb5_clear_preauth_context_use_counts(context, preauth_context);
+    krb5_clear_preauth_context_use_counts(context);
     if ((ret = sort_krb5_padata_sequence(context, &request.server->realm,
                                         local_as_reply->padata)))
        goto cleanup;
-    if ((ret = krb5_do_preauth(context, &preauth_context,
+    if ((ret = krb5_do_preauth(context,
                               &request,
                               encoded_request_body, encoded_previous_request,
                               local_as_reply->padata, &kdc_padata,
@@ -1252,10 +1253,7 @@ krb5_get_init_creds(krb5_context context,
     ret = 0;
 
 cleanup:
-    if (preauth_context != NULL) {
-       krb5_free_preauth_context(context, preauth_context);
-       preauth_context = NULL;
-    }
+    krb5_preauth_request_context_fini(context);
     if (encoded_previous_request != NULL) {
        krb5_free_data(context, encoded_previous_request);
        encoded_previous_request = NULL;
index 46c3068eee4b64265180b0a5fa79383f71dccb52..5ce00169a3488bd49c67893c217e0b20207e006c 100644 (file)
@@ -535,6 +535,7 @@ krb5_copy_context(krb5_context ctx, krb5_context *nctx_out)
     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;
index ce2bf688344ad188a9711763aee2800583b1263c..64823732fb1feda43a883c2205fe6e711d33ac76 100644 (file)
@@ -59,76 +59,25 @@ typedef struct _pa_types_t {
     int flags;
 } pa_types_t;
 
-/* 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 {
-    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 module's per-module context and a function to clear it. */
-       void *module_context;
-       void (*client_fini)(krb5_context context, krb5_preauthtype pa_type,
-                           void *module_context);
-       /* The module's table, and some of its members, copied here for
-        * convenience when we populated the list. */
-       struct krb5plugin_preauth_client_ftable_v0 *ftable;
-       const char *name;
-       int flags, use_count;
-       krb5_error_code (*client_process)(krb5_context context,
-                                         void *module_context,
-                                         void **request_context,
-                                         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_data *salt,
-                                         krb5_data *s2kparams,
-                                         void *gak_data,
-                                         krb5_keyblock *as_key,
-                                         krb5_pa_data **out_pa_data);
-       krb5_error_code (*client_tryagain)(krb5_context context,
-                                          void *module_context,
-                                          void **request_context,
-                                          krb5_kdc_req *request,
-                                          krb5_data *encoded_request_body,
-                                          krb5_error *err_reply,
-                                          krb5_pa_data *old_pa_data,
-                                          krb5_pa_data **new_pa_data);
-       void (*client_cleanup)(krb5_context context, void *module_context,
-                              void **request_context);
-       /* The per-pa_type context which the client_process() function
-        * might allocate, which we'll need to clean up later by
-        * calling the client_cleanup() function. */
-       void *request_context;
-    } *modules;
-};
-
-/* Create the per-AS-REQ 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 list of support pa_types
- * so that we can iterate over the modules more easily, and copying over the
- * relevant parts of the module's table. */
+/* 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
+ * list of support pa_types so that we can iterate over the modules more
+ * easily, and copying over the relevant parts of the module's table. */
 void
-krb5_init_preauth_context(krb5_context kcontext,
-                         krb5_preauth_context **preauth_context)
+krb5_init_preauth_context(krb5_context kcontext)
 {
     int n_modules, n_tables, i, j, k;
     void **tables;
     struct krb5plugin_preauth_client_ftable_v0 *table;
-    krb5_preauth_context *context;
-    void *module_context;
+    krb5_preauth_context *context = NULL;
+    void *plugin_context;
     krb5_preauthtype pa_type;
 
+    /* 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 (krb5int_open_plugin_dirs(objdirs, NULL,
@@ -167,10 +116,12 @@ krb5_init_preauth_context(krb5_context kcontext,
     /* allocate the space we need */
     context = malloc(sizeof(*context));
     if (context == NULL) {
+       krb5int_free_plugin_dir_data(tables);
         return;
     }
     context->modules = malloc(sizeof(context->modules[0]) * n_modules);
     if (context->modules == NULL) {
+       krb5int_free_plugin_dir_data(tables);
         free(context);
         return;
     }
@@ -182,28 +133,40 @@ krb5_init_preauth_context(krb5_context kcontext,
     for (i = 0; i < n_tables; i++) {
         table = tables[i];
         if ((table->pa_type_list != NULL) && (table->process != NULL)) {
-            for (j = 0; table->pa_type_list[j] > 0; j++) {
-               pa_type = table->pa_type_list[j];
-               module_context = NULL;
-               if ((table->init != NULL) &&
-                   ((*table->init)(kcontext, pa_type, &module_context) != 0)) {
+           plugin_context = NULL;
+           if ((table->init != NULL) &&
+               ((*table->init)(kcontext, &plugin_context) != 0)) {
 #ifdef DEBUG
-                       fprintf (stderr, "skip module \"%s\", pa_type %d\n",
-                                table->name, pa_type);
+                   fprintf (stderr, "init err, skipping module \"%s\"\n",
+                            table->name);
 #endif
-                       continue;
-               }
+                   continue;
+           }
+
+            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].module_context = module_context;
-               context->modules[k].client_fini = table->fini;
+               context->modules[k].plugin_context = plugin_context;
+               /* 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;
-               context->modules[k].client_cleanup = table->cleanup;
+               /* Only call request_init and request_fini once per plugin */
+               if (j == 0) {
+                   context->modules[k].client_req_init = table->request_init;
+                   context->modules[k].client_req_fini = table->request_fini;
+               } else {
+                   context->modules[k].client_req_init = NULL;
+                   context->modules[k].client_req_fini = NULL;
+               }
                context->modules[k].request_context = NULL;
 #ifdef DEBUG
                fprintf (stderr, "init module \"%s\", pa_type %d, flag %d\n",
@@ -215,60 +178,92 @@ krb5_init_preauth_context(krb5_context kcontext,
            }
        }
     }
+    krb5int_free_plugin_dir_data(tables);
 
     /* return the result */
-    *preauth_context = context;
+    kcontext->preauth_context = context;
 }
 
 /* Zero the use counts for the modules herein.  Usually used before we
  * start processing any data from the server, at which point every module
  * will again be able to take a crack at whatever the server sent. */
 void
-krb5_clear_preauth_context_use_counts(krb5_context context,
-                                     krb5_preauth_context *preauth_context)
+krb5_clear_preauth_context_use_counts(krb5_context context)
 {
     int i;
-    if (preauth_context != NULL) {
-       for (i = 0; i < preauth_context->n_modules; i++) {
-           preauth_context->modules[i].use_count = 0;
+    if (context->preauth_context != NULL) {
+       for (i = 0; i < context->preauth_context->n_modules; i++) {
+           context->preauth_context->modules[i].use_count = 0;
        }
     }
 }
 
-/* Free the per-AS-REQ context. This means clearing any module-specific or
- * request-specific context which the modules may have created, and then
+/* Free the per-krb5_context preauth_context. This means clearing any
+ * plugin-specific context which may have been created, and then
  * freeing the context itself. */
 void
-krb5_free_preauth_context(krb5_context context,
-                         krb5_preauth_context *preauth_context)
+krb5_free_preauth_context(krb5_context context)
 {
     int i;
-    krb5_preauthtype pa_type;
-    void **rctx, *mctx;
-    if (preauth_context != NULL) {
-       for (i = 0; i < preauth_context->n_modules; i++) {
-           mctx = preauth_context->modules[i].module_context;
-           if (preauth_context->modules[i].request_context != NULL) {
-               if (preauth_context->modules[i].client_cleanup != NULL) {
-                   rctx = &preauth_context->modules[i].request_context;
-                   preauth_context->modules[i].client_cleanup(context,
-                                                              mctx, rctx);
-               }
-               preauth_context->modules[i].request_context = NULL;
+    void *pctx;
+    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_fini != NULL) {
+               (*context->preauth_context->modules[i].client_fini)(context, pctx);
            }
-           if (preauth_context->modules[i].client_fini != NULL) {
-               pa_type = preauth_context->modules[i].pa_type;
-               (*preauth_context->modules[i].client_fini)(context, pa_type,
-                                                          mctx);
+           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;
+    }
+}
+
+/* Initialize the per-AS-REQ context. This means calling the client_req_init
+ * function to give the plugin a chance to allocate a per-request context. */
+void
+krb5_preauth_request_context_init(krb5_context context)
+{
+    int i;
+    void *rctx, *pctx;
+
+    /* 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;
+               (*context->preauth_context->modules[i].client_req_init) (context, pctx, rctx);
            }
-           memset(&preauth_context->modules[i], 0,
-                  sizeof(preauth_context->modules[i]));
        }
-       if (preauth_context->modules != NULL) {
-           free(preauth_context->modules);
-           preauth_context->modules = NULL;
+    }
+}
+
+/* Free the per-AS-REQ context. This means clearing any request-specific
+ * context which the plugin may have created. */
+void
+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;
+           }
        }
-       free(preauth_context);
     }
 }
 
@@ -337,24 +332,23 @@ grow_pa_list(krb5_pa_data ***out_pa_list, int *out_pa_list_size,
  * involved things. */
 void
 krb5_preauth_prepare_request(krb5_context kcontext,
-                            krb5_preauth_context **preauth_context,
                             krb5_get_init_creds_opt *options,
                             krb5_kdc_req *request)
 {
     int i, j;
 
-    if ((preauth_context == NULL) || (*preauth_context == NULL)) {
+    if (kcontext->preauth_context == NULL) {
        return;
     }
     /* Add the module-specific enctype list to the request, but only if
      * it's something we can safely modify. */
     if (!(options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST))) {
-       for (i = 0; i < (*preauth_context)->n_modules; i++) {
-           if ((*preauth_context)->modules[i].enctypes == NULL)
+       for (i = 0; i < kcontext->preauth_context->n_modules; i++) {
+           if (kcontext->preauth_context->modules[i].enctypes == NULL)
                continue;
-           for (j = 0; (*preauth_context)->modules[i].enctypes[j] != 0; j++) {
+           for (j = 0; kcontext->preauth_context->modules[i].enctypes[j] != 0; j++) {
                grow_ktypes(&request->ktype, &request->nktypes,
-                           (*preauth_context)->modules[i].enctypes[j]);
+                           kcontext->preauth_context->modules[i].enctypes[j]);
            }
        }
     }
@@ -365,7 +359,6 @@ krb5_preauth_prepare_request(krb5_context kcontext,
  * they don't generate preauth data), and run it. */
 static krb5_error_code
 krb5_run_preauth_plugins(krb5_context kcontext,
-                        krb5_preauth_context *preauth_context,
                         int module_required_flags,
                         krb5_kdc_req *request,
                         krb5_data *encoded_request_body,
@@ -388,12 +381,12 @@ krb5_run_preauth_plugins(krb5_context kcontext,
     krb5_error_code ret;
     struct _krb5_preauth_context_module *module;
 
-    if (preauth_context == NULL) {
+    if (kcontext->preauth_context == NULL) {
        return ENOENT;
     }
     /* iterate over all loaded modules */
-    for (i = 0; i < preauth_context->n_modules; i++) {
-       module = &preauth_context->modules[i];
+    for (i = 0; i < kcontext->preauth_context->n_modules; i++) {
+       module = &kcontext->preauth_context->modules[i];
        /* skip over those which don't match the preauth type */
        if (module->pa_type != in_padata->pa_type)
            continue;
@@ -418,14 +411,14 @@ krb5_run_preauth_plugins(krb5_context kcontext,
                module->name, module->pa_type, module->flags);
 #endif
        ret = module->client_process(kcontext,
-                                    module->module_context,
-                                    &module->request_context,
+                                    module->plugin_context,
+                                    module->request_context,
                                     request,
                                     encoded_request_body,
                                     encoded_previous_request,
                                     in_padata,
                                     prompter, prompter_data,
-                                    gak_fct, salt, s2kparams, gak_data,
+                                    gak_fct, gak_data, salt, s2kparams,
                                     as_key,
                                     &out_pa_data);
        /* Make note of the module's flags and status. */
@@ -439,7 +432,7 @@ krb5_run_preauth_plugins(krb5_context kcontext,
        }
        break;
     }
-    if (i >= preauth_context->n_modules) {
+    if (i >= kcontext->preauth_context->n_modules) {
        return ENOENT;
     }
     return 0;
@@ -1219,10 +1212,16 @@ static const pa_types_t pa_types[] = {
  */
 krb5_error_code
 krb5_do_preauth_tryagain(krb5_context kcontext,
-                        krb5_preauth_context **preauth_context,
                         krb5_kdc_req *request,
                         krb5_data *encoded_request_body,
-                        krb5_error *err_reply, krb5_pa_data **padata)
+                        krb5_data *encoded_previous_request,
+                        krb5_pa_data **padata,
+                        krb5_error *err_reply,
+                        krb5_data *salt, 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_error_code ret;
     krb5_pa_data *out_padata;
@@ -1231,10 +1230,10 @@ krb5_do_preauth_tryagain(krb5_context kcontext,
     int i, j;
 
     ret = KRB_ERR_GENERIC;
-    if (preauth_context == NULL) {
+    if (kcontext->preauth_context == NULL) {
        return KRB_ERR_GENERIC;
     }
-    context = *preauth_context;
+    context = kcontext->preauth_context;
     if (context == NULL) {
        return KRB_ERR_GENERIC;
     }
@@ -1250,12 +1249,16 @@ krb5_do_preauth_tryagain(krb5_context kcontext,
                continue;
            }
            if ((*module->client_tryagain)(kcontext,
-                                          module->module_context,
+                                          module->plugin_context,
                                           module->request_context,
                                           request,
                                           encoded_request_body,
-                                          err_reply,
+                                          encoded_previous_request,
                                           padata[i],
+                                          err_reply,
+                                          prompter, prompter_data,
+                                          gak_fct, gak_data, salt, s2kparams,
+                                          as_key,
                                           &out_padata) == 0) {
                if (out_padata != NULL) {
                    if (padata[i]->contents != NULL)
@@ -1272,7 +1275,6 @@ krb5_do_preauth_tryagain(krb5_context kcontext,
 
 krb5_error_code
 krb5_do_preauth(krb5_context context,
-               krb5_preauth_context **preauth_context,
                krb5_kdc_req *request,
                krb5_data *encoded_request_body,
                krb5_data *encoded_previous_request,
@@ -1450,18 +1452,15 @@ krb5_do_preauth(krb5_context context,
            }
 
            /* Try to use plugins now. */
-           if ((!realdone) && (preauth_context != NULL)) {
-               if (*preauth_context == NULL) {
-                   krb5_init_preauth_context(context, preauth_context);
-               }
-               if (*preauth_context != NULL) {
+           if (!realdone) {
+               krb5_init_preauth_context(context);
+               if (context->preauth_context != NULL) {
                    int module_ret, module_flags;
 #ifdef DEBUG
                    fprintf (stderr, "trying modules for pa_type %d, flag %d\n",
                             in_padata[i]->pa_type, paorder[h]);
 #endif
                    ret = krb5_run_preauth_plugins(context,
-                                                  *preauth_context,
                                                   paorder[h],
                                                   request,
                                                   encoded_request_body,
index bc7e007ff7d6dc191e4105f14fbab500a0afb9fc..b3d8dcf8c5e2f21500f37be661f03eb930d1aad4 100644 (file)
@@ -392,6 +392,7 @@ krb5_os_init_context(krb5_context ctx, krb5_boolean kdc)
        ctx->vtbl = 0;
        PLUGIN_DIR_INIT(&ctx->libkrb5_plugins);
        PLUGIN_DIR_INIT(&ctx->preauth_plugins);
+       ctx->preauth_context = NULL;
 
        retval = os_init_paths(ctx, kdc);
        /*
@@ -493,6 +494,10 @@ krb5_os_free_context(krb5_context ctx)
            ctx->profile = 0;
        }
 
+       if (ctx->preauth_context) {
+               krb5_free_preauth_context(ctx);
+               ctx->preauth_context = NULL;
+       }
        krb5int_close_plugin_dirs (&ctx->preauth_plugins);
        krb5int_close_plugin_dirs (&ctx->libkrb5_plugins);
 
index ddac24dcadd940ad60e81b1dcacd79d66261d96b..83d7cdb5b53a1187e7efd194d772f8b6772b0fc2 100644 (file)
@@ -9,7 +9,7 @@ PROG_RPATH=$(KRB5_LIBDIR)
 MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR)
 DEFS=@DEFS@
 
-LOCALINCLUDES = -I../../../include/krb5
+LOCALINCLUDES = -I../../../include/krb5 -I.
 
 LIBBASE=cksum_body
 LIBMAJOR=0
@@ -25,9 +25,9 @@ SHLIB_EXPLIBS= -lkrb5 -lcom_err -lk5crypto $(SUPPORT_LIB) $(LIBS)
 SHLIB_DIRS=-L$(TOPLIBD)
 SHLIB_RDIRS=$(KRB5_LIBDIR)
 STOBJLISTS=OBJS.ST
-STLIBOBJS=src/cksum_body.o
+STLIBOBJS=cksum_body_main.o
 
-SRCS= $(srcdir)/src/cksum_body.c
+SRCS= $(srcdir)/cksum_body_main.c
 
 all-unix:: $(LIBBASE)$(SO_EXT)
 install-unix:: install-libs
similarity index 94%
rename from src/plugins/preauth/cksum_body/src/cksum_body.c
rename to src/plugins/preauth/cksum_body/cksum_body_main.c
index 31ecaf839e19217d232ea07717be95c864dd7483..abf019a7545d7667df348b992e7e31dbcbcae16c 100644 (file)
@@ -44,7 +44,7 @@
 #ident "$Id$"
 
 #ifdef HAVE_CONFIG_H
-#include "../config.h"
+#include "config.h"
 #endif
 
 #ifdef HAVE_ERRNO_H
@@ -76,8 +76,8 @@ client_get_flags(krb5_context kcontext, krb5_preauthtype pa_type)
 
 static krb5_error_code
 client_process(krb5_context kcontext,
-              void *client_module_context,
-              void **client_request_context,
+              void *client_plugin_context,
+              void *client_request_context,
               krb5_kdc_req *request,
               krb5_data *encoded_request_body,
               krb5_data *encoded_previous_request,
@@ -85,8 +85,8 @@ client_process(krb5_context kcontext,
               krb5_prompter_fct prompter,
               void *prompter_data,
               preauth_get_as_key_proc gak_fct,
-              krb5_data *salt, krb5_data *s2kparams,
               void *gak_data,
+              krb5_data *salt, krb5_data *s2kparams,
               krb5_keyblock *as_key,
               krb5_pa_data **out_pa_data)
 {
@@ -94,7 +94,7 @@ client_process(krb5_context kcontext,
     krb5_checksum checksum;
     krb5_enctype enctype;
     krb5_cksumtype *cksumtypes;
-    krb5_error_code status;
+    krb5_error_code status = 0;
     krb5_int32 cksumtype, *enctypes;
     unsigned int i, n_enctypes, cksumtype_count;
 
@@ -193,8 +193,7 @@ client_process(krb5_context kcontext,
 
 /* Initialize and tear down the server-side module, and do stat tracking. */
 static krb5_error_code
-server_init(krb5_context kcontext, krb5_preauthtype pa_type,
-           void **module_context)
+server_init(krb5_context kcontext, void **module_context)
 {
     struct server_stats *stats;
     stats = malloc(sizeof(struct server_stats));
@@ -206,15 +205,14 @@ server_init(krb5_context kcontext, krb5_preauthtype pa_type,
     return 0;
 }
 static void
-server_fini(krb5_context kcontext, krb5_preauthtype pa_type,
-           void *module_context)
+server_fini(krb5_context kcontext, void *module_context)
 {
     struct server_stats *stats;
     stats = module_context;
     if (stats != NULL) {
 #ifdef DEBUG
-       fprintf(stderr, "Total %d clients failed pa_type %d, %d succeeded.\n",
-               stats->failures, pa_type, stats->successes);
+       fprintf(stderr, "Total: %d clients failed, %d succeeded.\n",
+               stats->failures, stats->successes);
 #endif
        free(stats);
     }
@@ -254,7 +252,7 @@ server_get_edata(krb5_context kcontext,
        krb5_free_keyblock_contents(kcontext, &keys[i]);
 
     /* Return the list of encryption types. */
-    enctypes = malloc(i * 4);
+    enctypes = malloc((unsigned)i * 4);
     if (enctypes == NULL) {
        krb5_free_data(kcontext, key_data);
        return ENOMEM;
@@ -469,15 +467,16 @@ static krb5_preauthtype supported_server_pa_types[] = {
 };
 
 struct krb5plugin_preauth_client_ftable_v0 preauthentication_client_0 = {
-    "cksum_body",
-    &supported_client_pa_types[0],
-    NULL,
-    NULL,
-    NULL,
-    client_get_flags,
-    NULL,
-    client_process,
-    NULL,
+    "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 */
 };
 
 struct krb5plugin_preauth_server_ftable_v0 preauthentication_server_0 = {
index 6b18a7c064572e92f23332b2a1813d4c5b891449..6c2830f50ba4b3423336042adda019338485cb87 100644 (file)
@@ -9,7 +9,7 @@ PROG_RPATH=$(KRB5_LIBDIR)
 MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR)
 DEFS=@DEFS@
 
-LOCALINCLUDES = -I../../../include/krb5
+LOCALINCLUDES = -I../../../include/krb5 -I.
 
 LIBBASE=wpse
 LIBMAJOR=0
@@ -25,9 +25,9 @@ SHLIB_EXPLIBS= -lkrb5 -lcom_err -lk5crypto $(SUPPORT_LIB) $(LIBS)
 SHLIB_DIRS=-L$(TOPLIBD)
 SHLIB_RDIRS=$(KRB5_LIBDIR)
 STOBJLISTS=OBJS.ST
-STLIBOBJS=src/wpse.o
+STLIBOBJS=wpse_main.o
 
-SRCS= $(srcdir)/src/wpse.c
+SRCS=wpse_main.c
 
 all-unix:: $(LIBBASE)$(SO_EXT)
 install-unix:: install-libs
similarity index 81%
rename from src/plugins/preauth/wpse/src/wpse.c
rename to src/plugins/preauth/wpse/wpse_main.c
index 07c52d95a3d3fd615769c9c44ca0b69669a40d28..e7d7b6d5575f992636d8d37c51fc821484acb2f6 100644 (file)
@@ -33,7 +33,7 @@
 #ident "$Id$"
 
 #ifdef HAVE_CONFIG_H
-#include "../config.h"
+#include "config.h"
 #endif
 
 #ifdef HAVE_ERRNO_H
@@ -60,36 +60,36 @@ client_get_flags(krb5_context kcontext, krb5_preauthtype pa_type)
 }
 
 static krb5_error_code
-client_init(krb5_context kcontext, krb5_preauthtype pa_type, void **ctx)
+client_init(krb5_context kcontext, void **ctx)
 {
-    int *mctx;
+    int *pctx;
 
-    mctx = malloc(sizeof(int));
-    if (mctx == NULL)
+    pctx = malloc(sizeof(int));
+    if (pctx == NULL)
        return ENOMEM;
-    *mctx = 0;
-    *ctx = mctx;
+    *pctx = 0;
+    *ctx = pctx;
     return 0;
 }
 
 static void
-client_fini(krb5_context kcontext, krb5_preauthtype pa_type, void *ctx)
+client_fini(krb5_context kcontext, void *ctx)
 {
-    int *mctx;
+    int *pctx;
 
-    mctx = ctx;
-    if (mctx) {
+    pctx = ctx;
+    if (pctx) {
 #ifdef DEBUG
-        fprintf(stderr, "wpse module called total of %d times\n", *mctx);
+        fprintf(stderr, "wpse module called total of %d times\n", *pctx);
 #endif
-        free(mctx);
+        free(pctx);
     }
 }
 
 static krb5_error_code
 client_process(krb5_context kcontext,
-              void *module_context,
-              void **request_context,
+              void *plugin_context,
+              void *request_context,
               krb5_kdc_req *request,
               krb5_data *encoded_request_body,
               krb5_data *encoded_previous_request,
@@ -97,8 +97,8 @@ client_process(krb5_context kcontext,
               krb5_prompter_fct prompter,
               void *prompter_data,
               preauth_get_as_key_proc gak_fct,
-              krb5_data *salt, krb5_data *s2kparams,
               void *gak_data,
+              krb5_data *salt, krb5_data *s2kparams,
               krb5_keyblock *as_key,
               krb5_pa_data **out_pa_data)
 {
@@ -106,16 +106,16 @@ client_process(krb5_context kcontext,
     krb5_int32 nnonce, enctype;
     krb5_keyblock *kb;
     krb5_error_code status;
-    int *mctx;
+    int *pctx;
 
 #ifdef DEBUG
     fprintf(stderr, "%d bytes of preauthentication data (type %d)\n",
            pa_data->length, pa_data->pa_type);
 #endif
 
-    mctx = module_context;
-    if (mctx) {
-       (*mctx)++;
+    pctx = plugin_context;
+    if (pctx) {
+       (*pctx)++;
     }
 
     if (pa_data->length == 0) {
@@ -134,10 +134,6 @@ client_process(krb5_context kcontext,
        nnonce = htonl(request->nonce);
        memcpy(send_pa->contents, &nnonce, 4);
        *out_pa_data = send_pa;
-       /* Allocate a context. Useful for verifying that we do in fact
-        * do per-request cleanup. */
-       if (*request_context == NULL)
-           *request_context = malloc(4);
     } else {
        /* A reply from the KDC.  Conventionally this would be
         * indicated by a different preauthentication type, but this
@@ -163,20 +159,56 @@ client_process(krb5_context kcontext,
     return 0;
 }
 
+#define WPSE_MAGIC 0x77707365
+typedef struct _wpse_req_ctx
+{
+    int magic;
+    int value;
+} wpse_req_ctx;
+
 static void
-client_cleanup(krb5_context kcontext, void *module_context,
-              void **request_context)
+client_req_init(krb5_context kcontext, void *plugin_context, void **req_context_p)
 {
-    if (*request_context != NULL) {
-       free(*request_context);
-       *request_context = NULL;
+    wpse_req_ctx *ctx;
+
+    *req_context_p = NULL;
+
+    /* Allocate a request context. Useful for verifying that we do in fact
+     * do per-request cleanup. */
+    ctx = (wpse_req_ctx *) malloc(sizeof(*ctx));
+    if (ctx == NULL)
+       return;
+    ctx->magic = WPSE_MAGIC;
+    ctx->value = 0xc0dec0de;
+
+    *req_context_p = ctx;
+}
+
+static void
+client_req_cleanup(krb5_context kcontext, void *plugin_context, void *req_context)
+{
+    wpse_req_ctx *ctx = (wpse_req_ctx *)req_context;
+
+    if (ctx) {
+#ifdef DEBUG
+       fprintf(stderr, "client_req_cleanup: req_ctx at %p has magic %x and value %x\n",
+               ctx, ctx->magic, ctx->value);
+#endif
+       if (ctx->magic != WPSE_MAGIC) {
+#ifdef DEBUG
+           fprintf(stderr, "client_req_cleanup: req_context at %p has bad magic value %x\n",
+                   ctx, ctx->magic);
+#endif
+           return;
+       }
+       free(ctx);
     }
     return;
 }
 
 /* Free state. */
 static krb5_error_code
-server_free_pa_request_context(krb5_context kcontext, void *module_context,
+server_free_pa_request_context(krb5_context kcontext, void *plugin_context,
                               void **request_context)
 {
     if (*request_context != NULL) {
@@ -317,15 +349,16 @@ 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_v0 preauthentication_client_0 = {
-    "wpse",
-    &supported_client_pa_types[0],
-    NULL,
-    client_init,
-    client_fini,
-    client_get_flags,
-    client_cleanup,
-    client_process,
-    NULL,
+    "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 */
 };
 
 struct krb5plugin_preauth_server_ftable_v0 preauthentication_server_0 = {