krb5 commit: Refactor KDC authdata list management helpers

Greg Hudson ghudson at mit.edu
Thu Feb 6 16:12:03 EST 2020


https://github.com/krb5/krb5/commit/b2190fdc253de6024001e0f1ff9fe56c31042bb7
commit b2190fdc253de6024001e0f1ff9fe56c31042bb7
Author: Greg Hudson <ghudson at mit.edu>
Date:   Wed Feb 5 18:46:11 2020 -0500

    Refactor KDC authdata list management helpers
    
    Remove the unused concat_authorization_data().  Split merge_authdata()
    into two helpers, one to destructively merge without filtering and one
    to add copied elements while filtering out KDC-only authdata types.
    Remove context parameters where they aren't needed (taking advantage
    of knowledge that some libkrb5 functions don't use their context
    parameters).

 src/kdc/kdc_authdata.c |  134 ++++++++++++++++++++++--------------------------
 src/kdc/kdc_util.c     |   50 ------------------
 src/kdc/kdc_util.h     |    5 --
 3 files changed, 62 insertions(+), 127 deletions(-)

diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c
index 1ebe872..010922c 100644
--- a/src/kdc/kdc_authdata.c
+++ b/src/kdc/kdc_authdata.c
@@ -108,7 +108,7 @@ unload_authdata_plugins(krb5_context context)
 /* Return true if authdata should be filtered when copying from untrusted
  * authdata.  If desired_type is non-zero, look only for that type. */
 static krb5_boolean
