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_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 *try_creds; krb5_creds *res_creds; krb5_name_canon_iterator name_canon_iter = NULL; krb5_name_canon_rule_options rule_opts; 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); return krb5_enomem(context); } if (opt && opt->enctype) { in_creds.session.keytype = opt->enctype; options |= KRB5_TC_MATCH_KEYTYPE; } /* Check for entry in ccache */ if (inprinc->name.name_type == KRB5_NT_SRV_HST_NEEDS_CANON) { ret = check_cc(context, options, ccache, &in_creds, res_creds); if (ret == 0) { *out_creds = res_creds; goto out; } } ret = krb5_name_canon_iterator_start(context, NULL, &in_creds, &name_canon_iter); if (ret) goto out; next_rule: ret = krb5_name_canon_iterate_creds(context, &name_canon_iter, &try_creds, &rule_opts); if (ret) return ret; if (name_canon_iter == NULL) { if (options & KRB5_GC_CACHED) ret = KRB5_CC_NOTFOUND; else ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } ret = check_cc(context, options, ccache, try_creds, res_creds); if (ret == 0) { *out_creds = res_creds; goto out; } else if(ret != KRB5_CC_END) { goto out; } if(options & KRB5_GC_CACHED) goto next_rule; if(rule_opts & KRB5_NCRO_USE_REFERRALS) flags.b.canonicalize = 1; else if(rule_opts & KRB5_NCRO_NO_REFERRALS) flags.b.canonicalize = 0; else flags.b.canonicalize = (options & KRB5_GC_CANONICALIZE) ? 1 : 0; 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; } tgts = NULL; ret = _krb5_get_cred_kdc_any(context, flags, ccache, try_creds, opt ? opt->self : 0, opt ? opt->ticket : 0, 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 == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN && !(rule_opts & KRB5_NCRO_SECURE)) goto next_rule; if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) store_cred(context, ccache, inprinc, *out_creds); out: if (ret) { krb5_free_creds(context, res_creds); ret = not_found(context, inprinc, ret); } krb5_free_principal(context, in_creds.client); krb5_free_name_canon_iterator(context, name_canon_iter); _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; }
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_name_canon_iterator name_canon_iter = NULL; krb5_name_canon_rule_options rule_opts; krb5_creds **tgts; krb5_creds *try_creds; krb5_creds *res_creds; int i; if (in_creds->session.keytype) { ret = krb5_enctype_valid(context, in_creds->session.keytype); if (ret) return ret; options |= KRB5_TC_MATCH_KEYTYPE; } *out_creds = NULL; res_creds = calloc(1, sizeof(*res_creds)); if (res_creds == NULL) return krb5_enomem(context); if (in_creds->server->name.name_type == KRB5_NT_SRV_HST_NEEDS_CANON) { ret = check_cc(context, options, ccache, in_creds, res_creds); if (ret == 0) { *out_creds = res_creds; return 0; } } ret = krb5_name_canon_iterator_start(context, NULL, in_creds, &name_canon_iter); if (ret) return ret; next_rule: krb5_free_cred_contents(context, res_creds); memset(res_creds, 0, sizeof (*res_creds)); ret = krb5_name_canon_iterate_creds(context, &name_canon_iter, &try_creds, &rule_opts); if (ret) goto out; if (name_canon_iter == NULL) { if (options & KRB5_GC_CACHED) ret = KRB5_CC_NOTFOUND; else ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } ret = check_cc(context, options, ccache, try_creds, res_creds); if (ret == 0) { *out_creds = res_creds; goto out; } else if(ret != KRB5_CC_END) { goto out; } if(options & KRB5_GC_CACHED) goto next_rule; 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, try_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 == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN && !(rule_opts & KRB5_NCRO_SECURE)) goto next_rule; if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) store_cred(context, ccache, in_creds->server, *out_creds); out: krb5_free_name_canon_iterator(context, name_canon_iter); if (ret) { krb5_free_creds(context, res_creds); return not_found(context, in_creds->server, ret); } return 0; }