Blob Blame History Raw
From 65f078dfc68f5680e87e686a59970291b64ebd95 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Sun, 11 Feb 2018 15:23:35 -0500
Subject: [PATCH] Simplify kdc_preauth.c systems table

Get rid of static_preauth_systems, and replace it with explicit calls
to helper functions in get_preauth_hint_list() and return_padata().
Stop preallocating pa-data lists, instead reallocating on each
addition using add_pa_data_element().  Also simplify
maybe_add_etype_info2() using add_pa_data_element().

The KRB5_PADATA_PAC_REQUEST table entry did nothing, and was probably
originally added back when the KDC would error out on unrecognized
padata types.  The KRB5_PADATA_SERVER_REFERRAL entry has been disabled
since it was first added.

(cherry picked from commit fea1a488924faa3938ef723feaa1ff12d22a91ff)
---
 src/kdc/kdc_preauth.c | 526 +++++++++++++++---------------------------
 1 file changed, 184 insertions(+), 342 deletions(-)

diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index edc30bd83..6f34dc289 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -101,108 +101,14 @@ typedef struct preauth_system_st {
     krb5_kdcpreauth_loop_fn loop;
 } preauth_system;
 
+static preauth_system *preauth_systems;
+static size_t n_preauth_systems;
+
 static krb5_error_code
 make_etype_info(krb5_context context, krb5_preauthtype pa_type,
                 krb5_principal client, krb5_key_data *client_key,
                 krb5_enctype enctype, krb5_pa_data **pa_out);
 
-static void
-get_etype_info(krb5_context context, krb5_kdc_req *request,
-               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-               krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
-               krb5_kdcpreauth_edata_respond_fn respond, void *arg);
-
-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_callbacks cb,
-                  krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
-                  krb5_kdcpreauth_modreq modreq);
-
-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_callbacks cb, krb5_kdcpreauth_rock rock,
-               krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq);
-
-
-
-static preauth_system static_preauth_systems[] = {
-    {
-        "FAST",
-        KRB5_PADATA_FX_FAST,
-        PA_HARDWARE,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        0
-    },
-    {
-        "etype-info",
-        KRB5_PADATA_ETYPE_INFO,
-        PA_HARDWARE,
-        NULL,
-        NULL,
-        NULL,
-        get_etype_info,
-        0,
-        return_etype_info
-    },
-    {
-        "etype-info2",
-        KRB5_PADATA_ETYPE_INFO2,
-        PA_HARDWARE,
-        NULL,
-        NULL,
-        NULL,
-        get_etype_info,
-        0,
-        return_etype_info
-    },
-    {
-        "pw-salt",
-        KRB5_PADATA_PW_SALT,
-        PA_PSEUDO,              /* Don't include this in the error list */
-        NULL,
-        NULL,
-        NULL,
-        0,
-        0,
-        return_pw_salt
-    },
-    {
-        "pac-request",
-        KRB5_PADATA_PAC_REQUEST,
-        PA_PSEUDO,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL
-    },
-#if 0
-    {
-        "server-referral",
-        KRB5_PADATA_SERVER_REFERRAL,
-        PA_PSEUDO,
-        0,
-        0,
-        return_server_referral
-    },
-#endif
-};
-
-#define NUM_STATIC_PREAUTH_SYSTEMS (sizeof(static_preauth_systems) /    \
-                                    sizeof(*static_preauth_systems))
-
-static preauth_system *preauth_systems;
-static size_t n_preauth_systems;
-
 /* Get all available kdcpreauth vtables and a count of preauth types they
  * support.  Return an empty list on failure. */
 static void
