1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-10 01:18:15 +03:00

CVE-2022-2031 s4:kdc: Split out a samba_kdc_get_entry_principal() function

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Joseph Sutton 2022-05-18 16:56:01 +12:00 committed by Jule Anger
parent 23a03911a7
commit c6d9350491

View File

@ -925,6 +925,101 @@ static bool is_kadmin_changepw(krb5_context context,
(principal_comp_strcmp(context, principal, 1, "changepw") == 0);
}
static krb5_error_code samba_kdc_get_entry_principal(
krb5_context context,
struct samba_kdc_db_context *kdc_db_ctx,
const char *samAccountName,
enum samba_kdc_ent_type ent_type,
unsigned flags,
krb5_const_principal in_princ,
krb5_principal *out_princ)
{
struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
krb5_error_code ret = 0;
/*
* If we are set to canonicalize, we get back the fixed UPPER
* case realm, and the real username (ie matching LDAP
* samAccountName)
*
* Otherwise, if we are set to enterprise, we
* get back the whole principal as-sent
*
* Finally, if we are not set to canonicalize, we get back the
* fixed UPPER case realm, but the as-sent username
*/
if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) {
if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) {
/*
* When requested to do so, ensure that the
* both realm values in the principal are set
* to the upper case, canonical realm
*/
ret = smb_krb5_make_principal(context, out_princ,
lpcfg_realm(lp_ctx), "krbtgt",
lpcfg_realm(lp_ctx), NULL);
if (ret) {
return ret;
}
smb_krb5_principal_set_type(context, *out_princ, KRB5_NT_SRV_INST);
} else {
ret = krb5_copy_principal(context, in_princ, out_princ);
if (ret) {
return ret;
}
/*
* this appears to be required regardless of
* the canonicalize flag from the client
*/
ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx));
if (ret) {
return ret;
}
}
} else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL) {
ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL);
if (ret) {
return ret;
}
} else if ((flags & SDB_F_FORCE_CANON) ||
((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) {
/*
* SDB_F_CANON maps from the canonicalize flag in the
* packet, and has a different meaning between AS-REQ
* and TGS-REQ. We only change the principal in the AS-REQ case
*
* The SDB_F_FORCE_CANON if for new MIT KDC code that wants
* the canonical name in all lookups, and takes care to
* canonicalize only when appropriate.
*/
ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL);
if (ret) {
return ret;
}
} else {
ret = krb5_copy_principal(context, in_princ, out_princ);
if (ret) {
return ret;
}
/* While we have copied the client principal, tests
* show that Win2k3 returns the 'corrected' realm, not
* the client-specified realm. This code attempts to
* replace the client principal's realm with the one
* we determine from our records */
/* this has to be with malloc() */
ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx));
if (ret) {
return ret;
}
}
return 0;
}
/*
* Construct an hdb_entry from a directory entry.
*/
@ -1017,93 +1112,8 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
userAccountControl |= msDS_User_Account_Control_Computed;
}
/*
* If we are set to canonicalize, we get back the fixed UPPER
* case realm, and the real username (ie matching LDAP
* samAccountName)
*
* Otherwise, if we are set to enterprise, we
* get back the whole principal as-sent
*
* Finally, if we are not set to canonicalize, we get back the
* fixed UPPER case realm, but the as-sent username
*/
if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) {
p->is_krbtgt = true;
if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) {
/*
* When requested to do so, ensure that the
* both realm values in the principal are set
* to the upper case, canonical realm
*/
ret = smb_krb5_make_principal(context, &entry->principal,
lpcfg_realm(lp_ctx), "krbtgt",
lpcfg_realm(lp_ctx), NULL);
if (ret) {
krb5_clear_error_message(context);
goto out;
}
smb_krb5_principal_set_type(context, entry->principal, KRB5_NT_SRV_INST);
} else {
ret = krb5_copy_principal(context, principal, &entry->principal);
if (ret) {
krb5_clear_error_message(context);
goto out;
}
/*
* this appears to be required regardless of
* the canonicalize flag from the client
*/
ret = smb_krb5_principal_set_realm(context, entry->principal, lpcfg_realm(lp_ctx));
if (ret) {
krb5_clear_error_message(context);
goto out;
}
}
} else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) {
ret = smb_krb5_make_principal(context, &entry->principal, lpcfg_realm(lp_ctx), samAccountName, NULL);
if (ret) {
krb5_clear_error_message(context);
goto out;
}
} else if ((flags & SDB_F_FORCE_CANON) ||
((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) {
/*
* SDB_F_CANON maps from the canonicalize flag in the
* packet, and has a different meaning between AS-REQ
* and TGS-REQ. We only change the principal in the AS-REQ case
*
* The SDB_F_FORCE_CANON if for new MIT KDC code that wants
* the canonical name in all lookups, and takes care to
* canonicalize only when appropriate.
*/
ret = smb_krb5_make_principal(context, &entry->principal, lpcfg_realm(lp_ctx), samAccountName, NULL);
if (ret) {
krb5_clear_error_message(context);
goto out;
}
} else {
ret = krb5_copy_principal(context, principal, &entry->principal);
if (ret) {
krb5_clear_error_message(context);
goto out;
}
/* While we have copied the client principal, tests
* show that Win2k3 returns the 'corrected' realm, not
* the client-specified realm. This code attempts to
* replace the client principal's realm with the one
* we determine from our records */
/* this has to be with malloc() */
ret = smb_krb5_principal_set_realm(context, entry->principal, lpcfg_realm(lp_ctx));
if (ret) {
krb5_clear_error_message(context);
goto out;
}
}
/* First try and figure out the flags based on the userAccountControl */
@ -1296,6 +1306,18 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
}
}
ret = samba_kdc_get_entry_principal(context,
kdc_db_ctx,
samAccountName,
ent_type,
flags,
principal,
&entry->principal);
if (ret != 0) {
krb5_clear_error_message(context);
goto out;
}
entry->valid_start = NULL;
entry->max_life = malloc(sizeof(*entry->max_life));