krb5 commit: Use new pa-data helpers where appropriate

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/154551ad22e90d2e5f60103059fbaaadac017420
commit 154551ad22e90d2e5f60103059fbaaadac017420
Author: Greg Hudson <[email protected]>
Date:   Mon Jun 3 17:32:20 2019 -0400

    Use new pa-data helpers where appropriate

 src/kdc/fast_util.c           |    5 +-
 src/kdc/kdc_preauth.c         |  112 +++++++++++++++-------------------------
 src/kdc/kdc_util.c            |   91 +++++----------------------------
 src/kdc/kdc_util.h            |    6 --
 src/lib/krb5/krb/get_in_tkt.c |   57 +++++----------------
 5 files changed, 72 insertions(+), 199 deletions(-)

diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c
index c9ba83e..a55fc1b 100644
--- a/src/kdc/fast_util.c
+++ b/src/kdc/fast_util.c
@@ -456,7 +456,7 @@ static krb5_error_code
 make_padata(krb5_preauthtype pa_type, const void *contents, size_t len,
             krb5_pa_data **out)
 {
-    if (alloc_pa_data(pa_type, len, out) != 0)
+    if (k5_alloc_pa_data(pa_type, len, out) != 0)
         return ENOMEM;
     memcpy((*out)->contents, contents, len);
     return 0;
@@ -696,7 +696,8 @@ kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state,
         goto cleanup;
 
     /* Construct the cookie pa-data entry. */
-    ret = alloc_pa_data(KRB5_PADATA_FX_COOKIE, 8 + enc.ciphertext.length, &pa);
+    ret = k5_alloc_pa_data(KRB5_PADATA_FX_COOKIE, 8 + enc.ciphertext.length,
+                           &pa);
     memcpy(pa->contents, "MIT1", 4);
     store_32_be(kvno, pa->contents + 4);
     memcpy(pa->contents + 8, enc.ciphertext.data, enc.ciphertext.length);
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index 508a5cf..8f89c06 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -108,9 +108,9 @@ 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,
+make_etype_info(krb5_context context, krb5_boolean etype_info2,
                 krb5_principal client, krb5_key_data *client_key,
-                krb5_enctype enctype, krb5_pa_data **pa_out);
+                krb5_enctype enctype, krb5_data **der_out);
 
 /* Get all available kdcpreauth vtables and a count of preauth types they
  * support.  Return an empty list on failure. */
@@ -753,32 +753,32 @@ add_etype_info(krb5_context context, krb5_kdcpreauth_rock rock,
                krb5_pa_data ***pa_list)
 {
     krb5_error_code ret;
-    krb5_pa_data *pa;
+    krb5_data *der;
 
     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);
+        ret = make_etype_info(context, FALSE, rock->client->princ,
+                              rock->client_key, rock->client_keyblock->enctype,
+                              &der);
         if (ret)
             return ret;
-        /* add_pa_data_element() claims pa on success or failure. */
-        ret = add_pa_data_element(pa_list, pa);
+        ret = k5_add_pa_data_from_data(pa_list, KRB5_PADATA_ETYPE_INFO, der);
+        krb5_free_data(context, der);
         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);
+    ret = make_etype_info(context, TRUE, rock->client->princ, rock->client_key,
+                          rock->client_keyblock->enctype, &der);
     if (ret)
         return ret;
-    /* add_pa_data_element() claims pa on success or failure. */
-    return add_pa_data_element(pa_list, pa);
+    ret = k5_add_pa_data_from_data(pa_list, KRB5_PADATA_ETYPE_INFO2, der);
+    krb5_free_data(context, der);
+    return ret;
 }
 
 /* Add PW-SALT entries to pa_list as appropriate for the request and client
@@ -788,7 +788,6 @@ 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;
 
@@ -801,18 +800,7 @@ add_pw_salt(krb5_context context, krb5_kdcpreauth_rock rock,
     if (ret)
         return 0;
 
-    /* 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:
+    ret = k5_add_pa_data_from_data(pa_list, KRB5_PADATA_PW_SALT, salt);
     krb5_free_data(context, salt);
     return ret;
 }
@@ -827,7 +815,7 @@ add_freshness_token(krb5_context context, krb5_kdcpreauth_rock rock,
     krb5_keyblock kb;
     krb5_checksum cksum;
     krb5_data d;
-    krb5_pa_data *pa;
+    krb5_pa_data *pa = NULL;
     char ckbuf[4];
 
     memset(&cksum, 0, sizeof(cksum));
@@ -857,19 +845,19 @@ add_freshness_token(krb5_context context, krb5_kdcpreauth_rock rock,
                                &d, &cksum);
 
     /* Compose a freshness token from the time, krbtgt kvno, and checksum. */