@@ -284,7 +190,6 @@ load_preauth_plugins(struct server_handle *handle, krb5_context context,
     get_plugin_vtables(context, &vtables, &n_tables, &n_systems);
 
     /* Allocate the list of static and plugin preauth systems. */
-    n_systems += NUM_STATIC_PREAUTH_SYSTEMS;
     preauth_systems = calloc(n_systems + 1, sizeof(preauth_system));
     if (preauth_systems == NULL)
         goto cleanup;
@@ -292,13 +197,8 @@ load_preauth_plugins(struct server_handle *handle, krb5_context context,
     if (get_realm_names(handle, &realm_names))
         goto cleanup;
 
-    /* Add the static system to the list first.  No static systems require
-     * initialization, so just make a direct copy. */
-    memcpy(preauth_systems, static_preauth_systems,
-           sizeof(static_preauth_systems));
-
     /* Add the dynamically-loaded mechanisms to the list. */
-    n_systems = NUM_STATIC_PREAUTH_SYSTEMS;
+    n_systems = 0;
     for (i = 0; i < n_tables; i++) {
         /* Try to initialize this module. */
         vt = &vtables[i];
@@ -622,7 +522,9 @@ find_pa_system(int type, preauth_system **preauth)
 {
     preauth_system *ap;
 
-    ap = preauth_systems ? preauth_systems : static_preauth_systems;
+    if (preauth_systems == NULL)
+        return KRB5_PREAUTH_BAD_TYPE;
+    ap = preauth_systems;
     while ((ap->type != -1) && (ap->type != type))
         ap++;
     if (ap->type == -1)
@@ -776,6 +678,98 @@ const char *missing_required_preauth(krb5_db_entry *client,
     return 0;
 }
 
+/* Return true if request's enctypes indicate support for etype-info2. */
+static krb5_boolean
+requires_info2(const krb5_kdc_req *request)
+{
+    int i;
+
+    for (i = 0; i < request->nktypes; i++) {
+        if (enctype_requires_etype_info_2(request->ktype[i]))
+            return TRUE;
+    }
+    return FALSE;
+}
+
+/* Add PA-ETYPE-INFO2 and possibly PA-ETYPE-INFO entries to pa_list as
+ * appropriate for the request and client principal. */
+static krb5_error_code
+add_etype_info(krb5_context context, krb5_kdcpreauth_rock rock,
+               krb5_pa_data ***pa_list)
+{
+    krb5_error_code ret;
+    krb5_pa_data *pa;
+
+    if (rock->client_key == NULL)
+        return 0;
+
+    if (!requires_info2(rock->request)) {
+        /* Include PA-ETYPE-INFO only for old clients. */
+        ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO,
+                              rock->client->princ, rock->client_key,
+                              rock->client_keyblock->enctype, &pa);
+        if (ret)
+            return ret;
+        /* add_pa_data_element() claims pa on success or failure. */
+        ret = add_pa_data_element(pa_list, pa);
+        if (ret)
+            return ret;
+    }
+
+    /* Always include PA-ETYPE-INFO2. */
+    ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
+                          rock->client->princ, rock->client_key,
+                          rock->client_keyblock->enctype, &pa);
+    if (ret)
+        return ret;
+    /* add_pa_data_element() claims pa on success or failure. */
+    return add_pa_data_element(pa_list, pa);
+}
+
+/* Add PW-SALT or AFS3-SALT entries to pa_list as appropriate for the request
+ * and client principal. */
+static krb5_error_code
+add_pw_salt(krb5_context context, krb5_kdcpreauth_rock rock,
+            krb5_pa_data ***pa_list)
+{
+    krb5_error_code ret;
+    krb5_pa_data *pa;
+    krb5_data *salt = NULL;
+    krb5_int16 salttype;
+
+    /* Only include this pa-data for old clients. */
+    if (rock->client_key == NULL || requires_info2(rock->request))
+        return 0;
+
+    ret = krb5_dbe_compute_salt(context, rock->client_key,
+                                rock->request->client, &salttype, &salt);
+    if (ret)
+        return 0;
+
+    if (salttype == KRB5_KDB_SALTTYPE_AFS3) {
+        ret = alloc_pa_data(KRB5_PADATA_AFS3_SALT, salt->length + 1, &pa);
+        if (ret)
+            goto cleanup;
+        memcpy(pa->contents, salt->data, salt->length);
+        pa->contents[salt->length] = '\0';
+    } else {
+        /* Steal memory from salt to make the pa-data entry. */
+        ret = alloc_pa_data(KRB5_PADATA_PW_SALT, 0, &pa);
+        if (ret)
+            goto cleanup;
+        pa->length = salt->length;
+        pa->contents = (uint8_t *)salt->data;
+        salt->data = NULL;
+    }
+
+    /* add_pa_data_element() claims pa on success or failure. */
+    ret = add_pa_data_element(pa_list, pa);
+
+cleanup:
+    krb5_free_data(context, salt);
+    return ret;
+}
+
 struct hint_state {
     kdc_hint_respond_fn respond;
     void *arg;
@@ -787,7 +781,7 @@ struct hint_state {
 
     int hw_only;
     preauth_system *ap;
-    krb5_pa_data **pa_data, **pa_cur;
+    krb5_pa_data **pa_data;
     krb5_preauthtype pa_type;
 };
 
@@ -799,7 +793,7 @@ hint_list_finish(struct hint_state *state, krb5_error_code code)
     kdc_realm_t *kdc_active_realm = state->realm;
 
     if (!code) {
-        if (state->pa_data[0] == 0) {
+        if (state->pa_data == NULL) {
             krb5_klog_syslog(LOG_INFO,
                              _("%spreauth required but hint list is empty"),
                              state->hw_only ? "hw" : "");
@@ -820,20 +814,27 @@ hint_list_next(struct hint_state *arg);
 static void
 finish_get_edata(void *arg, krb5_error_code code, krb5_pa_data *pa)
 {
+    krb5_error_code ret;
     struct hint_state *state = arg;
 
     if (code == 0) {
         if (pa == NULL) {
-            /* Include an empty value of the current type. */
-            pa = calloc(1, sizeof(*pa));
-            pa->magic = KV5M_PA_DATA;
-            pa->pa_type = state->pa_type;
+            ret = alloc_pa_data(state->pa_type, 0, &pa);
+            if (ret)
+                goto error;
         }
-        *state->pa_cur++ = pa;
+        /* add_pa_data_element() claims pa on success or failure. */
+        ret = add_pa_data_element(&state->pa_data, pa);
+        if (ret)
+            goto error;
     }
 
     state->ap++;
     hint_list_next(state);
+    return;
+
+error:
+    hint_list_finish(state, ret);
 }
 
 static void
@@ -870,16 +871,16 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
                       krb5_pa_data ***e_data_out, kdc_hint_respond_fn respond,
                       void *arg)
 {
+    kdc_realm_t *kdc_active_realm = rock->rstate->realm_data;
     struct hint_state *state;
+    krb5_pa_data *pa;
 
     *e_data_out = NULL;
 
     /* Allocate our state. */
     state = calloc(1, sizeof(*state));
-    if (state == NULL) {
-        (*respond)(arg);
-        return;
-    }
+    if (state == NULL)
+        goto error;
     state->hw_only = isflagset(rock->client->attributes,
                                KRB5_KDB_REQUIRES_HW_AUTH);
     state->respond = respond;
@@ -888,17 +889,27 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
     state->rock = rock;
     state->realm = rock->rstate->realm_data;
     state->e_data_out = e_data_out;
-
-    state->pa_data = calloc(n_preauth_systems + 1, sizeof(krb5_pa_data *));
-    if (!state->pa_data) {
-        free(state);
-        (*respond)(arg);
-        return;
-    }
-
-    state->pa_cur = state->pa_data;
+    state->pa_data = NULL;
     state->ap = preauth_systems;
+
+    /* Add an empty PA-FX-FAST element to advertise FAST support. */
+    if (alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa) != 0)
+        goto error;
+    /* add_pa_data_element() claims pa on success or failure. */
+    if (add_pa_data_element(&state->pa_data, pa) != 0)
+        goto error;
+
+    if (add_etype_info(kdc_context, rock, &state->pa_data) != 0)
+        goto error;
+
     hint_list_next(state);
+    return;
+
+error:
+    if (state != NULL)
+        krb5_free_pa_data(kdc_context, state->pa_data);
+    free(state);
+    (*respond)(arg);
 }
 
 /*
@@ -1029,10 +1040,10 @@ filter_preauth_error(krb5_error_code code)
 static krb5_error_code
 maybe_add_etype_info2(struct padata_state *state, krb5_error_code code)
 {
+    krb5_error_code ret;
     krb5_context context = state->context;
     krb5_kdcpreauth_rock rock = state->rock;
-    krb5_pa_data **list = state->pa_e_data;
-    size_t count;
+    krb5_pa_data *pa;
 
     /* Only add key information when requesting another preauth round trip. */
     if (code != KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
@@ -1048,18 +1059,14 @@ maybe_add_etype_info2(struct padata_state *state, krb5_error_code code)
                              KRB5_PADATA_FX_COOKIE) != NULL)
         return 0;
 
-    /* Reallocate state->pa_e_data to make room for the etype-info2 element. */
-    for (count = 0; list != NULL && list[count] != NULL; count++);
-    list = realloc(list, (count + 2) * sizeof(*list));
-    if (list == NULL)
-        return ENOMEM;
-    list[count] = list[count + 1] = NULL;
-    state->pa_e_data = list;
+    ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
+                          rock->client->princ, rock->client_key,
+                          rock->client_keyblock->enctype, &pa);
+    if (ret)
+        return ret;
 
-    /* Generate an etype-info2 element in the new slot. */
-    return make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
-                           rock->client->princ, rock->client_key,
-                           rock->client_keyblock->enctype, &list[count]);
+    /* add_pa_data_element() claims pa on success or failure. */
+    return add_pa_data_element(&state->pa_e_data, pa);
 }
 
 /* Release state and respond to the AS-REQ processing code with the result of
@@ -1279,17 +1286,20 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
 {
     krb5_error_code             retval;
     krb5_pa_data **             padata;
-    krb5_pa_data **             send_pa_list;
-    krb5_pa_data **             send_pa;
+    krb5_pa_data **             send_pa_list = NULL;
+    krb5_pa_data *              send_pa;
     krb5_pa_data *              pa = 0;
     krb5_pa_data null_item;
     preauth_system *            ap;
-    int *                       pa_order;
+    int *                       pa_order = NULL;
     int *                       pa_type;
     int                         size = 0;
     krb5_kdcpreauth_modreq      *modreq_ptr;
     krb5_boolean                key_modified;
     krb5_keyblock               original_key;
+
+    memset(&original_key, 0, sizeof(original_key));
+
     if ((!*padata_context) &&
         (make_padata_context(context, padata_context) != 0)) {
         return KRB5KRB_ERR_GENERIC;
@@ -1300,26 +1310,18 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
             size++;
     }
 
-    if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL)
-        return ENOMEM;
-    if ((pa_order = malloc((size+1) * sizeof(int))) == NULL) {
-        free(send_pa_list);
-        return ENOMEM;
-    }
+    pa_order = k5calloc(size + 1, sizeof(int), &retval);
+    if (pa_order == NULL)
+        goto cleanup;
     sort_pa_order(context, request, pa_order);
 
     retval = krb5_copy_keyblock_contents(context, encrypting_key,
                                          &original_key);
-    if (retval) {
-        free(send_pa_list);
-        free(pa_order);
-        return retval;
-    }
+    if (retval)
+        goto cleanup;
     key_modified = FALSE;
     null_item.contents = NULL;
     null_item.length = 0;
-    send_pa = send_pa_list;
-    *send_pa = 0;
 
     for (pa_type = pa_order; *pa_type != -1; pa_type++) {
         ap = &preauth_systems[*pa_type];
@@ -1349,20 +1351,30 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
                 }
             }
         }
+        send_pa = NULL;
         retval = ap->return_padata(context, pa, req_pkt, request, reply,
-                                   encrypting_key, send_pa, &callbacks, rock,
+                                   encrypting_key, &send_pa, &callbacks, rock,
                                    ap->moddata, *modreq_ptr);
         if (retval)
             goto cleanup;
 
-        if (*send_pa)
-            send_pa++;
-        *send_pa = 0;
+        if (send_pa != NULL) {
+            /* add_pa_data_element() claims send_pa on success or failure. */
+            retval = add_pa_data_element(&send_pa_list, send_pa);
+            if (retval)
+                goto cleanup;
+        }
     }
 
