Use type-safe callbacks in preauth interface
authorGreg Hudson <ghudson@mit.edu>
Thu, 6 Oct 2011 16:18:56 +0000 (16:18 +0000)
committerGreg Hudson <ghudson@mit.edu>
Thu, 6 Oct 2011 16:18:56 +0000 (16:18 +0000)
Replace the generic get_data functions in clpreauth and kdcpreauth
with structures containing callback functions.  Each structure has a
minor version number to allow adding new callbacks.

For simplicity, the new fast armor key callbacks return aliases, which
is how we would supply the armor key as a function parameter.  The new
client keys callback is paired with a free_keys callback to reduce the
amount of cleanup code needed in modules.

ticket: 6971

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

src/include/fast_factor.h
src/include/krb5/preauth_plugin.h
src/kdc/kdc_preauth.c
src/kdc/kdc_preauth_ec.c
src/lib/krb5/krb/preauth2.c
src/lib/krb5/krb/preauth_ec.c
src/plugins/preauth/cksum_body/cksum_body_main.c
src/plugins/preauth/pkinit/pkinit_clnt.c
src/plugins/preauth/pkinit/pkinit_srv.c
src/plugins/preauth/securid_sam2/securid_sam2_main.c
src/plugins/preauth/wpse/wpse_main.c

index 734d377797cdb2818244e30e4d2196c88e71e719..32581bd44fd4a0b848a78ca9de1ce94bfca5079c 100644 (file)
 
 #ifndef FAST_FACTOR_H
 
-/*
- * Returns success with a null armor_key if FAST is available but not in use.
- * Returns failure if the client library does not support FAST.
- */
-static inline krb5_error_code
-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, krb5_clpreauth_fast_armor, &data);
-    if (retval == 0) {
-        *armor_key = (krb5_keyblock *) data->data;
-        data->data = NULL;
-        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,
-                       krb5_kdcpreauth_get_data_fn get_data,
-                       krb5_kdcpreauth_rock rock,
-                       krb5_keyblock **armor_key)
-{
-    krb5_error_code retval;
-    krb5_data *data;
-    retval = (*get_data)(context, rock, krb5_kdcpreauth_fast_armor, &data);
-    if (retval == 0) {
-        *armor_key = (krb5_keyblock *) data->data;
-        data->data = NULL;
-        (*get_data)(context, rock, krb5_kdcpreauth_free_fast_armor, &data);
-    }
-    return retval;
-}
-
-
-
 static inline krb5_error_code
 fast_kdc_replace_reply_key(krb5_context context,
-                           krb5_kdcpreauth_get_data_fn get,
+                           krb5_kdcpreauth_callbacks cb,
                            krb5_kdcpreauth_rock rock)
 {
     return 0;
@@ -74,7 +36,7 @@ fast_kdc_replace_reply_key(krb5_context context,
 
 static inline krb5_error_code
 fast_set_kdc_verified(krb5_context context,
-                      krb5_clpreauth_get_data_fn get_data,
+                      krb5_clpreauth_callbacks cb,
                       krb5_clpreauth_rock rock)
 {
     return 0;
index c64cc369977f9054efa01b41735dc8133e99695d..1646263d9f55c294e1ed096d29659437d54d520f 100644 (file)
@@ -161,40 +161,26 @@ typedef krb5_error_code
                                 krb5_keyblock *as_key,
                                 void *gak_data);
 
-/*
- * Provided by krb5: a client module's callback functions are allowed to
- * request various information to enable it to process a request.
- */
-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,
+/* Before using a callback after version 1, modules must check the vers
+ * field of the callback structure. */
+typedef struct krb5_clpreauth_callbacks_st {
+    int vers;
 
     /*
-     * 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.
+     * Get 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_fast_armor = 3,
+    krb5_enctype (*get_etype)(krb5_context context, krb5_clpreauth_rock rock);
 
-    /*
-     * 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
-(*krb5_clpreauth_get_data_fn)(krb5_context context,
-                              krb5_clpreauth_rock rock,
-                              krb5_int32 request_type, krb5_data **data);
+    /* Get a pointer to the FAST armor key, or NULL if the client is not using
+     * FAST.  The returned pointer is an alias and should not be freed. */
+    krb5_keyblock *(*fast_armor)(krb5_context context,
+                                 krb5_clpreauth_rock rock);
+
+    /* End of version 1 clpreauth callbacks. */
+} *krb5_clpreauth_callbacks;
 
 /*
  * Optional: per-plugin initialization/cleanup.  The init function is called by
@@ -247,7 +233,7 @@ typedef krb5_error_code
                              krb5_clpreauth_moddata moddata,
                              krb5_clpreauth_modreq modreq,
                              krb5_get_init_creds_opt *opt,
-                             krb5_clpreauth_get_data_fn get_data,
+                             krb5_clpreauth_callbacks cb,
                              krb5_clpreauth_rock rock,
                              krb5_kdc_req *request,
                              krb5_data *encoded_request_body,
@@ -271,7 +257,7 @@ typedef krb5_error_code
                               krb5_clpreauth_moddata moddata,
                               krb5_clpreauth_modreq modreq,
                               krb5_get_init_creds_opt *opt,
-                              krb5_clpreauth_get_data_fn get_data,
+                              krb5_clpreauth_callbacks cb,
                               krb5_clpreauth_rock rock,
                               krb5_kdc_req *request,
                               krb5_data *encoded_request_body,
@@ -331,52 +317,50 @@ typedef struct krb5_kdcpreauth_rock_st *krb5_kdcpreauth_rock;
 typedef struct krb5_kdcpreauth_moddata_st *krb5_kdcpreauth_moddata;
 typedef struct krb5_kdcpreauth_modreq_st *krb5_kdcpreauth_modreq;
 
-/*
- * 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 krb5_kdcpreauth_request_type {
-    /* The returned krb5_data item holds a DER-encoded X.509 certificate. */
-    krb5_kdcpreauth_request_certificate = 1,
-    /* The returned krb5_data_item holds a krb5_deltat. */
-    krb5_kdcpreauth_max_time_skew = 2,
-    /*
-     * The returned krb5_data_item holds an array of krb5_keyblock structures,
-     * containing the client keys, 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 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,
+/* Before using a callback after version 1, modules must check the vers
+ * field of the callback structure. */
+typedef struct krb5_kdcpreauth_callbacks_st {
+    int vers;
+
+    krb5_deltat (*max_time_skew)(krb5_context context,
+                                 krb5_kdcpreauth_rock rock);
+
     /*
-     * 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.
+     * Get an array of krb5_keyblock structures containing the client keys
+     * matching the request enctypes, terminated by an entry with key type = 0.
+     * Returns ENOENT if no keys are available for the request enctypes.  Free
+     * the resulting object with the free_keys callback.
      */
-    krb5_kdcpreauth_free_fast_armor = 6,
+    krb5_error_code (*client_keys)(krb5_context context,
+                                   krb5_kdcpreauth_rock rock,
+                                   krb5_keyblock **keys_out);
+
+    /* Free the result of client_keys. */
+    void (*free_keys)(krb5_context context, krb5_kdcpreauth_rock rock,
+                      krb5_keyblock *keys);
+
     /*
-     * The returned krb5_data contains a pointer to the client DB entry.  The
-     * pointer is an alias and should not be freed.
+     * Get 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
+     * create any fatal errors if it doesn't match up.  Free the resulting data
+     * object with krb5_free_data.
      */
-    krb5_kdcpreauth_get_client = 7
-};
-typedef krb5_error_code
-(*krb5_kdcpreauth_get_data_fn)(krb5_context context, krb5_kdcpreauth_rock rock,
-                               krb5_int32 request_type, krb5_data **);
+    krb5_error_code (*request_body)(krb5_context context,
+                                    krb5_kdcpreauth_rock rock,
+                                    krb5_data **body_out);
+
+    /* Get a pointer to the FAST armor key, or NULL if the request did not use
+     * FAST.  The returned pointer is an alias and should not be freed. */
+    krb5_keyblock *(*fast_armor)(krb5_context context,
+                                 krb5_kdcpreauth_rock rock);
+
+    /* Get a pointer to the client DB entry (returned as a void pointer to
+     * avoid a dependency on a libkdb5 type). */
+    void *(*client_entry)(krb5_context context, krb5_kdcpreauth_rock rock);
+
+    /* End of version 1 kdcpreauth callbacks. */
+} *krb5_kdcpreauth_callbacks;
 
 /* Optional: preauth plugin initialization function. */
 typedef krb5_error_code
@@ -413,7 +397,7 @@ typedef int
  */
 typedef krb5_error_code
 (*krb5_kdcpreauth_edata_fn)(krb5_context context, krb5_kdc_req *request,
-                            krb5_kdcpreauth_get_data_fn get_data,
+                            krb5_kdcpreauth_callbacks cb,
                             krb5_kdcpreauth_rock rock,
                             krb5_kdcpreauth_moddata moddata,
                             krb5_pa_data *pa_out);
@@ -445,7 +429,7 @@ typedef void
                              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_callbacks cb,
                              krb5_kdcpreauth_rock rock,
                              krb5_kdcpreauth_moddata moddata,
                              krb5_kdcpreauth_verify_respond_fn respond,
@@ -464,7 +448,7 @@ typedef krb5_error_code
                              krb5_kdc_rep *reply,
                              krb5_keyblock *encrypting_key,
                              krb5_pa_data **send_pa_out,
-                             krb5_kdcpreauth_get_data_fn get_data,
+                             krb5_kdcpreauth_callbacks cb,
                              krb5_kdcpreauth_rock rock,
                              krb5_kdcpreauth_moddata moddata,
                              krb5_kdcpreauth_modreq modreq);
