From 722b77ba31ea4e2937e6820f0fe4a19a7445e8fc Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Tue, 15 Dec 2020 12:56:18 -0500 Subject: [PATCH] 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 610091a257..529ada5455 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 a7251e273e..267725240d 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; } -- 2.47.2