static krb5_error_code search_sprinc(kdc_realm_t *kdc_active_realm, krb5_kdc_req *req, krb5_flags flags, krb5_db_entry **server, const char **status) { krb5_error_code ret; krb5_principal princ = req->server; krb5_principal reftgs = NULL; ret = db_get_svc_princ(kdc_context, princ, flags, server, status); if (ret == 0 || ret != KRB5_KDB_NOENTRY) goto cleanup; if (!is_cross_tgs_principal(req->server)) { ret = find_referral_tgs(kdc_active_realm, req, &reftgs); if (ret != 0) goto cleanup; ret = db_get_svc_princ(kdc_context, reftgs, flags, server, status); if (ret == 0 || ret != KRB5_KDB_NOENTRY) goto cleanup; princ = reftgs; } ret = find_alternate_tgs(kdc_active_realm, princ, server, status); cleanup: if (ret != 0 && ret != KRB5KDC_ERR_SVC_UNAVAILABLE) { ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; if (*status == NULL) *status = "LOOKING_UP_SERVER"; } krb5_free_principal(kdc_context, reftgs); return ret; }
static krb5_error_code search_sprinc(kdc_realm_t *kdc_active_realm, krb5_kdc_req *req, krb5_flags flags, krb5_db_entry **server, const char **status) { krb5_error_code ret; krb5_principal princ = req->server; krb5_principal reftgs = NULL; krb5_boolean allow_referral; /* Do not allow referrals for u2u or ticket modification requests, because * the server is supposed to match an already-issued ticket. */ allow_referral = !(req->kdc_options & NO_REFERRAL_OPTION); if (!allow_referral) flags &= ~KRB5_KDB_FLAG_CANONICALIZE; ret = db_get_svc_princ(kdc_context, princ, flags, server, status); if (ret == 0 || ret != KRB5_KDB_NOENTRY || !allow_referral) goto cleanup; if (!is_cross_tgs_principal(req->server)) { ret = find_referral_tgs(kdc_active_realm, req, &reftgs); if (ret != 0) goto cleanup; ret = db_get_svc_princ(kdc_context, reftgs, flags, server, status); if (ret == 0 || ret != KRB5_KDB_NOENTRY) goto cleanup; princ = reftgs; } ret = find_alternate_tgs(kdc_active_realm, princ, server, status); cleanup: if (ret != 0 && ret != KRB5KDC_ERR_SVC_UNAVAILABLE) { ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; if (*status == NULL) *status = "LOOKING_UP_SERVER"; } krb5_free_principal(kdc_context, reftgs); return ret; }
/* * The request seems to be for a ticket-granting service somewhere else, * but we don't have a ticket for the final TGS. Try to give the requestor * some intermediate realm. */ static krb5_error_code find_alternate_tgs(kdc_realm_t *kdc_active_realm, krb5_principal princ, krb5_db_entry **server_ptr, const char **status) { krb5_error_code retval; krb5_principal *plist = NULL, *pl2; krb5_data tmp; krb5_db_entry *server = NULL; *server_ptr = NULL; assert(is_cross_tgs_principal(princ)); if ((retval = krb5_walk_realm_tree(kdc_context, krb5_princ_realm(kdc_context, princ), krb5_princ_component(kdc_context, princ, 1), &plist, KRB5_REALM_BRANCH_CHAR))) { goto cleanup; } /* move to the end */ for (pl2 = plist; *pl2; pl2++); /* the first entry in this array is for krbtgt/local@local, so we ignore it */ while (--pl2 > plist) { tmp = *krb5_princ_realm(kdc_context, *pl2); krb5_princ_set_realm(kdc_context, *pl2, krb5_princ_realm(kdc_context, princ)); retval = db_get_svc_princ(kdc_context, *pl2, 0, &server, status); krb5_princ_set_realm(kdc_context, *pl2, &tmp); if (retval == KRB5_KDB_NOENTRY) continue; else if (retval) goto cleanup; log_tgs_alt_tgt(kdc_context, server->princ); *server_ptr = server; server = NULL; goto cleanup; } cleanup: if (retval == 0 && *server_ptr == NULL) retval = KRB5_KDB_NOENTRY; if (retval != 0) *status = "UNKNOWN_SERVER"; krb5_free_realm_tree(kdc_context, plist); krb5_db_free_principal(kdc_context, server); return retval; }