CVE-2020-25722 s4/dsdb/pwd_hash: rework pwdLastSet bypass
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Wed, 20 Oct 2021 04:20:54 +0000 (17:20 +1300)
committerJule Anger <janger@samba.org>
Mon, 8 Nov 2021 09:52:11 +0000 (10:52 +0100)
This tightens the logic a bit, in that a message with trailing DELETE
elements is no longer accepted when the bypass flag is set. In any case
this is an unlikely scenario as this is an internal flag set by a private
control in pdb_samba_dsdb_replace_by_sam().

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

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/dsdb/samdb/ldb_modules/password_hash.c

index 5f033f9622b2c48fce21a803ba9bcb8392df5ff5..9fa2e36ba90db0e14306707ad6a48fed8cd09dcd 100644 (file)
@@ -2227,23 +2227,31 @@ static int setup_last_set_field(struct setup_password_fields_io *io)
        }
 
        if (io->ac->pwd_last_set_bypass) {
-               struct ldb_message_element *el1 = NULL;
-               struct ldb_message_element *el2 = NULL;
-
+               struct ldb_message_element *el = NULL;
+               size_t i;
+               size_t count = 0;
+               /*
+                * This is a message from pdb_samba_dsdb_replace_by_sam()
+                *
+                * We want to ensure there is only one pwdLastSet element, and
+                * it isn't deleting.
+                */
                if (msg == NULL) {
                        return LDB_ERR_CONSTRAINT_VIOLATION;
                }
 
-               el1 = dsdb_get_single_valued_attr(msg, "pwdLastSet",
-                                                 io->ac->req->operation);
-               if (el1 == NULL) {
-                       return LDB_ERR_CONSTRAINT_VIOLATION;
+               for (i = 0; i < msg->num_elements; i++) {
+                       if (ldb_attr_cmp(msg->elements[i].name,
+                                        "pwdLastSet") == 0) {
+                               count++;
+                               el = &msg->elements[i];
+                       }
                }
-               el2 = ldb_msg_find_element(msg, "pwdLastSet");
-               if (el2 == NULL) {
+               if (count != 1) {
                        return LDB_ERR_CONSTRAINT_VIOLATION;
                }
-               if (el1 != el2) {
+
+               if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
                        return LDB_ERR_CONSTRAINT_VIOLATION;
                }