[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Fri Sep 16 03:32:01 UTC 2022


The branch, master has been updated
       via  cc64ea24daa CVE-2020-25720 s4:dsdb/descriptor: explain lack of dSHeuristics check
       via  95fe9659574 CVE-2020-25720 s4:dsdb/descriptor: Validate owner SIDs written to security descriptors
       via  acc9999a08f CVE-2020-25720 s4-acl: Omit sDRightsEffective for computers unless all rights are granted
       via  5073d5997cb CVE-2020-25720: s4-acl: Owner no longer has implicit Write DACL
       via  72b8e98252b CVE-2020-25720 s4:ntvfs: Use se_file_access_check() to check file access rights
       via  6dc6ca56bd5 CVE-2020-25720: s4-acl: Adjusted some tests to work with the new behavior
       via  08187833fee CVE-2020-25720: s4-acl: Change behavior of Create Children check
       via  0e1d8929f87 CVE-2020-25720: s4-acl: Move definition of acl_check_self_membership()
       via  c2761a47fd1 CVE-2020-25720 s4-acl: Test Create Child permission should not allow full write to all attributes
       via  2563f85237b CVE-2020-25720 pydsdb: Add AD schema GUID constants
       via  cc709077822 CVE-2020-25720 pydsdb: Add dsHeuristics constant definitions
       via  0af5706b559 CVE-2020-25720 s4/dsdb/util: Add functions for dsHeuristics 28, 29
       via  890d2c5cf5d CVE-2020-25720 python:tests: Ensure that access checks don't succeed
       via  cbbf3fd7412 CVE-2020-25720 s4:tests/sec_descriptor: Add missing security descriptor modify
      from  b4455f04879 s3: libsmb: In cli_posix_open_internal_send() (SMBtrans2:TRANSACT2_SETPATHINFO) check for DFS pathname.

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit cc64ea24daa649dc8de4a212c7abfbe111095655
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Sep 16 14:18:37 2022 +1200

    CVE-2020-25720 s4:dsdb/descriptor: explain lack of dSHeuristics check
    
    It is strange that sDRightsEffective pays no attention to the
    dSHeuristics flags.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Fri Sep 16 03:31:42 UTC 2022 on sn-devel-184

commit 95fe9659574337234616625fc32d5f00035ae7c9
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 5 17:21:42 2022 +1200

    CVE-2020-25720 s4:dsdb/descriptor: Validate owner SIDs written to security descriptors
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit acc9999a08f12d5bff6edb631a9515fe7e5087c3
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 5 19:30:13 2022 +1200

    CVE-2020-25720 s4-acl: Omit sDRightsEffective for computers unless all rights are granted
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 5073d5997cb1d7f654423655e0d1eeb117bdab38
Author: Nadezhda Ivanova <nivanova at symas.com>
Date:   Fri Oct 22 21:33:03 2021 +0300

    CVE-2020-25720: s4-acl: Owner no longer has implicit Write DACL
    
    The implicit right of an object's owner to modify its security
    descriptor no longer exists, according to the new access rules. However,
    we continue to grant this implicit right for fileserver access checks.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Nadezhda Ivanova <nivanova at symas.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 72b8e98252b0231868f04d40456459057126980c
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon Sep 5 14:53:26 2022 +1200

    CVE-2020-25720 s4:ntvfs: Use se_file_access_check() to check file access rights
    
    se_access_check() will be changed in a following commit to remove the
    implicit WRITE_DAC right that comes with being the owner of an object.
    We want to keep this implicit right for file access, and by using
    se_file_access_check() we can preserve the existing behaviour.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 6dc6ca56bd517a5cba85bb4ec120fcfb5feadfb8
Author: Nadezhda Ivanova <nivanova at symas.com>
Date:   Fri Oct 22 21:10:35 2021 +0300

    CVE-2020-25720: s4-acl: Adjusted some tests to work with the new behavior
    
    Test using non-priviledged accounts now need to make sure they have
    WP access on the prvided attributes, or Write-DACL
    Some test create organizational units with a specific SD, and those now
    need the user to have WD or else they give errors
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Nadezhda Ivanova <nivanova at symas.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 08187833fee57a8dba6c67546dfca516cd1f9d7a
Author: Nadezhda Ivanova <nivanova at symas.com>
Date:   Mon Oct 25 13:10:56 2021 +0300

    CVE-2020-25720: s4-acl: Change behavior of Create Children check
    
    Up to now, the rights to modify an attribute were not checked during an LDAP
    add operation. This means that even if a user has no right to modify
    an attribute, they can still specify any value during object creation,
    and the validated writes were not checked.
    This patch changes this behavior. During an add operation,
    a security descriptor is created that does not include the one provided by the
    user, and is used to verify that the user has the right to modify the supplied attributes.
    Exception is made for an object's mandatory attributes, and if the user has Write DACL right,
    further checks are skipped.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Pair-Programmed-With: Joseph Sutton <josephsutton at catalyst.net.nz>
    
    Signed-off-by: Nadezhda Ivanova <nivanova at symas.com>
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 0e1d8929f872708e79edf802e5d2ff847c9b3ee5
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Fri Apr 22 15:01:00 2022 +1200

    CVE-2020-25720: s4-acl: Move definition of acl_check_self_membership()
    
    This allows us to make use of it in acl_add().
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c2761a47fd12cc2a79a02707ed9d778e496b1fd4
Author: Nadezhda Ivanova <nivanova at symas.com>
Date:   Mon Oct 25 11:34:57 2021 +0300

    CVE-2020-25720 s4-acl: Test Create Child permission should not allow full write to all attributes
    
    Up to now, the rights to modify an attribute were not checked during an LDAP
    add operation. This means that even if a user has no right to modify
    an attribute, they can still specify any value during object creation,
    and the validated writes were not checked.
    This patch includes tests for the proposed change of behavior.
    test_add_c3 and c4 pass, because mandatory attributes can still be
    set, and in the old behavior SD permissions were irrelevant
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Pair-Programmed-With: Joseph Sutton <josephsutton at catalyst.net.nz>
    
    Signed-off-by: Nadezhda Ivanova <nivanova at symas.com>
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2563f85237bd4260b7b527f3695f27da4cc61a74
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Sep 14 13:21:34 2022 +1200

    CVE-2020-25720 pydsdb: Add AD schema GUID constants
    
    This helps reduce the profusion of magic constant values in Python
    tests.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit cc709077822a39227174b91ed2345c2bd603f61f
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Tue Sep 6 19:23:13 2022 +1200

    CVE-2020-25720 pydsdb: Add dsHeuristics constant definitions
    
    We want to be able to use these values in Python tests.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 0af5706b559e89c77123ed174b41fd3d01705aa5
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu Apr 28 20:34:36 2022 +1200

    CVE-2020-25720 s4/dsdb/util: Add functions for dsHeuristics 28, 29
    
    These are the newly-added AttributeAuthorizationOnLDAPAdd and
    BlockOwnerImplicitRights.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 890d2c5cf5d47758b5429f87a064f04512ff7136
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Sat Apr 30 13:55:39 2022 +1200

    CVE-2020-25720 python:tests: Ensure that access checks don't succeed
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit cbbf3fd7412ba073b26b0d0a32fe25b343fed5ca
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu Apr 28 21:00:56 2022 +1200

    CVE-2020-25720 s4:tests/sec_descriptor: Add missing security descriptor modify
    
    The variable sub_sddl1 previously went unused, so this call to
    modify_sd_on_dn() was presumably intended to go here.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 libcli/security/access_check.c                    |  167 +-
 libcli/security/access_check.h                    |    8 +
 libds/common/flags.h                              |   16 +
 librpc/idl/security.idl                           |    9 +
 python/samba/tests/security.py                    |    2 +
 selftest/knownfail.d/bug-14810                    |    2 +
 source4/dsdb/pydsdb.c                             |   43 +
 source4/dsdb/samdb/ldb_modules/acl.c              |  531 +++-
 source4/dsdb/samdb/ldb_modules/acl_read.c         |   20 +-
 source4/dsdb/samdb/ldb_modules/acl_util.c         |   44 +-
 source4/dsdb/samdb/ldb_modules/descriptor.c       |  194 +-
 source4/dsdb/samdb/ldb_modules/util.c             |   40 +
 source4/dsdb/samdb/ldb_modules/util.h             |    1 +
 source4/dsdb/samdb/samdb.h                        |   12 +
 source4/dsdb/tests/python/acl.py                  | 3039 ++++++++++++++++++---
 source4/dsdb/tests/python/sec_descriptor.py       |   77 +-
 source4/dsdb/tests/python/user_account_control.py |   25 +-
 source4/libcli/ldap/ldap_controls.c               |    1 +
 source4/ntvfs/posix/pvfs_acl.c                    |    2 +-
 19 files changed, 3685 insertions(+), 548 deletions(-)
 create mode 100644 selftest/knownfail.d/bug-14810


Changeset truncated at 500 lines:

diff --git a/libcli/security/access_check.c b/libcli/security/access_check.c
index f5051b0fa93..7d8eca74c43 100644
--- a/libcli/security/access_check.c
+++ b/libcli/security/access_check.c
@@ -106,7 +106,8 @@ void se_map_standard(uint32_t *access_mask, const struct standard_mapping *mappi
   perform a SEC_FLAG_MAXIMUM_ALLOWED access check
 */
 static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
-					const struct security_token *token)
+					 const struct security_token *token,
+					 enum implicit_owner_rights implicit_owner_rights)
 {
 	uint32_t denied = 0, granted = 0;
 	bool am_owner = false;
@@ -115,7 +116,14 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
 
 	if (sd->dacl == NULL) {
 		if (security_token_has_sid(token, sd->owner_sid)) {
-			granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL;
+			switch (implicit_owner_rights) {
+			case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
+				granted |= SEC_STD_WRITE_DAC;
+				FALL_THROUGH;
+			case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
+				granted |= SEC_STD_READ_CONTROL;
+				break;
+			}
 		}
 		return granted;
 	}
@@ -145,7 +153,14 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
 	}
 
 	if (am_owner && !have_owner_rights_ace) {
-		granted |= SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL;
+		switch (implicit_owner_rights) {
+		case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
+			granted |= SEC_STD_WRITE_DAC;
+			FALL_THROUGH;
+		case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
+			granted |= SEC_STD_READ_CONTROL;
+			break;
+		}
 	}
 
 	for (i = 0;i<sd->dacl->num_aces; i++) {
@@ -183,15 +198,11 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
 	return granted & ~denied;
 }
 
