/* End of version 3 kdcpreauth callbacks. */
+ /*
+ * Return true if princ matches the principal named in the request or the
+ * client principal (possibly canonicalized). If princ does not match,
+ * attempt a database lookup of princ with aliases allowed and compare the
+ * result to the client principal, returning true if it matches.
+ * Otherwise, return false.
+ */
+ krb5_boolean (*match_client)(krb5_context context,
+ krb5_kdcpreauth_rock rock,
+ krb5_principal princ);
+
+ /* End of version 4 kdcpreauth callbacks. */
+
} *krb5_kdcpreauth_callbacks;
/* Optional: preauth plugin initialization function. */
return kdc_fast_set_cookie(rock->rstate, pa_type, data);
}
+static krb5_boolean
+match_client(krb5_context context, krb5_kdcpreauth_rock rock,
+ krb5_principal princ)
+{
+ krb5_db_entry *ent;
+ krb5_boolean match = FALSE;
+ krb5_principal req_client = rock->request->client;
+ krb5_principal client = rock->client->princ;
+
+ /* Check for a direct match against the request principal or
+ * the post-canon client principal. */
+ if (krb5_principal_compare_flags(context, princ, req_client,
+ KRB5_PRINCIPAL_COMPARE_ENTERPRISE) ||
+ krb5_principal_compare(context, princ, client))
+ return TRUE;
+
+ if (krb5_db_get_principal(context, princ, KRB5_KDB_FLAG_ALIAS_OK, &ent))
+ return FALSE;
+ match = krb5_principal_compare(context, ent->princ, client);
+ krb5_db_free_principal(context, ent);
+ return match;
+}
+
static struct krb5_kdcpreauth_callbacks_st callbacks = {
- 3,
+ 4,
max_time_skew,
client_keys,
free_keys,
client_keyblock,
add_auth_indicator,
get_cookie,
- set_cookie
+ set_cookie,
+ match_client
};
static krb5_error_code
/* Prevent abuse of embedded null characters. */
if (memchr(name.data, '\0', name.length))
break;
- ret = krb5_parse_name(context, name.data, &upns[u]);
+ ret = krb5_parse_name_flags(context, name.data,
+ KRB5_PRINCIPAL_PARSE_ENTERPRISE,
+ &upns[u]);
if (ret) {
pkiDebug("%s: failed parsing ms-upn san value\n",
__FUNCTION__);
verify_client_san(krb5_context context,
pkinit_kdc_context plgctx,
pkinit_kdc_req_context reqctx,
+ krb5_kdcpreauth_callbacks cb,
+ krb5_kdcpreauth_rock rock,
krb5_principal client,
int *valid_san)
{
__FUNCTION__, client_string, san_string);
krb5_free_unparsed_name(context, san_string);
#endif
- if (krb5_principal_compare(context, princs[i], client)) {
+ if (cb->match_client(context, rock, princs[i])) {
pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
*valid_san = 1;
retval = 0;
__FUNCTION__, client_string, san_string);
krb5_free_unparsed_name(context, san_string);
#endif
- if (krb5_principal_compare(context, upns[i], client)) {
+ if (cb->match_client(context, rock, upns[i])) {
pkiDebug("%s: upn san match found\n", __FUNCTION__);
*valid_san = 1;
retval = 0;
}
if (is_signed) {
- retval = verify_client_san(context, plgctx, reqctx, request->client,
- &valid_san);
+ retval = verify_client_san(context, plgctx, reqctx, cb, rock,
+ request->client, &valid_san);
if (retval)
goto cleanup;
if (!valid_san) {