server_lookup:
priv->server = NULL;
+ priv->server_princ = sp;
if (server)
_kdc_free_ent(context, server);
server = NULL;
Realm req_rlm;
krb5_realm *realms;
- if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
+ priv->ret = ret; /* advise policy plugin of failure reason */
+ ret2 = _kdc_referral_policy(priv);
+ if (ret2 == 0) {
+ heim_assert(priv->server_princ != sp,
+ "Referral policy plugin must update server principal");
+
+ krb5_free_principal(context, sp);
+ sp = priv->server_princ;
+
+ krb5_xfree(priv->sname);
+ priv->sname = NULL;
+ ret = krb5_unparse_name(context, sp, &priv->sname);
+ if (ret)
+ goto out;
+ spn = priv->sname;
+ goto server_lookup;
+ } else if (ret2 != KRB5_PLUGIN_NO_HANDLE) {
+ ret = ret2;
+ } else if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
if (capath == NULL) {
/* With referalls, hierarchical capaths are always enabled */
ret2 = _krb5_find_capath(context, tgt->crealm, our_realm,
return ret;
}
+static krb5_error_code KRB5_LIB_CALL
+referral_policy(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+ krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
+
+ if (ft->referral_policy == NULL)
+ return KRB5_PLUGIN_NO_HANDLE;
+ return ft->referral_policy((void *)plug, userctx);
+}
+
+krb5_error_code
+_kdc_referral_policy(astgs_request_t r)
+{
+ krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
+
+ if (have_plugin)
+ ret = _krb5_plugin_run_f(r->context, &windc_plugin_data, 0, r, referral_policy);
+
+ return ret;
+}
+
uintptr_t KRB5_CALLCONV
kdc_get_instance(const char *libname)
{
typedef krb5_error_code
(KRB5_CALLCONV *krb5plugin_windc_finalize_reply)(void *, astgs_request_t r);
+/*
+ * A referral policy plugin can either rewrite the server principal
+ * by resetting priv->server_princ, or it can disable referral
+ * processing entirely by returning an error.
+ *
+ * The error code from the previous server lookup is available as r->ret.
+ *
+ * If the function returns KRB5_PLUGIN_NO_HANDLE, the TGS will continue
+ * with its default referral handling.
+ */
+
+typedef krb5_error_code
+(KRB5_CALLCONV *krb5plugin_windc_referral_policy)(void *, astgs_request_t r);
+
#define KRB5_WINDC_PLUGIN_MINOR 8
#define KRB5_WINDC_PLUGING_MINOR KRB5_WINDC_PLUGIN_MINOR
krb5plugin_windc_pac_generate pac_generate;
krb5plugin_windc_pac_verify pac_verify;
krb5plugin_windc_client_access client_access;
+ krb5plugin_windc_referral_policy referral_policy;
krb5plugin_windc_finalize_reply finalize_reply;
} krb5plugin_windc_ftable;
pac_generate,
pac_verify,
client_access,
+ NULL, /* referral_policy */
finalize_reply
};