When building a princ name pick a sane def type

This is part of the fix to #173.  MSFT RODCs insist on the name type for
krbtgt principals be set to KRB5_NT_SRV_INST.

Commentary from Jeffrey Altman <jaltman@secure-endpoints.com>

As reported by David Mulder of Dell's Quest, Active Directory will
return a BAD_INTEGRITY error when a request for a krbtgt service
ticket is received with principal type NT-PRINCIPAL instead of NT-SRV-INST
as required by RFC 4120.

[Nico: RFC4120 does not require this.  See the description of the
       name-type field of PrincipalName on page 55.]

  ERROR: VAS_ERR_KRB5: Failed to obtain credentials.
  Client: SLED10-32$@F.QAS,
  Service: SLED10-32$@F.QAS, Server: ad2-f.f.qas
  Caused by: KRB5KRB_AP_ERR_BAD_INTEGRITY (-1765328353): Decrypt integrity check failed

Microsoft began enforcing principal type checking for RODCs in 2008R2.
Microsoft does state that ALL krgtgt/REALM tickets SHOULD be sent using
principal name type of KRB5_NT_SRV_INST instead of KRB5_NT_PRINCIPAL.

From Microsoft:

  "I believe we discovered the problem. There isn't a bug in Windows.
  There's been a code change to address another issue which puts in additional
  checks for Kerberos tickets. The problem is with the Unix clients when the
  client request a TGT. The Unix clients are using Name-type Principal
  [KRB_NT_PRINCIPAL (1)] instead of using Name-type Service and Instance
  [KRB_NT_SRV_INST (2)]...."

This change assigns the NT-SRV-INST principal type each time a krbtgt
service principal is created.  Unlike Microsoft, the Heimdal mostly does
not care about the name-type of any principals, with the exception of
referrals, where the name type is needed to decide how to find a
next-hop realm.
This commit is contained in:
Nicolas Williams
2016-11-11 16:31:46 -06:00
parent 84e959a752
commit a59bb7132f
3 changed files with 33 additions and 10 deletions

View File

@@ -63,6 +63,21 @@ host/admin@H5L.ORG
#define princ_ncomp(P, N) ((P)->name.name_string.val[(N)])
#define princ_realm(P) ((P)->realm)
static krb5_error_code
set_default_princ_type(krb5_principal p, NAME_TYPE defnt)
{
if (princ_num_comp(p) > 1 && strcmp(princ_ncomp(p, 0), KRB5_TGS_NAME) == 0)
princ_type(p) = KRB5_NT_SRV_INST;
else if (princ_num_comp(p) > 1 && strcmp(princ_ncomp(p, 0), "host") == 0)
princ_type(p) = KRB5_NT_SRV_HST;
else if (princ_num_comp(p) == 2 &&
strcmp(princ_ncomp(p, 0), KRB5_WELLKNOWN_NAME) == 0)
princ_type(p) = KRB5_NT_WELLKNOWN;
else
princ_type(p) = defnt;
return 0;
}
static krb5_error_code append_component(krb5_context, krb5_principal,
const char *, size_t);
@@ -346,13 +361,13 @@ krb5_parse_name_flags(krb5_context context,
ret = krb5_enomem(context);
goto exit;
}
if (enterprise)
(*principal)->name.name_type = KRB5_NT_ENTERPRISE_PRINCIPAL;
else
(*principal)->name.name_type = KRB5_NT_PRINCIPAL;
(*principal)->name.name_string.val = comp;
princ_num_comp(*principal) = n;
(*principal)->realm = realm;
if (enterprise)
princ_type(*principal) = KRB5_NT_ENTERPRISE_PRINCIPAL;
else
set_default_princ_type(*principal, KRB5_NT_PRINCIPAL);
free(s);
return 0;
exit:
@@ -817,10 +832,10 @@ build_principal(krb5_context context,
krb5_error_code ret;
krb5_principal p;
*principal = NULL;
p = calloc(1, sizeof(*p));
if (p == NULL)
return krb5_enomem(context);
princ_type(p) = KRB5_NT_PRINCIPAL;
princ_realm(p) = strdup(realm);
if (p->realm == NULL) {
@@ -829,9 +844,10 @@ build_principal(krb5_context context,
}
ret = func(context, p, ap);
if (ret == 0)
if (ret == 0) {
*principal = p;
else
set_default_princ_type(p, KRB5_NT_PRINCIPAL);
} else
krb5_free_principal(context, p);
return ret;
}
@@ -1192,7 +1208,6 @@ krb5_principal_is_krbtgt(krb5_context context, krb5_const_principal p)
{
return p->name.name_string.len == 2 &&
strcmp(p->name.name_string.val[0], KRB5_TGS_NAME) == 0;
}
/**

View File

@@ -244,6 +244,14 @@ test_dh2key(krb5_context context, int i, struct testcase *c)
ret = krb5_parse_name(context, c->server, &server);
if (ret)
krb5_err(context, 1, ret, "parse_name: %s", c->server);
/*
* Making krb5_build_principal*() set a reasonable default principal
* name type broke the test vectors here. Rather than regenerate
* the vectors, and to prove that this was the issue, we coerce the
* name types back to their original.
*/
krb5_principal_set_type(context, client, KRB5_NT_PRINCIPAL);
krb5_principal_set_type(context, server, KRB5_NT_PRINCIPAL);
if (verbose_flag) {
char *str;

View File

@@ -178,8 +178,8 @@ ${context} --name-type=krb5-principal-name host/lucid.test.h5l.se@${R} || \
echo "plain (krb5 realmless)" ; > messages.log
${context} --name-type=krb5-principal-name host/lucid.test.h5l.se || \
{ eval "$testfailed"; }
echo "plain (krb5 realmless short-form should fail)" ; > messages.log
${context} --name-type=krb5-principal-name host/lucid 2>/dev/null && \
echo "plain (krb5 realmless short-form)" ; > messages.log
${context} --name-type=krb5-principal-name host/lucid 2>/dev/null || \
{ eval "$testfailed"; }
echo "creating short-form princ"
${kadmin} add -p p1 --use-defaults host/lucid@${R} || exit 1