From: Greg Hudson Date: Tue, 15 Dec 2020 17:56:18 +0000 (-0500) Subject: Preserve cred order in memory ccache type X-Git-Tag: krb5-1.20-beta1~138 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1144%2Fhead;p=thirdparty%2Fkrb5.git 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. --- 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; }