-/*
-  The main entry point for access checking. If returning ACCESS_DENIED
-  this function returns the denied bits in the uint32_t pointed
-  to by the access_granted pointer.
-*/
-NTSTATUS se_access_check(const struct security_descriptor *sd,
-			  const struct security_token *token,
-			  uint32_t access_desired,
-			  uint32_t *access_granted)
+static NTSTATUS se_access_check_implicit_owner(const struct security_descriptor *sd,
+					       const struct security_token *token,
+					       uint32_t access_desired,
+					       uint32_t *access_granted,
+					       enum implicit_owner_rights implicit_owner_rights)
 {
 	uint32_t i;
 	uint32_t bits_remaining;
@@ -206,7 +217,7 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
 	if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
 		uint32_t orig_access_desired = access_desired;
 
-		access_desired |= access_check_max_allowed(sd, token);
+		access_desired |= access_check_max_allowed(sd, token, implicit_owner_rights);
 		access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
 		*access_granted = access_desired;
 		bits_remaining = access_desired;
@@ -251,7 +262,14 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
 		}
 	}
 	if (am_owner && !have_owner_rights_ace) {
-		bits_remaining &= ~(SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL);
+		switch (implicit_owner_rights) {
+		case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
+			bits_remaining &= ~SEC_STD_WRITE_DAC;
+			FALL_THROUGH;
+		case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
+			bits_remaining &= ~SEC_STD_READ_CONTROL;
+			break;
+		}
 	}
 
 	/* check each ace in turn. */
