/* * Request: * NameZ * Creds * * Response: * */ static krb5_error_code kcm_op_store(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { krb5_creds creds; krb5_error_code ret; kcm_ccache ccache; char *name; ret = krb5_ret_stringz(request, &name); if (ret) return ret; KCM_LOG_REQUEST_NAME(context, client, opcode, name); ret = krb5_ret_creds(request, &creds); if (ret) { free(name); return ret; } ret = kcm_ccache_resolve_client(context, client, opcode, name, &ccache); if (ret) { free(name); krb5_free_cred_contents(context, &creds); return ret; } ret = kcm_ccache_store_cred(context, ccache, &creds, 0); if (ret) { free(name); krb5_free_cred_contents(context, &creds); kcm_release_ccache(context, ccache); return ret; } kcm_ccache_enqueue_default(context, ccache, &creds); free(name); kcm_release_ccache(context, ccache); return 0; }
void KRB5_CALLCONV krb5_free_creds(krb5_context context, krb5_creds *val) { if (val == NULL) return; krb5_free_cred_contents(context, val); free(val); }
/* Convert a JSON value to a ccache handle or to NULL. Set *new_out to true if * the ccache handle is a newly created memory ccache, false otherwise. */ static int json_to_ccache(krb5_context context, k5_json_value v, krb5_ccache *ccache_out, krb5_boolean *new_out) { krb5_error_code ret; krb5_ccache ccache = NULL; krb5_principal princ; krb5_creds creds; k5_json_array array; size_t i, len; *ccache_out = NULL; *new_out = FALSE; if (k5_json_get_tid(v) == K5_JSON_TID_NULL) return 0; if (k5_json_get_tid(v) == K5_JSON_TID_STRING) { /* We got a reference to an external ccache; just resolve it. */ return krb5_cc_resolve(context, k5_json_string_utf8(v), ccache_out) ? -1 : 0; } /* We got the contents of a memory ccache. */ if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) return -1; array = v; len = k5_json_array_length(array); if (len < 1) return -1; /* Initialize a new memory ccache using the principal in the first array * entry.*/ if (krb5_cc_new_unique(context, "MEMORY", NULL, &ccache)) return -1; if (json_to_principal(context, k5_json_array_get(array, 0), &princ)) goto invalid; ret = krb5_cc_initialize(context, ccache, princ); krb5_free_principal(context, princ); if (ret) goto invalid; /* Add remaining array entries to the ccache as credentials. */ for (i = 1; i < len; i++) { if (json_to_creds(context, k5_json_array_get(array, 1), &creds)) goto invalid; ret = krb5_cc_store_cred(context, ccache, &creds); krb5_free_cred_contents(context, &creds); if (ret) goto invalid; } *ccache_out = ccache; *new_out = TRUE; return 0; invalid: (void)krb5_cc_destroy(context, ccache); return -1; }
uint32_t gpp_store_remote_creds(uint32_t *min, gssx_cred *creds) { krb5_context ctx = NULL; krb5_ccache ccache = NULL; krb5_creds cred; krb5_error_code ret; XDR xdrctx; bool xdrok; *min = 0; if (creds == NULL) return GSS_S_CALL_INACCESSIBLE_READ; memset(&cred, 0, sizeof(cred)); ret = krb5_init_context(&ctx); if (ret) return ret; ret = krb5_cc_default(ctx, &ccache); if (ret) goto done; ret = krb5_parse_name(ctx, creds->desired_name.display_name.octet_string_val, &cred.client); if (ret) goto done; ret = krb5_parse_name(ctx, GPKRB_SRV_NAME, &cred.server); if (ret) goto done; cred.ticket.data = malloc(GPKRB_MAX_CRED_SIZE); xdrmem_create(&xdrctx, cred.ticket.data, GPKRB_MAX_CRED_SIZE, XDR_ENCODE); xdrok = xdr_gssx_cred(&xdrctx, creds); if (!xdrok) { ret = ENOSPC; goto done; } cred.ticket.length = xdr_getpos(&xdrctx); ret = krb5_cc_store_cred(ctx, ccache, &cred); if (ret == KRB5_FCC_NOFILE) { /* If a ccache does not exit, try to create one */ ret = krb5_cc_initialize(ctx, ccache, cred.client); if (ret) goto done; /* and try again to store the cred */ ret = krb5_cc_store_cred(ctx, ccache, &cred); } done: if (ctx) { krb5_free_cred_contents(ctx, &cred); if (ccache) krb5_cc_close(ctx, ccache); krb5_free_context(ctx); } *min = ret; return ret ? GSS_S_FAILURE : GSS_S_COMPLETE; }
static krb5_error_code fast_armor_ap_request(krb5_context context, struct krb5int_fast_request_state *state, krb5_ccache ccache, krb5_principal target_principal) { krb5_error_code retval = 0; krb5_creds creds, *out_creds = NULL; krb5_auth_context authcontext = NULL; krb5_data encoded_authenticator; krb5_fast_armor *armor = NULL; krb5_keyblock *subkey = NULL, *armor_key = NULL; encoded_authenticator.data = NULL; memset(&creds, 0, sizeof(creds)); creds.server = target_principal; retval = krb5_cc_get_principal(context, ccache, &creds.client); if (retval == 0) retval = krb5_get_credentials(context, 0, ccache, &creds, &out_creds); if (retval == 0) { TRACE_FAST_ARMOR_CCACHE_KEY(context, &out_creds->keyblock); retval = krb5_mk_req_extended(context, &authcontext, AP_OPTS_USE_SUBKEY, NULL /*data*/, out_creds, &encoded_authenticator); } if (retval == 0) retval = krb5_auth_con_getsendsubkey(context, authcontext, &subkey); if (retval == 0) retval = krb5_c_fx_cf2_simple(context, subkey, "subkeyarmor", &out_creds->keyblock, "ticketarmor", &armor_key); if (retval == 0) { TRACE_FAST_ARMOR_KEY(context, armor_key); armor = calloc(1, sizeof(krb5_fast_armor)); if (armor == NULL) retval = ENOMEM; } if (retval == 0) { armor->armor_type = KRB5_FAST_ARMOR_AP_REQUEST; armor->armor_value = encoded_authenticator; encoded_authenticator.data = NULL; encoded_authenticator.length = 0; state->armor = armor; armor = NULL; state->armor_key = armor_key; armor_key = NULL; } krb5_free_keyblock(context, armor_key); krb5_free_keyblock(context, subkey); if (out_creds) krb5_free_creds(context, out_creds); /* target_principal is owned by caller. */ creds.server = NULL; krb5_free_cred_contents(context, &creds); if (encoded_authenticator.data) krb5_free_data_contents(context, &encoded_authenticator); krb5_auth_con_free(context, authcontext); return retval; }
/* * next_closest_tgt() * * Using CUR_TGT, attempt to get the cross-realm TGT having its remote * realm closest to the target principal's. Update NXT_TGT, NXT_KDC * accordingly. */ static krb5_error_code next_closest_tgt(struct tr_state *ts, krb5_principal client) { krb5_error_code retval; krb5_creds tgtq; retval = 0; memset(&tgtq, 0, sizeof(tgtq)); for (ts->nxt_kdc = ts->lst_kdc; ts->nxt_kdc > ts->cur_kdc; ts->nxt_kdc--) { krb5_free_cred_contents(ts->ctx, &tgtq); retval = kdc_mcred(ts, client, &tgtq); if (retval) goto cleanup; /* Don't waste time retrying ccache for direct path. */ if (ts->cur_kdc != ts->kdc_list || ts->nxt_kdc != ts->lst_kdc) { retval = try_ccache(ts, &tgtq); if (!retval) break; if (HARD_CC_ERR(retval)) goto cleanup; } /* Not in the ccache, so talk to a KDC. */ retval = try_kdc(ts, &tgtq); if (!retval) { break; } /* * Because try_kdc() validates referral TGTs, it can return an * error indicating a bogus referral. The loop continues when * it gets a bogus referral, which is arguably the right * thing. (Previous implementation unconditionally failed.) */ } /* * If we have a non-zero retval, we either have a hard error or we * failed to find a closer TGT. */ cleanup: krb5_free_cred_contents(ts->ctx, &tgtq); return retval; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_ret_creds_tag(krb5_storage *sp, krb5_creds *creds) { krb5_error_code ret; int8_t dummy8; int32_t dummy32, header; memset(creds, 0, sizeof(*creds)); ret = krb5_ret_int32 (sp, &header); if (ret) goto cleanup; if (header & SC_CLIENT_PRINCIPAL) { ret = krb5_ret_principal (sp, &creds->client); if(ret) goto cleanup; } if (header & SC_SERVER_PRINCIPAL) { ret = krb5_ret_principal (sp, &creds->server); if(ret) goto cleanup; } if (header & SC_SESSION_KEY) { ret = krb5_ret_keyblock (sp, &creds->session); if(ret) goto cleanup; } ret = krb5_ret_times (sp, &creds->times); if(ret) goto cleanup; ret = krb5_ret_int8 (sp, &dummy8); if(ret) goto cleanup; ret = krb5_ret_int32 (sp, &dummy32); if(ret) goto cleanup; creds->flags.b = int2TicketFlags(bitswap32(dummy32)); if (header & SC_ADDRESSES) { ret = krb5_ret_addrs (sp, &creds->addresses); if(ret) goto cleanup; } if (header & SC_AUTHDATA) { ret = krb5_ret_authdata (sp, &creds->authdata); if(ret) goto cleanup; } if (header & SC_TICKET) { ret = krb5_ret_data (sp, &creds->ticket); if(ret) goto cleanup; } if (header & SC_SECOND_TICKET) { ret = krb5_ret_data (sp, &creds->second_ticket); if(ret) goto cleanup; } cleanup: if(ret) { #if 0 krb5_free_cred_contents(context, creds); /* XXX */ #endif } return ret; }
/* * remove * * - remove the specified credentials from the NC */ krb5_error_code KRB5_CALLCONV krb5_stdccv3_remove (krb5_context context, krb5_ccache id, krb5_flags flags, krb5_creds *in_creds) { krb5_error_code err = 0; stdccCacheDataPtr ccapi_data = id->data; cc_credentials_iterator_t iterator = NULL; int found = 0; if (!err) { err = stdccv3_setup(context, ccapi_data); } if (!err) { err = cc_ccache_new_credentials_iterator(ccapi_data->NamedCache, &iterator); } /* Note: CCAPI v3 ccaches can contain both v4 and v5 creds */ while (!err && !found) { cc_credentials_t credentials = NULL; err = cc_credentials_iterator_next (iterator, &credentials); if (!err && (credentials->data->version == cc_credentials_v5)) { krb5_creds creds; err = copy_cc_cred_union_to_krb5_creds(context, credentials->data, &creds); if (!err) { found = krb5_creds_compare (context, in_creds, &creds); krb5_free_cred_contents (context, &creds); } if (!err && found) { err = cc_ccache_remove_credentials (ccapi_data->NamedCache, credentials); } } if (credentials) { cc_credentials_release (credentials); } } if (err == ccIteratorEnd) { err = ccErrCredentialsNotFound; } if (iterator) { err = cc_credentials_iterator_release(iterator); } if (!err) { cache_changed (); } return cc_err_xlate (err); }
static isc_result_t check_credentials(krb5_context context, krb5_ccache ccache, krb5_principal service) { char *realm = NULL; krb5_creds creds; krb5_creds mcreds; krb5_error_code krberr; krb5_timestamp now; isc_result_t result = ISC_R_FAILURE; memset(&mcreds, 0, sizeof(mcreds)); memset(&creds, 0, sizeof(creds)); krberr = krb5_get_default_realm(context, &realm); CHECK_KRB5(context, krberr, "Failed to retrieve default realm"); krberr = krb5_build_principal(context, &mcreds.server, strlen(realm), realm, "krbtgt", realm, NULL); CHECK_KRB5(context, krberr, "Failed to build 'krbtgt/REALM' principal"); mcreds.client = service; krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &creds); if (krberr) { const char * errmsg = krb5_get_error_message(context, krberr); log_error("Credentials are not present in cache (%s)\n", errmsg); krb5_free_error_message(context, errmsg); result = ISC_R_FAILURE; goto cleanup; } CHECK_KRB5(context, krberr, "Credentials are not present in cache "); krberr = krb5_timeofday(context, &now); CHECK_KRB5(context, krberr, "Failed to get time of day"); if (now > (creds.times.endtime + KRB_MIN_TIME)) { log_error("Credentials cache expired"); result = ISC_R_FAILURE; goto cleanup; } else { char buf[255]; char fill = ' '; krb5_timestamp_to_sfstring(creds.times.endtime, buf, 16, &fill); log_info("Credentials valid til %s\n", buf); } result = ISC_R_SUCCESS; cleanup: krb5_free_cred_contents(context, &creds); if (mcreds.server) krb5_free_principal(context, mcreds.server); if (realm) krb5_free_default_realm(context, realm); return result; }
static void get_creds(krb5_context context, const char *keytab_str, krb5_ccache *cache, const char *serverhost) { krb5_keytab keytab; krb5_principal client; krb5_error_code ret; krb5_get_init_creds_opt *init_opts; krb5_creds creds; char *server; char keytab_buf[256]; int aret; if (keytab_str == NULL) { ret = krb5_kt_default_name (context, keytab_buf, sizeof(keytab_buf)); if (ret) krb5_err (context, 1, ret, "krb5_kt_default_name"); keytab_str = keytab_buf; } ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "%s", keytab_str); ret = krb5_sname_to_principal (context, slave_str, IPROP_NAME, KRB5_NT_SRV_HST, &client); if (ret) krb5_err(context, 1, ret, "krb5_sname_to_principal"); ret = krb5_get_init_creds_opt_alloc(context, &init_opts); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); aret = asprintf (&server, "%s/%s", IPROP_NAME, serverhost); if (aret == -1 || server == NULL) krb5_errx (context, 1, "malloc: no memory"); ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 0, server, init_opts); free (server); krb5_get_init_creds_opt_free(context, init_opts); if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds"); ret = krb5_kt_close(context, keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_close"); ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, cache); if(ret) krb5_err(context, 1, ret, "krb5_cc_new_unique"); ret = krb5_cc_initialize(context, *cache, client); if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred(context, *cache, &creds); if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); krb5_free_cred_contents(context, &creds); krb5_free_principal(context, client); }
/* * Obtain renewed credentials for the given service using the existing * credentials in the provided ticket cache. */ krb5_error_code krb5_get_renewed_creds(krb5_context ctx, krb5_creds *creds, krb5_const_principal client, krb5_ccache ccache, const char *in_tkt_service) { krb5_kdc_flags flags; krb5_creds in, *old = NULL, *out = NULL; krb5_error_code code; flags.i = 0; flags.b.renewable = 1; flags.b.renew = 1; memset(&in, 0, sizeof(in)); code = krb5_copy_principal(ctx, client, &in.client); if (code != 0) goto done; if (in_tkt_service == NULL) { const char *realm; realm = krb5_principal_get_realm(ctx, client); if (realm == NULL) { code = KRB5_CONFIG_NODEFREALM; goto done; } code = krb5_build_principal(ctx, &in.server, strlen(realm), realm, "krbtgt", realm, (const char *) NULL); if (code != 0) goto done; } else { code = krb5_parse_name(ctx, in_tkt_service, &in.server); if (code != 0) goto done; } code = krb5_get_credentials(ctx, 0, ccache, &in, &old); if (code != 0) goto done; flags.b.forwardable = old->flags.b.forwardable; flags.b.proxiable = old->flags.b.proxiable; code = krb5_get_kdc_cred(ctx, ccache, flags, NULL, NULL, old, &out); if (code != 0) goto done; #ifdef HAVE_KRB5_COPY_CREDS_CONTENTS code = krb5_copy_creds_contents(ctx, out, creds); krb5_free_creds(ctx, out); #else /* No good alternative -- hope this works. */ *creds = *out; free(out); #endif done: krb5_free_cred_contents(ctx, &in); if (old != NULL) krb5_free_creds(ctx, old); return code; }
krb5_error_code KRB5_LIB_FUNCTION krb5_mk_req_exact(krb5_context context, krb5_auth_context *auth_context, const krb5_flags ap_req_options, const krb5_principal server, krb5_data *in_data, krb5_ccache ccache, krb5_data *outbuf) { krb5_error_code ret; krb5_creds this_cred, *cred; memset(&this_cred, 0, sizeof(this_cred)); ret = krb5_cc_get_principal(context, ccache, &this_cred.client); if(ret) return ret; ret = krb5_copy_principal (context, server, &this_cred.server); if (ret) { krb5_free_cred_contents (context, &this_cred); return ret; } this_cred.times.endtime = 0; if (auth_context && *auth_context && (*auth_context)->keytype) this_cred.session.keytype = (*auth_context)->keytype; ret = krb5_get_credentials (context, 0, ccache, &this_cred, &cred); krb5_free_cred_contents(context, &this_cred); if (ret) return ret; ret = krb5_mk_req_extended (context, auth_context, ap_req_options, in_data, cred, outbuf); krb5_free_creds(context, cred); return ret; }
/* * next_closest_tgt() * * Using CUR_TGT, attempt to get the cross-realm TGT having its remote * realm closest to the target principal's. Update NXT_TGT, NXT_KDC * accordingly. */ static krb5_error_code next_closest_tgt(struct tr_state *ts, krb5_principal client) { krb5_error_code retval; krb5_creds tgtq; retval = 0; memset(&tgtq, 0, sizeof(tgtq)); for (ts->nxt_kdc = ts->lst_kdc; ts->nxt_kdc > ts->cur_kdc; ts->nxt_kdc--) { krb5_free_cred_contents(ts->ctx, &tgtq); retval = kdc_mcred(ts, client, &tgtq); if (retval) goto cleanup; /* Don't waste time retrying ccache for direct path. */ if (ts->cur_kdc != ts->kdc_list || ts->nxt_kdc != ts->lst_kdc) { retval = try_ccache(ts, &tgtq); if (!retval) break; if (HARD_CC_ERR(retval)) goto cleanup; } /* Not in the ccache, so talk to a KDC. */ retval = try_kdc(ts, &tgtq); if (!retval) { break; } /* * In case of errors in try_kdc() or find_nxt_kdc(), continue * looping through the KDC list. */ } /* * If we have a non-zero retval, we either have a hard error or we * failed to find a closer TGT. */ cleanup: krb5_free_cred_contents(ts->ctx, &tgtq); return retval; }
/* Display the contents of cache. */ static int show_ccache(krb5_ccache cache) { krb5_cc_cursor cur; krb5_creds creds; krb5_principal princ; krb5_error_code ret; ret = krb5_cc_get_principal(context, cache, &princ); if (ret) { com_err(progname, ret, ""); return 1; } ret = krb5_unparse_name(context, princ, &defname); if (ret) { com_err(progname, ret, _("while unparsing principal name")); return 1; } printf(_("Ticket cache: %s:%s\nDefault principal: %s\n\n"), krb5_cc_get_type(context, cache), krb5_cc_get_name(context, cache), defname); /* XXX Translating would disturb table alignment; skip for now. */ fputs("Valid starting", stdout); fillit(stdout, timestamp_width - sizeof("Valid starting") + 3, (int) ' '); fputs("Expires", stdout); fillit(stdout, timestamp_width - sizeof("Expires") + 3, (int) ' '); fputs("Service principal\n", stdout); ret = krb5_cc_start_seq_get(context, cache, &cur); if (ret) { com_err(progname, ret, _("while starting to retrieve tickets")); return 1; } while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) { if (show_config || !krb5_is_config_principal(context, creds.server)) show_credential(&creds); krb5_free_cred_contents(context, &creds); } krb5_free_principal(context, princ); krb5_free_unparsed_name(context, defname); defname = NULL; if (ret == KRB5_CC_END) { ret = krb5_cc_end_seq_get(context, cache, &cur); if (ret) { com_err(progname, ret, _("while finishing ticket retrieval")); return 1; } return 0; } else { com_err(progname, ret, _("while retrieving a ticket")); return 1; } }
/* simulate a kinit, putting the tgt in the given credentials cache. Orignally by [email protected] */ int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, krb5_principal principal, const char *password, time_t *expire_time, time_t *kdc_time) { krb5_error_code code = 0; krb5_creds my_creds; krb5_get_init_creds_opt options; krb5_get_init_creds_opt_init(&options); krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, &options); if ((code = krb5_get_init_creds_password(ctx, &my_creds, principal, password, NULL, NULL, 0, NULL, &options))) { return code; } if ((code = krb5_cc_initialize(ctx, cc, principal))) { krb5_free_cred_contents(ctx, &my_creds); return code; } if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) { krb5_free_cred_contents(ctx, &my_creds); return code; } if (expire_time) { *expire_time = (time_t) my_creds.times.endtime; } if (kdc_time) { *kdc_time = (time_t) my_creds.times.starttime; } krb5_free_cred_contents(ctx, &my_creds); return 0; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) { krb5_error_code ret; int8_t dummy8; int32_t dummy32; memset(creds, 0, sizeof(*creds)); ret = krb5_ret_principal (sp, &creds->client); if(ret) goto cleanup; ret = krb5_ret_principal (sp, &creds->server); if(ret) goto cleanup; ret = krb5_ret_keyblock (sp, &creds->session); if(ret) goto cleanup; ret = krb5_ret_times (sp, &creds->times); if(ret) goto cleanup; ret = krb5_ret_int8 (sp, &dummy8); if(ret) goto cleanup; ret = krb5_ret_int32 (sp, &dummy32); if(ret) goto cleanup; /* * Runtime detect the what is the higher bits of the bitfield. If * any of the higher bits are set in the input data, it's either a * new ticket flag (and this code need to be removed), or it's a * MIT cache (or new Heimdal cache), lets change it to our current * format. */ { uint32_t mask = 0xffff0000; creds->flags.i = 0; creds->flags.b.anonymous = 1; if (creds->flags.i & mask) mask = ~mask; if (dummy32 & mask) dummy32 = bitswap32(dummy32); } creds->flags.i = dummy32; ret = krb5_ret_addrs (sp, &creds->addresses); if(ret) goto cleanup; ret = krb5_ret_authdata (sp, &creds->authdata); if(ret) goto cleanup; ret = krb5_ret_data (sp, &creds->ticket); if(ret) goto cleanup; ret = krb5_ret_data (sp, &creds->second_ticket); cleanup: if(ret) { #if 0 krb5_free_cred_contents(context, creds); /* XXX */ #endif } return ret; }
bool next_any() { krb5_context ctx = context_.get(); krb5_free_cred_contents(ctx, &creds_); memset(&creds_, 0, sizeof(creds_)); krb5_error_code code = krb5_cc_next_cred(ctx, cc_->get(), &cursor_, &creds_); if (code == KRB5_CC_END) { return false; } else { raiseIf(ctx, code, "reading next credential"); } return true; }
static int print_tickets (krb5_context context, krb5_ccache ccache, krb5_principal principal) { krb5_error_code ret; krb5_cc_cursor cursor; krb5_creds cred; char *str; ret = krb5_unparse_name (context, principal, &str); if (ret) { lreply(500, "krb5_unparse_name: %d", ret); return 500; } lreply(200, "%17s: %s:%s", "Credentials cache", krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache)); lreply(200, "%17s: %s", "Principal", str); free (str); ret = krb5_cc_start_seq_get (context, ccache, &cursor); if (ret) { lreply(500, "krb5_cc_start_seq_get: %d", ret); return 500; } lreply(200, " Issued Expires Principal"); while ((ret = krb5_cc_next_cred (context, ccache, &cursor, &cred)) == 0) { if (print_cred(context, &cred)) return 500; krb5_free_cred_contents (context, &cred); } if (ret != KRB5_CC_END) { lreply(500, "krb5_cc_get_next: %d", ret); return 500; } ret = krb5_cc_end_seq_get (context, ccache, &cursor); if (ret) { lreply(500, "krb5_cc_end_seq_get: %d", ret); return 500; } return 200; }
/* * Indicate the we failed to log in to this service/host with these * credentials. The caller passes an unsigned int which they * initialise to the number of times they would like to retry. * * This method is used to support re-trying with freshly fetched * credentials in case a server is rebuilt while clients have * non-expired tickets. When the client code gets a logon failure they * throw away the existing credentials for the server and retry. */ _PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred, const char *principal, unsigned int *count) { struct ccache_container *ccc; krb5_creds creds, creds2; int ret; if (principal == NULL) { /* no way to delete if we don't know the principal */ return false; } ccc = cred->ccache; if (ccc == NULL) { /* not a kerberos connection */ return false; } if (*count > 0) { /* We have already tried discarding the credentials */ return false; } (*count)++; ZERO_STRUCT(creds); ret = krb5_parse_name(ccc->smb_krb5_context->krb5_context, principal, &creds.server); if (ret != 0) { return false; } ret = krb5_cc_retrieve_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds, &creds2); if (ret != 0) { /* don't retry - we didn't find these credentials to remove */ return false; } ret = krb5_cc_remove_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds); krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds2); if (ret != 0) { /* don't retry - we didn't find these credentials to * remove. Note that with the current backend this * never happens, as it always returns 0 even if the * creds don't exist, which is why we do a separate * krb5_cc_retrieve_cred() above. */ return false; } return true; }
/* * clean_cc_tgts() * * Free CC_TGTS which were dirty, then mark them clean. */ static void clean_cc_tgts(struct tr_state *ts) { unsigned int i; struct cc_tgts *rb; rb = &ts->cc_tgts; for (i = 0; i < NCC_TGTS; i++) { if (rb->dirty[i]) { krb5_free_cred_contents(ts->ctx, &rb->cred[i]); rb->dirty[i] = 0; } } }
int ZGetCredsRealm(krb5_creds **creds_out, char *realm) { krb5_creds creds_in; krb5_creds creds_tmp; krb5_ccache ccache; /* XXX make this a global or static?*/ int result; result = krb5_cc_default(Z_krb5_ctx, &ccache); if (result) return result; memset((char *)&creds_in, 0, sizeof(creds_in)); result = krb5_build_principal(Z_krb5_ctx, &creds_in.server, strlen(realm), realm, SERVER_SERVICE, SERVER_INSTANCE, NULL); if (result) { krb5_cc_close(Z_krb5_ctx, ccache); return result; } result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client); if (!result) { result = krb5_cc_retrieve_cred(Z_krb5_ctx, ccache, #ifdef KRB5_TC_SUPPORTED_KTYPES KRB5_TC_SUPPORTED_KTYPES, /* MIT */ #else 0, /* Heimdal or other Space KRB5 */ #endif &creds_in, &creds_tmp); if (!result) { *creds_out = malloc(sizeof(creds_tmp)); if (*creds_out == NULL) result = errno; else memcpy(*creds_out, &creds_tmp, sizeof(creds_tmp)); } } if (result == KRB5_CC_NOTFOUND || result == KRB5_CC_END) result = krb5_get_credentials(Z_krb5_ctx, 0, ccache, &creds_in, creds_out); krb5_cc_close(Z_krb5_ctx, ccache); krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */ return result; }
static void check_ticket_count(gss_cred_id_t cred, int expected) { krb5_error_code ret; krb5_context context = NULL; krb5_creds kcred; krb5_cc_cursor cur; krb5_ccache ccache; int count = 0; gss_key_value_set_desc store; gss_key_value_element_desc elem; OM_uint32 major, minor; const char *ccname = "MEMORY:count"; store.count = 1; store.elements = &elem; elem.key = "ccache"; elem.value = ccname; major = gss_store_cred_into(&minor, cred, GSS_C_INITIATE, &mech_krb5, 1, 0, &store, NULL, NULL); check_gsserr("gss_store_cred_into", major, minor); ret = krb5_init_context(&context); check_k5err(context, "krb5_init_context", ret); ret = krb5_cc_resolve(context, ccname, &ccache); check_k5err(context, "krb5_cc_resolve", ret); ret = krb5_cc_start_seq_get(context, ccache, &cur); check_k5err(context, "krb5_cc_start_seq_get", ret); while (!krb5_cc_next_cred(context, ccache, &cur, &kcred)) { if (!krb5_is_config_principal(context, kcred.server)) count++; krb5_free_cred_contents(context, &kcred); } ret = krb5_cc_end_seq_get(context, ccache, &cur); check_k5err(context, "krb5_cc_end_seq_get", ret); if (expected != count) { printf("Expected %d tickets but got %d\n", expected, count); exit(1); } krb5_cc_destroy(context, ccache); krb5_free_context(context); }
static krb5_error_code copy_creds_except(krb5_context context, krb5_ccache incc, krb5_ccache outcc, krb5_principal princ) { krb5_error_code code; krb5_flags flags; krb5_cc_cursor cur; krb5_creds creds; flags = 0; /* turns off OPENCLOSE mode */ if ((code = krb5_cc_set_flags(context, incc, flags))) return(code); if ((code = krb5_cc_set_flags(context, outcc, flags))) return(code); if ((code = krb5_cc_start_seq_get(context, incc, &cur))) goto cleanup; while (!(code = krb5_cc_next_cred(context, incc, &cur, &creds))) { if (krb5_principal_compare(context, princ, creds.server)) continue; code = krb5_cc_store_cred(context, outcc, &creds); krb5_free_cred_contents(context, &creds); if (code) goto cleanup; } if (code != KRB5_CC_END) goto cleanup; code = 0; cleanup: flags = KRB5_TC_OPENCLOSE; if (code) krb5_cc_set_flags(context, incc, flags); else code = krb5_cc_set_flags(context, incc, flags); if (code) krb5_cc_set_flags(context, outcc, flags); else code = krb5_cc_set_flags(context, outcc, flags); return(code); }
static krb5_error_code verify_common (krb5_context context, krb5_principal principal, krb5_ccache ccache, krb5_keytab keytab, krb5_boolean secure, const char *service, krb5_creds cred) { krb5_error_code ret; krb5_principal server; krb5_verify_init_creds_opt vopt; krb5_ccache id; ret = krb5_sname_to_principal (context, NULL, service, KRB5_NT_SRV_HST, &server); if(ret) return ret; krb5_verify_init_creds_opt_init(&vopt); krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, secure); ret = krb5_verify_init_creds(context, &cred, server, keytab, NULL, &vopt); krb5_free_principal(context, server); if(ret) return ret; if(ccache == NULL) ret = krb5_cc_default (context, &id); else id = ccache; if(ret == 0){ ret = krb5_cc_initialize(context, id, principal); if(ret == 0){ ret = krb5_cc_store_cred(context, id, &cred); } if(ccache == NULL) krb5_cc_close(context, id); } krb5_free_cred_contents(context, &cred); return ret; }
int v5::credentialCheck(krb5_context kcontext, krb5_principal kprincipal, int promptInterval, krb5_timestamp *tgtEndtime) { krb5_creds my_creds; krb5_timestamp now; Ktw::reqAction retval = Ktw::none; if (!getTgtFromCcache(kcontext, &my_creds)) { tgtEndtime = 0; return retval; } if (krb5_principal_compare (kcontext, my_creds.client, kprincipal)) { krb5_free_principal(kcontext, kprincipal); krb5_copy_principal(kcontext, my_creds.client, &kprincipal); } if ((krb5_timeofday(kcontext, &now) == 0) && (now + (promptInterval * 60) >= my_creds.times.endtime)) { qDebug("now: %d", now); qDebug("starttime: %d", my_creds.times.starttime); qDebug("endtime: %d", my_creds.times.endtime); qDebug("next Prompt: %d", (now + (promptInterval * 60))); qDebug("renew possible untill: %d", my_creds.times.renew_till); if(now + (promptInterval * 60) >= my_creds.times.renew_till) { retval = Ktw::reinit; } else { retval = Ktw::renew; } } *tgtEndtime = my_creds.times.endtime; krb5_free_cred_contents(kcontext, &my_creds); qDebug("credentials_expiring_real returns: %d", retval); return retval; }
krb5_error_code KRB5_CALLCONV krb5_stdcc_retrieve (krb5_context context, krb5_ccache id, krb5_flags whichfields, krb5_creds *mcreds, krb5_creds *creds ) { krb5_error_code retval; krb5_cc_cursor curs = NULL; krb5_creds *fetchcreds; if ((retval = stdcc_setup(context, NULL))) return retval; fetchcreds = (krb5_creds *)malloc(sizeof(krb5_creds)); if (fetchcreds == NULL) return KRB5_CC_NOMEM; /* we're going to use the iterators */ krb5_stdcc_start_seq_get(context, id, &curs); while (!krb5_stdcc_next_cred(context, id, &curs, fetchcreds)) { /* * look at each credential for a match * use this match routine since it takes the * whichfields and the API doesn't */ if (stdccCredsMatch(context, fetchcreds, mcreds, whichfields)) { /* we found it, copy and exit */ *creds = *fetchcreds; krb5_stdcc_end_seq_get(context, id, &curs); return 0; } /* free copy allocated by next_cred */ krb5_free_cred_contents(context, fetchcreds); } /* no luck, end get and exit */ krb5_stdcc_end_seq_get(context, id, &curs); /* we're not using this anymore so we should get rid of it! */ free(fetchcreds); return KRB5_CC_NOTFOUND; }
static gboolean credentials_expiring_real (KaApplet *applet) { krb5_creds my_creds; krb5_timestamp now; gboolean retval = FALSE; if (!kcontext_valid) return retval; memset (&my_creds, 0, sizeof (my_creds)); ka_applet_set_tgt_renewable (applet, FALSE); if (!ka_get_tgt_from_ccache (kcontext, &my_creds)) { creds_expiry = 0; retval = TRUE; goto out; } /* copy principal from cache if any */ if (kprincipal == NULL || krb5_principal_compare (kcontext, my_creds.client, kprincipal)) { if (kprincipal) krb5_free_principal (kcontext, kprincipal); krb5_copy_principal (kcontext, my_creds.client, &kprincipal); } creds_expiry = my_creds.times.endtime; if ((krb5_timeofday (kcontext, &now) == 0) && (now + ka_applet_get_pw_prompt_secs (applet) > my_creds.times.endtime)) retval = TRUE; /* If our creds are expiring, determine whether they are renewable. * If the expiry is already at the renew_till time, don't consider * credentials renewable */ if (retval && get_cred_renewable (&my_creds) && my_creds.times.renew_till > now && my_creds.times.renew_till > creds_expiry) { ka_applet_set_tgt_renewable (applet, TRUE); } out: krb5_free_cred_contents (kcontext, &my_creds); ka_applet_update_status (applet, creds_expiry); return retval; }
static void get_creds(krb5_context context, krb5_ccache *cache) { krb5_keytab keytab; krb5_principal client; krb5_error_code ret; krb5_get_init_creds_opt *init_opts; krb5_preauthtype preauth = KRB5_PADATA_ENC_TIMESTAMP; krb5_creds creds; ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, ktname, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve"); ret = krb5_make_principal(context, &client, NULL, "kadmin", HPROP_NAME, NULL); if(ret) krb5_err(context, 1, ret, "krb5_make_principal"); ret = krb5_get_init_creds_opt_alloc(context, &init_opts); if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); krb5_get_init_creds_opt_set_preauth_list(init_opts, &preauth, 1); ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 0, NULL, init_opts); if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds"); krb5_get_init_creds_opt_free(context, init_opts); ret = krb5_kt_close(context, keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_close"); ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, cache); if(ret) krb5_err(context, 1, ret, "krb5_cc_new_unique"); ret = krb5_cc_initialize(context, *cache, client); if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); krb5_free_principal(context, client); ret = krb5_cc_store_cred(context, *cache, &creds); if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); krb5_free_cred_contents(context, &creds); }
static krb5_error_code mcc_remove_cred(krb5_context context, krb5_ccache id, krb5_flags which, krb5_creds *mcreds) { krb5_mcache *m = MCACHE(id); struct link **q, *p; for(q = &m->creds, p = *q; p; p = *q) { if(krb5_compare_creds(context, which, mcreds, &p->cred)) { *q = p->next; krb5_free_cred_contents(context, &p->cred); free(p); } else q = &p->next; } return 0; }
// Free function for the Kerberos::Krb5 class. static void rkrb5_free(RUBY_KRB5* ptr){ if(!ptr) return; if(ptr->keytab) krb5_kt_close(ptr->ctx, ptr->keytab); if(ptr->ctx) krb5_free_cred_contents(ptr->ctx, &ptr->creds); if(ptr->princ) krb5_free_principal(ptr->ctx, ptr->princ); if(ptr->ctx) krb5_free_context(ptr->ctx); free(ptr); }