static struct heim_plugin_data kdc_plugin_data = {
"krb5",
"kdc",
- KRB5_PLUGIN_KDC_VERSION_11,
+ KRB5_PLUGIN_KDC_VERSION_12,
kdc_plugin_deps,
kdc_get_instance
};
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((void *)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) {
+ ret = 0;
+ }
+
+ return ret;
+}
+
static krb5_error_code KRB5_LIB_CALL
finalize_reply(krb5_context context, const void *plug, void *plugctx, void *userctx)
{
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.
*/
* Plugins should carefully check API contract notes for changes
* between plugin API versions.
*/
-#define KRB5_PLUGIN_KDC_VERSION_11 11
+#define KRB5_PLUGIN_KDC_VERSION_12 12
typedef struct krb5plugin_kdc_ftable {
HEIM_PLUGIN_FTABLE_COMMON_ELEMENTS(krb5_context);
krb5plugin_kdc_pac_update pac_update;
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;
#define PA_REPLACE_REPLY_KEY 8 /* PA mech replaces reply key */
#define PA_USES_LONG_TERM_KEY 16 /* PA mech uses client's long-term key */
#define PA_USES_FAST_COOKIE 32 /* Multi-step PA mech maintains state in PA-FX-COOKIE */
+#define PA_HARDWARE_AUTH 64 /* PA mech uses hardware authentication */
krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa);
krb5_error_code (*finalize_pac)(astgs_request_t r);
void (*cleanup)(astgs_request_t r);
#ifdef PKINIT
{
KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)",
- PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY,
+ PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY | PA_HARDWARE_AUTH,
pa_pkinit_validate, NULL, NULL
},
{
- KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE | PA_REPLACE_REPLY_KEY,
+ KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE | PA_REPLACE_REPLY_KEY | PA_HARDWARE_AUTH,
pa_pkinit_validate, NULL, NULL
},
{
krb5_boolean is_tgs)
{
krb5_error_code ret;
- krb5_data data;
uint16_t rodc_id;
krb5_principal client;
krb5_const_principal canon_princ = NULL;
return ret;
}
- ret = _krb5_pac_sign(r->context,
- r->pac,
- r->et.authtime,
- client,
- &skey->key, /* Server key */
- &tkey->key, /* TGS key */
- rodc_id,
- NULL, /* UPN */
- canon_princ,
- FALSE, /* add_full_sig */
- is_tgs ? &r->pac_attributes : NULL,
- &data);
+ ret = _krb5_kdc_pac_sign_ticket(r->context,
+ r->pac,
+ client,
+ &skey->key, /* Server key */
+ &tkey->key, /* TGS key */
+ rodc_id,
+ NULL, /* UPN */
+ canon_princ,
+ !is_tgs, /* add_ticket_sig */
+ !is_tgs, /* add_full_sig */
+ &r->et,
+ is_tgs ? &r->pac_attributes : NULL);
krb5_free_principal(r->context, client);
krb5_pac_free(r->context, r->pac);
r->pac = NULL;
r->cname);
return ret;
}
-
- ret = _kdc_tkt_insert_pac(r->context, &r->et, &data);
- krb5_data_free(&data);
return ret;
}
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
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);
+ return ret;
+ }
+ }
kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
pat[n].name);
ret = pat[n].validate(r, pa);
if (ret)
goto out;
- /* Add the PAC */
- if (!r->et.flags.anonymous) {
- ret = generate_pac(r, skey, krbtgt_key, is_tgs);
- if (ret)
- goto out;
- }
-
if (r->client->flags.synthetic) {
ret = add_synthetic_princ_ad(r);
if (ret)
}
}
+ /* Add the PAC */
+ if (!r->et.flags.anonymous) {
+ ret = generate_pac(r, skey, krbtgt_key, is_tgs);
+ if (ret)
+ goto out;
+ }
+
+ /*
+ * No more changes to the ticket (r->et) from this point on, lest
+ * the checksums in the PAC be invalidated.
+ */
+
/*
* Last chance for plugins to update reply
*/