@@ -317,6 +335,23 @@ done:
 	return NT_STATUS_OK;
 }
 
+/*
+  The main entry point for access checking. If returning ACCESS_DENIED
+  this function returns the denied bits in the uint32_t pointed
+  to by the access_granted pointer.
+*/
+NTSTATUS se_access_check(const struct security_descriptor *sd,
+			 const struct security_token *token,
+			 uint32_t access_desired,
+			 uint32_t *access_granted)
+{
+	return se_access_check_implicit_owner(sd,
+					      token,
+					      access_desired,
+					      access_granted,
+					      IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS);
+}
+
 /*
   The main entry point for access checking FOR THE FILE SERVER ONLY !
   If returning ACCESS_DENIED this function returns the denied bits in
@@ -333,10 +368,11 @@ NTSTATUS se_file_access_check(const struct security_descriptor *sd,
 
 	if (!priv_open_requested) {
 		/* Fall back to generic se_access_check(). */
-		return se_access_check(sd,
-				token,
-				access_desired,
-				access_granted);
+		return se_access_check_implicit_owner(sd,
+						      token,
+						      access_desired,
+						      access_granted,
+						      IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS);
 	}
 
 	/*
@@ -349,7 +385,7 @@ NTSTATUS se_file_access_check(const struct security_descriptor *sd,
 	if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
 		uint32_t orig_access_desired = access_desired;
 
-		access_desired |= access_check_max_allowed(sd, token);
+		access_desired |= access_check_max_allowed(sd, token, true);
 		access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
 
 		if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
@@ -366,10 +402,11 @@ NTSTATUS se_file_access_check(const struct security_descriptor *sd,
 			access_desired));
 	}
 
-	status = se_access_check(sd,
-				token,
-				access_desired,
-				access_granted);
+	status = se_access_check_implicit_owner(sd,
+						token,
+						access_desired,
+						access_granted,
+						IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS);
 
 	if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
 		return status;
@@ -478,34 +515,13 @@ static NTSTATUS check_object_specific_access(struct security_ace *ace,
 	return NT_STATUS_OK;
 }
 
-/**
- * @brief Perform directoryservice (DS) related access checks for a given user
- *
- * Perform DS access checks for the user represented by its security_token, on
- * the provided security descriptor. If an tree associating GUID and access
- * required is provided then object access (OA) are checked as well. *
- * @param[in]   sd             The security descritor against which the required
- *                             access are requested
- *
- * @param[in]   token          The security_token associated with the user to
- *                             test
- *
- * @param[in]   access_desired A bitfield of rights that must be granted for the
- *                             given user in the specified SD.
- *
- * If one
- * of the entry in the tree grants all the requested rights for the given GUID
- * FIXME
- * tree can be null if not null it's the
- * Lots of code duplication, it will be united in just one
- * function eventually */
-
-NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
-			     const struct security_token *token,
-			     uint32_t access_desired,
-			     uint32_t *access_granted,
-			     struct object_tree *tree,
-			     struct dom_sid *replace_sid)
+NTSTATUS sec_access_check_ds_implicit_owner(const struct security_descriptor *sd,
+					    const struct security_token *token,
+					    uint32_t access_desired,
+					    uint32_t *access_granted,
+					    struct object_tree *tree,
+					    struct dom_sid *replace_sid,
+					    enum implicit_owner_rights implicit_owner_rights)
 {
 	uint32_t i;
 	uint32_t bits_remaining;
@@ -518,7 +534,7 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
 
 	/* handle the maximum allowed flag */
 	if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
-		access_desired |= access_check_max_allowed(sd, token);
+		access_desired |= access_check_max_allowed(sd, token, implicit_owner_rights);
 		access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
 		*access_granted = access_desired;
 		bits_remaining = access_desired;
@@ -535,7 +551,14 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
 	/* the owner always gets SEC_STD_WRITE_DAC and SEC_STD_READ_CONTROL */
 	if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
 	    security_token_has_sid(token, sd->owner_sid)) {
-		bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
+		switch (implicit_owner_rights) {
+		case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
+			bits_remaining &= ~SEC_STD_WRITE_DAC;
+			FALL_THROUGH;
+		case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
+			bits_remaining &= ~SEC_STD_READ_CONTROL;
+			break;
+		}
 	}
 
 	/* SEC_PRIV_TAKE_OWNERSHIP grants SEC_STD_WRITE_OWNER */
