Blame SOURCES/Refactor-KDC-krb5_pa_data-utility-functions.patch

c41359
From 7c59b7ee063489a4259c34b725728fee7e411c46 Mon Sep 17 00:00:00 2001
c41359
From: Greg Hudson <ghudson@mit.edu>
c41359
Date: Thu, 21 Dec 2017 11:28:52 -0500
c41359
Subject: [PATCH] Refactor KDC krb5_pa_data utility functions
c41359
c41359
Move alloc_padata from fast_util.c to kdc_util.c and make it
c41359
non-static so it can be used by other files.  Rename it to
c41359
alloc_pa_data for consistency with add_pa_data_element.  Make it
c41359
correctly handle zero length using a null contents pointer.
c41359
c41359
Make add_pa_data_element claim both the container and contents memory
c41359
from the caller, now that callers can use alloc_pa_data to simplify
c41359
allocation and copying.  Remove the copy parameter and the unused
c41359
context parameter, and put the list parameter first.  Adjust all
c41359
callers accordingly, making small simplifications to memory handling
c41359
where applicable.
c41359
c41359
(cherry picked from commit 4af478c18b02e1d2444a328bb79e6976ef3d312b)
c41359
---
c41359
 src/kdc/fast_util.c   |  28 +------
c41359
 src/kdc/kdc_preauth.c |  14 ++--
c41359
 src/kdc/kdc_util.c    | 187 +++++++++++++++++++++---------------------
c41359
 src/kdc/kdc_util.h    |   8 +-
c41359
 4 files changed, 109 insertions(+), 128 deletions(-)
c41359
c41359
diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c
c41359
index e05107ef3..6a3fc11b9 100644
c41359
--- a/src/kdc/fast_util.c
c41359
+++ b/src/kdc/fast_util.c
c41359
@@ -451,36 +451,12 @@ kdc_fast_hide_client(struct kdc_request_state *state)
c41359
     return (state->fast_options & KRB5_FAST_OPTION_HIDE_CLIENT_NAMES) != 0;
c41359
 }
c41359
 
c41359
-/* Allocate a pa-data entry with an uninitialized buffer of size len. */
c41359
-static krb5_error_code
c41359
-alloc_padata(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out)
c41359
-{
c41359
-    krb5_pa_data *pa;
c41359
-    uint8_t *buf;
c41359
-
c41359
-    *out = NULL;
c41359
-    buf = malloc(len);
c41359
-    if (buf == NULL)
c41359
-        return ENOMEM;
c41359
-    pa = malloc(sizeof(*pa));
c41359
-    if (pa == NULL) {
c41359
-        free(buf);
c41359
-        return ENOMEM;
c41359
-    }
c41359
-    pa->magic = KV5M_PA_DATA;
c41359
-    pa->pa_type = pa_type;
c41359
-    pa->length = len;
c41359
-    pa->contents = buf;
c41359
-    *out = pa;
c41359
-    return 0;
c41359
-}
c41359
-
c41359
 /* Create a pa-data entry with the specified type and contents. */
c41359
 static krb5_error_code
c41359
 make_padata(krb5_preauthtype pa_type, const void *contents, size_t len,
c41359
             krb5_pa_data **out)
