OM_uint32 _gsskrb5_cred_label_get(OM_uint32 *minor_status, gss_cred_id_t cred_handle, const char *label, gss_buffer_t value) { gsskrb5_cred cred = (gsskrb5_cred)cred_handle; krb5_context context; krb5_error_code ret; krb5_data data; GSSAPI_KRB5_INIT (&context); if (cred == NULL) return GSS_S_COMPLETE; if (cred->ccache == NULL) { *minor_status = GSS_KRB5_S_G_BAD_USAGE; return GSS_S_FAILURE; } ret = krb5_cc_get_config(context, cred->ccache, NULL, label, &data); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } value->value = data.data; value->length = data.length; return GSS_S_COMPLETE; }
static krb5_error_code store_ntlmkey(krb5_context context, krb5_ccache id, const char *domain, struct ntlm_buf *buf) { krb5_error_code ret; krb5_data data; char *name; int aret; ret = krb5_cc_get_config(context, id, NULL, "default-ntlm-domain", &data); if (ret == 0) { krb5_data_free(&data); } else { data.length = strlen(domain); data.data = rk_UNCONST(domain); ret = krb5_cc_set_config(context, id, NULL, "default-ntlm-domain", &data); if (ret != 0) return ret; } aret = asprintf(&name, "ntlm-key-%s", domain); if (aret == -1 || name == NULL) return krb5_enomem(context); data.length = buf->length; data.data = buf->data; ret = krb5_cc_set_config(context, id, NULL, name, &data); free(name); return ret; }
static krb5_error_code copy_configs(krb5_context context, krb5_ccache dst, krb5_ccache src, krb5_principal start_ticket_server) { krb5_error_code ret; const char *cfg_names[] = {"realm-config", "FriendlyName", NULL}; const char *cfg_names_w_pname[] = {"fast_avail", NULL}; krb5_data cfg_data; size_t i; for (i = 0; cfg_names[i]; i++) { ret = krb5_cc_get_config(context, src, NULL, cfg_names[i], &cfg_data); if (ret == KRB5_CC_NOTFOUND || ret == KRB5_CC_END) { continue; } else if (ret) { krb5_warn(context, ret, "krb5_cc_get_config"); return ret; } ret = krb5_cc_set_config(context, dst, NULL, cfg_names[i], &cfg_data); if (ret) krb5_warn(context, ret, "krb5_cc_set_config"); } for (i = 0; start_ticket_server && cfg_names_w_pname[i]; i++) { ret = krb5_cc_get_config(context, src, start_ticket_server, cfg_names_w_pname[i], &cfg_data); if (ret == KRB5_CC_NOTFOUND || ret == KRB5_CC_END) { continue; } else if (ret) { krb5_warn(context, ret, "krb5_cc_get_config"); return ret; } ret = krb5_cc_set_config(context, dst, start_ticket_server, cfg_names_w_pname[i], &cfg_data); if (ret && ret != KRB5_CC_NOTFOUND) krb5_warn(context, ret, "krb5_cc_set_config"); } /* * We don't copy cc configs for any other principals though (mostly * those are per-target time offsets and the like, so it's bad to * lose them, but hardly the end of the world, and as they may not * expire anyways, it's good to let them go). */ return 0; }
krb5_error_code krb5int_fast_as_armor(krb5_context context, struct krb5int_fast_request_state *state, krb5_gic_opt_ext *opte, krb5_kdc_req *request) { krb5_error_code retval = 0; krb5_ccache ccache = NULL; krb5_principal target_principal = NULL; krb5_data *target_realm; krb5_clear_error_message(context); target_realm = krb5_princ_realm(context, request->server); if (opte->opt_private->fast_ccache_name) { TRACE_FAST_ARMOR_CCACHE(context, opte->opt_private->fast_ccache_name); state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL; retval = krb5_cc_resolve(context, opte->opt_private->fast_ccache_name, &ccache); if (retval == 0) { retval = krb5int_tgtname(context, target_realm, target_realm, &target_principal); } if (retval == 0) { krb5_data config_data; config_data.data = NULL; retval = krb5_cc_get_config(context, ccache, target_principal, KRB5_CONF_FAST_AVAIL, &config_data); if ((retval == 0) && config_data.data) { TRACE_FAST_CCACHE_CONFIG(context); state->fast_state_flags |= KRB5INT_FAST_DO_FAST; } krb5_free_data_contents(context, &config_data); retval = 0; } if (opte->opt_private->fast_flags & KRB5_FAST_REQUIRED) { TRACE_FAST_REQUIRED(context); state->fast_state_flags |= KRB5INT_FAST_DO_FAST; } if (retval == 0 && (state->fast_state_flags & KRB5INT_FAST_DO_FAST)) { retval = fast_armor_ap_request(context, state, ccache, target_principal); } if (retval != 0) { const char * errmsg; errmsg = krb5_get_error_message(context, retval); if (errmsg) { krb5_set_error_message(context, retval, "%s constructing AP-REQ armor", errmsg); krb5_free_error_message(context, errmsg); } } } if (ccache) krb5_cc_close(context, ccache); if (target_principal) krb5_free_principal(context, target_principal); return retval; }
krb5_error_code krb5int_fast_as_armor(krb5_context context, struct krb5int_fast_request_state *state, krb5_get_init_creds_opt *opt, krb5_kdc_req *request) { krb5_error_code retval = 0; krb5_ccache ccache = NULL; krb5_principal target_principal = NULL; krb5_data *target_realm; const char *ccname = k5_gic_opt_get_fast_ccache_name(opt); krb5_flags fast_flags; krb5_clear_error_message(context); target_realm = &request->server->realm; if (ccname != NULL) { TRACE_FAST_ARMOR_CCACHE(context, ccname); state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL; retval = krb5_cc_resolve(context, ccname, &ccache); if (retval == 0) { retval = krb5int_tgtname(context, target_realm, target_realm, &target_principal); } if (retval == 0) { krb5_data config_data; config_data.data = NULL; retval = krb5_cc_get_config(context, ccache, target_principal, KRB5_CC_CONF_FAST_AVAIL, &config_data); if ((retval == 0) && config_data.data) { TRACE_FAST_CCACHE_CONFIG(context); state->fast_state_flags |= KRB5INT_FAST_DO_FAST; } krb5_free_data_contents(context, &config_data); retval = 0; } fast_flags = k5_gic_opt_get_fast_flags(opt); if (fast_flags & KRB5_FAST_REQUIRED) { TRACE_FAST_REQUIRED(context); state->fast_state_flags |= KRB5INT_FAST_DO_FAST; } if (retval == 0 && (state->fast_state_flags & KRB5INT_FAST_DO_FAST)) { retval = fast_armor_ap_request(context, state, ccache, target_principal); } if (retval != 0) { k5_prependmsg(context, retval, _("Error constructing AP-REQ armor")); } } if (ccache) krb5_cc_close(context, ccache); if (target_principal) krb5_free_principal(context, target_principal); return retval; }
static OM_uint32 _acquire_uuid_name(OM_uint32 *minor_status, krb5_context context, krb5_const_principal princ, int *iakerb, gsskrb5_cred handle) { krb5_error_code ret; krb5_uuid uuid; *iakerb = 0; if (princ->name.name_type != KRB5_NT_CACHE_UUID) return GSS_S_BAD_NAMETYPE; if (princ->name.name_string.len != 1 || strcmp(princ->realm, "UUID") != 0) return GSS_S_BAD_NAME; if (krb5_string_to_uuid(princ->name.name_string.val[0], uuid)) return GSS_S_BAD_NAME; ret = krb5_cc_resolve_by_uuid(context, NULL, &handle->ccache, uuid); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = krb5_cc_get_principal(context, handle->ccache, &handle->principal); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } { krb5_data data; ret = krb5_cc_get_config(context, handle->ccache, NULL, "iakerb", &data); if (ret == 0) { *iakerb = 1; handle->endtime = INT_MAX; krb5_data_free(&data); return 0; } } return __gsskrb5_ccache_lifetime(minor_status, context, handle->ccache, handle->principal, &handle->endtime); }
int main(int argc, char **argv) { krb5_context context; krb5_principal server; krb5_ccache ccache; krb5_data data; krb5_error_code ret; char *perr; int c; unsigned int i; bail_on_err(NULL, "Error initializing Kerberos library", krb5_init_context(&context)); bail_on_err(context, "Error getting location of default ccache", krb5_cc_default(context, &ccache)); server = NULL; while ((c = getopt(argc, argv, "p:")) != -1) { switch (c) { case 'p': if (asprintf(&perr, "Error parsing principal name \"%s\"", optarg) < 0) perr = "Error parsing principal name"; bail_on_err(context, perr, krb5_parse_name(context, optarg, &server)); break; } } if (argc - optind < 1 || argc - optind > 2) { fprintf(stderr, "Usage: %s [-p principal] key [value]\n", argv[0]); return 1; } memset(&data, 0, sizeof(data)); if (argc - optind == 2) { unset_config(context, ccache, server, argv[optind]); data = string2data(argv[optind + 1]); bail_on_err(context, "Error adding configuration data to ccache", krb5_cc_set_config(context, ccache, server, argv[optind], &data)); } else { ret = krb5_cc_get_config(context, ccache, server, argv[optind], &data); if (ret == 0) { for (i = 0; i < data.length; i++) putc((unsigned int)data.data[i], stdout); } } krb5_free_principal(context, server); krb5_cc_close(context, ccache); krb5_free_context(context); return 0; }
krb5_error_code func_get(krb5_context context, krb5_ccache id, krb5_const_principal principal, const char *key) { krb5_data config_data; krb5_error_code ret; config_data.data = NULL; ret = krb5_cc_get_config(context, id, principal, key, &config_data); if (ret){ return ret; } /* do something */ krb5_free_data_contents(context, &config_data); return ret; }
static OM_uint32 change_hold(OM_uint32 *minor_status, gsskrb5_cred cred, krb5_error_code (*func)(krb5_context, krb5_ccache)) { krb5_error_code ret; krb5_context context; krb5_data data; *minor_status = 0; krb5_data_zero(&data); GSSAPI_KRB5_INIT (&context); if (cred == NULL) return GSS_S_COMPLETE; if (cred->usage != GSS_C_INITIATE && cred->usage != GSS_C_BOTH) { *minor_status = GSS_KRB5_S_G_BAD_USAGE; return GSS_S_FAILURE; } /* XXX only refcount nah-created credentials */ ret = krb5_cc_get_config(context, cred->ccache, NULL, "nah-created", &data); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } krb5_data_free(&data); ret = func(context, cred->ccache); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } return GSS_S_COMPLETE; }
static int get_user_ccache(const ntlm_name name, char **domainp, char **usernamep, struct ntlm_buf *key) { krb5_context context = NULL; krb5_principal client; krb5_ccache id = NULL; krb5_error_code ret; char *confname; krb5_data data; int aret; *domainp = NULL; *usernamep = NULL; krb5_data_zero(&data); key->length = 0; key->data = NULL; ret = krb5_init_context(&context); if (ret) return ret; ret = krb5_cc_default(context, &id); if (ret) goto out; ret = krb5_cc_get_principal(context, id, &client); if (ret) goto out; ret = krb5_unparse_name_flags(context, client, KRB5_PRINCIPAL_UNPARSE_NO_REALM, usernamep); krb5_free_principal(context, client); if (ret) goto out; if (name != NULL) { *domainp = strdup(name->domain); } else { krb5_data data_domain; krb5_data_zero(&data_domain); ret = krb5_cc_get_config(context, id, NULL, "default-ntlm-domain", &data_domain); if (ret) goto out; *domainp = strndup(data_domain.data, data_domain.length); krb5_data_free(&data_domain); } if (*domainp == NULL) { ret = krb5_enomem(context); goto out; } aret = asprintf(&confname, "ntlm-key-%s", *domainp); if (aret == -1) { ret = krb5_enomem(context); goto out; } ret = krb5_cc_get_config(context, id, NULL, confname, &data); if (ret) goto out; key->data = malloc(data.length); if (key->data == NULL) { ret = ENOMEM; goto out; } key->length = data.length; memcpy(key->data, data.data, data.length); out: krb5_data_free(&data); if (id) krb5_cc_close(context, id); krb5_free_context(context); return ret; }
OM_uint32 _gssiakerb_acquire_cred(OM_uint32 * minor_status, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gss_cred_id_t * output_cred_handle, gss_OID_set * actual_mechs, OM_uint32 * time_rec) { krb5_principal princ = (krb5_principal)desired_name; OM_uint32 major_status, junk; krb5_context context; krb5_error_code ret; gsskrb5_cred handle; krb5_data data; int iakerb = 0; GSSAPI_KRB5_INIT(&context); *minor_status = 0; *output_cred_handle = NULL; if (cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) return GSS_S_FAILURE; if (princ == NULL) return GSS_S_FAILURE; handle = calloc(1, sizeof(*handle)); if (handle == NULL) return GSS_S_FAILURE; HEIMDAL_MUTEX_init(&handle->cred_id_mutex); major_status = _acquire_uuid_name(minor_status, context, princ, &iakerb, handle); if (major_status) return major_status; if (!iakerb) return GSS_S_BAD_NAME; if ((ret = krb5_cc_get_config(context, handle->ccache, NULL, "password", &data)) == 0) { ret = asprintf(&handle->password, "%.*s", (int)data.length, (char *)data.data); memset(data.data, 0, data.length); krb5_data_free(&data); if (ret <= 0 || handle->password == NULL) { _gsskrb5_release_cred(&junk, (gss_cred_id_t *)&handle); *minor_status = ENOMEM; return GSS_S_FAILURE; } #ifdef PKINIT } else if ((ret = krb5_cc_get_config(context, handle->ccache, NULL, "certificate-ref", &data)) == 0) { hx509_certs certs; hx509_query *q; ret = hx509_certs_init(context->hx509ctx, "KEYCHAIN:", 0, NULL, &certs); if (ret) { krb5_data_free(&data); hx509_certs_free(&certs); _gsskrb5_release_cred(&junk, (gss_cred_id_t *)&handle); *minor_status = ret; return GSS_S_FAILURE; } ret = hx509_query_alloc(context->hx509ctx, &q); if (ret) { krb5_data_free(&data); hx509_certs_free(&certs); _gsskrb5_release_cred(&junk, (gss_cred_id_t *)&handle); *minor_status = ret; return GSS_S_FAILURE; } hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); hx509_query_match_persistent(q, &data); ret = _krb5_pk_find_cert(context, 1, certs, q, &handle->cert); krb5_data_free(&data); hx509_certs_free(&certs); hx509_query_free(context->hx509ctx, q); if (ret != 0) { _gss_mg_log(1, "gss-krb5: failed to find certificate ref %d", ret); _gsskrb5_release_cred(&junk, (gss_cred_id_t *)&handle); *minor_status = ret; return GSS_S_FAILURE; } #endif } else if ((ret = krb5_cc_get_config(context, handle->ccache, NULL, "iakerb", &data)) == 0) { handle->cred_flags |= GSS_CF_IAKERB_RESOLVED; krb5_data_free(&data); } else { _gsskrb5_release_cred(&junk, (gss_cred_id_t *)&handle); *minor_status = 0; return GSS_S_FAILURE; } handle->usage = GSS_C_INITIATE; handle->endtime = INT_MAX; *output_cred_handle = (gss_cred_id_t)handle; *minor_status = 0; return GSS_S_COMPLETE; }
static int get_user_ccache(const ntlm_name name, char **username, struct ntlm_buf *key) { krb5_context context = NULL; krb5_principal client; krb5_ccache id = NULL; krb5_error_code ret; char *confname; krb5_data data; *username = NULL; krb5_data_zero(&data); key->length = 0; key->data = NULL; ret = krb5_init_context(&context); if (ret) return ret; ret = krb5_cc_default(context, &id); if (ret) goto out; ret = krb5_cc_get_principal(context, id, &client); if (ret) goto out; ret = krb5_unparse_name_flags(context, client, KRB5_PRINCIPAL_UNPARSE_NO_REALM, username); krb5_free_principal(context, client); if (ret) goto out; asprintf(&confname, "ntlm-key-%s", name->domain); if (confname == NULL) { krb5_clear_error_message(context); ret = ENOMEM; goto out; } ret = krb5_cc_get_config(context, id, NULL, confname, &data); if (ret) goto out; key->data = malloc(data.length); if (key->data == NULL) { ret = ENOMEM; goto out; } key->length = data.length; memcpy(key->data, data.data, data.length); out: krb5_data_free(&data); if (id) krb5_cc_close(context, id); krb5_free_context(context); return ret; }
static void test_cc_config(krb5_context context) { krb5_error_code ret; krb5_principal p; krb5_ccache id; unsigned int i; ret = krb5_cc_new_unique(context, "MEMORY", "bar", &id); if (ret) krb5_err(context, 1, ret, "krb5_cc_new_unique"); ret = krb5_parse_name(context, "*****@*****.**", &p); if (ret) krb5_err(context, 1, ret, "krb5_parse_name"); ret = krb5_cc_initialize(context, id, p); if (ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); for (i = 0; i < 1000; i++) { krb5_data data, data2; const char *name = "foo"; krb5_principal p1 = NULL; if (i & 1) p1 = p; data.data = rk_UNCONST(name); data.length = strlen(name); ret = krb5_cc_set_config(context, id, p1, "FriendlyName", &data); if (ret) krb5_errx(context, 1, "krb5_cc_set_config: add"); ret = krb5_cc_get_config(context, id, p1, "FriendlyName", &data2); if (ret) krb5_errx(context, 1, "krb5_cc_get_config: first"); krb5_data_free(&data2); ret = krb5_cc_set_config(context, id, p1, "FriendlyName", &data); if (ret) krb5_errx(context, 1, "krb5_cc_set_config: add -second"); ret = krb5_cc_get_config(context, id, p1, "FriendlyName", &data2); if (ret) krb5_errx(context, 1, "krb5_cc_get_config: second"); krb5_data_free(&data2); ret = krb5_cc_set_config(context, id, p1, "FriendlyName", NULL); if (ret) krb5_errx(context, 1, "krb5_cc_set_config: delete"); ret = krb5_cc_get_config(context, id, p1, "FriendlyName", &data2); if (ret == 0) krb5_errx(context, 1, "krb5_cc_get_config: non-existant"); } krb5_cc_destroy(context, id); krb5_free_principal(context, p); }