Add "get_data" function to the client preauth plugin interface
authorKevin Coffman <kwc@citi.umich.edu>
Thu, 9 Nov 2006 20:40:29 +0000 (20:40 +0000)
committerKevin Coffman <kwc@citi.umich.edu>
Thu, 9 Nov 2006 20:40:29 +0000 (20:40 +0000)
Modify the client preauth plugin interface to pass in a function
pointer and data pointer so the plugin may request information
otherwise unavailable.

ticket: new
Tags: pullup

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18790 dc483132-0cff-0310-8789-dd5450dbe970

src/include/k5-int.h
src/include/krb5/preauth_plugin.h
src/lib/krb5/krb/get_in_tkt.c
src/lib/krb5/krb/preauth2.c
src/plugins/preauth/cksum_body/cksum_body_main.c
src/plugins/preauth/wpse/wpse_main.c

index 884bd23c8a169b047e0520ac01cef182c7820046..13109e2913d9026bf4a8b9fd1f0dff7a17509344 100644 (file)
@@ -843,6 +843,17 @@ error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE)
 
 #include <krb5/preauth_plugin.h>
 
+#define CLIENT_ROCK_MAGIC 0x4352434b
+/* This structure is passed into the client preauth functions and passed
+ * back to the "get_data_proc" function so that it can locate the
+ * requested information.  It is opaque to the plugin code and can be
+ * expanded in the future as new types of requests are defined which
+ * may require other things to be passed through. */
+typedef struct _krb5_preauth_client_rock {
+       krb5_magic      magic;
+       krb5_kdc_rep    *as_reply;
+} 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. */
@@ -867,6 +878,8 @@ typedef struct _krb5_preauth_context {
        krb5_error_code (*client_process)(krb5_context context,
                                          void *plugin_context,
                                          void *request_context,
+                                         preauth_get_client_data_proc get_data_proc,
+                                         krb5_preauth_client_rock *rock,
                                          krb5_kdc_req *request,
                                          krb5_data *encoded_request_body,
                                          krb5_data *encoded_previous_request,
@@ -882,6 +895,8 @@ typedef struct _krb5_preauth_context {
        krb5_error_code (*client_tryagain)(krb5_context context,
                                           void *plugin_context,
                                           void *request_context,
+                                          preauth_get_client_data_proc get_data_proc,
+                                          krb5_preauth_client_rock *rock,
                                           krb5_kdc_req *request,
                                           krb5_data *encoded_request_body,
                                           krb5_data *encoded_previous_request,
@@ -1041,7 +1056,8 @@ krb5_error_code KRB5_CALLCONV krb5_do_preauth
         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_gic_get_as_key_fct gak_fct, void *gak_data,
+        krb5_preauth_client_rock *get_data_rock);
 krb5_error_code KRB5_CALLCONV krb5_do_preauth_tryagain
        (krb5_context context,
         krb5_kdc_req *request,
@@ -1052,7 +1068,8 @@ krb5_error_code KRB5_CALLCONV krb5_do_preauth_tryagain
         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_gic_get_as_key_fct gak_fct, void *gak_data,
+        krb5_preauth_client_rock *get_data_rock);
 void KRB5_CALLCONV krb5_init_preauth_context
        (krb5_context);
 void KRB5_CALLCONV krb5_free_preauth_context
index d164192affb3567299eb7f64876c171c7b12b38f..f1b7dd334509022f49831bc93b493c373f19c969 100644 (file)
@@ -44,6 +44,7 @@
  */
 struct _krb5_db_entry_new;
 struct _krb5_key_data;
+struct _krb5_preauth_client_rock;
 
 /*
  * Preauth mechanism property flags, unified from previous definitions in the
@@ -121,6 +122,23 @@ typedef krb5_error_code
                               krb5_int32 request_type,
                               krb5_data **);
 
+/*
+ * A client module's callback functions are allowed to request various
+ * information to enable it to process a request.
+ */
+enum krb5plugin_preauth_client_request_type {
+    /* The returned krb5_data item holds the enctype used to encrypt the
+     * encrypted portion of the AS_REP packet. */
+    krb5plugin_preauth_client_get_etype = 1,
+    /* Free the data returned from krb5plugin_preauth_client_req_get_etype */
+    krb5plugin_preauth_client_free_etype = 2,
+};
+typedef krb5_error_code
+(*preauth_get_client_data_proc)(krb5_context,
+                               struct _krb5_preauth_client_rock *,
+                               krb5_int32 request_type,
+                               krb5_data **);
+
 /*
  * 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,
@@ -189,6 +207,8 @@ typedef struct krb5plugin_preauth_client_ftable_v0 {
     krb5_error_code (*process)(krb5_context context,
                               void *plugin_context,
                               void *request_context,
+                              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,
@@ -207,6 +227,8 @@ typedef struct krb5plugin_preauth_client_ftable_v0 {
     krb5_error_code (*tryagain)(krb5_context context,
                                void *plugin_context,
                                void *request_context,
+                               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,
index 947984f62a897204a6894d211d50321ad64b42aa..a71d98d410801948225ab235cba2ba83a470467e 100644 (file)
@@ -865,6 +865,7 @@ krb5_get_init_creds(krb5_context context,
     krb5_kdc_rep *local_as_reply;
     krb5_timestamp time_now;
     krb5_enctype etype = 0;
+    krb5_preauth_client_rock get_data_rock;
 
     /* initialize everything which will be freed at cleanup */
 
@@ -1091,6 +1092,9 @@ krb5_get_init_creds(krb5_context context,
     if (ret)
         goto cleanup;
 
+    get_data_rock.magic = CLIENT_ROCK_MAGIC;
+    get_data_rock.as_reply = NULL;
+
     /* now, loop processing preauth data and talking to the kdc */
     for (loopcount = 0; loopcount < MAX_IN_TKT_LOOPS; loopcount++) {
        if (!err_reply) {
@@ -1106,7 +1110,8 @@ krb5_get_init_creds(krb5_context context,
                                       preauth_to_use, &request.padata,
                                       &salt, &s2kparams, &etype, &as_key,
                                       prompter, prompter_data,
-                                      gak_fct, gak_data)))
+                                      gak_fct, gak_data,
+                                      &get_data_rock)))
                goto cleanup;
        } else {
            /* retrying after an error other than PREAUTH_NEEDED, using e-data
@@ -1119,7 +1124,8 @@ krb5_get_init_creds(krb5_context context,
                                         err_reply,
                                         &salt, &s2kparams, &etype, &as_key,
                                         prompter, prompter_data,
-                                        gak_fct, gak_data)) {
+                                        gak_fct, gak_data,
+                                        &get_data_rock)) {
                /* couldn't come up with anything better */
                ret = err_reply->error + ERROR_TABLE_BASE_krb5;
                krb5_free_error(context, err_reply);
@@ -1193,12 +1199,14 @@ krb5_get_init_creds(krb5_context context,
     if ((ret = sort_krb5_padata_sequence(context, &request.server->realm,
                                         local_as_reply->padata)))
        goto cleanup;
+    get_data_rock.as_reply = local_as_reply;
     if ((ret = krb5_do_preauth(context,
                               &request,
                               encoded_request_body, encoded_previous_request,
                               local_as_reply->padata, &kdc_padata,
                               &salt, &s2kparams, &etype, &as_key, prompter,
-                              prompter_data, gak_fct, gak_data)))
+                              prompter_data, gak_fct, gak_data,
+                              &get_data_rock)))
        goto cleanup;
 
     /* XXX For 1.1.1 and prior KDC's, when SAM is used w/ USE_SAD_AS_KEY,
index 64823732fb1feda43a883c2205fe6e711d33ac76..b2a513e203dbd109e5f797613262bf0956b1d6f8 100644 (file)
@@ -327,6 +327,66 @@ grow_pa_list(krb5_pa_data ***out_pa_list, int *out_pa_list_size,
     return 0;
 }
 
+/*
+ * Retrieve a specific piece of information required by the plugin and
+ * return it in a new krb5_data item.  There are separate request_types
+ * to obtain the data and free it.
+ *
+ * This may require massaging data into a contrived format, but it will
+ * hopefully keep us from having to reveal library-internal functions
+ * or data to the plugin modules.
+ */
+
+static krb5_error_code
+client_data_proc(krb5_context kcontext,
+                krb5_preauth_client_rock *rock,
+                krb5_int32 request_type,
+                krb5_data **retdata)
+{
+    krb5_data *ret;
+    char *data;
+
+    if (rock->magic != CLIENT_ROCK_MAGIC)
+       return EINVAL;
+    if (retdata == NULL)
+       return EINVAL;
+
+    switch (request_type) {
+    case krb5plugin_preauth_client_get_etype:
+       {
+           krb5_enctype *eptr;
+           if (rock->as_reply == NULL)
+               return ENOENT;
+           ret = malloc(sizeof(krb5_data));
+           if (ret == NULL)
+               return ENOMEM;
+           data = malloc(sizeof(krb5_enctype));
+           if (data == NULL) {
+               free(ret);
+               return ENOMEM;
+           }
+           ret->data = data;
+           ret->length = sizeof(krb5_enctype);
+           eptr = (krb5_enctype *)data;
+           *eptr = rock->as_reply->enc_part.enctype;
+           *retdata = ret;
+           return 0;
+       }
+       break;
+    case krb5plugin_preauth_client_free_etype:
+       ret = *retdata;
+       if (ret == NULL)
+           return 0;
+       if (ret->data)
+           free(ret->data);
+       free(ret);
+       return 0;
+       break;
+    default:
+       return EINVAL;
+    }
+}
+
 /* Tweak the request body, for now adding any enctypes which the module claims
  * to add support for to the list, but in the future perhaps doing more
  * involved things. */
