CVE-2020-25722 Ensure the structural objectclass cannot be changed
authorAndrew Bartlett <abartlet@samba.org>
Tue, 19 Oct 2021 22:36:58 +0000 (11:36 +1300)
committerJule Anger <janger@samba.org>
Mon, 8 Nov 2021 09:52:12 +0000 (10:52 +0100)
If the structural objectclass is allowed to change, then the restrictions
locking an object to remaining a user or computer will not be enforcable.

Likewise other LDAP inheritance rules, which allow only certain
child objects can be bypassed, which can in turn allow creation of
(unprivileged) users where only DNS objects were expected.

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

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
selftest/knownfail.d/ldap
selftest/knownfail.d/modify-order
selftest/knownfail.d/uac_mod_lock [deleted file]
selftest/knownfail.d/uac_objectclass_restrict
source4/dsdb/samdb/ldb_modules/objectclass.c

index 545dc93db8e77aa34559311e240845ea2e727560..0331d3687d41a6e27f52505aca16d3edf1da7305 100644 (file)
@@ -1,4 +1,3 @@
 # the attributes too long test returns the wrong error
 ^samba4.ldap.python.+test_attribute_ranges_too_long
 samba4.ldap.python\(ad_dc_default\).*__main__.BasicTests.test_ldapSearchNoAttributes
-^samba4.ldap.python.+test_objectclasses
index e14cd1eb35644d8cbfd5ff28f7af1fd9f8312bec..76d538e1f9cfd89e87b51b3c4f2698fd553270bc 100644 (file)
@@ -1,8 +1,8 @@
 samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_account_locality_device
 samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_container_flags_multivalue
-samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_objectclass
 samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_objectclass2
 samba4.ldap_modify_order.python.+ModifyOrderTests.test_modify_order_singlevalue
 samba4.ldap_modify_order.normal_user.+ModifyOrderTests.test_modify_order_account_locality_device
 samba4.ldap_modify_order.normal_user.+ModifyOrderTests.test_modify_order_container_flags[^_]
+samba4.ldap_modify_order.normal_user.+ModifyOrderTests.test_modify_order_objectclass[^2]
 samba4.ldap_modify_order.normal_user.+ModifyOrderTests.test_modify_order_objectclass2
diff --git a/selftest/knownfail.d/uac_mod_lock b/selftest/knownfail.d/uac_mod_lock
deleted file mode 100644 (file)
index 068a47c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_NORMAL_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_priv_user_UF_NORMAL_ACCOUNT_to_computer_UF_WORKSTATION_TRUST_ACCOUNT_remove_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_NORMAL_ACCOUNT_to_user_UF_NORMAL_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_SERVER_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_SERVER_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_computer_UF_WORKSTATION_TRUST_ACCOUNT_to_user_UF_WORKSTATION_TRUST_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_keep_dollar
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_lock_wp_user_UF_NORMAL_ACCOUNT_to_computer_UF_NORMAL_ACCOUNT_remove_dollar
index c4d4507c833bfbe020e80ca77bc92b6ac0abc016..a9ed5e888cc0bd24e5e76122011898d46320d73e 100644 (file)
@@ -15,7 +15,3 @@
 ^samba4.priv_attrs.strict.python\(ad_dc_default\).__main__.PrivAttrsTests.test_priv_attr_userAccountControl-t4d-user_mod-replace_CC_default_computer\(ad_dc_default\)
 ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_add_computer_sd_cc\(ad_dc_default\)
 ^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_mod_computer_cc\(ad_dc_default\)
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_computer_replace\(ad_dc_default\)
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_NORMAL_ACCOUNT_user_replace\(ad_dc_default\)
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_SERVER_TRUST_ACCOUNT_computer_replace\(ad_dc_default\)
-^samba4.user_account_control.python\(ad_dc_default\).__main__.UserAccountControlTests.test_objectclass_mod_lock_UF_WORKSTATION_TRUST_ACCOUNT_computer_replace\(ad_dc_default\)
index 36ab76e19fc79f215a348ce6545e0f2c21bb2c2e..d8feff0262c19ab83a13124bc02bead01aea088a 100644 (file)
@@ -811,6 +811,7 @@ static int objectclass_do_mod(struct oc_context *ac)
        struct ldb_message_element *oc_el_entry, *oc_el_change;
        struct ldb_val *vals;
        struct ldb_message *msg;
+       const struct dsdb_class *current_structural_objectclass;
        const struct dsdb_class *objectclass;
        unsigned int i, j, k;
        bool found;
@@ -830,6 +831,22 @@ static int objectclass_do_mod(struct oc_context *ac)
                return ldb_operr(ldb);
        }
 
+       /*
+        * Get the current new top-most structural object class
+        *
+        * We must not allow this to change
+        */
+
+       current_structural_objectclass
+               = dsdb_get_last_structural_class(ac->schema,
+                                                oc_el_entry);
+       if (current_structural_objectclass == NULL) {
+               ldb_asprintf_errstring(ldb,
+                                      "objectclass: cannot find current structural objectclass on %s!",
+                                      ldb_dn_get_linearized(ac->search_res->message->dn));
+               return LDB_ERR_OBJECT_CLASS_VIOLATION;
+       }
+
        /* use a new message structure */
        msg = ldb_msg_new(ac);
        if (msg == NULL) {
@@ -939,6 +956,25 @@ static int objectclass_do_mod(struct oc_context *ac)
                        return LDB_ERR_OBJECT_CLASS_VIOLATION;
                }
 
+               /*
+                * Has (so far, we re-check for each and every
+                * "objectclass" in the message) the structural
+                * objectclass changed?
+                */
+
+               if (objectclass != current_structural_objectclass) {
+                       const char *dn
+                               = ldb_dn_get_linearized(ac->search_res->message->dn);
+                       ldb_asprintf_errstring(ldb,
+                                              "objectclass: not permitted "
+                                              "to change the structural "
+                                              "objectClass on %s [%s] => [%s]!",
+                                              dn,
+                                              current_structural_objectclass->lDAPDisplayName,
+                                              objectclass->lDAPDisplayName);
+                       return LDB_ERR_OBJECT_CLASS_VIOLATION;
+               }
+
                /* Check for unrelated objectclasses */
                ret = check_unrelated_objectclasses(ac->module, ac->schema,
                                                    objectclass,