index 87586d7005a4968cb764216bd1d39f977c7f825a..7e9cde1f9e1c905ba1436aea1b3f7f746713fee3 100644 (file)
@@ -107,24 +107,23 @@ typedef struct preauth_system_st {
 static void
 verify_enc_timestamp(krb5_context, 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,
-                     krb5_kdcpreauth_rock rock,
+                     krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                      krb5_kdcpreauth_moddata moddata,
                      krb5_kdcpreauth_verify_respond_fn respond, void *arg);
 
 static krb5_error_code
 get_enc_ts(krb5_context context, krb5_kdc_req *request,
-           krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+           krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
            krb5_kdcpreauth_moddata modata, krb5_pa_data *data);
 
 static krb5_error_code
 get_etype_info(krb5_context context, krb5_kdc_req *request,
-               krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                krb5_kdcpreauth_moddata moddata, krb5_pa_data *data);
 
 static krb5_error_code
 get_etype_info2(krb5_context context, krb5_kdc_req *request,
-                krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+                krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                 krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data);
 
 static krb5_error_code
@@ -140,7 +139,7 @@ static krb5_error_code
 return_etype_info(krb5_context, krb5_pa_data *padata,
                   krb5_data *req_pkt, krb5_kdc_req *request,
                   krb5_kdc_rep *reply, krb5_keyblock *encrypting_key,
-                  krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get,
+                  krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb,
                   krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
                   krb5_kdcpreauth_modreq modreq);
 
@@ -148,7 +147,7 @@ static krb5_error_code
 return_etype_info2(krb5_context, krb5_pa_data *padata,
                    krb5_data *req_pkt, krb5_kdc_req *request,
                    krb5_kdc_rep *reply, krb5_keyblock *encrypting_key,
-                   krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get,
+                   krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb,
                    krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
                    krb5_kdcpreauth_modreq modreq);
 
@@ -156,7 +155,7 @@ static krb5_error_code
 return_pw_salt(krb5_context, krb5_pa_data *padata,
                krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply,
                krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
-               krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq);
 
 
@@ -510,158 +509,87 @@ free_padata_context(krb5_context kcontext, void *padata_context)
     free(context);
 }
 
-/* Retrieve a specified tl_data item from the given entry, and return its
- * contents in a new krb5_data, which must be freed by the caller.
- */
-static krb5_error_code
-get_entry_tl_data(krb5_context context, krb5_db_entry *entry,
-                  krb5_int16 tl_data_type, krb5_data **result)
+static krb5_deltat
+max_time_skew(krb5_context context, krb5_kdcpreauth_rock rock)
 {
-    krb5_tl_data *tl;
-    for (tl = entry->tl_data; tl != NULL; tl = tl->tl_data_next) {
-        if (tl->tl_data_type == tl_data_type) {
-            *result = malloc(sizeof(krb5_data));
-            if (*result == NULL) {
-                return ENOMEM;
-            }
-            (*result)->magic = KV5M_DATA;
-            (*result)->data = malloc(tl->tl_data_length);
-            if ((*result)->data == NULL) {
-                free(*result);
-                *result = NULL;
-                return ENOMEM;
-            }
-            memcpy((*result)->data, tl->tl_data_contents, tl->tl_data_length);
-            return 0;
-        }
-    }
-    return ENOENT;
+    return context->clockskew;
 }
 
