From 3c34a51da12c4b1fb446f9a384ff57cdc6019632 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 16 Mar 2023 10:00:11 +0100
Subject: [PATCH 17/30] CVE-2023-4154 libcli/security: prepare
 security_descriptor_acl_add() to place the ace at a position

Often it is important to insert an ace at a specific position in the
ACL. As a default we still append by default by using -1, which is the
generic version of passing the number of existing aces.

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

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

(cherry picked from commit c3cb915a67aff6739b72b86d7d139609df309ada)

Conflict: NA
Reference: https://download.samba.org/pub/samba/patches/security/samba-4.17.12-security-2023-10-10.patch
[PATCH 17/30] CVE-2023-4154 libcli/security: prepare
 security_descriptor_acl_add() to place the ace at a position
---
 libcli/security/security_descriptor.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/libcli/security/security_descriptor.c b/libcli/security/security_descriptor.c
index 64c2d027876..8657c797364 100644
--- a/libcli/security/security_descriptor.c
+++ b/libcli/security/security_descriptor.c
@@ -267,9 +267,11 @@ NTSTATUS security_descriptor_for_client(TALLOC_CTX *mem_ctx,
 
 static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd,
 					    bool add_to_sacl,
-					    const struct security_ace *ace)
+					    const struct security_ace *ace,
+					    ssize_t _idx)
 {
 	struct security_acl *acl = NULL;
+	ssize_t idx;
 
 	if (add_to_sacl) {
 		acl = sd->sacl;
@@ -288,15 +290,28 @@ static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd,
 		acl->aces     = NULL;
 	}
 
+	if (_idx < 0) {
+		idx = (acl->num_aces + 1) + _idx;
+	} else {
+		idx = _idx;
+	}
+
+	if (idx < 0) {
+		return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
+	} else if (idx > acl->num_aces) {
+		return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
+	}
+
 	acl->aces = talloc_realloc(acl, acl->aces,
 				   struct security_ace, acl->num_aces+1);
 	if (acl->aces == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	acl->aces[acl->num_aces] = *ace;
+	ARRAY_INSERT_ELEMENT(acl->aces, acl->num_aces, *ace, idx);
+	acl->num_aces++;
 
-	switch (acl->aces[acl->num_aces].type) {
+	switch (acl->aces[idx].type) {
 	case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
 	case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
 	case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
@@ -307,8 +322,6 @@ static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd,
 		break;
 	}
 
-	acl->num_aces++;
-
 	if (add_to_sacl) {
 		sd->sacl = acl;
 		sd->type |= SEC_DESC_SACL_PRESENT;
@@ -327,7 +340,7 @@ static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd,
 NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd,
 				      const struct security_ace *ace)
 {
-	return security_descriptor_acl_add(sd, true, ace);
+	return security_descriptor_acl_add(sd, true, ace, -1);
 }
 
 /*
@@ -337,7 +350,7 @@ NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd,
 NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd,
 				      const struct security_ace *ace)
 {
-	return security_descriptor_acl_add(sd, false, ace);
+	return security_descriptor_acl_add(sd, false, ace, -1);
 }
 
 /*
-- 
2.34.1