@@ -613,3 +636,41 @@ done:
 
 	return NT_STATUS_OK;
 }
+
+/**
+ * @brief Perform directoryservice (DS) related access checks for a given user
+ *
+ * Perform DS access checks for the user represented by its security_token, on
+ * the provided security descriptor. If an tree associating GUID and access
+ * required is provided then object access (OA) are checked as well. *
+ * @param[in]   sd             The security descritor against which the required
+ *                             access are requested
+ *
+ * @param[in]   token          The security_token associated with the user to
+ *                             test
+ *
+ * @param[in]   access_desired A bitfield of rights that must be granted for the
+ *                             given user in the specified SD.
+ *
+ * If one
+ * of the entry in the tree grants all the requested rights for the given GUID
+ * FIXME
+ * tree can be null if not null it's the
+ * Lots of code duplication, it will be united in just one
+ * function eventually */
+
+NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
+			     const struct security_token *token,
+			     uint32_t access_desired,
+			     uint32_t *access_granted,
+			     struct object_tree *tree,
+			     struct dom_sid *replace_sid)
+{
+	return sec_access_check_ds_implicit_owner(sd,
+						  token,
+						  access_desired,
+						  access_granted,
+						  tree,
+						  replace_sid,
+						  IMPLICIT_OWNER_READ_CONTROL_RIGHTS);
+}
diff --git a/libcli/security/access_check.h b/libcli/security/access_check.h
index 96e33c6624f..e7150914524 100644
--- a/libcli/security/access_check.h
+++ b/libcli/security/access_check.h
@@ -65,6 +65,14 @@ NTSTATUS se_file_access_check(const struct security_descriptor *sd,
 			 uint32_t access_desired,
 			 uint32_t *access_granted);
 
