krb5_error_code KRB5_CALLCONV krb5_cc_store_cred (krb5_context context, krb5_ccache cache, krb5_creds *creds) { krb5_error_code ret; krb5_ticket *tkt; krb5_principal s1, s2; /* remove any dups */ krb5_cc_remove_cred(context, cache, 0, creds); ret = cache->ops->store(context, cache, creds); if (ret) return ret; /* * If creds->server and the server in the decoded ticket differ, * store both principals. */ s1 = creds->server; ret = decode_krb5_ticket(&creds->ticket, &tkt); /* Bail out on errors in case someone is storing a non-ticket. */ if (ret) return 0; s2 = tkt->server; if (!krb5_principal_compare(context, s1, s2)) { creds->server = s2; /* remove any dups */ krb5_cc_remove_cred(context, cache, 0, creds); ret = cache->ops->store(context, cache, creds); creds->server = s1; } krb5_free_ticket(context, tkt); return ret; }
krb5_error_code KRB5_CALLCONV krb5_cc_set_config(krb5_context context, krb5_ccache id, krb5_const_principal principal, const char *key, krb5_data *data) { krb5_error_code ret; krb5_creds cred; memset(&cred, 0, sizeof(cred)); TRACE_CC_SET_CONFIG(context, id, principal, key, data); ret = k5_build_conf_principals(context, id, principal, key, &cred); if (ret) goto out; if (data == NULL) { ret = krb5_cc_remove_cred(context, id, 0, &cred); } else { ret = krb5int_copy_data_contents(context, data, &cred.ticket); if (ret) goto out; ret = krb5_cc_store_cred(context, id, &cred); } out: krb5_free_cred_contents(context, &cred); return ret; }
/* * The krb5_cc_remove_cred() function is defined in the MIT API documentation, * however it is not implemented. So we don't bother trying to call it... */ krb5_error_code clear_old_certs(krb5_context k5_context, krb5_ccache cc, krb5_creds *creds) { if (krb5_cc_remove_cred(k5_context, cc, XXX, creds)) { log_printf("clear_old_certs: unable to initialize K5 context (%d)\n", k5_rc); return -1; } return 0; }
/* * 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 */ krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds); 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, &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; }
static void test_fcache_remove(krb5_context context) { krb5_error_code ret; krb5_ccache id; krb5_principal p; krb5_creds cred; ret = krb5_parse_name(context, "*****@*****.**", &p); if (ret) krb5_err(context, 1, ret, "krb5_parse_name"); ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &id); if (ret) krb5_err(context, 1, ret, "krb5_cc_gen_new"); ret = krb5_cc_initialize(context, id, p); if (ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); /* */ memset(&cred, 0, sizeof(cred)); ret = krb5_parse_name(context, "krbtgt/[email protected]", &cred.server); if (ret) krb5_err(context, 1, ret, "krb5_parse_name"); ret = krb5_parse_name(context, "*****@*****.**", &cred.client); if (ret) krb5_err(context, 1, ret, "krb5_parse_name"); ret = krb5_cc_store_cred(context, id, &cred); if (ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); ret = krb5_cc_remove_cred(context, id, 0, &cred); if (ret) krb5_err(context, 1, ret, "krb5_cc_remove_cred"); ret = krb5_cc_destroy(context, id); if (ret) krb5_err(context, 1, ret, "krb5_cc_destroy"); krb5_free_principal(context, p); krb5_free_principal(context, cred.server); krb5_free_principal(context, cred.client); }
static krb5_error_code check_cc(krb5_context context, krb5_flags options, krb5_ccache ccache, krb5_creds *in_creds, krb5_creds *out_creds) { krb5_error_code ret; krb5_timestamp timeret; /* * If we got a credential, check if credential is expired before * returning it. */ ret = krb5_cc_retrieve_cred(context, ccache, options & KRB5_TC_MATCH_KEYTYPE, in_creds, out_creds); if (ret != 0) return ret; /* Caller will check for KRB5_CC_END */ /* * If we got a credential, check if credential is expired before * returning it, but only if KRB5_GC_EXPIRED_OK is not set. */ /* If expired ok, don't bother checking */ if (options & KRB5_GC_EXPIRED_OK) return 0; krb5_timeofday(context, &timeret); if (out_creds->times.endtime > timeret) return 0; /* Expired and not ok; remove and pretend we didn't find it */ if (options & KRB5_GC_CACHED) krb5_cc_remove_cred(context, ccache, 0, out_creds); krb5_free_cred_contents(context, out_creds); memset(out_creds, 0, sizeof (*out_creds)); return KRB5_CC_END; }
static BOOL ads_cleanup_expired_creds(krb5_context context, krb5_ccache ccache, krb5_creds *credsp) { krb5_error_code retval; const char *cc_type = krb5_cc_get_type(context, ccache); DEBUG(3, ("ads_cleanup_expired_creds: Ticket in ccache[%s:%s] expiration %s\n", cc_type, krb5_cc_get_name(context, ccache), http_timestring(credsp->times.endtime))); /* we will probably need new tickets if the current ones will expire within 10 seconds. */ if (credsp->times.endtime >= (time(NULL) + 10)) return False; /* heimdal won't remove creds from a file ccache, and perhaps we shouldn't anyway, since internally we use memory ccaches, and a FILE one probably means that we're using creds obtained outside of our exectuable */ if (strequal(cc_type, "FILE")) { DEBUG(5, ("ads_cleanup_expired_creds: We do not remove creds from a %s ccache\n", cc_type)); return False; } retval = krb5_cc_remove_cred(context, ccache, 0, credsp); if (retval) { DEBUG(1, ("ads_cleanup_expired_creds: krb5_cc_remove_cred failed, err %s\n", error_message(retval))); /* If we have an error in this, we want to display it, but continue as though we deleted it */ } return True; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_get_creds(krb5_context context, krb5_get_creds_opt opt, krb5_ccache ccache, krb5_const_principal inprinc, krb5_creds **out_creds) { krb5_kdc_flags flags; krb5_flags options; krb5_creds in_creds; krb5_error_code ret; krb5_creds **tgts; krb5_creds *res_creds; int i; if (opt && opt->enctype) { ret = krb5_enctype_valid(context, opt->enctype); if (ret) return ret; } memset(&in_creds, 0, sizeof(in_creds)); in_creds.server = rk_UNCONST(inprinc); ret = krb5_cc_get_principal(context, ccache, &in_creds.client); if (ret) return ret; if (opt) options = opt->options; else options = 0; flags.i = 0; *out_creds = NULL; res_creds = calloc(1, sizeof(*res_creds)); if (res_creds == NULL) { krb5_free_principal(context, in_creds.client); krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } if (opt && opt->enctype) { in_creds.session.keytype = opt->enctype; options |= KRB5_TC_MATCH_KEYTYPE; } /* * If we got a credential, check if credential is expired before * returning it. */ ret = krb5_cc_retrieve_cred(context, ccache, options & KRB5_TC_MATCH_KEYTYPE, &in_creds, res_creds); /* * If we got a credential, check if credential is expired before * returning it, but only if KRB5_GC_EXPIRED_OK is not set. */ if (ret == 0) { krb5_timestamp timeret; /* If expired ok, don't bother checking */ if(options & KRB5_GC_EXPIRED_OK) { *out_creds = res_creds; krb5_free_principal(context, in_creds.client); goto out; } krb5_timeofday(context, &timeret); if(res_creds->times.endtime > timeret) { *out_creds = res_creds; krb5_free_principal(context, in_creds.client); goto out; } if(options & KRB5_GC_CACHED) krb5_cc_remove_cred(context, ccache, 0, res_creds); } else if(ret != KRB5_CC_END) { free(res_creds); krb5_free_principal(context, in_creds.client); goto out; } free(res_creds); if(options & KRB5_GC_CACHED) { krb5_free_principal(context, in_creds.client); ret = not_found(context, in_creds.server, KRB5_CC_NOTFOUND); goto out; } if(options & KRB5_GC_USER_USER) { flags.b.enc_tkt_in_skey = 1; options |= KRB5_GC_NO_STORE; } if (options & KRB5_GC_FORWARDABLE) flags.b.forwardable = 1; if (options & KRB5_GC_NO_TRANSIT_CHECK) flags.b.disable_transited_check = 1; if (options & KRB5_GC_CONSTRAINED_DELEGATION) { flags.b.request_anonymous = 1; /* XXX ARGH confusion */ flags.b.constrained_delegation = 1; } if (options & KRB5_GC_CANONICALIZE) flags.b.canonicalize = 1; tgts = NULL; ret = _krb5_get_cred_kdc_any(context, flags, ccache, &in_creds, opt->self, opt->ticket, out_creds, &tgts); krb5_free_principal(context, in_creds.client); for(i = 0; tgts && tgts[i]; i++) { krb5_cc_store_cred(context, ccache, tgts[i]); krb5_free_creds(context, tgts[i]); } free(tgts); if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) krb5_cc_store_cred(context, ccache, *out_creds); out: _krb5_debug(context, 5, "krb5_get_creds: ret = %d", ret); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_get_credentials_with_flags(krb5_context context, krb5_flags options, krb5_kdc_flags flags, krb5_ccache ccache, krb5_creds *in_creds, krb5_creds **out_creds) { krb5_error_code ret; krb5_creds **tgts; krb5_creds *res_creds; int i; if (in_creds->session.keytype) { ret = krb5_enctype_valid(context, in_creds->session.keytype); if (ret) return ret; } *out_creds = NULL; res_creds = calloc(1, sizeof(*res_creds)); if (res_creds == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } if (in_creds->session.keytype) options |= KRB5_TC_MATCH_KEYTYPE; /* * If we got a credential, check if credential is expired before * returning it. */ ret = krb5_cc_retrieve_cred(context, ccache, in_creds->session.keytype ? KRB5_TC_MATCH_KEYTYPE : 0, in_creds, res_creds); /* * If we got a credential, check if credential is expired before * returning it, but only if KRB5_GC_EXPIRED_OK is not set. */ if (ret == 0) { krb5_timestamp timeret; /* If expired ok, don't bother checking */ if(options & KRB5_GC_EXPIRED_OK) { *out_creds = res_creds; return 0; } krb5_timeofday(context, &timeret); if(res_creds->times.endtime > timeret) { *out_creds = res_creds; return 0; } if(options & KRB5_GC_CACHED) krb5_cc_remove_cred(context, ccache, 0, res_creds); } else if(ret != KRB5_CC_END) { free(res_creds); return ret; } free(res_creds); if(options & KRB5_GC_CACHED) return not_found(context, in_creds->server, KRB5_CC_NOTFOUND); if(options & KRB5_GC_USER_USER) flags.b.enc_tkt_in_skey = 1; if (flags.b.enc_tkt_in_skey) options |= KRB5_GC_NO_STORE; tgts = NULL; ret = _krb5_get_cred_kdc_any(context, flags, ccache, in_creds, NULL, NULL, out_creds, &tgts); for(i = 0; tgts && tgts[i]; i++) { krb5_cc_store_cred(context, ccache, tgts[i]); krb5_free_creds(context, tgts[i]); } free(tgts); if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) krb5_cc_store_cred(context, ccache, *out_creds); return ret; }
static krb5_error_code fcc_remove_cred(krb5_context context, krb5_ccache id, krb5_flags which, krb5_creds *cred) { krb5_error_code ret; krb5_ccache copy, newfile; char *newname; int fd; ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, ©); if (ret) return ret; ret = krb5_cc_copy_cache(context, id, copy); if (ret) { krb5_cc_destroy(context, copy); return ret; } ret = krb5_cc_remove_cred(context, copy, which, cred); if (ret) { krb5_cc_destroy(context, copy); return ret; } asprintf(&newname, "FILE:%s.XXXXXX", FILENAME(id)); if (newname == NULL) { krb5_cc_destroy(context, copy); return ret; } fd = mkstemp(&newname[5]); if (fd < 0) { ret = errno; krb5_cc_destroy(context, copy); return ret; } close(fd); ret = krb5_cc_resolve(context, newname, &newfile); if (ret) { unlink(&newname[5]); free(newname); krb5_cc_destroy(context, copy); return ret; } ret = krb5_cc_copy_cache(context, copy, newfile); krb5_cc_destroy(context, copy); if (ret) { free(newname); krb5_cc_destroy(context, newfile); return ret; } ret = rename(&newname[5], FILENAME(id)); if (ret) ret = errno; free(newname); krb5_cc_close(context, newfile); return ret; }
int main (int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache ccache; int optidx = 0; int exit_val = 0; setprogname (argv[0]); if(getarg(args, num_args, argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag){ print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (argc != 0) usage (1); ret = krb5_init_context (&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); if (all_flag) { krb5_cccol_cursor cursor; ret = krb5_cccol_cursor_new (context, &cursor); if (ret) krb5_err(context, 1, ret, "krb5_cccol_cursor_new"); while (krb5_cccol_cursor_next (context, cursor, &ccache) == 0 && ccache != NULL) { ret = krb5_cc_destroy (context, ccache); if (ret) { krb5_warn(context, ret, "krb5_cc_destroy"); exit_val = 1; } } krb5_cccol_cursor_free(context, &cursor); } else { if(cache == NULL) { ret = krb5_cc_default(context, &ccache); if (ret) krb5_err(context, 1, ret, "krb5_cc_default"); } else { ret = krb5_cc_resolve(context, cache, &ccache); if (ret) krb5_err(context, 1, ret, "krb5_cc_resolve"); } if (ret == 0) { if (credential) { krb5_creds mcred; krb5_cc_clear_mcred(&mcred); ret = krb5_parse_name(context, credential, &mcred.server); if (ret) krb5_err(context, 1, ret, "Can't parse principal %s", credential); ret = krb5_cc_remove_cred(context, ccache, 0, &mcred); if (ret) krb5_err(context, 1, ret, "Failed to remove principal %s", credential); krb5_cc_close(context, ccache); krb5_free_principal(context, mcred.server); krb5_free_context(context); return 0; } ret = krb5_cc_destroy (context, ccache); if (ret) { krb5_warn(context, ret, "krb5_cc_destroy"); exit_val = 1; } } } krb5_free_context (context); #ifndef NO_AFS if (unlog_flag && k_hasafs ()) { if (k_unlog ()) exit_val = 1; } #endif return exit_val; }