diff options
-rw-r--r-- | src/lib/krb5/ccache/Makefile.in | 7 | ||||
-rw-r--r-- | src/lib/krb5/ccache/cc_file.c | 87 | ||||
-rw-r--r-- | src/lib/krb5/ccache/cccursor.c | 244 | ||||
-rw-r--r-- | src/lib/krb5/ccache/t_cccol.py | 44 | ||||
-rw-r--r-- | src/lib/krb5/ccache/t_cccursor.c | 263 |
5 files changed, 146 insertions, 499 deletions
diff --git a/src/lib/krb5/ccache/Makefile.in b/src/lib/krb5/ccache/Makefile.in index eaf0e00d4..00aaae7d6 100644 --- a/src/lib/krb5/ccache/Makefile.in +++ b/src/lib/krb5/ccache/Makefile.in @@ -101,11 +101,12 @@ T_CCCURSOR_OBJS = t_cccursor.o t_cccursor: $(T_CCCURSOR_OBJS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o $@ $(T_CCCURSOR_OBJS) $(KRB5_BASE_LIBS) -check-unix:: t_cc t_cccursor +check-unix:: t_cc KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\ $(RUN_SETUP) $(VALGRIND) ./t_cc - KRB5_CONFIG=$(srcdir)/../krb/t_krb5.conf ; export KRB5_CONFIG ;\ - $(RUN_SETUP) $(VALGRIND) ./t_cccursor + +check-pytests:: t_cccursor + $(RUNPYTEST) $(srcdir)/t_cccol.py $(PYTESTFLAGS) clean-unix:: $(RM) t_cc t_cc.o t_cccursor t_cccursor.o diff --git a/src/lib/krb5/ccache/cc_file.c b/src/lib/krb5/ccache/cc_file.c index 459930932..39f81d8b4 100644 --- a/src/lib/krb5/ccache/cc_file.c +++ b/src/lib/krb5/ccache/cc_file.c @@ -324,7 +324,7 @@ static struct fcc_set *fccs = NULL; /* Iterator over file caches. */ struct krb5_fcc_ptcursor_data { - struct fcc_set *cur; + krb5_boolean first; }; /* An off_t can be arbitrarily complex */ @@ -2332,71 +2332,53 @@ krb5_fcc_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor) if (n == NULL) return ENOMEM; n->ops = &krb5_fcc_ops; - cdata = malloc(sizeof(struct krb5_fcc_ptcursor_data)); + cdata = malloc(sizeof(*cdata)); if (cdata == NULL) { - ret = ENOMEM; - goto errout; + free(n); + return ENOMEM; } + cdata->first = TRUE; n->data = cdata; - ret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex); - if (ret) - goto errout; - cdata->cur = fccs; - ret = k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); - if (ret) - goto errout; - -errout: - if (ret) { - krb5_fcc_ptcursor_free(context, &n); - } *cursor = n; return ret; } static krb5_error_code KRB5_CALLCONV -krb5_fcc_ptcursor_next(krb5_context context, - krb5_cc_ptcursor cursor, - krb5_ccache *ccache) +krb5_fcc_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor, + krb5_ccache *cache_out) { - krb5_error_code ret = 0; - struct krb5_fcc_ptcursor_data *cdata = NULL; - krb5_ccache n; - - *ccache = NULL; - n = malloc(sizeof(*n)); - if (n == NULL) - return ENOMEM; - - cdata = cursor->data; + krb5_error_code ret; + struct krb5_fcc_ptcursor_data *cdata = cursor->data; + const char *defname, *residual; + krb5_ccache cache; + struct stat sb; - ret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex); - if (ret) - goto errout; + *cache_out = NULL; + if (!cdata->first) + return 0; + cdata->first = FALSE; - if (cdata->cur == NULL) { - k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); - free(n); - n = NULL; - goto errout; - } + defname = krb5_cc_default_name(context); + if (!defname) + return 0; - n->ops = &krb5_fcc_ops; - n->data = cdata->cur->data; - cdata->cur->refcount++; + /* Check if the default has type FILE or no type; find the residual. */ + if (strncmp(defname, "FILE:", 5) == 0) + residual = defname + 5; + else if (strchr(defname + 2, ':') == NULL) /* Skip drive prefix if any. */ + residual = defname; + else + return 0; - cdata->cur = cdata->cur->next; + /* Don't yield a nonexistent default file cache. */ + if (stat(residual, &sb) != 0) + return 0; - ret = k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + ret = krb5_cc_resolve(context, defname, &cache); if (ret) - goto errout; -errout: - if (ret && n != NULL) { - free(n); - n = NULL; - } - *ccache = n; - return ret; + return ret; + *cache_out = cache; + return 0; } static krb5_error_code KRB5_CALLCONV @@ -2405,8 +2387,7 @@ krb5_fcc_ptcursor_free(krb5_context context, { if (*cursor == NULL) return 0; - if ((*cursor)->data != NULL) - free((*cursor)->data); + free((*cursor)->data); free(*cursor); *cursor = NULL; return 0; diff --git a/src/lib/krb5/ccache/cccursor.c b/src/lib/krb5/ccache/cccursor.c index 7bb074938..2efaa322c 100644 --- a/src/lib/krb5/ccache/cccursor.c +++ b/src/lib/krb5/ccache/cccursor.c @@ -32,61 +32,29 @@ #include <assert.h> -#define CCCURSOR_CONTEXT 1 -#define CCCURSOR_ENV 2 -#define CCCURSOR_OS 3 -#define CCCURSOR_PERTYPE 4 - -#define NFULLNAMES 3 - -/* Prefix and residual parts of a full ccache name. */ -struct cc_fullname { - char *pfx; - char *res; -}; - struct _krb5_cccol_cursor { - int pos; krb5_cc_typecursor typecursor; const krb5_cc_ops *ops; krb5_cc_ptcursor ptcursor; - int cur_fullname; - struct cc_fullname fullnames[NFULLNAMES]; /* previously seen ccaches */ }; /* typedef of krb5_cccol_cursor is in krb5.h */ -static int cccol_already(krb5_context, krb5_cccol_cursor, krb5_ccache *); - -static int cccol_cmpname(const char *, const char *, struct cc_fullname *); - -static krb5_error_code -cccol_do_resolve(krb5_context, krb5_cccol_cursor, const char *, krb5_ccache *); - -static krb5_error_code -cccol_pertype_next(krb5_context, krb5_cccol_cursor, krb5_ccache *); - krb5_error_code KRB5_CALLCONV krb5_cccol_cursor_new(krb5_context context, krb5_cccol_cursor *cursor) { krb5_error_code ret = 0; krb5_cccol_cursor n = NULL; - int i; *cursor = NULL; n = malloc(sizeof(*n)); if (n == NULL) return ENOMEM; - n->pos = CCCURSOR_CONTEXT; n->typecursor = NULL; n->ptcursor = NULL; n->ops = NULL; - for (i = 0; i < NFULLNAMES; i++) { - n->fullnames[i].pfx = n->fullnames[i].res = NULL; - } - n->cur_fullname = 0; ret = krb5int_cc_typecursor_new(context, &n->typecursor); if (ret) goto errout; @@ -113,62 +81,44 @@ errout: krb5_error_code KRB5_CALLCONV krb5_cccol_cursor_next(krb5_context context, krb5_cccol_cursor cursor, - krb5_ccache *ccache) + krb5_ccache *ccache_out) { krb5_error_code ret = 0; - char *name; - krb5_os_context os_ctx = NULL; + krb5_ccache ccache; - *ccache = NULL; - os_ctx = &context->os_context; + *ccache_out = NULL; - switch (cursor->pos) { - case CCCURSOR_CONTEXT: - name = os_ctx->default_ccname; - if (name != NULL) { - cursor->pos = CCCURSOR_ENV; - ret = cccol_do_resolve(context, cursor, name, ccache); - if (ret) - goto errout; - if (*ccache != NULL) - break; - } - /* fall through */ - case CCCURSOR_ENV: - name = getenv(KRB5_ENV_CCNAME); - if (name != NULL) { - cursor->pos = CCCURSOR_OS; - ret = cccol_do_resolve(context, cursor, name, ccache); - if (ret) - goto errout; - if (*ccache != NULL) - break; - } - /* fall through */ - case CCCURSOR_OS: - ret = krb5int_cc_os_default_name(context, &name); - if (ret) goto errout; - if (name != NULL) { - cursor->pos = CCCURSOR_PERTYPE; - ret = cccol_do_resolve(context, cursor, name, ccache); - free(name); - if (ret) - goto errout; - if (*ccache != NULL) - break; + /* Are we out of backends? */ + if (cursor->ops == NULL) + return 0; + + while (1) { + ret = cursor->ops->ptcursor_next(context, cursor->ptcursor, &ccache); + if (ret) + return ret; + if (ccache != NULL) { + *ccache_out = ccache; + return 0; } - /* fall through */ - case CCCURSOR_PERTYPE: - cursor->pos = CCCURSOR_PERTYPE; + + ret = cursor->ops->ptcursor_free(context, &cursor->ptcursor); + if (ret) + return ret; + do { - ret = cccol_pertype_next(context, cursor, ccache); + /* Find next type with ptcursor functionality. */ + ret = krb5int_cc_typecursor_next(context, cursor->typecursor, + &cursor->ops); if (ret) - goto errout; - } while (cccol_already(context, cursor, ccache)); - break; + return ret; + if (cursor->ops == NULL) + return 0; + } while (cursor->ops->ptcursor_new == NULL); + + ret = cursor->ops->ptcursor_new(context, &cursor->ptcursor); + if (ret) + return ret; } -errout: - return ret; } krb5_error_code KRB5_CALLCONV @@ -176,17 +126,10 @@ krb5_cccol_cursor_free(krb5_context context, krb5_cccol_cursor *cursor) { krb5_cccol_cursor c = *cursor; - int i; if (c == NULL) return 0; - for (i = 0; i < NFULLNAMES; i++) { - if (c->fullnames[i].pfx != NULL) - free(c->fullnames[i].pfx); - if (c->fullnames[i].res != NULL) - free(c->fullnames[i].res); - } if (c->ptcursor != NULL) c->ops->ptcursor_free(context, &c->ptcursor); if (c->typecursor != NULL) @@ -232,133 +175,6 @@ krb5_cccol_last_change_time(krb5_context context, * krb5_cccol_lock and krb5_cccol_unlock are defined in ccbase.c */ -/* - * Determine if a ccache from a per-type cursor was already one of the - * higher-priority defaults. - */ -static int -cccol_already(krb5_context context, - krb5_cccol_cursor c, - krb5_ccache *ccache) -{ - const char *name = NULL, *prefix = NULL; - int i; - - if (*ccache == NULL) - return 0; - name = krb5_cc_get_name(context, *ccache); - if (name == NULL) - return 0; - prefix = krb5_cc_get_type(context, *ccache); - - assert(c->cur_fullname < NFULLNAMES); - for (i = 0; i < c->cur_fullname; i++) { - if (cccol_cmpname(prefix, name, &c->fullnames[i])) { - krb5_cc_close(context, *ccache); - *ccache = NULL; - return 1; - } - } - return 0; -} - -/* - * Compare {prefix, name} against a cc_fullname. - */ -static int -cccol_cmpname(const char *prefix, - const char *name, - struct cc_fullname *fullname) -{ - if (fullname->pfx == NULL || fullname->res == NULL) - return 0; - if (strcmp(prefix, fullname->pfx)) - return 0; - if (strcmp(name, fullname->res)) - return 0; - - return 1; -} - -/* - * Resolve one of the high-precedence ccaches, and cache its full name - * {prefix, residual} for exclusion when doing per-type ccache - * iteration. Also check to see if we've already seen the ccache - * name we're given. - */ -static krb5_error_code -cccol_do_resolve(krb5_context context, - krb5_cccol_cursor cursor, - const char *name, - krb5_ccache *ccache) -{ - krb5_error_code ret = 0; - struct cc_fullname *fullname; - - assert(cursor->cur_fullname < NFULLNAMES); - ret = krb5_cc_resolve(context, name, ccache); - if (ret) - return ret; - - if (cccol_already(context, cursor, ccache)) - return 0; - - fullname = &cursor->fullnames[cursor->cur_fullname]; - fullname->pfx = strdup(krb5_cc_get_type(context, *ccache)); - fullname->res = strdup(krb5_cc_get_name(context, *ccache)); - cursor->cur_fullname++; - return ret; -} - -/* - * Find next ccache in current backend, iterating through backends if - * ccache list of the current backend is exhausted. - */ -static krb5_error_code -cccol_pertype_next(krb5_context context, - krb5_cccol_cursor cursor, - krb5_ccache *ccache) -{ - krb5_error_code ret = 0; - - *ccache = NULL; - - /* Are we out of backends? */ - if (cursor->ops == NULL) - return 0; - /* - * Loop in case there are multiple backends with empty ccache - * lists. - */ - while (*ccache == NULL) { - ret = cursor->ops->ptcursor_next(context, cursor->ptcursor, ccache); - if (ret) - goto errout; - if (*ccache != NULL) - return 0; - - ret = cursor->ops->ptcursor_free(context, &cursor->ptcursor); - if (ret) - goto errout; - - do { - /* Find first backend with ptcursor functionality. */ - ret = krb5int_cc_typecursor_next(context, cursor->typecursor, - &cursor->ops); - if (ret) - goto errout; - if (cursor->ops == NULL) - return 0; - } while (cursor->ops->ptcursor_new == NULL); - - ret = cursor->ops->ptcursor_new(context, &cursor->ptcursor); - if (ret) - goto errout; - } -errout: - return ret; -} - krb5_error_code krb5_cc_cache_match(krb5_context context, krb5_principal client, krb5_ccache *cache_out) diff --git a/src/lib/krb5/ccache/t_cccol.py b/src/lib/krb5/ccache/t_cccol.py new file mode 100644 index 000000000..d80997108 --- /dev/null +++ b/src/lib/krb5/ccache/t_cccol.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +from k5test import * + +realm = K5Realm(create_host=False, start_kadmind=False) + +realm.addprinc('alice', password('alice')) +realm.addprinc('bob', password('bob')) + +ccdir = os.path.join(realm.testdir, 'cc') +dccname = 'DIR:%s' % ccdir +duser = 'DIR::%s/tkt1' % ccdir +dalice = 'DIR::%s/tkt2' % ccdir +dbob = 'DIR::%s/tkt3' % ccdir +os.mkdir(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]) + +def cursor_test(testname, args, expected): + outlines = realm.run_as_client(['./t_cccursor'] + args).splitlines() + outlines.sort() + expected.sort() + if outlines != expected: + fail('Output not expected for %s\n' % testname + + 'Expected output:\n\n' + '\n'.join(expected) + '\n\n' + + 'Actual output:\n\n' + '\n'.join(outlines)) + +fccname = 'FILE:%s' % realm.ccache +cursor_test('file-default', [], [fccname]) +cursor_test('file-default2', [realm.ccache], [fccname]) +cursor_test('file-default3', [fccname], [fccname]) + +cursor_test('dir', [dccname], [duser, dalice, dbob]) + +mfoo = 'MEMORY:foo' +mbar = 'MEMORY:bar' +cursor_test('filemem', [fccname, mfoo, mbar], [fccname, mfoo, mbar]) +cursor_test('dirmem', [dccname, mfoo], [duser, dalice, dbob, mfoo]) + +# Make sure FILE doesn't yield a nonexistent default cache. +realm.run_as_client([kdestroy]) +cursor_test('noexist', [], []) + +success('Renewing credentials.') diff --git a/src/lib/krb5/ccache/t_cccursor.c b/src/lib/krb5/ccache/t_cccursor.c index b708aa6f9..a0c758603 100644 --- a/src/lib/krb5/ccache/t_cccursor.c +++ b/src/lib/krb5/ccache/t_cccursor.c @@ -1,7 +1,7 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* lib/krb5/ccache/t_cccursor.c */ +/* lib/krb5/ccache/t_cccursor.c - Simple test harness for cccol API */ /* - * Copyright 2006 by the Massachusetts Institute of Technology. + * Copyright 2011 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -24,242 +24,47 @@ * or implied warranty. */ -#include "autoconf.h" -#include "krb5.h" - -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -struct crlist { - char *ccname; - char *pname; -}; - -struct crlist crlist[] = { - { "foo", NULL }, - { "MEMORY:env", "env" }, - { "MEMORY:0", "foo0" }, - { "MEMORY:1", "foo1" }, - { "MEMORY:2", "foo2" }, -}; -#define NCRLIST (sizeof(crlist)/sizeof(struct crlist)) - -struct chklist { - char *pfx; - char *res; -}; - -struct chklist chklist0[] = { - { NULL, NULL }, - { NULL, NULL }, - { "MEMORY", "2" }, - { "MEMORY", "1" }, - { "MEMORY", "0" }, - { "MEMORY", "env" }, -}; -#define NCHKLIST0 (sizeof(chklist0)/sizeof(struct chklist)) - -struct chklist chklist1[] = { - { "MEMORY", "env" }, - { NULL, NULL }, - { "MEMORY", "2" }, - { "MEMORY", "1" }, - { "MEMORY", "0" }, -}; -#define NCHKLIST1 (sizeof(chklist1)/sizeof(struct chklist)) - -struct chklist chklist2[] = { - { "MEMORY", "env" }, - { NULL, NULL }, - { "MEMORY", "2" }, - { "MEMORY", "1" }, - { "MEMORY", "0" }, -}; -#define NCHKLIST2 (sizeof(chklist2)/sizeof(struct chklist)) - -krb5_error_code -cr_cache(krb5_context, const char *, const char *); - -krb5_error_code -dest_cache(krb5_context, const char *, const char *); - -krb5_error_code -do_chk(krb5_context, struct chklist *, int nmax, int *); - -int -do_chk_one(const char *, const char *, struct chklist *); - -krb5_error_code -cr_cache(krb5_context context, const char *ccname, const char *pname) -{ - krb5_error_code ret; - krb5_principal princ = NULL; - krb5_ccache ccache = NULL; - - ret = krb5_cc_resolve(context, ccname, &ccache); - if (ret) - goto errout; - if (pname != NULL) { - ret = krb5_parse_name(context, pname, &princ); - if (ret) - return ret; - ret = krb5_cc_initialize(context, ccache, princ); - if (ret) - goto errout; - printf("created cache %s with principal %s\n", ccname, pname); - } else - printf("created cache %s (uninitialized)\n", ccname); -errout: - if (princ != NULL) - krb5_free_principal(context, princ); - if (ccache != NULL) - krb5_cc_close(context, ccache); - return ret; -} - -krb5_error_code -dest_cache(krb5_context context, const char *ccname, const char *pname) -{ - krb5_error_code ret; - krb5_ccache ccache = NULL; +/* + * Displays a list of caches returned by the cccol cursor. The first argument, + * if given, is set to the default cache name for the context before iterating. + * Any remaining argments are resolved as caches and kept open during the + * iteration. + */ - ret = krb5_cc_resolve(context, ccname, &ccache); - if (ret) - goto errout; - if (pname != NULL) { - ret = krb5_cc_destroy(context, ccache); - if (ret) - return ret; - printf("Destroyed cache %s\n", ccname); - } else { - printf("Closed cache %s (uninitialized)\n", ccname); - ret = krb5_cc_close(context, ccache); - } -errout: - return ret; -} +#include "k5-int.h" int -do_chk_one(const char *prefix, const char *name, struct chklist *chk) +main(int argc, char **argv) { - - if (chk->pfx == NULL) - return 0; - if (strcmp(chk->pfx, prefix) || strcmp(chk->res, name)) { - fprintf(stderr, "MATCH FAILED: expected %s:%s\n", - chk->pfx, chk->res); - return 1; - } - return 0; -} - -krb5_error_code -do_chk( - krb5_context context, - struct chklist *chklist, - int nmax, - int *good) -{ - krb5_error_code ret = 0; - krb5_cccol_cursor cursor = NULL; - krb5_ccache ccache; - const char *prefix, *name; + krb5_context ctx; + krb5_cccol_cursor cursor; + krb5_ccache cache, hold[64]; int i; + char *name; - ret = krb5_cccol_cursor_new(context, &cursor); - if (ret) goto errout; - - i = 0; - printf(">>>\n"); - for (i = 0; ; i++) { - ret = krb5_cccol_cursor_next(context, cursor, &ccache); - if (ret) goto errout; - if (ccache == NULL) { - printf("<<< end of list\n"); - break; - } - prefix = krb5_cc_get_type(context, ccache); - name = krb5_cc_get_name(context, ccache); - printf("cursor: %s:%s\n", prefix, name); - - if (i < nmax) { - if (do_chk_one(prefix, name, &chklist[i])) { - *good = 0; - } - } - ret = krb5_cc_close(context, ccache); - if (ret) goto errout; - } + assert(krb5_init_context(&ctx) == 0); + if (argc > 1) + assert(krb5_cc_set_default_name(ctx, argv[1]) == 0); - if (i != nmax) { - fprintf(stderr, "total ccaches %d != expected ccaches %d\n", i, nmax); - *good = 0; + if (argc > 2) { + assert(argc < 60); + for (i = 2; i < argc; i++) + assert(krb5_cc_resolve(ctx, argv[i], &hold[i - 2]) == 0); } -errout: - if (cursor != NULL) - krb5_cccol_cursor_free(context, &cursor); - return ret; -} - -int -main(int argc, char *argv[]) -{ - krb5_error_code ret = 0; - krb5_context context; - unsigned int i; - int good = 1; - - ret = krb5_init_context(&context); - if (ret) exit(1); - - for (i = 0; i < NCRLIST; i++) { - ret = cr_cache(context, crlist[i].ccname, crlist[i].pname); - if (ret) goto errout; - } - -#ifdef HAVE_SETENV - setenv("KRB5CCNAME", "foo", 1); -#else - putenv("KRB5CCNAME=foo"); -#endif - printf("KRB5CCNAME=foo\n"); - ret = do_chk(context, chklist0, NCHKLIST0, &good); - if (ret) - goto errout; - -#ifdef HAVE_SETENV - setenv("KRB5CCNAME", "MEMORY:env", 1); -#else - putenv("KRB5CCNAME=MEMORY:env"); -#endif - printf("KRB5CCNAME=MEMORY:env\n"); - ret = do_chk(context, chklist1, NCHKLIST1, &good); - if (ret) - goto errout; - - ret = krb5_cc_set_default_name(context, "MEMORY:env"); - if (ret) - goto errout; - - printf("KRB5CCNAME=MEMORY:env, ccdefname=MEMORY:env\n"); - ret = do_chk(context, chklist2, NCHKLIST2, &good); - if (ret) - goto errout; - - for (i = 0; i < NCRLIST; i++) { - ret = dest_cache(context, crlist[i].ccname, crlist[i].pname); - if (ret) goto errout; + assert(krb5_cccol_cursor_new(ctx, &cursor) == 0); + while (1) { + assert(krb5_cccol_cursor_next(ctx, cursor, &cache) == 0); + if (cache == NULL) + break; + assert(krb5_cc_get_full_name(ctx, cache, &name) == 0); + printf("%s\n", name); + krb5_free_string(ctx, name); + krb5_cc_close(ctx, cache); } + assert(krb5_cccol_cursor_free(ctx, &cursor) == 0); -errout: - krb5_free_context(context); - if (ret) { - com_err("main", ret, ""); - exit(1); - } else { - exit(!good); - } + for (i = 2; i < argc; i++) + krb5_cc_close(ctx, hold[i - 2]); + return 0; } |