+NTSTATUS sec_access_check_ds_implicit_owner(const struct security_descriptor *sd,
+					    const struct security_token *token,
+					    uint32_t access_desired,
+					    uint32_t *access_granted,
+					    struct object_tree *tree,
+					    struct dom_sid *replace_sid,
+					    enum implicit_owner_rights implicit_owner_rights);
+
 /* modified access check for the purposes of DS security
  * Lots of code duplication, it will be united in just one
  * function eventually */
diff --git a/libds/common/flags.h b/libds/common/flags.h
index 75e04b0c488..c013d2f0f25 100644
--- a/libds/common/flags.h
+++ b/libds/common/flags.h
@@ -237,6 +237,20 @@
 /* wellknown GUIDs for optional directory features */
 #define DS_GUID_FEATURE_RECYCLE_BIN		      "766ddcd8-acd0-445e-f3b9-a7f9b6744f2a"
 
+/* GUIDs for AD schema attributes and classes */
+#define DS_GUID_SCHEMA_ATTR_DEPARTMENT                "bf96794f-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_DNS_HOST_NAME             "72e39547-7b18-11d1-adef-00c04fd8d5cd"
+#define DS_GUID_SCHEMA_ATTR_INSTANCE_TYPE             "bf96798c-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_MS_SFU_30                 "16c5d1d3-35c2-4061-a870-a5cefda804f0"
+#define DS_GUID_SCHEMA_ATTR_NT_SECURITY_DESCRIPTOR    "bf9679e3-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_PRIMARY_GROUP_ID          "bf967a00-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_SERVICE_PRINCIPAL_NAME    "f3a64788-5306-11d1-a9c5-0000f80367c1"
+#define DS_GUID_SCHEMA_ATTR_USER_ACCOUNT_CONTROL      "bf967a68-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_ATTR_USER_PASSWORD             "bf967a6e-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_CLASS_COMPUTER                 "bf967a86-0de6-11d0-a285-00aa003049e2"
+#define DS_GUID_SCHEMA_CLASS_MANAGED_SERVICE_ACCOUNT  "ce206244-5827-4a86-ba1c-1c0c386c1b64"
+#define DS_GUID_SCHEMA_CLASS_USER                     "bf967aba-0de6-11d0-a285-00aa003049e2"
+
 /* dsHeuristics character indexes see MS-ADTS 7.1.1.2.4.1.2 */
 
 #define DS_HR_SUPFIRSTLASTANR                     0x00000001
@@ -258,6 +272,8 @@
 #define DS_HR_KVNOEMUW2K                          0x00000011
 
 #define DS_HR_TWENTIETH_CHAR                      0x00000014
+#define DS_HR_ATTR_AUTHZ_ON_LDAP_ADD              0x0000001C
+#define DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS         0x0000001D
 #define DS_HR_THIRTIETH_CHAR                      0x0000001E
 #define DS_HR_FOURTIETH_CHAR                      0x00000028
 #define DS_HR_FIFTIETH_CHAR                       0x00000032
diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl
index d05e3c3e1b7..2ef34170479 100644
--- a/librpc/idl/security.idl
+++ b/librpc/idl/security.idl
@@ -206,6 +206,15 @@ interface security
 		 SEC_ADS_GENERIC_READ           |
 		 SEC_ADS_GENERIC_ALL_DS);
 
+	/*
+	 * Rights implicitly granted to a user who is an owner of the security
+	 * descriptor being processed.
+	 */
+	typedef enum {
+		IMPLICIT_OWNER_READ_CONTROL_RIGHTS,
+		IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS
+	} implicit_owner_rights;
+
 	/***************************************************************/
 	/* WELL KNOWN SIDS */
 
diff --git a/python/samba/tests/security.py b/python/samba/tests/security.py
index 1dacf78499a..2be58e0962a 100644
--- a/python/samba/tests/security.py
+++ b/python/samba/tests/security.py
@@ -166,3 +166,5 @@ class CheckAccessTests(samba.tests.TestCase):
                 self.assertTrue(isinstance(e, NTSTATUSError))
                 e_num, e_msg = e.args
                 self.assertEqual(num, e_num)
+            else:
+                self.fail()
diff --git a/selftest/knownfail.d/bug-14810 b/selftest/knownfail.d/bug-14810
new file mode 100644
index 00000000000..b96e9904ee7
--- /dev/null
+++ b/selftest/knownfail.d/bug-14810
@@ -0,0 +1,2 @@
+^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_add_computer_cc_normal_bare\(.*\)
+^samba4.user_account_control.python\(.*\).__main__.UserAccountControlTests.test_add_computer_sd_cc\(.*\)
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index 0f3a2bc62bd..7aa1b287d0b 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -1664,6 +1664,36 @@ MODULE_INIT_FUNC(dsdb)
 	ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_NTDSCONN_XLATE);
 	ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_SPN_REGISTRATION);
 
+	/* dsHeuristics character indexes (see MS-ADTS 7.1.1.2.4.1.2) */
+	ADD_DSDB_FLAG(DS_HR_SUPFIRSTLASTANR);
+	ADD_DSDB_FLAG(DS_HR_SUPLASTFIRSTANR);
+	ADD_DSDB_FLAG(DS_HR_DOLISTOBJECT);
+	ADD_DSDB_FLAG(DS_HR_DONICKRES);
+	ADD_DSDB_FLAG(DS_HR_LDAP_USEPERMMOD);
+	ADD_DSDB_FLAG(DS_HR_HIDEDSID);
+	ADD_DSDB_FLAG(DS_HR_BLOCK_ANONYMOUS_OPS);
+	ADD_DSDB_FLAG(DS_HR_ALLOW_ANON_NSPI);
+	ADD_DSDB_FLAG(DS_HR_USER_PASSWORD_SUPPORT);
+	ADD_DSDB_FLAG(DS_HR_TENTH_CHAR);
+	ADD_DSDB_FLAG(DS_HR_SPECIFY_GUID_ON_ADD);
+	ADD_DSDB_FLAG(DS_HR_NO_STANDARD_SD);
+	ADD_DSDB_FLAG(DS_HR_ALLOW_NONSECURE_PWD_OPS);
+	ADD_DSDB_FLAG(DS_HR_NO_PROPAGATE_ON_NOCHANGE);
+	ADD_DSDB_FLAG(DS_HR_COMPUTE_ANR_STATS);
+	ADD_DSDB_FLAG(DS_HR_ADMINSDEXMASK);
+	ADD_DSDB_FLAG(DS_HR_KVNOEMUW2K);
+
+	ADD_DSDB_FLAG(DS_HR_TWENTIETH_CHAR);
+	ADD_DSDB_FLAG(DS_HR_ATTR_AUTHZ_ON_LDAP_ADD);
+	ADD_DSDB_FLAG(DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS);
+	ADD_DSDB_FLAG(DS_HR_THIRTIETH_CHAR);
+	ADD_DSDB_FLAG(DS_HR_FOURTIETH_CHAR);
+	ADD_DSDB_FLAG(DS_HR_FIFTIETH_CHAR);
+	ADD_DSDB_FLAG(DS_HR_SIXTIETH_CHAR);
+	ADD_DSDB_FLAG(DS_HR_SEVENTIETH_CHAR);
+	ADD_DSDB_FLAG(DS_HR_EIGHTIETH_CHAR);
+	ADD_DSDB_FLAG(DS_HR_NINETIETH_CHAR);
+
 	ADD_DSDB_FLAG(NTDSCONN_KCC_GC_TOPOLOGY);
 	ADD_DSDB_FLAG(NTDSCONN_KCC_RING_TOPOLOGY);
 	ADD_DSDB_FLAG(NTDSCONN_KCC_MINIMIZE_HOPS_TOPOLOGY);
