static int list_ccache(krb5_ccache cache) { krb5_error_code ret; krb5_principal princ = NULL; char *princname = NULL, *ccname = NULL; int expired, status = 1; ret = krb5_cc_get_principal(context, cache, &princ); if (ret) /* Uninitialized cache file, probably. */ goto cleanup; ret = krb5_unparse_name(context, princ, &princname); if (ret) goto cleanup; ret = krb5_cc_get_full_name(context, cache, &ccname); if (ret) goto cleanup; expired = check_ccache(cache); printf("%-30.30s %s", princname, ccname); if (expired) printf(" %s", _("(Expired)")); printf("\n"); status = 0; cleanup: krb5_free_principal(context, princ); krb5_free_unparsed_name(context, princname); krb5_free_string(context, ccname); return status; }
char * sss_get_ccache_name_for_principal(TALLOC_CTX *mem_ctx, krb5_context ctx, krb5_principal principal, const char *location) { #ifdef HAVE_KRB5_CC_COLLECTION krb5_error_code kerr; krb5_ccache tmp_cc = NULL; char *tmp_ccname = NULL; char *ret_ccname = NULL; DEBUG(SSSDBG_TRACE_ALL, "Location: [%s]\n", location); kerr = krb5_cc_set_default_name(ctx, location); if (kerr != 0) { KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr); return NULL; } kerr = krb5_cc_cache_match(ctx, principal, &tmp_cc); if (kerr != 0) { const char *err_msg = sss_krb5_get_error_message(ctx, kerr); DEBUG(SSSDBG_TRACE_INTERNAL, "krb5_cc_cache_match failed: [%d][%s]\n", kerr, err_msg); sss_krb5_free_error_message(ctx, err_msg); return NULL; } kerr = krb5_cc_get_full_name(ctx, tmp_cc, &tmp_ccname); if (kerr != 0) { KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr); goto done; } DEBUG(SSSDBG_TRACE_ALL, "tmp_ccname: [%s]\n", tmp_ccname); ret_ccname = talloc_strdup(mem_ctx, tmp_ccname); if (ret_ccname == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed (ENOMEM).\n"); } done: if (tmp_cc != NULL) { kerr = krb5_cc_close(ctx, tmp_cc); if (kerr != 0) { KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr); } } krb5_free_string(ctx, tmp_ccname); return ret_ccname; #else return NULL; #endif /* HAVE_KRB5_CC_COLLECTION */ }
/* Check that the name of cache matches expected_name. */ static void check_name(krb5_ccache cache, const char *expected_name) { char *name; check(krb5_cc_get_full_name(ctx, cache, &name)); assert(strcmp(name, expected_name) == 0); krb5_free_string(ctx, name); }
krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_set_fast_ccache(krb5_context context, krb5_get_init_creds_opt *opt, krb5_ccache ccache) { krb5_error_code ret; char *name; ret = krb5_cc_get_full_name(context, ccache, &name); if (ret) return ret; ret = krb5_get_init_creds_opt_set_fast_ccache_name(context, opt, name); free(name); return ret; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred_by_oid (OM_uint32 * minor_status, const gss_cred_id_t cred_handle, const gss_OID desired_object, gss_buffer_set_t *data_set) { krb5_context context; gsskrb5_cred cred = (gsskrb5_cred)cred_handle; krb5_error_code ret; gss_buffer_desc buffer; char *str; GSSAPI_KRB5_INIT (&context); if (gss_oid_equal(desired_object, GSS_KRB5_COPY_CCACHE_X) == 0) { *minor_status = EINVAL; return GSS_S_FAILURE; } HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); if (cred->ccache == NULL) { HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = EINVAL; return GSS_S_FAILURE; } ret = krb5_cc_get_full_name(context, cred->ccache, &str); HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } buffer.value = str; buffer.length = strlen(str); ret = gss_add_buffer_set_member(minor_status, &buffer, data_set); if (ret != GSS_S_COMPLETE) _gsskrb5_clear_status (); free(str); *minor_status = 0; return GSS_S_COMPLETE; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context ctx; krb5_cccol_cursor cursor; krb5_ccache cache, hold[64]; int i; char *name; assert(krb5_init_context(&ctx) == 0); if (argc > 1) assert(krb5_cc_set_default_name(ctx, argv[1]) == 0); if (argc > 2) { assert(argc < 60); for (i = 2; i < argc; i++) { if (strcmp(argv[i], "CONTENT") == 0) { ret = krb5_cccol_have_content(ctx); krb5_free_context(ctx); return ret != 0; } assert(krb5_cc_resolve(ctx, argv[i], &hold[i - 2]) == 0); } } 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); for (i = 2; i < argc; i++) krb5_cc_close(ctx, hold[i - 2]); krb5_free_context(ctx); return 0; }
/* Construct a list of the names of each credential cache in the collection. */ static void get_collection_names(char ***list_out, size_t *count_out) { krb5_cccol_cursor cursor; krb5_ccache cache; char **list = NULL; size_t count = 0; char *name; check(krb5_cccol_cursor_new(ctx, &cursor)); while (1) { check(krb5_cccol_cursor_next(ctx, cursor, &cache)); if (cache == NULL) break; check(krb5_cc_get_full_name(ctx, cache, &name)); krb5_cc_close(ctx, cache); list = realloc(list, (count + 1) * sizeof(*list)); assert(list != NULL); list[count++] = name; } krb5_cccol_cursor_free(ctx, &cursor); *list_out = list; *count_out = count; }
OM_uint32 _gsskrb5_krb5_import_cred(OM_uint32 *minor_status, krb5_ccache id, krb5_principal keytab_principal, krb5_keytab keytab, gss_cred_id_t *cred) { krb5_context context; krb5_error_code kret; gsskrb5_cred handle; OM_uint32 ret; *cred = NULL; GSSAPI_KRB5_INIT (&context); handle = calloc(1, sizeof(*handle)); if (handle == NULL) { _gsskrb5_clear_status (); *minor_status = ENOMEM; return (GSS_S_FAILURE); } HEIMDAL_MUTEX_init(&handle->cred_id_mutex); handle->usage = 0; if (id) { char *str; handle->usage |= GSS_C_INITIATE; kret = krb5_cc_get_principal(context, id, &handle->principal); if (kret) { free(handle); *minor_status = kret; return GSS_S_FAILURE; } if (keytab_principal) { krb5_boolean match; match = krb5_principal_compare(context, handle->principal, keytab_principal); if (match == FALSE) { krb5_free_principal(context, handle->principal); free(handle); _gsskrb5_clear_status (); *minor_status = EINVAL; return GSS_S_FAILURE; } } ret = __gsskrb5_ccache_lifetime(minor_status, context, id, handle->principal, &handle->lifetime); if (ret != GSS_S_COMPLETE) { krb5_free_principal(context, handle->principal); free(handle); return ret; } kret = krb5_cc_get_full_name(context, id, &str); if (kret) goto out; kret = krb5_cc_resolve(context, str, &handle->ccache); free(str); if (kret) goto out; } if (keytab) { char *str; handle->usage |= GSS_C_ACCEPT; if (keytab_principal && handle->principal == NULL) { kret = krb5_copy_principal(context, keytab_principal, &handle->principal); if (kret) goto out; } kret = krb5_kt_get_full_name(context, keytab, &str); if (kret) goto out; kret = krb5_kt_resolve(context, str, &handle->keytab); free(str); if (kret) goto out; } if (id || keytab) { ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); if (ret == GSS_S_COMPLETE) ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, &handle->mechanisms); if (ret != GSS_S_COMPLETE) { kret = *minor_status; goto out; } } *minor_status = 0; *cred = (gss_cred_id_t)handle; return GSS_S_COMPLETE; out: gss_release_oid_set(minor_status, &handle->mechanisms); if (handle->ccache) krb5_cc_close(context, handle->ccache); if (handle->keytab) krb5_kt_close(context, handle->keytab); if (handle->principal) krb5_free_principal(context, handle->principal); HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); free(handle); *minor_status = kret; return GSS_S_FAILURE; }
static int list_caches(krb5_context context) { krb5_cc_cache_cursor cursor; const char *cdef_name; char *def_name; krb5_error_code ret; krb5_ccache id; rtbl_t ct; cdef_name = krb5_cc_default_name(context); if (cdef_name == NULL) krb5_errx(context, 1, "krb5_cc_default_name"); def_name = strdup(cdef_name); ret = krb5_cc_cache_get_first (context, NULL, &cursor); if (ret == KRB5_CC_NOSUPP) return 0; else if (ret) krb5_err (context, 1, ret, "krb5_cc_cache_get_first"); ct = rtbl_create(); rtbl_add_column(ct, COL_NAME, 0); rtbl_add_column(ct, COL_CACHENAME, 0); rtbl_add_column(ct, COL_EXPIRES, 0); rtbl_add_column(ct, COL_DEFCACHE, 0); rtbl_set_prefix(ct, " "); rtbl_set_column_prefix(ct, COL_NAME, ""); while (krb5_cc_cache_next (context, cursor, &id) == 0) { krb5_principal principal = NULL; int expired = 0; char *name; time_t t; ret = krb5_cc_get_principal(context, id, &principal); if (ret) continue; expired = check_for_tgt (context, id, principal, &t); ret = krb5_cc_get_friendly_name(context, id, &name); if (ret == 0) { const char *str; char *fname; rtbl_add_column_entry(ct, COL_NAME, name); rtbl_add_column_entry(ct, COL_CACHENAME, krb5_cc_get_name(context, id)); if (expired) str = N_(">>> Expired <<<", ""); else str = printable_time(t); rtbl_add_column_entry(ct, COL_EXPIRES, str); free(name); ret = krb5_cc_get_full_name(context, id, &fname); if (ret) krb5_err (context, 1, ret, "krb5_cc_get_full_name"); if (strcmp(fname, def_name) == 0) rtbl_add_column_entry(ct, COL_DEFCACHE, "*"); else rtbl_add_column_entry(ct, COL_DEFCACHE, ""); krb5_xfree(fname); } krb5_cc_close(context, id); krb5_free_principal(context, principal); } krb5_cc_cache_end_seq_get(context, cursor); free(def_name); rtbl_format(ct, stdout); rtbl_destroy(ct); return 0; }
OM_uint32 gss_krb5_import_cred(OM_uint32 *minor_status, krb5_ccache id, krb5_principal keytab_principal, krb5_keytab keytab, gss_cred_id_t *cred) { gss_buffer_desc buffer; OM_uint32 major_status; krb5_context context; krb5_error_code ret; krb5_storage *sp; krb5_data data; char *str; *cred = GSS_C_NO_CREDENTIAL; ret = krb5_init_context(&context); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } sp = krb5_storage_emem(); if (sp == NULL) { *minor_status = ENOMEM; major_status = GSS_S_FAILURE; goto out; } if (id) { ret = krb5_cc_get_full_name(context, id, &str); if (ret == 0) { ret = krb5_store_string(sp, str); free(str); } } else ret = krb5_store_string(sp, ""); if (ret) { *minor_status = ret; major_status = GSS_S_FAILURE; goto out; } if (keytab_principal) { ret = krb5_unparse_name(context, keytab_principal, &str); if (ret == 0) { ret = krb5_store_string(sp, str); free(str); } } else krb5_store_string(sp, ""); if (ret) { *minor_status = ret; major_status = GSS_S_FAILURE; goto out; } if (keytab) { ret = krb5_kt_get_full_name(context, keytab, &str); if (ret == 0) { ret = krb5_store_string(sp, str); free(str); } } else krb5_store_string(sp, ""); if (ret) { *minor_status = ret; major_status = GSS_S_FAILURE; goto out; } ret = krb5_storage_to_data(sp, &data); if (ret) { *minor_status = ret; major_status = GSS_S_FAILURE; goto out; } buffer.value = data.data; buffer.length = data.length; major_status = gss_set_cred_option(minor_status, cred, GSS_KRB5_IMPORT_CRED_X, &buffer); krb5_data_free(&data); out: if (sp) krb5_storage_free(sp); krb5_free_context(context); return major_status; }
static int list_caches(krb5_context context, struct klist_options *opt) { krb5_cccol_cursor cursor; const char *cdef_name; char *def_name; krb5_error_code ret; krb5_ccache id; rtbl_t ct; cdef_name = krb5_cc_default_name(context); if (cdef_name == NULL) krb5_errx(context, 1, "krb5_cc_default_name"); def_name = strdup(cdef_name); ret = krb5_cccol_cursor_new(context, &cursor); if (ret == KRB5_CC_NOSUPP) return 0; else if (ret) krb5_err (context, 1, ret, "krb5_cc_cache_get_first"); ct = rtbl_create(); rtbl_add_column(ct, COL_DEFCACHE, 0); rtbl_add_column(ct, COL_NAME, 0); rtbl_add_column(ct, COL_CACHENAME, 0); rtbl_add_column(ct, COL_EXPIRES, 0); rtbl_add_column(ct, COL_DEFCACHE, 0); rtbl_set_prefix(ct, " "); rtbl_set_column_prefix(ct, COL_DEFCACHE, ""); rtbl_set_column_prefix(ct, COL_NAME, " "); if (opt->json_flag) rtbl_set_flags(ct, RTBL_JSON); while (krb5_cccol_cursor_next(context, cursor, &id) == 0) { int expired = 0; char *name; time_t t; expired = check_expiration(context, id, &t); ret = krb5_cc_get_friendly_name(context, id, &name); if (ret == 0) { const char *str; char *fname; rtbl_add_column_entry(ct, COL_NAME, name); free(name); if (expired) str = N_(">>> Expired <<<", ""); else str = printable_time(t); rtbl_add_column_entry(ct, COL_EXPIRES, str); ret = krb5_cc_get_full_name(context, id, &fname); if (ret) krb5_err (context, 1, ret, "krb5_cc_get_full_name"); rtbl_add_column_entry(ct, COL_CACHENAME, fname); if (opt->json_flag) ; else if (strcmp(fname, def_name) == 0) rtbl_add_column_entry(ct, COL_DEFCACHE, "*"); else rtbl_add_column_entry(ct, COL_DEFCACHE, ""); krb5_xfree(fname); } krb5_cc_close(context, id); } krb5_cccol_cursor_free(context, &cursor); free(def_name); rtbl_format(ct, stdout); rtbl_destroy(ct); if (opt->json_flag) printf("\n"); return 0; }
static void print_tickets (krb5_context context, krb5_ccache ccache, krb5_principal principal, int do_verbose, int do_flags, int do_hidden, int do_json) { char *str, *name, *fullname; krb5_error_code ret; krb5_cc_cursor cursor; krb5_creds creds; krb5_deltat sec; rtbl_t ct = NULL; ret = krb5_unparse_name (context, principal, &str); if (ret) krb5_err (context, 1, ret, "krb5_unparse_name"); ret = krb5_cc_get_full_name(context, ccache, &fullname); if (ret) krb5_err (context, 1, ret, "krb5_cc_get_full_name"); if (!do_json) { printf ("%17s: %s\n", N_("Credentials cache", ""), fullname); printf ("%17s: %s\n", N_("Principal", ""), str); ret = krb5_cc_get_friendly_name(context, ccache, &name); if (ret == 0) { if (strcmp(name, str) != 0) printf ("%17s: %s\n", N_("Friendly name", ""), name); free(name); } free (str); if(do_verbose) { printf ("%17s: %d\n", N_("Cache version", ""), krb5_cc_get_version(context, ccache)); } else { krb5_cc_set_flags(context, ccache, KRB5_TC_NOTICKET); } ret = krb5_cc_get_kdc_offset(context, ccache, &sec); if (ret == 0 && do_verbose && sec != 0) { char buf[BUFSIZ]; int val; int sig; val = (int)sec; sig = 1; if (val < 0) { sig = -1; val = -val; } unparse_time (val, buf, sizeof(buf)); printf ("%17s: %s%s\n", N_("KDC time offset", ""), sig == -1 ? "-" : "", buf); } printf("\n"); } else { printf ("{ \"cache\" : \"%s\", \"principal\" : \"%s\", ", fullname, str); } ret = krb5_cc_start_seq_get (context, ccache, &cursor); if (ret) krb5_err(context, 1, ret, "krb5_cc_start_seq_get"); if(!do_verbose) { ct = rtbl_create(); rtbl_add_column(ct, COL_ISSUED, 0); rtbl_add_column(ct, COL_EXPIRES, 0); if(do_flags) rtbl_add_column(ct, COL_FLAGS, 0); rtbl_add_column(ct, COL_PRINCIPAL, 0); rtbl_set_separator(ct, " "); if (do_json) { rtbl_set_flags(ct, RTBL_JSON); printf("\"tickets\" : "); } } if (do_verbose && do_json) printf("\"tickets\" : ["); while ((ret = krb5_cc_next_cred (context, ccache, &cursor, &creds)) == 0) { if (!do_hidden && krb5_is_config_principal(context, creds.server)) { ; }else if(do_verbose){ print_cred_verbose(context, &creds, do_json); }else{ print_cred(context, &creds, ct, do_flags); } krb5_free_cred_contents (context, &creds); } if(ret != KRB5_CC_END) krb5_err(context, 1, ret, "krb5_cc_get_next"); ret = krb5_cc_end_seq_get (context, ccache, &cursor); if (ret) krb5_err (context, 1, ret, "krb5_cc_end_seq_get"); if(!do_verbose) { rtbl_format(ct, stdout); rtbl_destroy(ct); } if (do_json) { if (do_verbose) printf("]"); printf("}"); } }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_export_cred(OM_uint32 *minor_status, gss_cred_id_t cred_handle, gss_buffer_t cred_token) { gsskrb5_cred handle = (gsskrb5_cred)cred_handle; krb5_context context; krb5_error_code ret; krb5_storage *sp; krb5_data data, mech; char *str; GSSAPI_KRB5_INIT (&context); if (handle->usage != GSS_C_INITIATE && handle->usage != GSS_C_BOTH) { *minor_status = GSS_KRB5_S_G_BAD_USAGE; return GSS_S_FAILURE; } sp = krb5_storage_emem(); if (sp == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } /* type = krb5_cc_get_type(context, handle->ccache); * * XXX Always use reference keys since that makes it easier to * transport between processing in seprate authentication domain. * * We should encrypt credentials in KCM though using the kcm * session key. */ if (1 /*strcmp(type, "MEMORY") == 0 */) { krb5_creds *creds; ret = krb5_store_uint32(sp, 0); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = _krb5_get_krbtgt(context, handle->ccache, handle->principal->realm, &creds); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_store_creds(sp, creds); krb5_free_creds(context, creds); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } } else { ret = krb5_store_uint32(sp, 1); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_cc_get_full_name(context, handle->ccache, &str); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_store_string(sp, str); free(str); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } } ret = krb5_storage_to_data(sp, &data); krb5_storage_free(sp); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } sp = krb5_storage_emem(); if (sp == NULL) { krb5_data_free(&data); *minor_status = ENOMEM; return GSS_S_FAILURE; } mech.data = GSS_KRB5_MECHANISM->elements; mech.length = GSS_KRB5_MECHANISM->length; ret = krb5_store_data(sp, mech); if (ret) { krb5_data_free(&data); krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_store_data(sp, data); krb5_data_free(&data); if (ret) { krb5_storage_free(sp); *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_storage_to_data(sp, &data); krb5_storage_free(sp); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } cred_token->value = data.data; cred_token->length = data.length; return GSS_S_COMPLETE; }
static int create_krb5_cred(krb5_context ctx, char *realm, char *user, char *password, char *ktname, krb5_ccache *ccache, gss_cred_id_t *gsscred, char **errmsg) { int rc = 0, len = 0; unsigned int minor_stat = 0, major_stat = 0; const char *errmsg_tmp = NULL; const char *cctype = NULL; char *cname = NULL; krb5_ccache defcc = NULL; krb5_creds creds; krb5_principal princ = NULL; krb5_keytab keytab = NULL; gss_key_value_element_desc elems[2]; gss_key_value_set_desc store; gss_name_t sname = NULL; gss_buffer_desc pr_name; pr_name.value = NULL; pr_name.length = 0; store.count = 0; store.elements = elems; if (user == NULL || realm == NULL) return 1; len = strlen(realm); if (len == 0 || strlen(user) == 0) return 0; DEBUG("create_krb5_cred (ctx:%p, realm:%s, user:%s, password:%s, ktname: %s," " ccache:%p, gsscred:%p)", ctx, realm, user, "****", ktname, ccache, gsscred); rc = krb5_cc_default(ctx, &defcc); if (rc != 0) goto end; cctype = krb5_cc_get_type(ctx, defcc); rc = krb5_cc_new_unique(ctx, cctype, NULL, ccache); if (rc != 0) goto end; rc = krb5_build_principal(ctx, &princ, len, realm, user, NULL); if (rc != 0) goto end; rc = krb5_cc_initialize(ctx, *ccache, princ); if (rc != 0) goto end; if (password != NULL && strlen(password) > 0) { rc = krb5_get_init_creds_password(ctx, &creds, princ, password, 0, NULL, 0, NULL, NULL); if (rc != 0) goto end; rc = krb5_cc_store_cred(ctx, *ccache, &creds); if (rc != 0) goto end; rc = krb5_cc_get_full_name(ctx, *ccache, &cname); if (rc != 0) goto end; store.elements[store.count].key = "ccache"; store.elements[store.count].value = cname; store.count++; } if (ktname != NULL && strlen(ktname) > 0) { rc = krb5_kt_resolve(ctx, ktname, &keytab); if (rc != 0) goto end; rc = krb5_get_init_creds_keytab(ctx, &creds, princ, keytab, 0, NULL, NULL); if (rc != 0) goto end; rc = krb5_cc_store_cred(ctx, *ccache, &creds); if (rc != 0) goto end; rc = krb5_cc_get_full_name(ctx, *ccache, &cname); if (rc != 0) goto end; store.elements[store.count].key = "client_keytab"; store.elements[store.count].value = ktname; store.count++; store.elements[store.count].key = "ccache"; store.elements[store.count].value = cname; store.count++; rc = krb5_unparse_name(ctx, princ, (char**)&pr_name.value); if (rc != 0) goto end; pr_name.length = strlen(pr_name.value); major_stat = gss_import_name(&minor_stat, &pr_name, GSS_KRB5_NT_PRINCIPAL_NAME, &sname); if (major_stat != 0) goto end; } // Does not work with GSS-SPENGO. //major_stat = gss_krb5_import_cred(&minor_stat, *ccache, princ, NULL, gsscred); major_stat = gss_acquire_cred_from(&minor_stat, sname, 0, GSS_C_NO_OID_SET, GSS_C_INITIATE, &store, gsscred, NULL, NULL); end: if (keytab != NULL) krb5_kt_close(ctx, keytab); if (princ != NULL) krb5_free_principal(ctx, princ); if (defcc != NULL) krb5_cc_close(ctx, defcc); if (cname != NULL) free(cname); if (pr_name.value != NULL) krb5_free_unparsed_name(ctx, pr_name.value); if (sname != NULL) { major_stat = gss_release_name(&minor_stat, &sname); } if (rc != 0) { /* Create error message with the error code. */ errmsg_tmp = krb5_get_error_message(ctx, rc); if (errmsg != NULL && errmsg_tmp != NULL) { len = strlen(errmsg_tmp) + 26; *errmsg = (char *)malloc(len); if (*errmsg == NULL) { krb5_free_error_message(ctx, errmsg_tmp); return -1; } snprintf(*errmsg, len,"%s. (KRB5_ERROR 0x%08x)", errmsg_tmp, rc); } krb5_free_error_message(ctx, errmsg_tmp); } if (major_stat != 0) return major_stat; return rc; }
int main(int argc, char **argv) { krb5_ccache ccinitial, ccu1, ccu2; krb5_principal princ1, princ2, princ3; const char *collection_name, *typename; char *initial_primary_name, *unique1_name, *unique2_name; /* * Get the collection name from the command line. This is a ccache name * with collection semantics, like DIR:/path/to/directory. This test * program assumes that the collection is empty to start with. */ assert(argc == 2); collection_name = argv[1]; /* * Set the default ccache for the context to be the collection name, so the * library can find the collection. */ check(krb5_init_context(&ctx)); check(krb5_cc_set_default_name(ctx, collection_name)); /* * Resolve the collection name. Since the collection is empty, this should * generate a subsidiary name of an uninitialized cache. Getting the name * of the resulting cache should give us the subsidiary name, not the * collection name. This resulting subsidiary name should be consistent if * we resolve the collection name again, and the collection should still be * empty since we haven't initialized the cache. */ check(krb5_cc_resolve(ctx, collection_name, &ccinitial)); check(krb5_cc_get_full_name(ctx, ccinitial, &initial_primary_name)); assert(strcmp(initial_primary_name, collection_name) != 0); check_primary_name(collection_name, initial_primary_name); check_collection(NULL, 0); check_princ(collection_name, NULL); check_princ(initial_primary_name, NULL); /* * Before initializing the primary ccache, generate and initialize two * unique caches of the collection's type. Check that the cache names * resolve to the generated caches and appear in the collection. (They * might appear before being initialized; that's not currently considered * important). The primary cache for the collection should remain as the * unitialized cache from the previous step. */ typename = krb5_cc_get_type(ctx, ccinitial); check(krb5_cc_new_unique(ctx, typename, NULL, &ccu1)); check(krb5_cc_get_full_name(ctx, ccu1, &unique1_name)); check(krb5_parse_name(ctx, "princ1@X", &princ1)); check(krb5_cc_initialize(ctx, ccu1, princ1)); check_princ(unique1_name, princ1); check_match(princ1, unique1_name); check_collection(NULL, 1, unique1_name); check(krb5_cc_new_unique(ctx, typename, NULL, &ccu2)); check(krb5_cc_get_full_name(ctx, ccu2, &unique2_name)); check(krb5_parse_name(ctx, "princ2@X", &princ2)); check(krb5_cc_initialize(ctx, ccu2, princ2)); check_princ(unique2_name, princ2); check_match(princ1, unique1_name); check_match(princ2, unique2_name); check_collection(NULL, 2, unique1_name, unique2_name); assert(strcmp(unique1_name, initial_primary_name) != 0); assert(strcmp(unique1_name, collection_name) != 0); assert(strcmp(unique2_name, initial_primary_name) != 0); assert(strcmp(unique2_name, collection_name) != 0); assert(strcmp(unique2_name, unique1_name) != 0); check_primary_name(collection_name, initial_primary_name); /* * Initialize the initial primary cache. Make sure it didn't change names, * that the previously retrieved name and the collection name both resolve * to the initialized cache, and that it now appears first in the * collection. */ check(krb5_parse_name(ctx, "princ3@X", &princ3)); check(krb5_cc_initialize(ctx, ccinitial, princ3)); check_name(ccinitial, initial_primary_name); check_princ(initial_primary_name, princ3); check_princ(collection_name, princ3); check_match(princ3, initial_primary_name); check_collection(initial_primary_name, 2, unique1_name, unique2_name); /* * Switch the primary cache to each cache we have open. One each switch, * check the primary name, check that the collection resolves to the * expected cache, and check that the new primary name appears first in the * collection. */ check(krb5_cc_switch(ctx, ccu1)); check_primary_name(collection_name, unique1_name); check_princ(collection_name, princ1); check_collection(unique1_name, 2, initial_primary_name, unique2_name); check(krb5_cc_switch(ctx, ccu2)); check_primary_name(collection_name, unique2_name); check_princ(collection_name, princ2); check_collection(unique2_name, 2, initial_primary_name, unique1_name); check(krb5_cc_switch(ctx, ccinitial)); check_primary_name(collection_name, initial_primary_name); check_princ(collection_name, princ3); check_collection(initial_primary_name, 2, unique1_name, unique2_name); /* * Temporarily set the context default ccache to a subsidiary name, and * check that iterating over the collection yields that subsidiary cache * and no others. */ check(krb5_cc_set_default_name(ctx, unique1_name)); check_collection(unique1_name, 0); check(krb5_cc_set_default_name(ctx, collection_name)); /* * Destroy the primary cache. Make sure this causes both the initial * primary name and the collection name to resolve to an uninitialized * cache. Make sure the primary name doesn't change and doesn't appear in * the collection any more. */ check(krb5_cc_destroy(ctx, ccinitial)); check_princ(initial_primary_name, NULL); check_princ(collection_name, NULL); check_primary_name(collection_name, initial_primary_name); check_match(princ1, unique1_name); check_match(princ2, unique2_name); check_match(princ3, NULL); check_collection(NULL, 2, unique1_name, unique2_name); /* * Switch to the first unique cache after destroying the primary cache. * Check that the collection name resolves to this cache and that the new * primary name appears first in the collection. */ check(krb5_cc_switch(ctx, ccu1)); check_primary_name(collection_name, unique1_name); check_princ(collection_name, princ1); check_collection(unique1_name, 1, unique2_name); /* * Destroy the second unique cache (which is not the current primary), * check that it is on longer initialized, and check that it no longer * appears in the collection. Check that destroying the non-primary cache * doesn't affect the primary name. */ check(krb5_cc_destroy(ctx, ccu2)); check_princ(unique2_name, NULL); check_match(princ2, NULL); check_collection(unique1_name, 0); check_primary_name(collection_name, unique1_name); check_match(princ1, unique1_name); check_princ(collection_name, princ1); /* * Destroy the first unique cache. Check that the collection is empty and * still has the same primary name. */ check(krb5_cc_destroy(ctx, ccu1)); check_princ(unique1_name, NULL); check_princ(collection_name, NULL); check_primary_name(collection_name, unique1_name); check_match(princ1, NULL); check_collection(NULL, 0); krb5_free_string(ctx, initial_primary_name); krb5_free_string(ctx, unique1_name); krb5_free_string(ctx, unique2_name); krb5_free_principal(ctx, princ1); krb5_free_principal(ctx, princ2); krb5_free_principal(ctx, princ3); krb5_free_context(ctx); return 0; }