Optional backwards-compatible anon-pkinit behaviour

* Anonymous pkinit responses from the KDC where the name
  type is not well-known (as issued by 7.5 KDCs and earlier)
  are accepted by the client.  There is no need for the client
  to strictly enforce the name type.

* With historical_anon_pkinit = true, the kinit(1) client's
  "--anonymous" option only performs anon pkinit, and does
  not require an '@' prefix for the realm argument.

* With historical_anon_realm = true, the KDC issues anon
  pkinit tickets with the legacy pre-7.0 "real" realm.
This commit is contained in:
Viktor Dukhovni
2019-07-14 23:02:57 -04:00
committed by Viktor Dukhovni
parent f40d393c83
commit fae8df3839
11 changed files with 141 additions and 27 deletions

View File

@@ -1258,19 +1258,43 @@ krb5_principal_is_anonymous(krb5_context context,
krb5_const_principal p,
unsigned int flags)
{
int anon_realm;
/*
* Heimdal versions 7.5 and below left the name-type at KRB5_NT_PRINCIPAL
* even with anonymous pkinit responses. To retain interoperability with
* legacy KDCs, the name-type is not checked by the client after requesting
* a fully anonymous ticket.
*/
if (!(flags & KRB5_ANON_IGNORE_NAME_TYPE) &&
p->name.name_type != KRB5_NT_WELLKNOWN &&
p->name.name_type != KRB5_NT_UNKNOWN)
return FALSE;
if ((p->name.name_type != KRB5_NT_WELLKNOWN &&
p->name.name_type != KRB5_NT_UNKNOWN) ||
p->name.name_string.len != 2 ||
if (p->name.name_string.len != 2 ||
strcmp(p->name.name_string.val[0], KRB5_WELLKNOWN_NAME) != 0 ||
strcmp(p->name.name_string.val[1], KRB5_ANON_NAME) != 0)
return FALSE;
anon_realm = strcmp(p->realm, KRB5_ANON_REALM) == 0;
/*
* While unauthenticated clients SHOULD get "WELLKNOWN:ANONYMOUS" as their
* realm, Heimdal KDCs prior to 7.0 returned the requested realm. While
* such tickets might lead *servers* to unwittingly grant access to fully
* anonymous clients, trusting that the client was authenticated to the
* realm in question, doing it right is the KDC's job, the client should
* not refuse such a ticket.
*
* If we ever do decide to enforce WELLKNOWN:ANONYMOUS for unauthenticated
* clients, it is essential that calls that pass KRB5_ANON_MATCH_ANY still
* ignore the realm, as in that case either case matches one of the two
* possible conditions.
*/
if (flags & KRB5_ANON_MATCH_UNAUTHENTICATED)
return TRUE;
return ((flags & KRB5_ANON_MATCH_AUTHENTICATED) && !anon_realm) ||
((flags & KRB5_ANON_MATCH_UNAUTHENTICATED) && anon_realm);
/*
* Finally, authenticated clients that asked to be only anonymized do
* legitimately expect a non-anon realm.
*/
return strcmp(p->realm, KRB5_ANON_REALM) != 0;
}
static int