-    retval = 0;
+    /* Add etype-info and pw-salt pa-data as needed. */
+    retval = add_etype_info(context, rock, &send_pa_list);
+    if (retval)
+        goto cleanup;
+    retval = add_pw_salt(context, rock, &send_pa_list);
+    if (retval)
+        goto cleanup;
 
-    if (send_pa_list[0]) {
+    if (send_pa_list != NULL) {
         reply->padata = send_pa_list;
         send_pa_list = 0;
     }
@@ -1370,8 +1382,7 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
 cleanup:
     krb5_free_keyblock_contents(context, &original_key);
     free(pa_order);
-    if (send_pa_list)
-        krb5_free_pa_data(context, send_pa_list);
+    krb5_free_pa_data(context, send_pa_list);
 
     return (retval);
 }
@@ -1438,9 +1449,8 @@ make_etype_info(krb5_context context, krb5_preauthtype pa_type,
                 krb5_enctype enctype, krb5_pa_data **pa_out)
 {
     krb5_error_code retval;
-    krb5_pa_data *pa = NULL;
     krb5_etype_info_entry **entry = NULL;
-    krb5_data *scratch = NULL;
+    krb5_data *der_etype_info = NULL;
     int etype_info2 = (pa_type == KRB5_PADATA_ETYPE_INFO2);
 
     *pa_out = NULL;
@@ -1454,125 +1464,23 @@ make_etype_info(krb5_context context, krb5_preauthtype pa_type,
         goto cleanup;
 
     if (etype_info2)
-        retval = encode_krb5_etype_info2(entry, &scratch);
+        retval = encode_krb5_etype_info2(entry, &der_etype_info);
     else
-        retval = encode_krb5_etype_info(entry, &scratch);
+        retval = encode_krb5_etype_info(entry, &der_etype_info);
     if (retval)
         goto cleanup;
-    pa = k5alloc(sizeof(*pa), &retval);
-    if (pa == NULL)
+
+    /* Steal the data from der_etype_info to create a pa-data element. */
+    retval = alloc_pa_data(pa_type, 0, pa_out);
+    if (retval)
         goto cleanup;
-    pa->magic = KV5M_PA_DATA;
-    pa->pa_type = pa_type;
-    pa->contents = (unsigned char *)scratch->data;
-    pa->length = scratch->length;
-    scratch->data = NULL;
-    *pa_out = pa;
+    (*pa_out)->contents = (uint8_t *)der_etype_info->data;
+    (*pa_out)->length = der_etype_info->length;
+    der_etype_info->data = NULL;
 
 cleanup:
     krb5_free_etype_info(context, entry);
-    krb5_free_data(context, scratch);
-    return retval;
-}
-
-/* Return true if request's enctypes indicate support for etype-info2. */
-static krb5_boolean
-requires_info2(const krb5_kdc_req *request)
-{
-    int i;
-
-    for (i = 0; i < request->nktypes; i++) {
-        if (enctype_requires_etype_info_2(request->ktype[i]))
-            return TRUE;
-    }
-    return FALSE;
-}
-
-/* Generate hint list padata for PA-ETYPE-INFO or PA-ETYPE-INFO2. */
-static void
-get_etype_info(krb5_context context, krb5_kdc_req *request,
-               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-               krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
-               krb5_kdcpreauth_edata_respond_fn respond, void *arg)
-{
-    krb5_error_code ret;
-    krb5_pa_data *pa = NULL;
-
-    if (rock->client_key == NULL) {
-        ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
-    } else if (pa_type == KRB5_PADATA_ETYPE_INFO && requires_info2(request)) {
-        ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
-    } else {
-        ret = make_etype_info(context, pa_type, rock->client->princ,
-                              rock->client_key, rock->client_keyblock->enctype,
-                              &pa);
-    }
-    (*respond)(arg, ret, pa);
-}
-
-/* Generate AS-REP padata for PA-ETYPE-INFO or PA-ETYPE-INFO2. */
-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_callbacks cb,
-                  krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
-                  krb5_kdcpreauth_modreq modreq)
-{
-    *send_pa = NULL;
-    if (rock->client_key == NULL)
-        return 0;
-    if (padata->pa_type == KRB5_PADATA_ETYPE_INFO && requires_info2(request))
-        return 0;
-    return make_etype_info(context, padata->pa_type, rock->client->princ,
-                           rock->client_key, encrypting_key->enctype, send_pa);
-}
-
-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_callbacks cb, krb5_kdcpreauth_rock rock,
-               krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq)
-{
-    krb5_error_code     retval;
-    krb5_pa_data *      padata;
-    krb5_data *         salt = NULL;
-    krb5_int16          salttype;
-    krb5_key_data *     client_key = rock->client_key;
-
-    if (client_key == NULL || requires_info2(request))
-        return 0;
-
-    retval = krb5_dbe_compute_salt(context, client_key, request->client,
-                                   &salttype, &salt);
-    if (retval)
-        return 0;
-
-    padata = k5alloc(sizeof(*padata), &retval);
-    if (padata == NULL)
-        goto cleanup;
-    padata->magic = KV5M_PA_DATA;
-
-    if (salttype == KRB5_KDB_SALTTYPE_AFS3) {
-        padata->contents = k5memdup0(salt->data, salt->length, &retval);
-        if (padata->contents == NULL)
-            goto cleanup;
-        padata->pa_type = KRB5_PADATA_AFS3_SALT;
-        padata->length = salt->length + 1;
-    } else {
-        padata->pa_type = KRB5_PADATA_PW_SALT;
-        padata->length = salt->length;
-        padata->contents = (krb5_octet *)salt->data;
-        salt->data = NULL;
-    }
-
-    *send_pa = padata;
-    padata = NULL;
-
-cleanup:
-    free(padata);
-    krb5_free_data(context, salt);
+    krb5_free_data(context, der_etype_info);
     return retval;
 }
 
