]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Preserve cred order in memory ccache type 1144/head
authorGreg Hudson <ghudson@mit.edu>
Tue, 15 Dec 2020 17:56:18 +0000 (12:56 -0500)
committerGreg Hudson <ghudson@mit.edu>
Tue, 22 Dec 2020 19:29:24 +0000 (14:29 -0500)
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
src/lib/krb5/ccache/t_cc.c

index 610091a2573a9fe53b9c7b52c6cb348338e92849..529ada5455c227f978ea8e095ccf1e8f689a6bdb 100644 (file)
@@ -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);
index a7251e273ec87a7ce77e7753f837c966828b1846..267725240d1f41c423bf73a748521ad0b2de7708 100644 (file)
@@ -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;
 }