From b9962c1e5e481191063e75550757c74e63c38039 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Wed, 20 Oct 2021 17:20:54 +1300 Subject: [PATCH] CVE-2020-25722 s4/dsdb/pwd_hash: rework pwdLastSet bypass 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 Reviewed-by: Andrew Bartlett --- .../dsdb/samdb/ldb_modules/password_hash.c | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index c285e2d0457..348696a895c 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -2247,23 +2247,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) { + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(msg->elements[i].name, + "pwdLastSet") == 0) { + count++; + el = &msg->elements[i]; + } + } + if (count != 1) { return LDB_ERR_CONSTRAINT_VIOLATION; } - el2 = ldb_msg_find_element(msg, "pwdLastSet"); - if (el2 == NULL) { - return LDB_ERR_CONSTRAINT_VIOLATION; - } - if (el1 != el2) { + + if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) { return LDB_ERR_CONSTRAINT_VIOLATION; }