@@ -1656,69 +1564,3 @@ return_enc_padata(krb5_context context, krb5_data *req_pkt,
 cleanup:
     return code;
 }
-
-
-#if 0
-static krb5_error_code return_server_referral(krb5_context context,
-                                              krb5_pa_data * padata,
-                                              krb5_db_entry *client,
-                                              krb5_db_entry *server,
-                                              krb5_kdc_req *request,
-                                              krb5_kdc_rep *reply,
-                                              krb5_key_data *client_key,
-                                              krb5_keyblock *encrypting_key,
-                                              krb5_pa_data **send_pa)
-{
-    krb5_error_code             code;
-    krb5_tl_data                tl_data;
-    krb5_pa_data                *pa_data;
-    krb5_enc_data               enc_data;
-    krb5_data                   plain;
-    krb5_data                   *enc_pa_data;
-
-    *send_pa = NULL;
-
-    tl_data.tl_data_type = KRB5_TL_SERVER_REFERRAL;
-
-    code = krb5_dbe_lookup_tl_data(context, server, &tl_data);
-    if (code || tl_data.tl_data_length == 0)
-        return 0; /* no server referrals to return */
-
-    plain.length = tl_data.tl_data_length;
-    plain.data = tl_data.tl_data_contents;
-
-    /* Encrypt ServerReferralData */
-    code = krb5_encrypt_helper(context, encrypting_key,
-                               KRB5_KEYUSAGE_PA_SERVER_REFERRAL_DATA,
-                               &plain, &enc_data);
-    if (code)
-        return code;
-
-    /* Encode ServerReferralData into PA-SERVER-REFERRAL-DATA */
-    code = encode_krb5_enc_data(&enc_data, &enc_pa_data);
-    if (code) {
-        krb5_free_data_contents(context, &enc_data.ciphertext);
-        return code;
-    }
-
-    krb5_free_data_contents(context, &enc_data.ciphertext);
-
-    /* Return PA-SERVER-REFERRAL-DATA */
-    pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data));
-    if (pa_data == NULL) {
-        krb5_free_data(context, enc_pa_data);
-        return ENOMEM;
-    }
-
-    pa_data->magic = KV5M_PA_DATA;
-    pa_data->pa_type = KRB5_PADATA_SVR_REFERRAL_INFO;
-    pa_data->length = enc_pa_data->length;
-    pa_data->contents = enc_pa_data->data;
-
-    free(enc_pa_data); /* don't free contents */
-
-    *send_pa = pa_data;
-
-    return 0;
-}
-#endif