From 935997b92ebea5941a04c553934e203b33f1d7d7 Mon Sep 17 00:00:00 2001
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Date: Fri, 22 Oct 2021 14:12:25 +1300
Subject: [PATCH 151/266] CVE-2020-25722 s4/dsdb/samldb: add
 samldb_get_single_valued_attr() helper

This takes a string of logic out of samldb_unique_attr_check() that we
are going to need in other places, and that would be very tedious to
repeat.

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

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>

Conflict:NA
Reference:https://gitlab.com/samba-team/samba/-/commit/935997b92ebea5941a04c553934e203b33f1d7d7

---
 source4/dsdb/samdb/ldb_modules/samldb.c | 49 +++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 6db7840b0c1..40dfab6390b 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -161,6 +161,55 @@ static int samldb_next_step(struct samldb_ctx *ac)
 	}
 }
 
+static int samldb_get_single_valued_attr(struct ldb_context *ldb,
+					 struct samldb_ctx *ac,
+					 const char *attr,
+					 const char **value)
+{
+	/*
+	 * The steps we end up going through to get and check a single valued
+	 * attribute.
+	 */
+	struct ldb_message_element *el = NULL;
+
+	*value = NULL;
+
+	el = dsdb_get_single_valued_attr(ac->msg, attr,
+					 ac->req->operation);
+	if (el == NULL) {
+		/* we are not affected */
+		return LDB_SUCCESS;
+	}
+
+	if (el->num_values > 1) {
+		ldb_asprintf_errstring(
+			ldb,
+		        "samldb: %s has %u values, should be single-valued!",
+			attr, el->num_values);
+		return LDB_ERR_CONSTRAINT_VIOLATION;
+	} else if (el->num_values == 0) {
+		ldb_asprintf_errstring(
+			ldb,
+			"samldb: new value for %s "
+			"not provided for mandatory, single-valued attribute!",
+			attr);
+		return LDB_ERR_OBJECT_CLASS_VIOLATION;
+	}
+
+
+	if (el->values[0].length == 0) {
+		ldb_asprintf_errstring(
+			ldb,
+			"samldb: %s is of zero length, should have a value!",
+			attr);
+		return LDB_ERR_OBJECT_CLASS_VIOLATION;
+	}
+
+	*value = (char *)el->values[0].data;
+
+	return LDB_SUCCESS;
+}
+
 static int samldb_unique_attr_check(struct samldb_ctx *ac, const char *attr,
 				    const char *attr_conflict,
 				    struct ldb_dn *base_dn)
-- 
2.23.0

