From de619531084d1993bd4ccb95716387a14715ee1c Mon Sep 17 00:00:00 2001 From: Love Hornquist Astrand Date: Mon, 29 Apr 2013 22:54:11 -0700 Subject: [PATCH] handle creation of DIR caches --- lib/krb5/constants.c | 1 + lib/krb5/dcache.c | 98 ++++++++++++++++++++++++++++--------- lib/krb5/krb5.h | 1 + lib/krb5/test_cc.c | 9 ++++ lib/krb5/version-script.map | 1 + 5 files changed, 87 insertions(+), 23 deletions(-) diff --git a/lib/krb5/constants.c b/lib/krb5/constants.c index 674bcc19b..87147c22b 100644 --- a/lib/krb5/constants.c +++ b/lib/krb5/constants.c @@ -63,3 +63,4 @@ KRB5_LIB_VARIABLE const char *krb5_cc_type_file = "FILE"; KRB5_LIB_VARIABLE const char *krb5_cc_type_memory = "MEMORY"; KRB5_LIB_VARIABLE const char *krb5_cc_type_kcm = "KCM"; KRB5_LIB_VARIABLE const char *krb5_cc_type_scc = "SCC"; +KRB5_LIB_VARIABLE const char *krb5_cc_type_dcc = "DIR"; diff --git a/lib/krb5/dcache.c b/lib/krb5/dcache.c index 195e1d250..8b4d49201 100644 --- a/lib/krb5/dcache.c +++ b/lib/krb5/dcache.c @@ -44,6 +44,10 @@ typedef struct krb5_dcache{ #define DCACHE(X) ((krb5_dcache*)(X)->data.data) #define D2FCACHE(X) ((X)->fcache) +static krb5_error_code KRB5_CALLCONV dcc_close(krb5_context, krb5_ccache); +static krb5_error_code KRB5_CALLCONV dcc_get_default_name(krb5_context, char **); + + static char * primary_create(krb5_dcache *dc) { @@ -146,6 +150,13 @@ get_default_cache(krb5_context context, krb5_dcache *dc, char **residual) f = fopen(primary, "r"); if (f == NULL) { + if (errno == ENOENT) { + free(primary); + *residual = strdup("tkt"); + if (*residual == NULL) + return krb5_enomem(context); + return 0; + } ret = errno; krb5_set_error_message(context, ret, "failed to open %s", primary); free(primary); @@ -229,6 +240,7 @@ dcc_release(krb5_context context, krb5_dcache *dc) free(dc->dir); if (dc->name) free(dc->name); + memset(dc, 0, sizeof(*dc)); free(dc); } @@ -263,7 +275,7 @@ dcc_resolve(krb5_context context, krb5_ccache *id, const char *res) if (res[0] == ':') { char *q; - dc->dir = strdup(res); + dc->dir = strdup(&res[1]); q = strrchr(dc->dir, '/'); if (q) { *q++ = '\0'; @@ -294,12 +306,7 @@ dcc_resolve(krb5_context context, krb5_ccache *id, const char *res) } else { char *residual; - - ret = verify_directory(context, res); - if (ret) { - dcc_release(context, dc); - return ret; - } + size_t len; dc->dir = strdup(res); if (dc->dir == NULL) { @@ -307,6 +314,17 @@ dcc_resolve(krb5_context context, krb5_ccache *id, const char *res) return krb5_enomem(context); } + len = strlen(dc->dir); + + if (dc->dir[len - 1] == '/') + dc->dir[len - 1] = '\0'; + + ret = verify_directory(context, dc->dir); + if (ret) { + dcc_release(context, dc); + return ret; + } + ret = get_default_cache(context, dc, &residual); if (ret) { dcc_release(context, dc); @@ -339,25 +357,60 @@ dcc_resolve(krb5_context context, krb5_ccache *id, const char *res) return 0; } -#if 0 static krb5_error_code KRB5_CALLCONV dcc_gen_new(krb5_context context, krb5_ccache *id) { + krb5_error_code ret; + const char *defname; + char *name = NULL; krb5_dcache *dc; + size_t len; + int fd; - dc = malloc(sizeof(*dc)); - if (dc == NULL) { - krb5_set_error_message(context, KRB5_CC_NOMEM, - N_("malloc: out of memory", "")); - return KRB5_CC_NOMEM; + len = strlen(krb5_dcc_ops.prefix); + + defname = krb5_cc_default_name(context); + if (defname == NULL || + strncmp(defname, krb5_dcc_ops.prefix, len) != 0 || + defname[len] != ':') + { + ret = dcc_get_default_name(context, &name); + if (ret) { + krb5_set_error_message(context, KRB5_CC_FORMAT, + N_("Can't generate DIR caches unless its the default type", "")); + return KRB5_CC_FORMAT; + } + defname = name; + } + + ret = dcc_resolve(context, id, &defname[len + 1]); + if (name) { + free(name); + name = NULL; } + if (ret) + return ret; + + dc = DCACHE((*id)); + + asprintf(&name, ":%s/tktXXXXXX", dc->dir); + if (name == NULL) { + dcc_close(context, *id); + return krb5_enomem(context); + } + free(dc->name); + + fd = mkstemp(&name[1]); + if (fd < 0) { + dcc_close(context, *id); + return krb5_enomem(context); + } + close(fd); + + dc->name = name; - (*id)->data.data = dc; - (*id)->data.length = sizeof(*dc); return 0; } -#endif - static krb5_error_code KRB5_CALLCONV dcc_initialize(krb5_context context, @@ -372,10 +425,7 @@ static krb5_error_code KRB5_CALLCONV dcc_close(krb5_context context, krb5_ccache id) { - krb5_dcache *dc = DCACHE(id); - (void)krb5_cc_close(context, D2FCACHE(dc)); - free(dc->dir); - free(dc); + dcc_release(context, DCACHE(id)); return 0; } @@ -384,7 +434,9 @@ dcc_destroy(krb5_context context, krb5_ccache id) { krb5_dcache *dc = DCACHE(id); - return krb5_cc_destroy(context, D2FCACHE(dc)); + krb5_ccache fcache = D2FCACHE(dc); + dc->fcache = NULL; + return krb5_cc_destroy(context, fcache); } static krb5_error_code KRB5_CALLCONV @@ -568,7 +620,7 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_dcc_ops = { "DIR", dcc_get_name, dcc_resolve, - NULL /* dcc_gen_new */, + dcc_gen_new, dcc_initialize, dcc_destroy, dcc_close, diff --git a/lib/krb5/krb5.h b/lib/krb5/krb5.h index 0a11d797a..baca4ba8b 100644 --- a/lib/krb5/krb5.h +++ b/lib/krb5/krb5.h @@ -962,6 +962,7 @@ extern KRB5_LIB_VARIABLE const char *krb5_cc_type_file; extern KRB5_LIB_VARIABLE const char *krb5_cc_type_memory; extern KRB5_LIB_VARIABLE const char *krb5_cc_type_kcm; extern KRB5_LIB_VARIABLE const char *krb5_cc_type_scc; +extern KRB5_LIB_VARIABLE const char *krb5_cc_type_dcc; #endif /* __KRB5_H__ */ diff --git a/lib/krb5/test_cc.c b/lib/krb5/test_cc.c index c8290b6aa..fd0b04d2e 100644 --- a/lib/krb5/test_cc.c +++ b/lib/krb5/test_cc.c @@ -669,6 +669,7 @@ main(int argc, char **argv) test_init_vs_destroy(context, krb5_cc_type_api); #endif test_init_vs_destroy(context, krb5_cc_type_scc); + test_init_vs_destroy(context, krb5_cc_type_dcc); test_mcc_default(); test_def_cc_name(context); @@ -694,6 +695,8 @@ main(int argc, char **argv) test_cache_iter(context, krb5_cc_type_api, 0); test_cache_iter(context, krb5_cc_type_scc, 0); test_cache_iter(context, krb5_cc_type_scc, 1); + test_cache_iter(context, krb5_cc_type_dcc, 0); + test_cache_iter(context, krb5_cc_type_dcc, 1); test_copy(context, krb5_cc_type_file, krb5_cc_type_file); test_copy(context, krb5_cc_type_memory, krb5_cc_type_memory); @@ -703,6 +706,9 @@ main(int argc, char **argv) test_copy(context, krb5_cc_type_file, krb5_cc_type_scc); test_copy(context, krb5_cc_type_scc, krb5_cc_type_memory); test_copy(context, krb5_cc_type_memory, krb5_cc_type_scc); + test_copy(context, krb5_cc_type_dcc, krb5_cc_type_memory); + test_copy(context, krb5_cc_type_dcc, krb5_cc_type_file); + test_copy(context, krb5_cc_type_dcc, krb5_cc_type_scc); test_move(context, krb5_cc_type_file); test_move(context, krb5_cc_type_memory); @@ -710,6 +716,7 @@ main(int argc, char **argv) test_move(context, krb5_cc_type_kcm); #endif test_move(context, krb5_cc_type_scc); + test_move(context, krb5_cc_type_dcc); test_prefix_ops(context, "FILE:/tmp/foo", &krb5_fcc_ops); test_prefix_ops(context, "FILE", &krb5_fcc_ops); @@ -720,6 +727,8 @@ main(int argc, char **argv) test_prefix_ops(context, "SCC:", &krb5_scc_ops); test_prefix_ops(context, "SCC:foo", &krb5_scc_ops); #endif + test_prefix_ops(context, "DIR:", &krb5_dcc_ops); + test_prefix_ops(context, "DIR:tkt1", &krb5_dcc_ops); krb5_cc_destroy(context, id1); krb5_cc_destroy(context, id2); diff --git a/lib/krb5/version-script.map b/lib/krb5/version-script.map index e7e7725bc..0c11ca0b2 100644 --- a/lib/krb5/version-script.map +++ b/lib/krb5/version-script.map @@ -717,6 +717,7 @@ HEIMDAL_KRB5_2.0 { krb5_config_file; krb5_defkeyname; krb5_cc_type_api; + krb5_cc_type_dcc; krb5_cc_type_file; krb5_cc_type_memory; krb5_cc_type_kcm;