-    ret = alloc_pa_data(KRB5_PADATA_AS_FRESHNESS, 8 + cksum.length, &pa);
+    ret = k5_alloc_pa_data(KRB5_PADATA_AS_FRESHNESS, 8 + cksum.length, &pa);
     if (ret)
         goto cleanup;
     store_32_be(now, pa->contents);
     store_32_be(kd->key_data_kvno, pa->contents + 4);
     memcpy(pa->contents + 8, cksum.contents, cksum.length);
 
-    /* add_pa_data_element() claims pa on success or failure. */
-    ret = add_pa_data_element(pa_list, pa);
+    ret = k5_add_pa_data_element(pa_list, &pa);
 
 cleanup:
     krb5_free_keyblock_contents(context, &kb);
     krb5_free_checksum_contents(context, &cksum);
+    k5_free_pa_data_element(pa);
     return ret;
 }
 
@@ -927,12 +915,12 @@ finish_get_edata(void *arg, krb5_error_code code, krb5_pa_data *pa)
 
     if (code == 0) {
         if (pa == NULL) {
-            ret = alloc_pa_data(state->pa_type, 0, &pa);
+            ret = k5_alloc_pa_data(state->pa_type, 0, &pa);
             if (ret)
                 goto error;
         }
-        /* add_pa_data_element() claims pa on success or failure. */
-        ret = add_pa_data_element(&state->pa_data, pa);
+        ret = k5_add_pa_data_element(&state->pa_data, &pa);
+        k5_free_pa_data_element(pa);
         if (ret)
             goto error;
     }
@@ -981,7 +969,6 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
 {
     kdc_realm_t *kdc_active_realm = rock->rstate->realm_data;
     struct hint_state *state;
-    krb5_pa_data *pa;
 
     *e_data_out = NULL;
 
@@ -1001,10 +988,7 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
     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)
+    if (k5_add_empty_pa_data(&state->pa_data, KRB5_PADATA_FX_FAST) != 0)
         goto error;
 
     if (add_etype_info(kdc_context, rock, &state->pa_data) != 0)
@@ -1151,7 +1135,7 @@ 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 *pa;
+    krb5_data *der;
 
     /* Only add key information when requesting another preauth round trip. */
     if (code != KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
@@ -1167,14 +1151,14 @@ maybe_add_etype_info2(struct padata_state *state, krb5_error_code code)
                              KRB5_PADATA_FX_COOKIE) != NULL)
         return 0;
 
-    ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
-                          rock->client->princ, rock->client_key,
-                          rock->client_keyblock->enctype, &pa);
+    ret = make_etype_info(context, TRUE, rock->client->princ, rock->client_key,
+                          rock->client_keyblock->enctype, &der);
     if (ret)
         return ret;
-
-    /* add_pa_data_element() claims pa on success or failure. */
-    return add_pa_data_element(&state->pa_e_data, pa);
+    ret = k5_add_pa_data_from_data(&state->pa_e_data, KRB5_PADATA_ETYPE_INFO2,
+                                   der);
+    krb5_free_data(context, der);
+    return ret;
 }
 
 /* Release state and respond to the AS-REQ processing code with the result of
@@ -1468,8 +1452,8 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
             goto cleanup;
 
         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);
+            retval = k5_add_pa_data_element(&send_pa_list, &send_pa);
+            k5_free_pa_data_element(send_pa);
             if (retval)
                 goto cleanup;
         }
@@ -1552,19 +1536,17 @@ cleanup:
     return retval;
 }
 
-/* Create etype-info or etype-info2 padata for client_key with the given
+/* Encode an etype-info or etype-info2 message for client_key with the given
  * enctype, using client to compute the salt if necessary. */
 static krb5_error_code
