240 lines
7.5 KiB
Diff
240 lines
7.5 KiB
Diff
From f68877af829bf73da8e965c9458a9846d1757038 Mon Sep 17 00:00:00 2001
|
|
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Date: Wed, 18 May 2022 16:56:01 +1200
|
|
Subject: [PATCH 82/99] 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>
|
|
|
|
[jsutton@samba.org Adapted entry to entry_ex->entry]
|
|
|
|
[jsutton@samba.org Fixed conflicts caused by superfluous whitespace]
|
|
---
|
|
source4/kdc/db-glue.c | 192 +++++++++++++++++++++++-------------------
|
|
1 file changed, 107 insertions(+), 85 deletions(-)
|
|
|
|
diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c
|
|
index 45159e6e64d..ac0c206b5c1 100644
|
|
--- a/source4/kdc/db-glue.c
|
|
+++ b/source4/kdc/db-glue.c
|
|
@@ -824,6 +824,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.
|
|
*/
|
|
@@ -913,93 +1008,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_ex->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_ex->entry.principal, KRB5_NT_SRV_INST);
|
|
- } else {
|
|
- ret = krb5_copy_principal(context, principal, &entry_ex->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_ex->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_ex->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_ex->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_ex->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_ex->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 */
|
|
@@ -1185,6 +1195,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_ex->entry.principal);
|
|
+ if (ret != 0) {
|
|
+ krb5_clear_error_message(context);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
entry_ex->entry.valid_start = NULL;
|
|
|
|
entry_ex->entry.max_life = malloc(sizeof(*entry_ex->entry.max_life));
|
|
--
|
|
2.25.1
|