commit b874882dc93e5ece4f7218617ed7942656985471 Author: Greg Hudson Date: Mon Apr 22 17:00:35 2013 -0400 Include default DIR::file ccache in collection If the context's default ccache name is a subsidiary file of a directory collection, include that single cache in the cursor walk over the DIR type. ticket: 7172 diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c index cee21ac..b8231ed 100644 --- a/src/lib/krb5/ccache/cc_dir.c +++ b/src/lib/krb5/ccache/cc_dir.c @@ -266,6 +266,28 @@ get_context_default_dir(krb5_context context, char **dirname_out) return 0; } +/* + * If the default ccache name for context is a subsidiary file in a directory + * collection, set *subsidiary_out to the residual value. Otherwise set + * *subsidiary_out to NULL. + */ +static krb5_error_code +get_context_subsidiary_file(krb5_context context, char **subsidiary_out) +{ + const char *defname; + char *residual; + + *subsidiary_out = NULL; + defname = krb5_cc_default_name(context); + if (defname == NULL || strncmp(defname, "DIR::", 5) != 0) + return 0; + residual = strdup(defname + 4); + if (residual == NULL) + return ENOMEM; + *subsidiary_out = residual; + return 0; +} + static const char * KRB5_CALLCONV dcc_get_name(krb5_context context, krb5_ccache cache) { @@ -562,6 +584,18 @@ dcc_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor_out) *cursor_out = NULL; + /* If the default cache is a subsidiary file, make a cursor with the + * specified file as the primary but with no directory collection. */ + ret = get_context_subsidiary_file(context, &primary); + if (ret) + goto cleanup; + if (primary != NULL) { + ret = make_cursor(NULL, primary, NULL, cursor_out); + if (ret) + free(primary); + return ret; + } + /* Open the directory for the context's default cache. */ ret = get_context_default_dir(context, &dirname); if (ret || dirname == NULL) @@ -607,16 +641,17 @@ dcc_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor, struct stat sb; *cache_out = NULL; - if (data->dir == NULL) /* Empty cursor */ - return 0; - /* Return the primary cache if we haven't yet. */ + /* Return the primary or specified subsidiary cache if we haven't yet. */ if (data->first) { data->first = FALSE; if (data->primary != NULL && stat(data->primary + 1, &sb) == 0) return dcc_resolve(context, cache_out, data->primary); } + if (data->dir == NULL) /* No directory collection */ + return 0; + /* Look for the next filename of the correct form, without repeating the * primary cache. */ while ((ent = readdir(data->dir)) != NULL) { diff --git a/src/lib/krb5/ccache/t_cccol.py b/src/lib/krb5/ccache/t_cccol.py index acd2b6e..f0792e9 100644 --- a/src/lib/krb5/ccache/t_cccol.py +++ b/src/lib/krb5/ccache/t_cccol.py @@ -11,6 +11,7 @@ dccname = 'DIR:%s' % ccdir duser = 'DIR::%s/tkt1' % ccdir dalice = 'DIR::%s/tkt2' % ccdir dbob = 'DIR::%s/tkt3' % ccdir +dnoent = 'DIR::%s/noent' % ccdir realm.kinit('user', password('user'), flags=['-c', duser]) realm.kinit('alice', password('alice'), flags=['-c', dalice]) realm.kinit('bob', password('bob'), flags=['-c', dbob]) @@ -30,6 +31,8 @@ cursor_test('file-default2', [realm.ccache], [fccname]) cursor_test('file-default3', [fccname], [fccname]) cursor_test('dir', [dccname], [duser, dalice, dbob]) +cursor_test('dir-subsidiary', [duser], [duser]) +cursor_test('dir-nofile', [dnoent], []) mfoo = 'MEMORY:foo' mbar = 'MEMORY:bar'