-make_etype_info(krb5_context context, krb5_preauthtype pa_type,
+make_etype_info(krb5_context context, krb5_boolean etype_info2,
                 krb5_principal client, krb5_key_data *client_key,
-                krb5_enctype enctype, krb5_pa_data **pa_out)
+                krb5_enctype enctype, krb5_data **der_out)
 {
     krb5_error_code retval;
     krb5_etype_info_entry **entry = NULL;
-    krb5_data *der_etype_info = NULL;
-    int etype_info2 = (pa_type == KRB5_PADATA_ETYPE_INFO2);
 
-    *pa_out = NULL;
+    *der_out = NULL;
 
     entry = k5calloc(2, sizeof(*entry), &retval);
     if (entry == NULL)
@@ -1575,23 +1557,12 @@ make_etype_info(krb5_context context, krb5_preauthtype pa_type,
         goto cleanup;
 
     if (etype_info2)
-        retval = encode_krb5_etype_info2(entry, &der_etype_info);
+        retval = encode_krb5_etype_info2(entry, der_out);
     else
-        retval = encode_krb5_etype_info(entry, &der_etype_info);
-    if (retval)
-        goto cleanup;
-
-    /* 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_out)->contents = (uint8_t *)der_etype_info->data;
-    (*pa_out)->length = der_etype_info->length;
-    der_etype_info->data = NULL;
+        retval = encode_krb5_etype_info(entry, der_out);
 
 cleanup:
     krb5_free_etype_info(context, entry);
-    krb5_free_data(context, der_etype_info);
     return retval;
 }
 
@@ -1643,13 +1614,14 @@ return_referral_enc_padata( krb5_context context,
     if (code || tl_data.tl_data_length == 0)
         return 0;
 
-    code = alloc_pa_data(KRB5_PADATA_SVR_REFERRAL_INFO, tl_data.tl_data_length,
-                         &pa);
+    code = k5_alloc_pa_data(KRB5_PADATA_SVR_REFERRAL_INFO,
+                            tl_data.tl_data_length, &pa);
     if (code)
         return code;
     memcpy(pa->contents, tl_data.tl_data_contents, tl_data.tl_data_length);
-    /* add_pa_data_element() claims pa on success or failure. */
-    return add_pa_data_element(&reply->enc_padata, pa);
+    code = k5_add_pa_data_element(&reply->enc_padata, &pa);
+    k5_free_pa_data_element(pa);
+    return code;
 }
 
 krb5_error_code
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 02d9342..2b949cf 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -1375,7 +1375,7 @@ kdc_make_s4u2self_rep(krb5_context context,
     krb5_error_code             code;
     krb5_data                   *der_user_id = NULL, *der_s4u_x509_user = NULL;
     krb5_pa_s4u_x509_user       rep_s4u_user;
-    krb5_pa_data                *pa;
+    krb5_pa_data                *pa = NULL;
     krb5_enctype                enctype;
     krb5_keyusage               usage;
 
@@ -1405,15 +1405,8 @@ kdc_make_s4u2self_rep(krb5_context context,
     if (code != 0)
         goto cleanup;
 
-    /* Add a padata element, stealing memory from der_s4u_x509_user. */
-    code = alloc_pa_data(KRB5_PADATA_S4U_X509_USER, 0, &pa);
-    if (code != 0)
-        goto cleanup;
-    pa->length = der_s4u_x509_user->length;
-    pa->contents = (uint8_t *)der_s4u_x509_user->data;
-    der_s4u_x509_user->data = NULL;
-    /* add_pa_data_element() claims pa on success or failure. */
-    code = add_pa_data_element(&reply->padata, pa);
+    code = k5_add_pa_data_from_data(&reply->padata, KRB5_PADATA_S4U_X509_USER,
+                                    der_s4u_x509_user);
     if (code != 0)
         goto cleanup;
 
@@ -1429,9 +1422,9 @@ kdc_make_s4u2self_rep(krb5_context context,
      */
     if ((req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE) &&
         enctype_requires_etype_info_2(enctype) == FALSE) {
-        code = alloc_pa_data(KRB5_PADATA_S4U_X509_USER,
-                             req_s4u_user->cksum.length +
-                             rep_s4u_user.cksum.length, &pa);
+        code = k5_alloc_pa_data(KRB5_PADATA_S4U_X509_USER,
+                                req_s4u_user->cksum.length +
+                                rep_s4u_user.cksum.length, &pa);
         if (code != 0)
             goto cleanup;
         memcpy(pa->contents,
@@ -1439,8 +1432,7 @@ kdc_make_s4u2self_rep(krb5_context context,
         memcpy(&pa->contents[req_s4u_user->cksum.length],
                rep_s4u_user.cksum.contents, rep_s4u_user.cksum.length);
 
-        /* add_pa_data_element() claims pa on success or failure. */
-        code = add_pa_data_element(&reply_encpart->enc_padata, pa);
+        code = k5_add_pa_data_element(&reply_encpart->enc_padata, &pa);
         if (code != 0)
             goto cleanup;
     }
@@ -1450,7 +1442,7 @@ cleanup:
         krb5_free_checksum_contents(context, &rep_s4u_user.cksum);
     krb5_free_data(context, der_user_id);
     krb5_free_data(context, der_s4u_x509_user);
-
+    k5_free_pa_data_element(pa);
     return code;
 }
 
@@ -1778,53 +1770,6 @@ enctype_requires_etype_info_2(krb5_enctype enctype)
     }
 }
 
-/* Allocate a pa-data entry with an uninitialized buffer of size len. */
-krb5_error_code
-alloc_pa_data(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out)
-{
-    krb5_pa_data *pa;
-    uint8_t *buf = NULL;
-
-    *out = NULL;
-    if (len > 0) {
-        buf = malloc(len);
-        if (buf == NULL)
-            return ENOMEM;
-    }
-    pa = malloc(sizeof(*pa));
-    if (pa == NULL) {
-        free(buf);
-        return ENOMEM;
-    }
-    pa->magic = KV5M_PA_DATA;
-    pa->pa_type = pa_type;
-    pa->length = len;
-    pa->contents = buf;
-    *out = pa;
-    return 0;
-}
-
-/* Add pa to list, claiming its memory.  Free pa on failure. */
-krb5_error_code
-add_pa_data_element(krb5_pa_data ***list, krb5_pa_data *pa)
-{
-    size_t count;
-    krb5_pa_data **newlist;
-
-    for (count = 0; *list != NULL && (*list)[count] != NULL; count++);
-
-    newlist = realloc(*list, (count + 2) * sizeof(*newlist));
-    if (newlist == NULL) {
-        free(pa->contents);
-        free(pa);
-        return ENOMEM;
-    }
-    newlist[count] = pa;
-    newlist[count + 1] = NULL;
-    *list = newlist;
-    return 0;
-}
-
 void
 kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm,
                        krb5_timestamp starttime,
@@ -1926,7 +1871,7 @@ kdc_handle_protected_negotiation(krb5_context context,
     krb5_error_code retval = 0;
     krb5_checksum checksum;
     krb5_data *der_cksum = NULL;
-    krb5_pa_data *pa, *pa_in;
+    krb5_pa_data *pa_in;
 
     memset(&checksum, 0, sizeof(checksum));
 
@@ -1944,24 +1889,14 @@ kdc_handle_protected_negotiation(krb5_context context,
     if (retval != 0)
         goto cleanup;
 
-    /* Add a pa-data element to the list, stealing memory from der_cksum. */
-    retval = alloc_pa_data(KRB5_ENCPADATA_REQ_ENC_PA_REP, 0, &pa);
-    if (retval)
-        goto cleanup;
-    pa->length = der_cksum->length;
-    pa->contents = (uint8_t *)der_cksum->data;
-    der_cksum->data = NULL;
-    /* add_pa_data_element() claims pa on success or failure. */
-    retval = add_pa_data_element(out_enc_padata, pa);
+    retval = k5_add_pa_data_from_data(out_enc_padata,
+                                      KRB5_ENCPADATA_REQ_ENC_PA_REP,
+                                      der_cksum);
     if (retval)
         goto cleanup;
 
     /* Add a zero-length PA-FX-FAST element to the list. */
-    retval = alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa);
-    if (retval)
-        goto cleanup;
-    /* add_pa_data_element() claims pa on success or failure. */
-    retval = add_pa_data_element(out_enc_padata, pa);
+    retval = k5_add_empty_pa_data(out_enc_padata, KRB5_PADATA_FX_FAST);
 
 cleanup:
     krb5_free_checksum_contents(context, &checksum);
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 1314bdd..fea35d7 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -198,12 +198,6 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
 void
 free_padata_context(krb5_context context, void *padata_context);
 
-krb5_error_code
-alloc_pa_data(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out);
-
-krb5_error_code
-add_pa_data_element(krb5_pa_data ***list, krb5_pa_data *pa);
-
 /* kdc_preauth_ec.c */
 krb5_error_code
 kdcpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver,
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index 1e53d7a..dcf6663 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -402,40 +402,6 @@ make_preauth_list(krb5_context  context,
 
 #define MAX_IN_TKT_LOOPS 16
 
-/* Add a pa-data item with the specified type and contents to *padptr. */
-static krb5_error_code
-add_padata(krb5_pa_data ***padptr, krb5_preauthtype pa_type,
-           const void *contents, unsigned int length)
-{
-    size_t size = 0;
-    krb5_pa_data **pad = *padptr;
-    krb5_pa_data *pa= NULL;
-    if (pad)
-        for (size=0; pad[size]; size++);
-    pad = realloc(pad, sizeof(*pad)*(size+2));
-    if (pad == NULL)
-        return ENOMEM;
-    *padptr = pad;
-    pad[size] = pad[size + 1] = NULL;
-
-    pa = malloc(sizeof(krb5_pa_data));
-    if (pa == NULL)
-        return ENOMEM;
-    pa->contents = NULL;
-    pa->length = length;
-    if (contents != NULL) {
-        pa->contents = malloc(length);
-        if (pa->contents == NULL) {
-            free(pa);
-            return ENOMEM;
-        }
-        memcpy(pa->contents, contents, length);
-    }
-    pa->pa_type = pa_type;
-    pad[size] = pa;
-    return 0;
-}
-
 /* Sort a pa_data sequence so that types named in the "preferred_preauth_types"
  * libdefaults entry are listed before any others. */
 static krb5_error_code
@@ -1300,8 +1266,8 @@ maybe_add_pac_request(krb5_context context, krb5_init_creds_context ctx)
     code = encode_krb5_pa_pac_req(&pac_req, &encoded);
     if (code)
         return code;
-    code = add_padata(&ctx->request->padata, KRB5_PADATA_PAC_REQUEST,
-                      encoded->data, encoded->length);
+    code = k5_add_pa_data_from_data(&ctx->request->padata,
+                                    KRB5_PADATA_PAC_REQUEST, encoded);
     krb5_free_data(context, encoded);
     return code;
 }
@@ -1313,6 +1279,7 @@ init_creds_step_request(krb5_context context,
 {
     krb5_error_code code;
     krb5_preauthtype pa_type;
+    krb5_data copy;
     struct errinfo save = EMPTY_ERRINFO;
     uint32_t rcode = (ctx->err_reply == NULL) ? 0 : ctx->err_reply->error;
 
@@ -1414,21 +1381,25 @@ init_creds_step_request(krb5_context context,
         ctx->encoded_previous_request = NULL;
     }
     if (ctx->info_pa_permitted) {
-        code = add_padata(&ctx->request->padata, KRB5_PADATA_AS_FRESHNESS,
-                          NULL, 0);
+        code = k5_add_empty_pa_data(&ctx->request->padata,
+                                    KRB5_PADATA_AS_FRESHNESS);
         if (code)
             goto cleanup;
-        code = add_padata(&ctx->request->padata, KRB5_ENCPADATA_REQ_ENC_PA_REP,
-                          NULL, 0);
+        code = k5_add_empty_pa_data(&ctx->request->padata,
+                                    KRB5_ENCPADATA_REQ_ENC_PA_REP);
     }
     if (code)
         goto cleanup;
 
     if (ctx->subject_cert != NULL) {
-        code = add_padata(&ctx->request->padata, KRB5_PADATA_S4U_X509_USER,
-                          ctx->subject_cert->data, ctx->subject_cert->length);
+        code = krb5int_copy_data_contents(context, ctx->subject_cert, &copy);
         if (code)
-            return code;
+            goto cleanup;
+        code = k5_add_pa_data_from_data(&ctx->request->padata,
+                                        KRB5_PADATA_S4U_X509_USER, &copy);
+        krb5_free_data_contents(context, &copy);
+        if (code)
+            goto cleanup;
     }
 
     code = maybe_add_pac_request(context, ctx);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.