-is_kdc_issued_authdatum(krb5_context context, krb5_authdata *authdata,
+is_kdc_issued_authdatum(krb5_authdata *authdata,
                         krb5_authdatatype desired_type)
 {
     krb5_boolean result = FALSE;
@@ -117,7 +117,7 @@ is_kdc_issued_authdatum(krb5_context context, krb5_authdata *authdata,
     krb5_authdatatype *ad_types, *containee_types = NULL;
 
     if (authdata->ad_type == KRB5_AUTHDATA_IF_RELEVANT) {
-        if (krb5int_get_authdata_containee_types(context, authdata, &count,
+        if (krb5int_get_authdata_containee_types(NULL, authdata, &count,
                                                  &containee_types) != 0)
             goto cleanup;
         ad_types = containee_types;
@@ -152,7 +152,7 @@ cleanup:
 /* Return true if authdata contains any elements which should only come from
  * the KDC.  If desired_type is non-zero, look only for that type. */
 static krb5_boolean
-has_kdc_issued_authdata(krb5_context context, krb5_authdata **authdata,
+has_kdc_issued_authdata(krb5_authdata **authdata,
                         krb5_authdatatype desired_type)
 {
     int i;
@@ -160,7 +160,7 @@ has_kdc_issued_authdata(krb5_context context, krb5_authdata **authdata,
     if (authdata == NULL)
         return FALSE;
     for (i = 0; authdata[i] != NULL; i++) {
-        if (is_kdc_issued_authdatum(context, authdata[i], desired_type))
+        if (is_kdc_issued_authdatum(authdata[i], desired_type))
             return TRUE;
     }
     return FALSE;
@@ -181,66 +181,71 @@ has_mandatory_for_kdc_authdata(krb5_context context, krb5_authdata **authdata)
     return FALSE;
 }
 
-/*
- * Add the elements of in_authdata to out_authdata.  If copy is false,
- * in_authdata is invalid on successful return.  If ignore_kdc_issued is true,
- * KDC-issued authdata is not copied.
- */
+/* Add elements from *new_elements to *existing_list, reallocating as
+ * necessary.  On success, release *new_elements and set it to NULL. */
 static krb5_error_code
-merge_authdata(krb5_context context, krb5_authdata **in_authdata,
-               krb5_authdata ***out_authdata, krb5_boolean copy,
-               krb5_boolean ignore_kdc_issued)
+merge_authdata(krb5_authdata ***existing_list, krb5_authdata ***new_elements)
 {
-    krb5_error_code ret;
-    size_t i, j, nadata = 0;
-    krb5_authdata **in_copy = NULL, **authdata = *out_authdata;
+    size_t count = 0, ncount = 0;
+    krb5_authdata **list = *existing_list, **nlist = *new_elements;
 
-    if (in_authdata == NULL || in_authdata[0] == NULL)
+    if (nlist == NULL)
         return 0;
 
-    if (authdata != NULL) {
-        for (nadata = 0; authdata[nadata] != NULL; nadata++)
-            ;
-    }
+    for (count = 0; list != NULL && list[count] != NULL; count++);
+    for (ncount = 0; nlist[ncount] != NULL; ncount++);
 
-    for (i = 0; in_authdata[i] != NULL; i++)
-        ;
+    list = realloc(list, (count + ncount + 1) * sizeof(*list));
+    if (list == NULL)
+        return ENOMEM;
 
-    if (copy) {
-        ret = krb5_copy_authdata(context, in_authdata, &in_copy);
-        if (ret)
-            return ret;
-        in_authdata = in_copy;
-    }
+    memcpy(list + count, nlist, ncount * sizeof(*nlist));
+    list[count + ncount] = NULL;
+    free(nlist);
 
-    authdata = realloc(authdata, (nadata + i + 1) * sizeof(krb5_authdata *));
-    if (authdata == NULL) {
-        krb5_free_authdata(context, in_copy);
-        return ENOMEM;
+    if (list[0] == NULL) {
+        free(list);
+        list = NULL;
     }
 
-    for (i = 0, j = 0; in_authdata[i] != NULL; i++) {
-        if (ignore_kdc_issued &&
-            is_kdc_issued_authdatum(context, in_authdata[i], 0)) {
-            free(in_authdata[i]->contents);
-            free(in_authdata[i]);
-        } else {
-            authdata[nadata + j++] = in_authdata[i];
-        }
-    }
+    *new_elements = NULL;
+    *existing_list = list;
+    return 0;
+}
+
+/* Add a copy of new_elements to *existing_list, omitting KDC-issued
+ * authdata. */
+static krb5_error_code
+add_filtered_authdata(krb5_authdata ***existing_list,
+                      krb5_authdata **new_elements)
+{
+    krb5_error_code ret;
+    krb5_authdata **copy;
+    size_t i, j;
 
-    authdata[nadata + j] = NULL;
+    if (new_elements == NULL)
+        return 0;
 
-    free(in_authdata);
+    ret = krb5_copy_authdata(NULL, new_elements, &copy);
+    if (ret)
+        return ret;
 
-    if (authdata[0] == NULL) {
-        free(authdata);
-        authdata = NULL;
+    /* Remove KDC-issued elements from copy. */
+    j = 0;
+    for (i = 0; copy[i] != NULL; i++) {
+        if (is_kdc_issued_authdatum(copy[i], 0)) {
+            free(copy[i]->contents);
+            free(copy[i]);
+        } else {
+            copy[j++] = copy[i];
+        }
     }
+    copy[j] = NULL;
 
-    *out_authdata = authdata;
-
-    return 0;
+    /* Destructively merge the filtered copy into existing_list. */
+    ret = merge_authdata(existing_list, &copy);
+    krb5_free_authdata(NULL, copy);
+    return ret;
 }
 
 /* Copy TGS-REQ authorization data into the ticket authdata. */
@@ -289,10 +294,7 @@ copy_request_authdata(krb5_context context, krb5_keyblock *client_key,
         goto cleanup;
     }
 
-    /* Add a copy of the requested authdata to the ticket, ignoring KDC-issued
-     * types. */
-    ret = merge_authdata(context, req->unenc_authdata, tkt_authdata, TRUE,
-                         TRUE);
+    ret = add_filtered_authdata(tkt_authdata, req->unenc_authdata);
 
 cleanup:
     free(plaintext.data);
@@ -307,9 +309,7 @@ copy_tgt_authdata(krb5_context context, krb5_kdc_req *request,
     if (has_mandatory_for_kdc_authdata(context, tgt_authdata))
         return KRB5KDC_ERR_POLICY;
 
-    /* Add a copy of the TGT authdata to the ticket, ignoring KDC-issued
-     * types. */
-    return merge_authdata(context, tgt_authdata, tkt_authdata, TRUE, TRUE);
+    return add_filtered_authdata(tkt_authdata, tgt_authdata);
 }
 
 /* Fetch authorization data from KDB module. */
@@ -374,8 +374,7 @@ fetch_kdb_authdata(krb5_context context, unsigned int flags,
 
     /* Put the KDB authdata first in the ticket.  A successful merge places the
      * combined list in db_authdata and releases the old ticket authdata. */
-    ret = merge_authdata(context, enc_tkt_reply->authorization_data,
-                         &db_authdata, FALSE, FALSE);
+    ret = merge_authdata(&db_authdata, &enc_tkt_reply->authorization_data);
     if (ret)
         krb5_free_authdata(context, db_authdata);
     else
@@ -404,8 +403,7 @@ make_signedpath_data(krb5_context context, krb5_const_principal client,
             return ret;
 
         for (i = 0, j = 0; authdata[i] != NULL; i++) {
-            if (is_kdc_issued_authdatum(context, authdata[i],
-                                        KRB5_AUTHDATA_SIGNTICKET))
+            if (is_kdc_issued_authdatum(authdata[i], KRB5_AUTHDATA_SIGNTICKET))
                 continue;
 
             sign_authdata[j++] = authdata[i];
@@ -635,12 +633,8 @@ make_signedpath(krb5_context context, krb5_const_principal for_user_princ,
     if (ret)
         goto cleanup;
 
-    /* Add the authdata to the ticket, without copying or filtering. */
-    ret = merge_authdata(context, if_relevant,
-                         &enc_tkt_reply->authorization_data, FALSE, FALSE);
-    if (ret)
-        goto cleanup;
-    if_relevant = NULL;         /* merge_authdata() freed */
+    /* Add the signedpath authdata to the ticket. */
+    ret = merge_authdata(&enc_tkt_reply->authorization_data, &if_relevant);
 
 cleanup:
     free(sp.delegated);
@@ -665,7 +659,7 @@ free_deleg_path(krb5_context context, krb5_principal *deleg_path)
 static krb5_boolean
 has_pac(krb5_context context, krb5_authdata **authdata)
 {
-    return has_kdc_issued_authdata(context, authdata, KRB5_AUTHDATA_WIN2K_PAC);
+    return has_kdc_issued_authdata(authdata, KRB5_AUTHDATA_WIN2K_PAC);
 }
 
 /* Verify AD-SIGNTICKET authdata if we need to, and insert an AD-SIGNEDPATH
@@ -746,11 +740,7 @@ add_auth_indicators(krb5_context context, krb5_data *const *auth_indicators,
         goto cleanup;
 
     /* Add the wrapped authdata to the ticket, without copying or filtering. */
-    ret = merge_authdata(context, cammac, &enc_tkt_reply->authorization_data,
-                         FALSE, FALSE);
-    if (ret)
-        goto cleanup;
-    cammac = NULL;              /* merge_authdata() freed */
+    ret = merge_authdata(&enc_tkt_reply->authorization_data, &cammac);
 
 cleanup:
     krb5_free_data(context, der_indicators);
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 221bde1..a514f34 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -78,56 +78,6 @@ static krb5_error_code find_server_key(krb5_context,
                                        krb5_kvno, krb5_keyblock **,
                                        krb5_kvno *);
 
-/*
- * concatenate first two authdata arrays, returning an allocated replacement.
- * The replacement should be freed with krb5_free_authdata().
- */
-krb5_error_code
-concat_authorization_data(krb5_context context,
-                          krb5_authdata **first, krb5_authdata **second,
-                          krb5_authdata ***output)
-{
-    int i, j;
-    krb5_authdata **ptr, **retdata;
-
-    /* count up the entries */
-    i = 0;
-    if (first)
-        for (ptr = first; *ptr; ptr++)
-            i++;
-    if (second)
-        for (ptr = second; *ptr; ptr++)
-            i++;
-
-    retdata = (krb5_authdata **)malloc((i+1)*sizeof(*retdata));
-    if (!retdata)
-        return ENOMEM;
-    retdata[i] = 0;                     /* null-terminated array */
-    for (i = 0, j = 0, ptr = first; j < 2 ; ptr = second, j++)
-        while (ptr && *ptr) {
-            /* now walk & copy */
-            retdata[i] = (krb5_authdata *)malloc(sizeof(*retdata[i]));
-            if (!retdata[i]) {
-                krb5_free_authdata(context, retdata);
-                return ENOMEM;
-            }
-            *retdata[i] = **ptr;
-            if (!(retdata[i]->contents =
-                  (krb5_octet *)malloc(retdata[i]->length))) {
-                free(retdata[i]);
-                retdata[i] = 0;
-                krb5_free_authdata(context, retdata);
-                return ENOMEM;
-            }
-            memcpy(retdata[i]->contents, (*ptr)->contents, retdata[i]->length);
-
-            ptr++;
-            i++;
-        }
-    *output = retdata;
-    return 0;
-}
-
 krb5_boolean
 is_local_principal(kdc_realm_t *kdc_active_realm, krb5_const_principal princ1)
 {
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 384b21a..0b087d2 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -52,11 +52,6 @@ compress_transited (krb5_data *,
                     krb5_principal,
                     krb5_data *);
 krb5_error_code
-concat_authorization_data (krb5_context,
-                           krb5_authdata **,
-                           krb5_authdata **,
-                           krb5_authdata ***);
-krb5_error_code
 fetch_last_req_info (krb5_db_entry *, krb5_last_req_entry ***);
 
 krb5_error_code


More information about the cvs-krb5 mailing list