-/*
- * Retrieve a specific piece of information pertaining to the client entry or
- * request and return it in a new krb5_data item which the caller must free.
- *
- * This may require massaging data into a contrived format, but it will
- * hopefully keep us from having to reveal library-internal functions to
- * modules.
- */
 static krb5_error_code
-get_data(krb5_context context, krb5_kdcpreauth_rock rock, krb5_int32 type,
-         krb5_data **result)
+client_keys(krb5_context context, krb5_kdcpreauth_rock rock,
+            krb5_keyblock **keys_out)
 {
-    int i, k;
-    krb5_data *ret;
-    krb5_deltat *delta;
-    krb5_keyblock *keys;
-    krb5_key_data *entry_key;
-    krb5_error_code error;
     krb5_kdc_req *request = rock->request;
-    struct kdc_request_state *state = rock->rstate;
     krb5_db_entry *client = rock->client;
+    krb5_keyblock *keys, key;
+    krb5_key_data *entry_key;
+    int i, k;
 
-    switch (type) {
-    case krb5_kdcpreauth_request_certificate:
-        return get_entry_tl_data(context, client, KRB5_TL_USER_CERTIFICATE,
-                                 result);
-        break;
-    case krb5_kdcpreauth_max_time_skew:
-        ret = malloc(sizeof(krb5_data));
-        if (ret == NULL)
-            return ENOMEM;
-        delta = malloc(sizeof(krb5_deltat));
-        if (delta == NULL) {
-            free(ret);
-            return ENOMEM;
-        }
-        *delta = context->clockskew;
-        ret->data = (char *) delta;
-        ret->length = sizeof(*delta);
-        *result = ret;
-        return 0;
-        break;
-    case krb5_kdcpreauth_keys:
-        ret = malloc(sizeof(krb5_data));
-        if (ret == NULL)
-            return ENOMEM;
-        keys = malloc(sizeof(krb5_keyblock) * (request->nktypes + 1));
-        if (keys == NULL) {
-            free(ret);
-            return ENOMEM;
-        }
-        ret->data = (char *) keys;
-        ret->length = sizeof(krb5_keyblock) * (request->nktypes + 1);
-        memset(ret->data, 0, ret->length);
-        k = 0;
-        for (i = 0; i < request->nktypes; i++) {
-            entry_key = NULL;
-            if (krb5_dbe_find_enctype(context, client, request->ktype[i],
-                                      -1, 0, &entry_key) != 0)
-                continue;
-            if (krb5_dbe_decrypt_key_data(context, NULL, entry_key,
-                                          &keys[k], NULL) != 0) {
-                if (keys[k].contents != NULL)
-                    krb5_free_keyblock_contents(context, &keys[k]);
-                memset(&keys[k], 0, sizeof(keys[k]));
-                continue;
-            }
-            k++;
-        }
-        if (k > 0) {
-            *result = ret;
-            return 0;
-        } else {
-            free(keys);
-            free(ret);
-        }
-        break;
-    case krb5_kdcpreauth_request_body:
-        ret = NULL;
-        encode_krb5_kdc_req_body(request, &ret);
-        if (ret != NULL) {
-            *result = ret;
-            return 0;
-        }
-        return ASN1_PARSE_ERROR;
-        break;
-    case krb5_kdcpreauth_fast_armor:
-        ret = calloc(1, sizeof(krb5_data));
-        if (ret == NULL)
-            return ENOMEM;
-        if (state->armor_key == NULL) {
-            *result = ret;
-            return 0;
-        }
-        error = krb5_copy_keyblock(context, state->armor_key, &keys);
-        if (error == 0) {
-            ret->data = (char *) keys;
-            ret->length = sizeof(krb5_keyblock);
-            *result = ret;
-            return 0;
-        }
-        free(ret);
-        return error;
-    case krb5_kdcpreauth_free_fast_armor:
-        if ((*result)->data) {
-            keys = (krb5_keyblock *) (*result)->data;
-            krb5_free_keyblock(context, keys);
-        }
-        free(*result);
-        return 0;
-    case krb5_kdcpreauth_get_client:
-        ret = malloc(sizeof(krb5_data));
-        if (ret == NULL)
-            return ENOMEM;
-        ret->data = (char *)&rock->client;
-        ret->length = sizeof(rock->client);
-        *result = ret;
-        return 0;
-    default:
-        break;
+    keys = malloc(sizeof(krb5_keyblock) * (request->nktypes + 1));
+    if (keys == NULL)
+        return ENOMEM;
+
+    memset(keys, 0, sizeof(krb5_keyblock) * (request->nktypes + 1));
+    k = 0;
+    for (i = 0; i < request->nktypes; i++) {
+        entry_key = NULL;
+        if (krb5_dbe_find_enctype(context, client, request->ktype[i],
+                                  -1, 0, &entry_key) != 0)
+            continue;
+        if (krb5_dbe_decrypt_key_data(context, NULL, entry_key,
+                                      &key, NULL) != 0)
+            continue;
+        keys[k++] = key;
     }
-    return ENOENT;
+    if (k == 0) {
+        free(keys);
+        return ENOENT;
+    }
+    *keys_out = keys;
+    return 0;
 }
 
+static void free_keys(krb5_context context, krb5_kdcpreauth_rock rock,
+                      krb5_keyblock *keys)
+{
+    krb5_keyblock *k;
+
+    if (keys == NULL)
+        return;
+    for (k = keys; k->enctype != 0; k++)
+        krb5_free_keyblock_contents(context, k);
+    free(keys);
+}
+
+static krb5_error_code
+request_body(krb5_context context, krb5_kdcpreauth_rock rock,
+             krb5_data **body_out)
+{
+    return encode_krb5_kdc_req_body(rock->request, body_out);
+}
+
+static krb5_keyblock *
+fast_armor(krb5_context context, krb5_kdcpreauth_rock rock)
+{
+    return rock->rstate->armor_key;
+}
+
+static void *
+client_entry(krb5_context context, krb5_kdcpreauth_rock rock)
+{
+    return rock->client;
+}
+
+static struct krb5_kdcpreauth_callbacks_st callbacks = {
+    1,
+    max_time_skew,
+    client_keys,
+    free_keys,
+    request_body,
+    fast_armor,
+    client_entry
+};
+
 static krb5_error_code
 find_pa_system(int type, preauth_system **preauth)
 {
@@ -851,7 +779,7 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
         (*pa)->magic = KV5M_PA_DATA;
         (*pa)->pa_type = ap->type;
         if (ap->get_edata) {
-            retval = ap->get_edata(kdc_context, request, get_data, rock,
+            retval = ap->get_edata(kdc_context, request, &callbacks, rock,
                                    ap->moddata, *pa);
             if (retval) {
                 /* just failed on this type, continue */
@@ -1139,7 +1067,7 @@ next_padata(struct padata_state *state)
     state->pa_found++;
     state->pa_sys->verify_padata(state->context, state->req_pkt,
                                  state->request, state->enc_tkt_reply,
-                                 *state->padata, get_data, state->rock,
+                                 *state->padata, &callbacks, state->rock,
                                  state->pa_sys->moddata, finish_verify_padata,
                                  state);
     return;
@@ -1282,7 +1210,7 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
             }
         }
         retval = ap->return_padata(context, pa, req_pkt, request, reply,
-                                   encrypting_key, send_pa, get_data, rock,
+                                   encrypting_key, send_pa, &callbacks, rock,
                                    ap->moddata, *modreq_ptr);
         if (retval)
             goto cleanup;
@@ -1321,7 +1249,7 @@ request_contains_enctype(krb5_context context,  const krb5_kdc_req *request,
 
 static krb5_error_code
 get_enc_ts(krb5_context context, krb5_kdc_req *request,
-           krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+           krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
            krb5_kdcpreauth_moddata moddata, krb5_pa_data *data)
 {
     if (rock->rstate->armor_key != NULL)
@@ -1333,7 +1261,7 @@ get_enc_ts(krb5_context context, krb5_kdc_req *request,
 static void
 verify_enc_timestamp(krb5_context 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 get,
+                     krb5_pa_data *pa, krb5_kdcpreauth_callbacks cb,
                      krb5_kdcpreauth_rock rock,
                      krb5_kdcpreauth_moddata moddata,
                      krb5_kdcpreauth_verify_respond_fn respond,
@@ -1576,7 +1504,7 @@ cleanup:
 
 static krb5_error_code
 get_etype_info(krb5_context context, krb5_kdc_req *request,
-               krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data)
 {
     int i;
@@ -1591,7 +1519,7 @@ get_etype_info(krb5_context context, krb5_kdc_req *request,
 
 static krb5_error_code
 get_etype_info2(krb5_context context, krb5_kdc_req *request,
-                krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+                krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                 krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data)
 {
     return etype_info_helper(context, request, rock->client, pa_data, 1);
@@ -1678,7 +1606,7 @@ static krb5_error_code
 return_etype_info2(krb5_context context, krb5_pa_data * padata,
                    krb5_data *req_pkt, krb5_kdc_req *request,
                    krb5_kdc_rep *reply, krb5_keyblock *encrypting_key,
-                   krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get,
+                   krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb,
                    krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
                    krb5_kdcpreauth_modreq modreq)
 {
@@ -1692,7 +1620,7 @@ static krb5_error_code
 return_etype_info(krb5_context context, krb5_pa_data *padata,
                   krb5_data *req_pkt, krb5_kdc_req *request,
                   krb5_kdc_rep *reply, krb5_keyblock *encrypting_key,
-                  krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get,
+                  krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb,
                   krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
                   krb5_kdcpreauth_modreq modreq)
 {
@@ -1705,7 +1633,7 @@ static krb5_error_code
 return_pw_salt(krb5_context context, krb5_pa_data *in_padata,
                krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply,
                krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
-               krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq)
 {
     krb5_error_code     retval;
index 62fa615e01fb09a6f2f3a06319fcfd00890b02f8..b52d03620c9e44303443f53ef5331f6311bced0e 100644 (file)
 
 static krb5_error_code
 kdc_include_padata(krb5_context context, krb5_kdc_req *request,
-                   krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+                   krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                    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, rock, &armor_key);
-    if (retval)
-        return retval;
-    if (armor_key == 0)
-        return ENOENT;
-    krb5_free_keyblock(context, armor_key);
-    return 0;
+    krb5_keyblock *armor_key = cb->fast_armor(context, rock);
+
+    return (armor_key == NULL) ? ENOENT : 0;
 }
 
 static void
 kdc_verify_preauth(krb5_context context, 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,
+                   krb5_pa_data *data, krb5_kdcpreauth_callbacks cb,
                    krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
                    krb5_kdcpreauth_verify_respond_fn respond,
                    void *arg)
@@ -62,10 +56,9 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
     krb5_timestamp now;
     krb5_enc_data *enc = NULL;
     krb5_data scratch, plain;
-    krb5_keyblock *armor_key = NULL;
+    krb5_keyblock *armor_key = cb->fast_armor(context, rock);
     krb5_pa_enc_ts *ts = NULL;
     krb5_keyblock *client_keys = NULL;
-    krb5_data *client_data = NULL;
     krb5_keyblock *challenge_key = NULL;
     krb5_keyblock *kdc_challenge_key;
     krb5_kdcpreauth_modreq modreq = NULL;
@@ -73,8 +66,7 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
 
     plain.data = NULL;
 
-    retval = fast_kdc_get_armor_key(context, get, rock, &armor_key);
-    if (retval == 0 &&armor_key == NULL) {
+    if (armor_key == NULL) {
         retval = ENOENT;
         krb5_set_error_message(context, ENOENT, "Encrypted Challenge used outside of FAST tunnel");
     }
@@ -89,9 +81,8 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
             retval = ENOMEM;
     }
     if (retval == 0)
-        retval = (*get)(context, rock, krb5_kdcpreauth_keys, &client_data);
+        retval = cb->client_keys(context, rock, &client_keys);
     if (retval == 0) {
-        client_keys = (krb5_keyblock *) client_data->data;
         for (i = 0; client_keys[i].enctype&& (retval == 0); i++ ) {
             retval = krb5_c_fx_cf2_simple(context,
                                           armor_key, "clientchallengearmor",
@@ -108,18 +99,11 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
                 break;
             /*We failed to decrypt. Try next key*/
             retval = 0;
-            krb5_free_keyblock_contents(context, &client_keys[i]);
         }
         if (client_keys[i].enctype == 0) {
             retval = KRB5KDC_ERR_PREAUTH_FAILED;
             krb5_set_error_message(context, retval, "Incorrect password  in encrypted challenge");
-        } else { /*not run out of keys*/
-            int j;
-            assert (retval == 0);
-            for (j = i+1; client_keys[j].enctype; j++)
-                krb5_free_keyblock_contents(context, &client_keys[j]);
         }
-
     }
     if (retval == 0)
         retval = decode_krb5_pa_enc_ts(&plain, &ts);
@@ -133,7 +117,7 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
              * may cause the client to fail, but at this point the KDC has
              * considered this a success, so the return value is ignored.
              */
-            fast_kdc_replace_reply_key(context, get, rock);
+            fast_kdc_replace_reply_key(context, cb, rock);
             if (krb5_c_fx_cf2_simple(context, armor_key, "kdcchallengearmor",
                                      &client_keys[i], "challengelongterm",
                                      &kdc_challenge_key) == 0)
@@ -142,13 +126,7 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
             retval = KRB5KRB_AP_ERR_SKEW;
         }
     }
-    if (client_keys) {
-        if (client_keys[i].enctype)
-            krb5_free_keyblock_contents(context, &client_keys[i]);
-        krb5_free_data(context, client_data);
-    }
-    if (armor_key)
-        krb5_free_keyblock(context, armor_key);
+    cb->free_keys(context, rock, client_keys);
     if (plain.data)
         free(plain.data);
     if (enc)
@@ -163,7 +141,7 @@ static krb5_error_code
 kdc_return_preauth(krb5_context context, krb5_pa_data *padata,
                    krb5_data *req_pkt, krb5_kdc_req *request,
                    krb5_kdc_rep *reply, krb5_keyblock *encrypting_key,
-                   krb5_pa_data **send_pa, krb5_kdcpreauth_get_data_fn get,
+                   krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb,
                    krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
                    krb5_kdcpreauth_modreq modreq)
 {
index 9807eeafd059a97c19d050a8d54eacb5cd737be0..8c43938ef40eb8b92960000fcaee698376b97313 100644 (file)
@@ -372,94 +372,24 @@ 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_clpreauth_rock rock,
-                 krb5_int32 request_type, krb5_data **retdata)
+static krb5_enctype
+get_etype(krb5_context context, krb5_clpreauth_rock rock)
 {
-    krb5_data *ret;
-    krb5_error_code retval;
-    char *data;
-
-    if (rock->magic != CLIENT_ROCK_MAGIC)
-        return EINVAL;
-    if (retdata == NULL)
-        return EINVAL;
+    return *rock->etype;
+}
 
-    switch (request_type) {
-    case krb5_clpreauth_get_etype:
-    {
-        krb5_enctype *eptr;
-        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->etype;
-        *retdata = ret;
-        return 0;
-    }
-    break;
-    case krb5_clpreauth_free_etype:
-        ret = *retdata;
-        if (ret == NULL)
-            return 0;
-        if (ret->data)
-            free(ret->data);
-        free(ret);
-        return 0;
-        break;
-    case krb5_clpreauth_fast_armor: {
-        krb5_keyblock *key = NULL;
-        ret = calloc(1, sizeof(krb5_data));
-        if (ret == NULL)
-            return ENOMEM;
-        retval = 0;
-        if (rock->fast_state->armor_key)
-            retval = krb5_copy_keyblock(kcontext, rock->fast_state->armor_key,
-                                        &key);
-        if (retval == 0) {
-            ret->data = (char *) key;
-            ret->length = key?sizeof(krb5_keyblock):0;
-            key = NULL;
-        }
-        if (retval == 0) {
-            *retdata = ret;
-            ret = NULL;
-        }
-        if (ret)
-            free(ret);
-        return retval;
-    }
-    case krb5_clpreauth_free_fast_armor:
-        ret = *retdata;
-        if (ret) {
-            if (ret->data)
-                krb5_free_keyblock(kcontext, (krb5_keyblock *) ret->data);
-            free(ret);
-            *retdata = NULL;
-        }
-        return 0;
-    default:
-        return EINVAL;
-    }
+static krb5_keyblock *
+fast_armor(krb5_context context, krb5_clpreauth_rock rock)
+{
+    return rock->fast_state->armor_key;
 }
 
+static struct krb5_clpreauth_callbacks_st callbacks = {
+    1,
+    get_etype,
+    fast_armor
+};
+
 /* 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. */
@@ -545,7 +475,7 @@ run_preauth_plugins(krb5_context kcontext,
         ret = module->client_process(kcontext, module->moddata,
                                      *module->modreq_p,
                                      (krb5_get_init_creds_opt *)opte,
-                                     client_data_proc, preauth_rock,
+                                     &callbacks, preauth_rock,
                                      request, encoded_request_body,
                                      encoded_previous_request, in_padata,
                                      prompter, prompter_data, gak_fct,
@@ -1535,8 +1465,7 @@ krb5_do_preauth_tryagain(krb5_context kcontext,
             if ((*module->client_tryagain)(kcontext, module->moddata,
                                            *module->modreq_p,
                                            (krb5_get_init_creds_opt *)opte,
-                                           client_data_proc,
-                                           preauth_rock,
+                                           &callbacks, preauth_rock,
                                            request,
                                            encoded_request_body,
                                            encoded_previous_request,
index 94c9284619c7389a6a49ad0aa0202ec88662da29..6ef3975682145f98fb6ebc1c71c635c193265803 100644 (file)
@@ -43,7 +43,7 @@ preauth_flags(krb5_context context, krb5_preauthtype pa_type)
 static krb5_error_code
 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_callbacks cb,
                 krb5_clpreauth_rock rock, krb5_kdc_req *request,
                 krb5_data *encoded_request_body,
                 krb5_data *encoded_previous_request, krb5_pa_data *padata,
@@ -53,22 +53,16 @@ process_preauth(krb5_context context, krb5_clpreauth_moddata moddata,
                 krb5_pa_data ***out_padata)
 {
     krb5_error_code retval = 0;
-    krb5_enctype enctype = 0;
-    krb5_keyblock *challenge_key = NULL, *armor_key = NULL;
-    krb5_data *etype_data = NULL;
+    krb5_enctype enctype;
+    krb5_keyblock *challenge_key = NULL, *armor_key;
 
-    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, krb5_clpreauth_get_etype,
-                           &etype_data);
-    if (retval == 0) {
-        enctype = *((krb5_enctype *)etype_data->data);
-        if (as_key->length == 0 ||as_key->enctype != enctype)
-            retval = gak_fct(context, request->client,
-                             enctype, prompter, prompter_data,
-                             salt, s2kparams,
-                             as_key, gak_data);
+    armor_key = cb->fast_armor(context, rock);
+    enctype = cb->get_etype(context, rock);
+    if (as_key->length == 0 ||as_key->enctype != enctype) {
+        retval = gak_fct(context, request->client,
+                         enctype, prompter, prompter_data,
+                         salt, s2kparams,
+                         as_key, gak_data);
     }
     if (retval == 0 && padata->length) {
         krb5_enc_data *enc = NULL;
@@ -99,7 +93,7 @@ process_preauth(krb5_context context, krb5_clpreauth_moddata moddata,
         if (scratch.data)
             krb5_free_data_contents(context, &scratch);
         if (retval == 0)
-            fast_set_kdc_verified(context, get_data_proc, rock);
+            fast_set_kdc_verified(context, cb, rock);
         if (enc)
             krb5_free_enc_data(context, enc);
     } else if (retval == 0) { /*No padata; we send*/
@@ -158,10 +152,6 @@ process_preauth(krb5_context context, krb5_clpreauth_moddata moddata,
     }
     if (challenge_key)
         krb5_free_keyblock(context, challenge_key);
-    if (armor_key)
-        krb5_free_keyblock(context, armor_key);
-    if (etype_data != NULL)
-        get_data_proc(context, rock, krb5_clpreauth_free_etype, &etype_data);
     return retval;
 }
 
index 794cd2ffb3c715a4602a57d9764f819ed9ab26f9..da2643fc1849ce0eec9a8551c1f33df58281b978 100644 (file)
@@ -83,7 +83,7 @@ client_process(krb5_context kcontext,
                krb5_clpreauth_moddata moddata,
                krb5_clpreauth_modreq modreq,
                krb5_get_init_creds_opt *opt,
-               krb5_clpreauth_get_data_fn client_get_data_proc,
+               krb5_clpreauth_callbacks cb,
                krb5_clpreauth_rock rock,
                krb5_kdc_req *request,
                krb5_data *encoded_request_body,
@@ -273,34 +273,28 @@ server_fini(krb5_context kcontext, krb5_kdcpreauth_moddata moddata)
  * client) which matches type data->pa_type. */
 static krb5_error_code
 server_get_edata(krb5_context kcontext, krb5_kdc_req *request,
-                 krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+                 krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                  krb5_kdcpreauth_moddata moddata, krb5_pa_data *data)
 {
-    krb5_data *key_data;
-    krb5_keyblock *keys, *key;
+    krb5_keyblock *keys;
     krb5_int32 *enctypes, enctype;
     int i;
 
     /* Retrieve the client's keys. */
-    key_data = NULL;
-    if ((*get)(kcontext, rock, krb5_kdcpreauth_keys, &key_data) != 0) {
+    if (cb->client_keys(kcontext, rock, &keys) != 0) {
 #ifdef DEBUG
         fprintf(stderr, "Error retrieving client keys.\n");
 #endif
         return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
     }
 
-    /* Count which types of keys we've got, freeing the contents, which we
-     * don't need at this point. */
-    keys = (krb5_keyblock *) key_data->data;
-    key = NULL;
-    for (i = 0; keys[i].enctype != 0; i++)
-        krb5_free_keyblock_contents(kcontext, &keys[i]);
+    /* Count which types of keys we've got. */
+    for (i = 0; keys[i].enctype != 0; i++);
 
     /* Return the list of encryption types. */
     enctypes = malloc((unsigned)i * 4);
     if (enctypes == NULL) {
-        krb5_free_data(kcontext, key_data);
+        cb->free_keys(kcontext, rock, keys);
         return ENOMEM;
     }
 #ifdef DEBUG
@@ -319,7 +313,7 @@ server_get_edata(krb5_context kcontext, krb5_kdc_req *request,
     data->pa_type = KRB5_PADATA_CKSUM_BODY_REQ;
     data->length = (i * 4);
     data->contents = (unsigned char *) enctypes;
-    krb5_free_data(kcontext, key_data);
+    cb->free_keys(kcontext, rock, keys);
     return 0;
 }
 
@@ -330,7 +324,7 @@ server_verify(krb5_context kcontext,
               krb5_kdc_req *request,
               krb5_enc_tkt_part *enc_tkt_reply,
               krb5_pa_data *data,
-              krb5_kdcpreauth_get_data_fn get,
+              krb5_kdcpreauth_callbacks cb,
               krb5_kdcpreauth_rock rock,
               krb5_kdcpreauth_moddata moddata,
               krb5_kdcpreauth_verify_respond_fn respond,
@@ -339,11 +333,10 @@ server_verify(krb5_context kcontext,
     krb5_int32 cksumtype;
     krb5_checksum checksum;
     krb5_boolean valid;
-    krb5_data *key_data, *req_body;
+    krb5_data *req_body;
     krb5_keyblock *keys, *key;
     size_t length;
-    int i;
-    unsigned int j, cksumtypes_count;
+    unsigned int i, cksumtypes_count;
     krb5_cksumtype *cksumtypes;
     krb5_error_code status;
     struct server_stats *stats;
@@ -387,8 +380,7 @@ server_verify(krb5_context kcontext,
     checksum.length = length;
 
     /* Pull up the client's keys. */
-    key_data = NULL;
-    if ((*get)(kcontext, rock, krb5_kdcpreauth_keys, &key_data) != 0) {
+    if (cb->client_keys(kcontext, rock, &keys) != 0) {
 #ifdef DEBUG
         fprintf(stderr, "Error retrieving client keys.\n");
 #endif
@@ -398,56 +390,47 @@ server_verify(krb5_context kcontext,
     }
 
     /* Find the key which would have been used to generate the checksum. */
-    keys = (krb5_keyblock *) key_data->data;
-    key = NULL;
-    for (i = 0; keys[i].enctype != 0; i++) {
-        key = &keys[i];
+    for (key = keys; key->enctype != 0; key++) {
         cksumtypes_count = 0;
         cksumtypes = NULL;
         if (krb5_c_keyed_checksum_types(kcontext, key->enctype,
                                         &cksumtypes_count, &cksumtypes) != 0)
             continue;
-        for (j = 0; j < cksumtypes_count; j++) {
-            if (cksumtypes[j] == checksum.checksum_type)
+        for (i = 0; i < cksumtypes_count; i++) {
+            if (cksumtypes[i] == checksum.checksum_type)
                 break;
         }
         if (cksumtypes != NULL)
             krb5_free_cksumtypes(kcontext, cksumtypes);
-        if (j < cksumtypes_count) {
+        if (i < cksumtypes_count) {
 #ifdef DEBUG
             fprintf(stderr, "Found checksum key.\n");
 #endif
             break;
         }
     }
-    if ((key == NULL) || (key->enctype == 0)) {
-        for (i = 0; keys[i].enctype != 0; i++)
-            krb5_free_keyblock_contents(kcontext, &keys[i]);
-        krb5_free_data(kcontext, key_data);
+    if (key->enctype == 0) {
+        cb->free_keys(kcontext, rock, keys);
         stats->failures++;
         (*respond)(arg, KRB5KDC_ERR_SUMTYPE_NOSUPP, NULL, NULL, NULL);
         return;
     }
 
     /* Save a copy of the key. */
-    if (krb5_copy_keyblock(kcontext, &keys[i], &key) != 0) {
-        for (i = 0; keys[i].enctype != 0; i++)
-            krb5_free_keyblock_contents(kcontext, &keys[i]);
-        krb5_free_data(kcontext, key_data);
+    if (krb5_copy_keyblock(kcontext, keys, &key) != 0) {
+        cb->free_keys(kcontext, rock, keys);
         stats->failures++;
         (*respond)(arg, KRB5KDC_ERR_SUMTYPE_NOSUPP, NULL, NULL, NULL);
         return;
     }
-    for (i = 0; keys[i].enctype != 0; i++)
-        krb5_free_keyblock_contents(kcontext, &keys[i]);
-    krb5_free_data(kcontext, key_data);
+    cb->free_keys(kcontext, rock, keys);
 
     /* Rebuild a copy of the client's request-body.  If we were serious
      * about doing this with any chance of working interoperability, we'd
      * extract the structure directly from the req_pkt structure.  This
      * will probably work if it's us on both ends, though. */
     req_body = NULL;
-    if ((*get)(kcontext, rock, krb5_kdcpreauth_request_body, &req_body) != 0) {
+    if (cb->request_body(kcontext, rock, &req_body) != 0) {
         krb5_free_keyblock(kcontext, key);
         stats->failures++;
         (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, NULL, NULL);
@@ -563,7 +546,7 @@ server_return(krb5_context kcontext,
               krb5_kdc_rep *reply,
               krb5_keyblock *encrypting_key,
               krb5_pa_data **send_pa,
-              krb5_kdcpreauth_get_data_fn get,
+              krb5_kdcpreauth_callbacks cb,
               krb5_kdcpreauth_rock rock,
               krb5_kdcpreauth_moddata moddata,
               krb5_kdcpreauth_modreq modreq)
index a6232e9979da399d592b852034ad84b0bdf76df6..85a1e427d4a80617173e5699671d2b1521a0480e 100644 (file)
@@ -1020,9 +1020,8 @@ static krb5_error_code
 pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
                       krb5_clpreauth_modreq modreq,
                       krb5_get_init_creds_opt *gic_opt,
-                      krb5_clpreauth_get_data_fn get_data_proc,
-                      krb5_clpreauth_rock rock, krb5_kdc_req *request,
-                      krb5_data *encoded_request_body,
+                      krb5_clpreauth_callbacks cb, 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,
@@ -1032,22 +1031,18 @@ pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
 {
     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)moddata;
     pkinit_req_context reqctx = (pkinit_req_context)modreq;
-    krb5_keyblock *armor_key = NULL;
+    krb5_keyblock *armor_key = cb->fast_armor(context, rock);
 
     pkiDebug("pkinit_client_process %p %p %p %p\n",
              context, plgctx, reqctx, request);
 
     /* Remove (along with armor_key) when FAST PKINIT is settled. */
-    retval = fast_get_armor_key(context, get_data_proc, rock, &armor_key);
-    if (retval == 0 && armor_key != NULL) {
-        /* Don't use PKINIT if also using FAST. */
-        krb5_free_keyblock(context, armor_key);
+    /* Don't use PKINIT if also using FAST. */
+    if (armor_key != NULL)
         return EINVAL;
-    }
 
     if (plgctx == NULL || reqctx == NULL)
         return EINVAL;
@@ -1100,15 +1095,7 @@ pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
         /*
          * Get the enctype of the reply.
          */
-        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, krb5_clpreauth_free_etype, &cdata);
+        enctype = cb->get_etype(context, rock);
         retval = pa_pkinit_parse_rep(context, plgctx, reqctx, request,
                                      in_padata, enctype, as_key,
                                      encoded_previous_request);
@@ -1123,9 +1110,8 @@ static krb5_error_code
 pkinit_client_tryagain(krb5_context context, krb5_clpreauth_moddata moddata,
                        krb5_clpreauth_modreq modreq,
                        krb5_get_init_creds_opt *gic_opt,
-                       krb5_clpreauth_get_data_fn get_data_proc,
-                       krb5_clpreauth_rock rock, krb5_kdc_req *request,
-                       krb5_data *encoded_request_body,
+                       krb5_clpreauth_callbacks cb, 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,
index b7aea625ad7386120a46f01842897e7afe18b379..4a477afec9503c3a108965889ea3838ba6ddb5e9 100644 (file)
@@ -101,24 +101,21 @@ cleanup:
 static krb5_error_code
 pkinit_server_get_edata(krb5_context context,
                         krb5_kdc_req *request,
-                        krb5_kdcpreauth_get_data_fn get,
+                        krb5_kdcpreauth_callbacks cb,
                         krb5_kdcpreauth_rock rock,
                         krb5_kdcpreauth_moddata moddata,
                         krb5_pa_data *data)
 {
     krb5_error_code retval = 0;
     pkinit_kdc_context plgctx = NULL;
-    krb5_keyblock *armor_key = NULL;
+    krb5_keyblock *armor_key = cb->fast_armor(context, rock);
 
     pkiDebug("pkinit_server_get_edata: entered!\n");
 
     /* Remove (along with armor_key) when FAST PKINIT is settled. */
-    retval = fast_kdc_get_armor_key(context, get, rock, &armor_key);
-    if (retval == 0 && armor_key != NULL) {
-        /* Don't advertise PKINIT if the client used FAST. */
-        krb5_free_keyblock(context, armor_key);
+    /* Don't advertise PKINIT if the client used FAST. */
+    if (armor_key != NULL)
         return EINVAL;
-    }
 
     /*
      * If we don't have a realm context for the given realm,
@@ -291,7 +288,7 @@ pkinit_server_verify_padata(krb5_context context,
                             krb5_kdc_req * request,
                             krb5_enc_tkt_part * enc_tkt_reply,
                             krb5_pa_data * data,
-                            krb5_kdcpreauth_get_data_fn get,
+                            krb5_kdcpreauth_callbacks cb,
                             krb5_kdcpreauth_rock rock,
                             krb5_kdcpreauth_moddata moddata,
                             krb5_kdcpreauth_verify_respond_fn respond,
@@ -311,7 +308,7 @@ pkinit_server_verify_padata(krb5_context context,
     krb5_kdc_req *tmp_as_req = NULL;
     krb5_data k5data;
     int is_signed = 1;
-    krb5_keyblock *armor_key;
+    krb5_keyblock *armor_key = cb->fast_armor(context, rock);
     krb5_pa_data **e_data = NULL;
     krb5_kdcpreauth_modreq modreq = NULL;
 
@@ -322,10 +319,8 @@ pkinit_server_verify_padata(krb5_context context,
     }
 
     /* Remove (along with armor_key) when FAST PKINIT is settled. */
-    retval = fast_kdc_get_armor_key(context, get, rock, &armor_key);
-    if (retval == 0 && armor_key != NULL) {
-        /* Don't allow PKINIT if the client used FAST. */
-        krb5_free_keyblock(context, armor_key);
+    /* Don't allow PKINIT if the client used FAST. */
+    if (armor_key != NULL) {
         (*respond)(arg, EINVAL, NULL, NULL, NULL);
         return;
     }
@@ -700,7 +695,7 @@ pkinit_server_return_padata(krb5_context context,
                             krb5_kdc_rep * reply,
                             krb5_keyblock * encrypting_key,
                             krb5_pa_data ** send_pa,
-                            krb5_kdcpreauth_get_data_fn get,
+                            krb5_kdcpreauth_callbacks cb,
                             krb5_kdcpreauth_rock rock,
                             krb5_kdcpreauth_moddata moddata,
                             krb5_kdcpreauth_modreq modreq)
index 5ed59c811172450f009714c2019e7d35f9557bb9..80335ff8295589ffdb9bde1415d7ffbc225855ef 100644 (file)
@@ -50,19 +50,6 @@ static struct {
     { 0, 0 },
 };
 
-static krb5_db_entry *
-get_client_entry(krb5_context context, krb5_kdcpreauth_get_data_fn get,
-                 krb5_kdcpreauth_rock rock)
-{
-    krb5_data *data;
-    krb5_db_entry *client;
-
-    (*get)(context, rock, krb5_kdcpreauth_get_client, &data);
-    client = *(krb5_db_entry **)data->data;
-    free(data);
-    return client;
-}
-
 krb5_error_code
 sam_get_db_entry(krb5_context context, krb5_principal client,
                  int *sam_type, struct _krb5_db_entry_new **db_entry)
@@ -127,11 +114,10 @@ cleanup:
 
 static krb5_error_code
 kdc_include_padata(krb5_context context, krb5_kdc_req *request,
-                   krb5_kdcpreauth_get_data_fn get, krb5_kdcpreauth_rock rock,
+                   krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                    krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data)
 {
     krb5_error_code retval;
-    krb5_data *client_keys_data = NULL;
     krb5_keyblock *client_key = NULL;
     krb5_sam_challenge_2 sc2;
     krb5_sam_challenge_2_body sc2b;
@@ -144,15 +130,14 @@ kdc_include_padata(krb5_context context, krb5_kdc_req *request,
     sc2b.magic = KV5M_SAM_CHALLENGE_2;
     sc2b.sam_type = sam_type;
 
-    client = get_client_entry(context, get, rock);
+    client = cb->client_entry(context, rock);
     retval = sam_get_db_entry(context, client->princ, &sam_type,
                               &sam_db_entry);
     if (retval)
         return retval;
-    retval = (*get)(context, rock, krb5_kdcpreauth_keys, &client_keys_data);
+    retval = cb->client_keys(context, rock, &client_key);
     if (retval)
         goto cleanup;
-    client_key = (krb5_keyblock *) client_keys_data->data;
     if (client_key->enctype == 0) {
         retval = KRB5KDC_ERR_ETYPE_NOSUPP;
         com_err("krb5kdc", retval,
@@ -203,20 +188,14 @@ cleanup:
     krb5_free_data(context, encoded_challenge);
     if (sam_db_entry)
         krb5_db_free_principal(context, sam_db_entry);
-    if (client_keys_data) {
-        while (client_key->enctype) {
-            krb5_free_keyblock_contents(context, client_key);
-            client_key++;
-        }
-        krb5_free_data(context, client_keys_data);
-    }
+    cb->free_keys(context, rock, client_key);
     return retval;
 }
 
 static void
 kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
                    krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
-                   krb5_pa_data *pa_data, krb5_kdcpreauth_get_data_fn get,
+                   krb5_pa_data *pa_data, krb5_kdcpreauth_callbacks cb,
                    krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
                    krb5_kdcpreauth_verify_respond_fn respond, void *arg)
 {
@@ -225,7 +204,7 @@ kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
     krb5_data scratch, *scratch2, *e_data = NULL;
     char *client_name = NULL;
     krb5_sam_challenge_2 *out_sc2 = NULL;
-    krb5_db_entry *client = get_client_entry(context, get, rock);
+    krb5_db_entry *client = cb->client_entry(context, rock);
 
     scratch.data = (char *) pa_data->contents;
     scratch.length = pa_data->length;
index e437d6b0322438d020c840082a21f0d1ea6d404e..4da2c2f48cb2e1bbc10252b0e62b8d37537a43a0 100644 (file)
@@ -90,7 +90,7 @@ client_process(krb5_context kcontext,
                krb5_clpreauth_moddata moddata,
                krb5_clpreauth_modreq modreq,
                krb5_get_init_creds_opt *opt,
-               krb5_clpreauth_get_data_fn client_get_data_proc,
+               krb5_clpreauth_callbacks cb,
                krb5_clpreauth_rock rock,
                krb5_kdc_req *request,
                krb5_data *encoded_request_body,
@@ -246,7 +246,7 @@ server_free_modreq(krb5_context kcontext,
 static krb5_error_code
 server_get_edata(krb5_context kcontext,
                  krb5_kdc_req *request,
-                 krb5_kdcpreauth_get_data_fn get,
+                 krb5_kdcpreauth_callbacks cb,
                  krb5_kdcpreauth_rock rock,
                  krb5_kdcpreauth_moddata moddata,
                  krb5_pa_data *data)
@@ -264,7 +264,7 @@ server_verify(krb5_context kcontext,
               krb5_kdc_req *request,
               krb5_enc_tkt_part *enc_tkt_reply,
               krb5_pa_data *data,
-              krb5_kdcpreauth_get_data_fn get,
+              krb5_kdcpreauth_callbacks cb,
               krb5_kdcpreauth_rock rock,
               krb5_kdcpreauth_moddata moddata,
               krb5_kdcpreauth_verify_respond_fn respond,
@@ -360,7 +360,7 @@ server_return(krb5_context kcontext,
               krb5_kdc_rep *reply,
               krb5_keyblock *encrypting_key,
               krb5_pa_data **send_pa,
-              krb5_kdcpreauth_get_data_fn get,
+              krb5_kdcpreauth_callbacks cb,
               krb5_kdcpreauth_rock rock,
               krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq)
 {