@@ -370,6 +430,7 @@ krb5_run_preauth_plugins(krb5_context kcontext,
                         krb5_data *salt,
                         krb5_data *s2kparams,
                         void *gak_data,
+                        krb5_preauth_client_rock *get_data_rock,
                         krb5_keyblock *as_key,
                         krb5_pa_data ***out_pa_list,
                         int *out_pa_list_size,
@@ -413,6 +474,8 @@ krb5_run_preauth_plugins(krb5_context kcontext,
        ret = module->client_process(kcontext,
                                     module->plugin_context,
                                     module->request_context,
+                                    client_data_proc,
+                                    get_data_rock,
                                     request,
                                     encoded_request_body,
                                     encoded_previous_request,
@@ -1221,7 +1284,8 @@ krb5_do_preauth_tryagain(krb5_context kcontext,
                         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_gic_get_as_key_fct gak_fct, void *gak_data,
+                        krb5_preauth_client_rock *get_data_rock)
 {
     krb5_error_code ret;
     krb5_pa_data *out_padata;
@@ -1251,6 +1315,8 @@ krb5_do_preauth_tryagain(krb5_context kcontext,
            if ((*module->client_tryagain)(kcontext,
                                           module->plugin_context,
                                           module->request_context,
+                                          client_data_proc,
+                                          get_data_rock,
                                           request,
                                           encoded_request_body,
                                           encoded_previous_request,
@@ -1283,7 +1349,8 @@ krb5_do_preauth(krb5_context context,
                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_gic_get_as_key_fct gak_fct, void *gak_data,
+               krb5_preauth_client_rock *get_data_rock)
 {
     int h, i, j, out_pa_list_size;
     int seen_etype_info2 = 0;
@@ -1471,6 +1538,7 @@ krb5_do_preauth(krb5_context context,
                                                   gak_fct,
                                                   salt, s2kparams,
                                                   gak_data,
+                                                  get_data_rock,
                                                   as_key,
                                                   &out_pa_list,
                                                   &out_pa_list_size,
index abf019a7545d7667df348b992e7e31dbcbcae16c..8d7aa00af16282b0f9464913fbf94cf32bbf66a6 100644 (file)
@@ -78,6 +78,8 @@ static krb5_error_code
 client_process(krb5_context kcontext,
               void *client_plugin_context,
               void *client_request_context,
+              preauth_get_client_data_proc client_get_data_proc,
+              struct _krb5_preauth_client_rock *rock,
               krb5_kdc_req *request,
               krb5_data *encoded_request_body,
               krb5_data *encoded_previous_request,
index e7d7b6d5575f992636d8d37c51fc821484acb2f6..8ccd7cd129be6b9f3da560b240c53779051ea9a3 100644 (file)
@@ -90,6 +90,8 @@ static krb5_error_code
 client_process(krb5_context kcontext,
               void *plugin_context,
               void *request_context,
+              preauth_get_client_data_proc client_get_data_proc,
+              struct _krb5_preauth_client_rock *rock,
               krb5_kdc_req *request,
               krb5_data *encoded_request_body,
               krb5_data *encoded_previous_request,