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:
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user