diff --git a/kdc/kdc-plugin.c b/kdc/kdc-plugin.c index cce40bb87..145f09000 100644 --- a/kdc/kdc-plugin.c +++ b/kdc/kdc-plugin.c @@ -51,7 +51,7 @@ static const char *kdc_plugin_deps[] = { static struct heim_plugin_data kdc_plugin_data = { "krb5", "kdc", - KRB5_PLUGIN_KDC_VERSION_10, + KRB5_PLUGIN_KDC_VERSION_11, kdc_plugin_deps, kdc_get_instance }; @@ -239,6 +239,33 @@ _kdc_referral_policy(astgs_request_t r) return ret; } +static krb5_error_code KRB5_LIB_CALL +hwauth_policy(krb5_context context, const void *plug, void *plugctx, void *userctx) +{ + const krb5plugin_kdc_ftable *ft = plug; + + if (ft->hwauth_policy == NULL) { + return KRB5_PLUGIN_NO_HANDLE; + } + return ft->hwauth_policy(rk_UNCONST(plug), userctx); +} + +krb5_error_code +_kdc_hwauth_policy(astgs_request_t r) +{ + krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE; + + if (have_plugin) { + ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, hwauth_policy); + } + + if (ret != KRB5_PLUGIN_NO_HANDLE) { + return ret; + } + + return r->client->flags.require_hwauth ? KRB5KDC_ERR_POLICY : 0; +} + static krb5_error_code KRB5_LIB_CALL finalize_reply(krb5_context context, const void *plug, void *plugctx, void *userctx) { diff --git a/kdc/kdc-plugin.h b/kdc/kdc-plugin.h index 05286257b..956412770 100644 --- a/kdc/kdc-plugin.h +++ b/kdc/kdc-plugin.h @@ -95,6 +95,16 @@ typedef krb5_error_code typedef krb5_error_code (KRB5_CALLCONV *krb5plugin_kdc_referral_policy)(void *, astgs_request_t); +/* + * A hardware authentication policy plugin can indicate what is to + * happen when a client authenticates using a method other than + * hardware authentication. It can return zero to allow the + * authentication, or an appropriate error code to deny it. + */ + +typedef krb5_error_code +(KRB5_CALLCONV *krb5plugin_kdc_hwauth_policy)(void *, astgs_request_t); + /* * Update the AS or TGS reply immediately prior to encoding. */ @@ -117,7 +127,7 @@ typedef krb5_error_code * Plugins should carefully check API contract notes for changes * between plugin API versions. */ -#define KRB5_PLUGIN_KDC_VERSION_10 10 +#define KRB5_PLUGIN_KDC_VERSION_11 11 typedef struct krb5plugin_kdc_ftable { HEIM_PLUGIN_FTABLE_COMMON_ELEMENTS(krb5_context); @@ -125,6 +135,7 @@ typedef struct krb5plugin_kdc_ftable { krb5plugin_kdc_pac_verify pac_verify; krb5plugin_kdc_client_access client_access; krb5plugin_kdc_referral_policy referral_policy; + krb5plugin_kdc_hwauth_policy hwauth_policy; krb5plugin_kdc_finalize_reply finalize_reply; krb5plugin_kdc_audit audit; } krb5plugin_kdc_ftable; diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index 51eddbe3f..ee17692d7 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -2270,12 +2270,12 @@ _kdc_as_rep(astgs_request_t r) ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; goto out; } - if (r->client->flags.require_hwauth && - !(pat[n].flags & PA_HARDWARE_AUTH)) { - kdc_log(r->context, config, 4, "Hardware authentication required for %s", r->cname); - - ret = KRB5KDC_ERR_POLICY; - goto out; + if (!(pat[n].flags & PA_HARDWARE_AUTH)) { + ret = _kdc_hwauth_policy(r); + if (ret) { + kdc_log(r->context, config, 4, "Hardware authentication required for %s", r->cname); + goto out; + } } kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s", pat[n].name); diff --git a/tests/plugin/kdc_test_plugin.c b/tests/plugin/kdc_test_plugin.c index 0effd9783..475867af7 100644 --- a/tests/plugin/kdc_test_plugin.c +++ b/tests/plugin/kdc_test_plugin.c @@ -162,13 +162,14 @@ audit(void *ctx, astgs_request_t r) } static krb5plugin_kdc_ftable kdc_plugin = { - KRB5_PLUGIN_KDC_VERSION_10, + KRB5_PLUGIN_KDC_VERSION_11, init, fini, pac_generate, pac_verify, client_access, NULL, /* referral_policy */ + NULL, /* hwauth_policy */ finalize_reply, audit };