@@ -1724,5 +1754,18 @@ MODULE_INIT_FUNC(dsdb)
 	ADD_DSDB_STRING(DS_GUID_SYSTEMS_CONTAINER);
 	ADD_DSDB_STRING(DS_GUID_USERS_CONTAINER);
 
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_DEPARTMENT);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_DNS_HOST_NAME);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_INSTANCE_TYPE);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_MS_SFU_30);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_NT_SECURITY_DESCRIPTOR);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_PRIMARY_GROUP_ID);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_SERVICE_PRINCIPAL_NAME);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_USER_ACCOUNT_CONTROL);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_ATTR_USER_PASSWORD);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_CLASS_COMPUTER);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_CLASS_MANAGED_SERVICE_ACCOUNT);
+	ADD_DSDB_STRING(DS_GUID_SCHEMA_CLASS_USER);
+
 	return m;
 }
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
index 4098ae2d671..dd15dddfb50 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -502,13 +502,24 @@ static int acl_sDRightsEffective(struct ldb_module *module,
 		if (ret == LDB_SUCCESS) {
 			flags |= SECINFO_OWNER | SECINFO_GROUP;
 		}
-		ret = acl_check_access_on_attribute(module,
-						    msg,
-						    sd,
-						    sid,
-						    SEC_STD_WRITE_DAC,
-						    attr,
-						    objectclass);
+
+		/*
+		 * This call is made with
+		 * IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS
+		 * and without reference to the dSHeuristics via
+		 * dsdb_block_owner_implicit_rights().  This is
+		 * probably a Windows bug but for now we match
+		 * exactly.
+		 */
+		ret = acl_check_access_on_attribute_implicit_owner(
+			module,
+			msg,
+			sd,
+			sid,
+			SEC_STD_WRITE_DAC,
+			attr,
+			objectclass,
+			IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS);
 		if (ret == LDB_SUCCESS) {
 			flags |= SECINFO_DACL;
 		}
@@ -523,6 +534,17 @@ static int acl_sDRightsEffective(struct ldb_module *module,
 			flags |= SECINFO_SACL;
 		}
 	}
+
+	if (flags != (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_SACL)) {
+		const struct ldb_message_element *el = samdb_find_attribute(ldb,
+									    sd_msg,
+									    "objectclass",
+									    "computer");
+		if (el != NULL) {
+			return LDB_SUCCESS;
+		}
+	}
+
 	return samdb_msg_add_uint(ldb_module_get_ctx(module), msg, msg,
 				  "sDRightsEffective", flags);
 }
@@ -714,6 +736,8 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx,
 	const struct ldb_val *sam_account_name_val = NULL;
 	struct GUID ntds;
 	char *ntds_guid = NULL;
+	const struct ldb_message *msg = NULL;
+	const struct ldb_message *search_res = NULL;
 
 	static const char *acl_attrs[] = {
 		"samAccountName",
@@ -726,6 +750,12 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx,
 		NULL
 	};
 
+	if (req->operation == LDB_MODIFY) {
+		msg = req->op.mod.message;
+	} else if (req->operation == LDB_ADD) {
+		msg = req->op.add.message;
+	}
+
 	if (implicit_validated_write_control != NULL) {
 		/*
 		 * The validated write control dispenses with ACL
@@ -758,7 +788,7 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx,
 
 		if (ret != LDB_SUCCESS) {
 			dsdb_acl_debug(sd, acl_user_token(module),
-				       req->op.mod.message->dn,
+				       msg->dn,
 				       true,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list