From 0d888f0c902ebd98cfb82d50ab8b8b3928341ee2 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Tue, 14 Jun 2022 14:16:10 +1200
Subject: [PATCH 05/15] CVE-2022-32743 s4/dsdb/util: Add function to check for
 a subclass relationship

We need to be able to determine whether an object is a subclass of a
specific objectclass such as 'computer'.

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

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
---
 source4/dsdb/samdb/ldb_modules/util.c | 38 +++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c
index 42aa9a2..9e00aed 100644
--- a/source4/dsdb/samdb/ldb_modules/util.c
+++ b/source4/dsdb/samdb/ldb_modules/util.c
@@ -1718,6 +1718,44 @@ const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schem
 	return dsdb_get_last_structural_class(schema, oc_el);
 }
 
+/*
+  Get the parent class of an objectclass, or NULL if none exists.
+ */
+const struct dsdb_class *dsdb_get_parent_class(const struct dsdb_schema *schema,
+					       const struct dsdb_class *objectclass)
+{
+	if (ldb_attr_cmp(objectclass->lDAPDisplayName, "top") == 0) {
+		return NULL;
+	}
+
+	if (objectclass->subClassOf == NULL) {
+		return NULL;
+	}
+
+	return dsdb_class_by_lDAPDisplayName(schema, objectclass->subClassOf);
+}
+
+/*
+  Return true if 'struct_objectclass' is a subclass of 'other_objectclass'. The
+  two objectclasses must originate from the same schema, to allow for
+  pointer-based identity comparison.
+ */
+bool dsdb_is_subclass_of(const struct dsdb_schema *schema,
+			 const struct dsdb_class *struct_objectclass,
+			 const struct dsdb_class *other_objectclass)
+{
+	while (struct_objectclass != NULL) {
+		/* Pointer comparison can be used due to the same schema str. */
+		if (struct_objectclass == other_objectclass) {
+			return true;
+		}
+
+		struct_objectclass = dsdb_get_parent_class(schema, struct_objectclass);
+	}
+
+	return false;
+}
+
 /* Fix the DN so that the relative attribute names are in upper case so that the DN:
    cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
    CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
-- 
1.8.3.1