c41359
 {
c41359
-    if (alloc_padata(pa_type, len, out) != 0)
c41359
+    if (alloc_pa_data(pa_type, len, out) != 0)
c41359
         return ENOMEM;
c41359
     memcpy((*out)->contents, contents, len);
c41359
     return 0;
c41359
@@ -720,7 +696,7 @@ kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state,
c41359
         goto cleanup;
c41359
 
c41359
     /* Construct the cookie pa-data entry. */
c41359
-    ret = alloc_padata(KRB5_PADATA_FX_COOKIE, 8 + enc.ciphertext.length, &pa);
c41359
+    ret = alloc_pa_data(KRB5_PADATA_FX_COOKIE, 8 + enc.ciphertext.length, &pa);
c41359
     memcpy(pa->contents, "MIT1", 4);
c41359
     store_32_be(kvno, pa->contents + 4);
c41359
     memcpy(pa->contents + 8, enc.ciphertext.data, enc.ciphertext.length);
c41359
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
c41359
index 739c5e776..edc30bd83 100644
c41359
--- a/src/kdc/kdc_preauth.c
c41359
+++ b/src/kdc/kdc_preauth.c
c41359
@@ -1617,18 +1617,20 @@ return_referral_enc_padata( krb5_context context,
c41359
 {
c41359
     krb5_error_code             code;
c41359
     krb5_tl_data                tl_data;
c41359
-    krb5_pa_data                pa_data;
c41359
+    krb5_pa_data                *pa;
c41359
 
c41359
     tl_data.tl_data_type = KRB5_TL_SVR_REFERRAL_DATA;
c41359
     code = krb5_dbe_lookup_tl_data(context, server, &tl_data);
c41359
     if (code || tl_data.tl_data_length == 0)
c41359
         return 0;
c41359
 
c41359
-    pa_data.magic = KV5M_PA_DATA;
c41359
-    pa_data.pa_type = KRB5_PADATA_SVR_REFERRAL_INFO;
c41359
-    pa_data.length = tl_data.tl_data_length;
c41359
-    pa_data.contents = tl_data.tl_data_contents;
c41359
-    return add_pa_data_element(context, &pa_data, &reply->enc_padata, TRUE);
c41359
+    code = alloc_pa_data(KRB5_PADATA_SVR_REFERRAL_INFO, tl_data.tl_data_length,
c41359
+                         &pa);
c41359
+    if (code)
c41359
+        return code;
c41359
+    memcpy(pa->contents, tl_data.tl_data_contents, tl_data.tl_data_length);
c41359
+    /* add_pa_data_element() claims pa on success or failure. */
c41359
+    return add_pa_data_element(&reply->enc_padata, pa);
c41359
 }
c41359
 
c41359
 krb5_error_code
c41359
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
c41359
index 754570c01..13111215d 100644
c41359
--- a/src/kdc/kdc_util.c
c41359
+++ b/src/kdc/kdc_util.c
c41359
@@ -1353,9 +1353,9 @@ kdc_make_s4u2self_rep(krb5_context context,
c41359
                       krb5_enc_kdc_rep_part *reply_encpart)
c41359
 {
c41359
     krb5_error_code             code;
c41359
-    krb5_data                   *data = NULL;
c41359
+    krb5_data                   *der_user_id = NULL, *der_s4u_x509_user = NULL;
c41359
     krb5_pa_s4u_x509_user       rep_s4u_user;
c41359
-    krb5_pa_data                padata;
c41359
+    krb5_pa_data                *pa;
c41359
     krb5_enctype                enctype;
c41359
     krb5_keyusage               usage;
c41359
 
c41359
@@ -1366,7 +1366,7 @@ kdc_make_s4u2self_rep(krb5_context context,
c41359
     rep_s4u_user.user_id.options =
c41359
         req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE;
c41359
 
c41359
-    code = encode_krb5_s4u_userid(&rep_s4u_user.user_id, &data);
c41359
+    code = encode_krb5_s4u_userid(&rep_s4u_user.user_id, &der_user_id);
c41359
     if (code != 0)
c41359
         goto cleanup;
c41359
 
c41359
@@ -1377,29 +1377,25 @@ kdc_make_s4u2self_rep(krb5_context context,
c41359
 
c41359
     code = krb5_c_make_checksum(context, req_s4u_user->cksum.checksum_type,
c41359
                                 tgs_subkey != NULL ? tgs_subkey : tgs_session,
c41359
-                                usage, data,
c41359
-                                &rep_s4u_user.cksum);
c41359
+                                usage, der_user_id, &rep_s4u_user.cksum);
c41359
     if (code != 0)
c41359
         goto cleanup;
c41359
 
c41359
-    krb5_free_data(context, data);
c41359
-    data = NULL;
c41359
-
c41359
-    code = encode_krb5_pa_s4u_x509_user(&rep_s4u_user, &data);
c41359
+    code = encode_krb5_pa_s4u_x509_user(&rep_s4u_user, &der_s4u_x509_user);
c41359
     if (code != 0)
c41359
         goto cleanup;
c41359
 
c41359
-    padata.magic = KV5M_PA_DATA;
c41359
-    padata.pa_type = KRB5_PADATA_S4U_X509_USER;
c41359
-    padata.length = data->length;
c41359
-    padata.contents = (krb5_octet *)data->data;
c41359
-
c41359
-    code = add_pa_data_element(context, &padata, &reply->padata, FALSE);
c41359
+    /* Add a padata element, stealing memory from der_s4u_x509_user. */
c41359
+    code = alloc_pa_data(KRB5_PADATA_S4U_X509_USER, 0, &pa);
c41359
+    if (code != 0)
c41359
+        goto cleanup;
c41359
+    pa->length = der_s4u_x509_user->length;
c41359
+    pa->contents = (uint8_t *)der_s4u_x509_user->data;
c41359
+    der_s4u_x509_user->data = NULL;
c41359
+    /* add_pa_data_element() claims pa on success or failure. */
c41359
+    code = add_pa_data_element(&reply->padata, pa);
c41359
     if (code != 0)
c41359
         goto cleanup;
c41359
-
c41359
-    free(data);
c41359
-    data = NULL;
c41359
 
c41359
     if (tgs_subkey != NULL)
c41359
         enctype = tgs_subkey->enctype;
c41359
@@ -1413,33 +1409,27 @@ kdc_make_s4u2self_rep(krb5_context context,
c41359
      */
c41359
     if ((req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE) &&
c41359
         enctype_requires_etype_info_2(enctype) == FALSE) {
c41359
-        padata.length = req_s4u_user->cksum.length +
c41359
-            rep_s4u_user.cksum.length;
c41359
-        padata.contents = malloc(padata.length);
c41359
-        if (padata.contents == NULL) {
c41359
-            code = ENOMEM;
c41359
+        code = alloc_pa_data(KRB5_PADATA_S4U_X509_USER,
c41359
+                             req_s4u_user->cksum.length +
c41359
+                             rep_s4u_user.cksum.length, &pa);
c41359
+        if (code != 0)
c41359
             goto cleanup;
c41359
-        }
c41359
+        memcpy(pa->contents,
c41359
+               req_s4u_user->cksum.contents, req_s4u_user->cksum.length);
c41359
+        memcpy(&pa->contents[req_s4u_user->cksum.length],
c41359
+               rep_s4u_user.cksum.contents, rep_s4u_user.cksum.length);
c41359
 
c41359
-        memcpy(padata.contents,
c41359
-               req_s4u_user->cksum.contents,
c41359
-               req_s4u_user->cksum.length);
c41359
-        memcpy(&padata.contents[req_s4u_user->cksum.length],
c41359
-               rep_s4u_user.cksum.contents,
c41359
-               rep_s4u_user.cksum.length);
c41359
-
c41359
-        code = add_pa_data_element(context,&padata,
c41359
-                                   &reply_encpart->enc_padata, FALSE);
c41359
-        if (code != 0) {
c41359
-            free(padata.contents);
c41359
+        /* add_pa_data_element() claims pa on success or failure. */
c41359
+        code = add_pa_data_element(&reply_encpart->enc_padata, pa);
c41359
+        if (code != 0)
c41359
             goto cleanup;
c41359
-        }
c41359
     }
c41359
 
c41359
 cleanup:
c41359
     if (rep_s4u_user.cksum.contents != NULL)
c41359
         krb5_free_checksum_contents(context, &rep_s4u_user.cksum);
c41359
-    krb5_free_data(context, data);
c41359
+    krb5_free_data(context, der_user_id);
c41359
+    krb5_free_data(context, der_s4u_x509_user);
c41359
 
c41359
     return code;
c41359
 }
c41359
@@ -1707,46 +1697,50 @@ enctype_requires_etype_info_2(krb5_enctype enctype)
c41359
     }
c41359
 }
c41359
 
c41359
-/* XXX where are the generic helper routines for this? */
c41359
+/* Allocate a pa-data entry with an uninitialized buffer of size len. */
c41359
 krb5_error_code
c41359
-add_pa_data_element(krb5_context context,
c41359
-                    krb5_pa_data *padata,
c41359
-                    krb5_pa_data ***inout_padata,
c41359
-                    krb5_boolean copy)
c41359
+alloc_pa_data(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out)
c41359
 {
c41359
-    int                         i;
c41359
-    krb5_pa_data                **p;
c41359
+    krb5_pa_data *pa;
c41359
+    uint8_t *buf = NULL;
c41359
 
c41359
-    if (*inout_padata != NULL) {
c41359
-        for (i = 0; (*inout_padata)[i] != NULL; i++)
c41359
-            ;
c41359
-    } else
c41359
-        i = 0;
c41359
-
c41359
-    p = realloc(*inout_padata, (i + 2) * sizeof(krb5_pa_data *));
c41359
-    if (p == NULL)
c41359
-        return ENOMEM;
c41359
-
c41359
-    *inout_padata = p;
c41359
-
c41359
-    p[i] = (krb5_pa_data *)malloc(sizeof(krb5_pa_data));
c41359
-    if (p[i] == NULL)
c41359
-        return ENOMEM;
c41359
-    *(p[i]) = *padata;
c41359
-
c41359
-    p[i + 1] = NULL;
c41359
-
c41359
-    if (copy) {
c41359
-        p[i]->contents = (krb5_octet *)malloc(padata->length);
c41359
-        if (p[i]->contents == NULL) {
c41359
-            free(p[i]);
c41359
-            p[i] = NULL;
c41359
+    *out = NULL;
c41359
+    if (len > 0) {
c41359
+        buf = malloc(len);
c41359
+        if (buf == NULL)
c41359
             return ENOMEM;
c41359
-        }
c41359
-
c41359
-        memcpy(p[i]->contents, padata->contents, padata->length);
c41359
     }
c41359
+    pa = malloc(sizeof(*pa));
c41359
+    if (pa == NULL) {
c41359
+        free(buf);
c41359
+        return ENOMEM;
c41359
+    }
c41359
+    pa->magic = KV5M_PA_DATA;
c41359
+    pa->pa_type = pa_type;
c41359
+    pa->length = len;
c41359
+    pa->contents = buf;
c41359
+    *out = pa;
c41359
+    return 0;
c41359
+}
c41359
 
c41359
+/* Add pa to list, claiming its memory.  Free pa on failure. */
c41359
+krb5_error_code
c41359
+add_pa_data_element(krb5_pa_data ***list, krb5_pa_data *pa)
c41359
+{
c41359
+    size_t count;
c41359
+    krb5_pa_data **newlist;
c41359
+
c41359
+    for (count = 0; *list != NULL && (*list)[count] != NULL; count++);
c41359
+
c41359
+    newlist = realloc(*list, (count + 2) * sizeof(*newlist));
c41359
+    if (newlist == NULL) {
c41359
+        free(pa->contents);
c41359
+        free(pa);
c41359
+        return ENOMEM;
c41359
+    }
c41359
+    newlist[count] = pa;
c41359
+    newlist[count + 1] = NULL;
c41359
+    *list = newlist;
c41359
     return 0;
c41359
 }
c41359
 
c41359
@@ -1850,38 +1844,47 @@ kdc_handle_protected_negotiation(krb5_context context,
c41359
 {
c41359
     krb5_error_code retval = 0;
c41359
     krb5_checksum checksum;
c41359
-    krb5_data *out = NULL;
c41359
-    krb5_pa_data pa, *pa_in;
c41359
+    krb5_data *der_cksum = NULL;
c41359
+    krb5_pa_data *pa, *pa_in;
c41359
+
c41359
+    memset(&checksum, 0, sizeof(checksum));
c41359
+
c41359
     pa_in = krb5int_find_pa_data(context, request->padata,
c41359
                                  KRB5_ENCPADATA_REQ_ENC_PA_REP);
c41359
     if (pa_in == NULL)
c41359
         return 0;
c41359
-    pa.magic = KV5M_PA_DATA;
c41359
-    pa.pa_type = KRB5_ENCPADATA_REQ_ENC_PA_REP;
c41359
-    memset(&checksum, 0, sizeof(checksum));
c41359
-    retval = krb5_c_make_checksum(context,0, reply_key,
c41359
-                                  KRB5_KEYUSAGE_AS_REQ, req_pkt, &checksum);
c41359
+
c41359
+    /* Compute and encode a checksum over the AS-REQ. */
c41359
+    retval = krb5_c_make_checksum(context, 0, reply_key, KRB5_KEYUSAGE_AS_REQ,
c41359
+                                  req_pkt, &checksum);
c41359
     if (retval != 0)
c41359
         goto cleanup;
c41359
-    retval = encode_krb5_checksum(&checksum, &out;;
c41359
+    retval = encode_krb5_checksum(&checksum, &der_cksum);
c41359
     if (retval != 0)
c41359
         goto cleanup;
c41359
-    pa.contents = (krb5_octet *) out->data;
c41359
-    pa.length = out->length;
c41359
-    retval = add_pa_data_element(context, &pa, out_enc_padata, FALSE);
c41359
+
c41359
+    /* Add a pa-data element to the list, stealing memory from der_cksum. */
c41359
+    retval = alloc_pa_data(KRB5_ENCPADATA_REQ_ENC_PA_REP, 0, &pa);
c41359
     if (retval)
c41359
         goto cleanup;
c41359
-    out->data = NULL;
c41359
-    pa.magic = KV5M_PA_DATA;
c41359
-    pa.pa_type = KRB5_PADATA_FX_FAST;
c41359
-    pa.length = 0;
c41359
-    pa.contents = NULL;
c41359
-    retval = add_pa_data_element(context, &pa, out_enc_padata, FALSE);
c41359
+    pa->length = der_cksum->length;
c41359
+    pa->contents = (uint8_t *)der_cksum->data;
c41359
+    der_cksum->data = NULL;
c41359
+    /* add_pa_data_element() claims pa on success or failure. */
c41359
+    retval = add_pa_data_element(out_enc_padata, pa);
c41359
+    if (retval)
c41359
+        goto cleanup;
c41359
+
c41359
+    /* Add a zero-length PA-FX-FAST element to the list. */
c41359
+    retval = alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa);
c41359
+    if (retval)
c41359
+        goto cleanup;
c41359
+    /* add_pa_data_element() claims pa on success or failure. */
c41359
+    retval = add_pa_data_element(out_enc_padata, pa);
c41359
+
c41359
 cleanup:
c41359
-    if (checksum.contents)
c41359
-        krb5_free_checksum_contents(context, &checksum);
c41359
-    if (out != NULL)
c41359
-        krb5_free_data(context, out);
c41359
+    krb5_free_checksum_contents(context, &checksum);
c41359
+    krb5_free_data(context, der_cksum);
c41359
     return retval;
c41359
 }
c41359
 
c41359
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
c41359
index c57d48f73..198eab9c4 100644
c41359
--- a/src/kdc/kdc_util.h
c41359
+++ b/src/kdc/kdc_util.h
c41359
@@ -202,10 +202,10 @@ void
c41359
 free_padata_context(krb5_context context, void *padata_context);
c41359
 
c41359
 krb5_error_code
c41359
-add_pa_data_element (krb5_context context,
c41359
-                     krb5_pa_data *padata,
c41359
-                     krb5_pa_data ***out_padata,
c41359
-                     krb5_boolean copy);
c41359
+alloc_pa_data(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out);
c41359
+
c41359
+krb5_error_code
c41359
+add_pa_data_element(krb5_pa_data ***list, krb5_pa_data *pa);
c41359
 
c41359
 /* kdc_preauth_ec.c */
c41359
 krb5_error_code