krb5 commit: Preserve cred order in memory ccache type

Greg Hudson ghudson at mit.edu
Tue Dec 22 16:13:59 EST 2020


https://github.com/krb5/krb5/commit/722b77ba31ea4e2937e6820f0fe4a19a7445e8fc
commit 722b77ba31ea4e2937e6820f0fe4a19a7445e8fc
Author: Greg Hudson <ghudson at mit.edu>
Date:   Tue Dec 15 12:56:18 2020 -0500

    Preserve cred order in memory ccache type
    
    In the memory credential cache type, add new creds to the tail of the
    list so that iteration does not reverse the order.

 src/lib/krb5/ccache/cc_memory.c |   11 ++++++++-
 src/lib/krb5/ccache/t_cc.c      |   43 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c
index 610091a..529ada5 100644
--- a/src/lib/krb5/ccache/cc_memory.c
+++ b/src/lib/krb5/ccache/cc_memory.c
@@ -108,6 +108,7 @@ typedef struct _krb5_mcc_data {
     k5_cc_mutex lock;
     krb5_principal prin;
     krb5_mcc_link *link;
+    krb5_mcc_link **tail;       /* Where to store next added cred */
     /* Time offsets for clock-skewed clients.  */
     krb5_int32 time_offset;
     krb5_int32 usec_offset;
@@ -159,6 +160,7 @@ empty_mcc_cache(krb5_context context, krb5_mcc_data *d)
         free(curr);
     }
     d->link = NULL;
+    d->tail = &d->link;
     d->generation++;
     krb5_free_principal(context, d->prin);
     d->prin = NULL;
@@ -470,6 +472,7 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
         return KRB5_CC_NOMEM;
     }
     d->link = NULL;
+    d->tail = &d->link;
     d->prin = NULL;
     d->time_offset = 0;
     d->usec_offset = 0;
@@ -665,13 +668,17 @@ krb5_mcc_store(krb5_context ctx, krb5_ccache id, krb5_creds *creds)
     new_node = malloc(sizeof(krb5_mcc_link));
     if (new_node == NULL)
         return ENOMEM;
+    new_node->next = NULL;
     err = krb5_copy_creds(ctx, creds, &new_node->creds);
     if (err)
         goto cleanup;
+
+    /* Place the new node at the tail of the list. */
     k5_cc_mutex_lock(ctx, &mptr->lock);
-    new_node->next = mptr->link;
-    mptr->link = new_node;
+    *mptr->tail = new_node;
+    mptr->tail = &new_node->next;
     k5_cc_mutex_unlock(ctx, &mptr->lock);
+
     return 0;
 cleanup:
     free(new_node);
diff --git a/src/lib/krb5/ccache/t_cc.c b/src/lib/krb5/ccache/t_cc.c
index a7251e2..2677252 100644
--- a/src/lib/krb5/ccache/t_cc.c
+++ b/src/lib/krb5/ccache/t_cc.c
@@ -560,6 +560,47 @@ test_memory_concurrent(krb5_context context)
     free_test_cred(context);
 }
 
+/* Check that order is preserved during iteration.  Not all cache types have
+ * this property. */
+static void
+test_order(krb5_context context, const char *name)
+{
+    krb5_error_code kret;
+    krb5_ccache id;
+    krb5_cc_cursor cursor;
+    krb5_creds creds;
+
+    kret = init_test_cred(context);
+    CHECK(kret, "init_creds");
+
+    kret = krb5_cc_resolve(context, name, &id);
+    CHECK(kret, "resolve");
+    kret = krb5_cc_initialize(context, id, test_creds.client);
+    CHECK(kret, "initialize");
+    kret = krb5_cc_store_cred(context, id, &test_creds);
+    CHECK(kret, "store 1");
+    kret = krb5_cc_store_cred(context, id, &test_creds2);
+    CHECK(kret, "store 2");
+
+    kret = krb5_cc_start_seq_get(context, id, &cursor);
+    CHECK(kret, "start_seq_get");
+    kret = krb5_cc_next_cred(context, id, &cursor, &creds);
+    CHECK(kret, "next_cred 1");
+    CHECK_BOOL(krb5_principal_compare(context, creds.server,
+                                      test_creds.server) != TRUE,
+               "first cred does not match", "principal_compare");
+    krb5_free_cred_contents(context, &creds);
+
+    kret = krb5_cc_next_cred(context, id, &cursor, &creds);
+    CHECK(kret, "next_cred 2");
+    CHECK_BOOL(krb5_principal_compare(context, creds.server,
+                                      test_creds2.server) != TRUE,
+               "second cred does not match", "principal_compare");
+    krb5_free_cred_contents(context, &creds);
+
+    free_test_cred(context);
+}
+
 extern const krb5_cc_ops krb5_mcc_ops;
 extern const krb5_cc_ops krb5_fcc_ops;
 
@@ -610,6 +651,8 @@ main(void)
 
     test_memory_concurrent(context);
 
+    test_order(context, "MEMORY:order");
+
     krb5_free_context(context);
     return 0;
 }


More information about the cvs-krb5 mailing list