From 2c34455394cf7bbaf355afb8078959cf3ff2f985 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Feb 2022 12:43:52 +1300 Subject: [PATCH 01/10] CVE-2022-32746 ldb:rdn_name: Use LDB_FLAG_MOD_TYPE() for flags equality check Now unrelated flags will no longer affect the result. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 Signed-off-by: Joseph Sutton --- lib/ldb/modules/rdn_name.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ldb/modules/rdn_name.c b/lib/ldb/modules/rdn_name.c index e69ad9315ae..25cffe07591 100644 --- a/lib/ldb/modules/rdn_name.c +++ b/lib/ldb/modules/rdn_name.c @@ -545,7 +545,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) if (e != NULL) { ldb_asprintf_errstring(ldb, "Modify of 'distinguishedName' on %s not permitted, must use 'rename' operation instead", ldb_dn_get_linearized(req->op.mod.message->dn)); - if (e->flags == LDB_FLAG_MOD_REPLACE) { + if (LDB_FLAG_MOD_TYPE(e->flags) == LDB_FLAG_MOD_REPLACE) { return LDB_ERR_CONSTRAINT_VIOLATION; } else { return LDB_ERR_UNWILLING_TO_PERFORM; -- 2.25.1 From acdf919c4332f5f57a09c10b6a3319d57340f064 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 21 Feb 2022 16:10:32 +1300 Subject: [PATCH 02/10] CVE-2022-32746 ldb: Add flag to mark message element values as shared When making a shallow copy of an ldb message, mark the message elements of the copy as sharing their values with the message elements in the original message. This flag value will be heeded in the next commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 Signed-off-by: Joseph Sutton --- lib/ldb/common/ldb_msg.c | 43 +++++++++++++++++++++++++++++++----- lib/ldb/include/ldb_module.h | 6 +++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c index 57dfc5a04c2..2a9ce384bb9 100644 --- a/lib/ldb/common/ldb_msg.c +++ b/lib/ldb/common/ldb_msg.c @@ -833,11 +833,7 @@ void ldb_msg_sort_elements(struct ldb_message *msg) ldb_msg_element_compare_name); } -/* - shallow copy a message - copying only the elements array so that the caller - can safely add new elements without changing the message -*/ -struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, +static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx, const struct ldb_message *msg) { struct ldb_message *msg2; @@ -863,6 +859,35 @@ failed: return NULL; } +/* + shallow copy a message - copying only the elements array so that the caller + can safely add new elements without changing the message +*/ +struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg) +{ + struct ldb_message *msg2; + unsigned int i; + + msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg); + if (msg2 == NULL) { + return NULL; + } + + for (i = 0; i < msg2->num_elements; ++i) { + /* + * Mark this message's elements as sharing their values with the + * original message, so that we don't inadvertently modify or + * free them. We don't mark the original message element as + * shared, so the original message element should not be + * modified or freed while the shallow copy lives. + */ + struct ldb_message_element *el = &msg2->elements[i]; + el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES; + } + + return msg2; +} /* copy a message, allocating new memory for all parts @@ -873,7 +898,7 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, struct ldb_message *msg2; unsigned int i, j; - msg2 = ldb_msg_copy_shallow(mem_ctx, msg); + msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg); if (msg2 == NULL) return NULL; if (msg2->dn != NULL) { @@ -894,6 +919,12 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, goto failed; } } + + /* + * Since we copied this element's values, we can mark them as + * not shared. + */ + el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES; } return msg2; diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h index 8c1e5ee7936..4c7c85a17f0 100644 --- a/lib/ldb/include/ldb_module.h +++ b/lib/ldb/include/ldb_module.h @@ -96,6 +96,12 @@ struct ldb_module; */ #define LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX 0x100 +/* + * indicates that this element's values are shared with another element (for + * example, in a shallow copy of an ldb_message) and should not be freed + */ +#define LDB_FLAG_INTERNAL_SHARED_VALUES 0x200 + /* an extended match rule that always fails to match */ #define SAMBA_LDAP_MATCH_ALWAYS_FALSE "1.3.6.1.4.1.7165.4.5.1" -- 2.25.1 From 64cd461d24b40fa31cb6bbdbd9c40292943c90fa Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Feb 2022 12:35:13 +1300 Subject: [PATCH 03/10] CVE-2022-32746 ldb: Ensure shallow copy modifications do not affect original message Using the newly added ldb flag, we can now detect when a message has been shallow-copied so that its elements share their values with the original message elements. Then when adding values to the copied message, we now make a copy of the shared values array first. This should prevent a use-after-free that occurred in LDB modules when new values were added to a shallow copy of a message by calling talloc_realloc() on the original values array, invalidating the 'values' pointer in the original message element. The original values pointer can later be used in the database audit logging module which logs database requests, and potentially cause a crash. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 Signed-off-by: Joseph Sutton --- lib/ldb/common/ldb_msg.c | 52 ++++++++++++++++++++++++++++++++------ lib/ldb/include/ldb.h | 6 +++++ source4/dsdb/common/util.c | 20 +++++---------- 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c index 2a9ce384bb9..44d3b29e9a7 100644 --- a/lib/ldb/common/ldb_msg.c +++ b/lib/ldb/common/ldb_msg.c @@ -417,6 +417,47 @@ int ldb_msg_add(struct ldb_message *msg, return LDB_SUCCESS; } +/* + * add a value to a message element + */ +int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx, + struct ldb_message_element *el, + const struct ldb_val *val) +{ + struct ldb_val *vals; + + if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) { + /* + * Another message is using this message element's values array, + * so we don't want to make any modifications to the original + * message, or potentially invalidate its own values by calling + * talloc_realloc(). Make a copy instead. + */ + el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES; + + vals = talloc_array(mem_ctx, struct ldb_val, + el->num_values + 1); + if (vals == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (el->values != NULL) { + memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val)); + } + } else { + vals = talloc_realloc(mem_ctx, el->values, struct ldb_val, + el->num_values + 1); + if (vals == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + el->values = vals; + el->values[el->num_values] = *val; + el->num_values++; + + return LDB_SUCCESS; +} + /* add a value to a message */ @@ -426,7 +467,6 @@ int ldb_msg_add_value(struct ldb_message *msg, struct ldb_message_element **return_el) { struct ldb_message_element *el; - struct ldb_val *vals; int ret; el = ldb_msg_find_element(msg, attr_name); @@ -437,14 +477,10 @@ int ldb_msg_add_value(struct ldb_message *msg, } } - vals = talloc_realloc(msg->elements, el->values, struct ldb_val, - el->num_values+1); - if (!vals) { - return LDB_ERR_OPERATIONS_ERROR; + ret = ldb_msg_element_add_value(msg->elements, el, val); + if (ret != LDB_SUCCESS) { + return ret; } - el->values = vals; - el->values[el->num_values] = *val; - el->num_values++; if (return_el) { *return_el = el; diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h index bc44157eaf4..129beefeaf5 100644 --- a/lib/ldb/include/ldb.h +++ b/lib/ldb/include/ldb.h @@ -1981,6 +1981,12 @@ int ldb_msg_add_empty(struct ldb_message *msg, int flags, struct ldb_message_element **return_el); +/** + add a value to a message element +*/ +int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx, + struct ldb_message_element *el, + const struct ldb_val *val); /** add a element to a ldb_message */ diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index bd59de5cb32..0f22067c960 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -795,7 +795,7 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const char *value) { struct ldb_message_element *el; - struct ldb_val val, *vals; + struct ldb_val val; char *v; unsigned int i; bool found = false; @@ -830,14 +830,10 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, } } - vals = talloc_realloc(msg->elements, el->values, struct ldb_val, - el->num_values + 1); - if (vals == NULL) { + ret = ldb_msg_element_add_value(msg->elements, el, &val); + if (ret != LDB_SUCCESS) { return ldb_oom(sam_ldb); } - el->values = vals; - el->values[el->num_values] = val; - ++(el->num_values); return LDB_SUCCESS; } @@ -851,7 +847,7 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const char *value) { struct ldb_message_element *el; - struct ldb_val val, *vals; + struct ldb_val val; char *v; unsigned int i; bool found = false; @@ -886,14 +882,10 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, } } - vals = talloc_realloc(msg->elements, el->values, struct ldb_val, - el->num_values + 1); - if (vals == NULL) { + ret = ldb_msg_element_add_value(msg->elements, el, &val); + if (ret != LDB_SUCCESS) { return ldb_oom(sam_ldb); } - el->values = vals; - el->values[el->num_values] = val; - ++(el->num_values); return LDB_SUCCESS; } -- 2.25.1 From 14936792a80c090575613a30ba6dba0938d8cdda Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Feb 2022 16:30:03 +1300 Subject: [PATCH 04/10] CVE-2022-32746 ldb: Add functions for appending to an ldb_message Currently, there are many places where we use ldb_msg_add_empty() to add an empty element to a message, and then call ldb_msg_add_value() or similar to add values to that element. However, this performs an unnecessary search of the message's elements to locate the new element. Moreover, if an element with the same attribute name already exists earlier in the message, the values will be added to that element, instead of to the intended newly added element. A similar pattern exists where we add values to a message, and then call ldb_msg_find_element() to locate that message element and sets its flags to (e.g.) LDB_FLAG_MOD_REPLACE. This also performs an unnecessary search, and may locate the wrong message element for setting the flags. To avoid these problems, add functions for appending a value to a message, so that a particular value can be added to the end of a message in a single operation. For ADD requests, it is important that no two message elements share the same attribute name, otherwise things will break. (Normally, ldb_msg_normalize() is called before processing the request to help ensure this.) Thus, we must be careful not to append an attribute to an ADD message, unless we are sure (e.g. through ldb_msg_find_element()) that an existing element for that attribute is not present. These functions will be used in the next commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 Signed-off-by: Joseph Sutton --- lib/ldb/common/ldb_msg.c | 165 ++++++++++++++++++++++++++++++++++++++- lib/ldb/include/ldb.h | 24 ++++++ 2 files changed, 185 insertions(+), 4 deletions(-) diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c index 44d3b29e9a7..9cd7998e21c 100644 --- a/lib/ldb/common/ldb_msg.c +++ b/lib/ldb/common/ldb_msg.c @@ -509,12 +509,15 @@ int ldb_msg_add_steal_value(struct ldb_message *msg, /* - add a string element to a message + add a string element to a message, specifying flags */ -int ldb_msg_add_string(struct ldb_message *msg, - const char *attr_name, const char *str) +int ldb_msg_add_string_flags(struct ldb_message *msg, + const char *attr_name, const char *str, + int flags) { struct ldb_val val; + int ret; + struct ldb_message_element *el = NULL; val.data = discard_const_p(uint8_t, str); val.length = strlen(str); @@ -524,7 +527,25 @@ int ldb_msg_add_string(struct ldb_message *msg, return LDB_SUCCESS; } - return ldb_msg_add_value(msg, attr_name, &val, NULL); + ret = ldb_msg_add_value(msg, attr_name, &val, &el); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (flags != 0) { + el->flags = flags; + } + + return LDB_SUCCESS; +} + +/* + add a string element to a message +*/ +int ldb_msg_add_string(struct ldb_message *msg, + const char *attr_name, const char *str) +{ + return ldb_msg_add_string_flags(msg, attr_name, str, 0); } /* @@ -586,6 +607,142 @@ int ldb_msg_add_fmt(struct ldb_message *msg, return ldb_msg_add_steal_value(msg, attr_name, &val); } +static int ldb_msg_append_value_impl(struct ldb_message *msg, + const char *attr_name, + const struct ldb_val *val, + int flags, + struct ldb_message_element **return_el) +{ + struct ldb_message_element *el = NULL; + int ret; + + ret = ldb_msg_add_empty(msg, attr_name, flags, &el); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_msg_element_add_value(msg->elements, el, val); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (return_el != NULL) { + *return_el = el; + } + + return LDB_SUCCESS; +} + +/* + append a value to a message +*/ +int ldb_msg_append_value(struct ldb_message *msg, + const char *attr_name, + const struct ldb_val *val, + int flags) +{ + return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL); +} + +/* + append a value to a message, stealing it into the 'right' place +*/ +int ldb_msg_append_steal_value(struct ldb_message *msg, + const char *attr_name, + struct ldb_val *val, + int flags) +{ + int ret; + struct ldb_message_element *el = NULL; + + ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el); + if (ret == LDB_SUCCESS) { + talloc_steal(el->values, val->data); + } + return ret; +} + +/* + append a string element to a message, stealing it into the 'right' place +*/ +int ldb_msg_append_steal_string(struct ldb_message *msg, + const char *attr_name, char *str, + int flags) +{ + struct ldb_val val; + + val.data = (uint8_t *)str; + val.length = strlen(str); + + if (val.length == 0) { + /* allow empty strings as non-existent attributes */ + return LDB_SUCCESS; + } + + return ldb_msg_append_steal_value(msg, attr_name, &val, flags); +} + +/* + append a string element to a message +*/ +int ldb_msg_append_string(struct ldb_message *msg, + const char *attr_name, const char *str, int flags) +{ + struct ldb_val val; + + val.data = discard_const_p(uint8_t, str); + val.length = strlen(str); + + if (val.length == 0) { + /* allow empty strings as non-existent attributes */ + return LDB_SUCCESS; + } + + return ldb_msg_append_value(msg, attr_name, &val, flags); +} + +/* + append a DN element to a message + WARNING: this uses the linearized string from the dn, and does not + copy the string. +*/ +int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name, + struct ldb_dn *dn, int flags) +{ + char *str = ldb_dn_alloc_linearized(msg, dn); + + if (str == NULL) { + /* we don't want to have unknown DNs added */ + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_msg_append_steal_string(msg, attr_name, str, flags); +} + +/* + append a printf formatted element to a message +*/ +int ldb_msg_append_fmt(struct ldb_message *msg, int flags, + const char *attr_name, const char *fmt, ...) +{ + struct ldb_val val; + va_list ap; + char *str = NULL; + + va_start(ap, fmt); + str = talloc_vasprintf(msg, fmt, ap); + va_end(ap); + + if (str == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + val.data = (uint8_t *)str; + val.length = strlen(str); + + return ldb_msg_append_steal_value(msg, attr_name, &val, flags); +} + /* compare two ldb_message_element structures assumes case sensitive comparison diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h index 129beefeaf5..63d8aedd672 100644 --- a/lib/ldb/include/ldb.h +++ b/lib/ldb/include/ldb.h @@ -2002,12 +2002,36 @@ int ldb_msg_add_steal_value(struct ldb_message *msg, struct ldb_val *val); int ldb_msg_add_steal_string(struct ldb_message *msg, const char *attr_name, char *str); +int ldb_msg_add_string_flags(struct ldb_message *msg, + const char *attr_name, const char *str, + int flags); int ldb_msg_add_string(struct ldb_message *msg, const char *attr_name, const char *str); int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name, struct ldb_dn *dn); int ldb_msg_add_fmt(struct ldb_message *msg, const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +/** + append a element to a ldb_message +*/ +int ldb_msg_append_value(struct ldb_message *msg, + const char *attr_name, + const struct ldb_val *val, + int flags); +int ldb_msg_append_steal_value(struct ldb_message *msg, + const char *attr_name, + struct ldb_val *val, + int flags); +int ldb_msg_append_steal_string(struct ldb_message *msg, + const char *attr_name, char *str, + int flags); +int ldb_msg_append_string(struct ldb_message *msg, + const char *attr_name, const char *str, + int flags); +int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name, + struct ldb_dn *dn, int flags); +int ldb_msg_append_fmt(struct ldb_message *msg, int flags, + const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(4,5); /** compare two message elements - return 0 on match -- 2.25.1 From bcfe458af4ccc870328c38e60f98354afed48069 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Mon, 21 Feb 2022 16:27:37 +1300 Subject: [PATCH 05/10] CVE-2022-32746 ldb: Make use of functions for appending to an ldb_message This aims to minimise usage of the error-prone pattern of searching for a just-added message element in order to make modifications to it (and potentially finding the wrong element). BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 Signed-off-by: Joseph Sutton --- lib/ldb/ldb_map/ldb_map.c | 5 +- lib/ldb/ldb_map/ldb_map_inbound.c | 9 +- lib/ldb/modules/rdn_name.c | 22 +--- source3/passdb/pdb_samba_dsdb.c | 14 +-- source4/dns_server/dnsserver_common.c | 12 +- source4/dsdb/common/util.c | 114 ++++++++++++++---- source4/dsdb/samdb/ldb_modules/descriptor.c | 10 +- source4/dsdb/samdb/ldb_modules/objectguid.c | 20 +-- .../dsdb/samdb/ldb_modules/partition_init.c | 14 +-- .../dsdb/samdb/ldb_modules/repl_meta_data.c | 24 +--- source4/dsdb/samdb/ldb_modules/samldb.c | 78 +++++------- .../samdb/ldb_modules/tombstone_reanimate.c | 12 +- source4/nbt_server/wins/winsdb.c | 13 +- source4/rpc_server/lsa/dcesrv_lsa.c | 55 +++------ source4/winbind/idmap.c | 10 +- 15 files changed, 183 insertions(+), 229 deletions(-) diff --git a/lib/ldb/ldb_map/ldb_map.c b/lib/ldb/ldb_map/ldb_map.c index b453dff80d2..c7b0c228631 100644 --- a/lib/ldb/ldb_map/ldb_map.c +++ b/lib/ldb/ldb_map/ldb_map.c @@ -946,10 +946,7 @@ struct ldb_request *map_build_fixup_req(struct map_context *ac, if ( ! dn || ! ldb_dn_validate(msg->dn)) { goto failed; } - if (ldb_msg_add_empty(msg, IS_MAPPED, LDB_FLAG_MOD_REPLACE, NULL) != 0) { - goto failed; - } - if (ldb_msg_add_string(msg, IS_MAPPED, dn) != 0) { + if (ldb_msg_append_string(msg, IS_MAPPED, dn, LDB_FLAG_MOD_REPLACE) != 0) { goto failed; } diff --git a/lib/ldb/ldb_map/ldb_map_inbound.c b/lib/ldb/ldb_map/ldb_map_inbound.c index 324295737da..50b9427c26c 100644 --- a/lib/ldb/ldb_map/ldb_map_inbound.c +++ b/lib/ldb/ldb_map/ldb_map_inbound.c @@ -569,12 +569,9 @@ static int map_modify_do_local(struct map_context *ac) /* No local record present, add it instead */ /* Add local 'IS_MAPPED' */ /* TODO: use GUIDs here instead */ - if (ldb_msg_add_empty(ac->local_msg, IS_MAPPED, - LDB_FLAG_MOD_ADD, NULL) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } - ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED, - ac->remote_req->op.mod.message->dn); + ret = ldb_msg_append_linearized_dn(ac->local_msg, IS_MAPPED, + ac->remote_req->op.mod.message->dn, + LDB_FLAG_MOD_ADD); if (ret != 0) { return LDB_ERR_OPERATIONS_ERROR; } diff --git a/lib/ldb/modules/rdn_name.c b/lib/ldb/modules/rdn_name.c index 25cffe07591..3cb62bf567b 100644 --- a/lib/ldb/modules/rdn_name.c +++ b/lib/ldb/modules/rdn_name.c @@ -308,16 +308,10 @@ static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares) } rdn_val = ldb_val_dup(msg, rdn_val_p); - if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { + if (ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { goto error; } - if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) { - goto error; - } - if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { - goto error; - } - if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) { + if (ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { goto error; } @@ -466,11 +460,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) if (ret != 0) { return ldb_module_oom(module); } - ret = ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_ADD, NULL); - if (ret != 0) { - return ldb_module_oom(module); - } - ret = ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL); + ret = ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_ADD); if (ret != 0) { return ldb_module_oom(module); } @@ -479,11 +469,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) if (ret != 0) { return ldb_module_oom(module); } - ret = ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_ADD, NULL); - if (ret != 0) { - return ldb_module_oom(module); - } - ret = ldb_msg_add_value(msg, "name", &rdn_val, NULL); + ret = ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_ADD); if (ret != 0) { return ldb_module_oom(module); } diff --git a/source3/passdb/pdb_samba_dsdb.c b/source3/passdb/pdb_samba_dsdb.c index 4f1d2f697f0..d9c31e57186 100644 --- a/source3/passdb/pdb_samba_dsdb.c +++ b/source3/passdb/pdb_samba_dsdb.c @@ -2776,18 +2776,10 @@ static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m, } msg->num_elements = 0; - ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", - LDB_FLAG_MOD_REPLACE, NULL); + ret = ldb_msg_append_value(msg, "trustAuthOutgoing", + &new_val, LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { - DEBUG(0, ("ldb_msg_add_empty() failed\n")); - TALLOC_FREE(tmp_ctx); - ldb_transaction_cancel(state->ldb); - return false; - } - ret = ldb_msg_add_value(msg, "trustAuthOutgoing", - &new_val, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("ldb_msg_add_value() failed\n")); + DEBUG(0, ("ldb_msg_append_value() failed\n")); TALLOC_FREE(tmp_ctx); ldb_transaction_cancel(state->ldb); return false; diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c index 71aeee8169d..03f76d4a871 100644 --- a/source4/dns_server/dnsserver_common.c +++ b/source4/dns_server/dnsserver_common.c @@ -1124,15 +1124,9 @@ WERROR dns_common_replace(struct ldb_context *samdb, } if (was_tombstoned || become_tombstoned) { - ret = ldb_msg_add_empty(msg, "dNSTombstoned", - LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - werr = DNS_ERR(SERVER_FAILURE); - goto exit; - } - - ret = ldb_msg_add_fmt(msg, "dNSTombstoned", "%s", - become_tombstoned ? "TRUE" : "FALSE"); + ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE, + "dNSTombstoned", "%s", + become_tombstoned ? "TRUE" : "FALSE"); if (ret != LDB_SUCCESS) { werr = DNS_ERR(SERVER_FAILURE); goto exit; diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 0f22067c960..f8299e371ae 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -903,6 +903,16 @@ int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct l return ldb_msg_add_string(msg, attr_name, s); } +int samdb_msg_add_int_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, + const char *attr_name, int v, int flags) +{ + const char *s = talloc_asprintf(mem_ctx, "%d", v); + if (s == NULL) { + return ldb_oom(sam_ldb); + } + return ldb_msg_add_string_flags(msg, attr_name, s, flags); +} + /* * Add an unsigned int element to a message * @@ -921,6 +931,12 @@ int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v); } +int samdb_msg_add_uint_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, + const char *attr_name, unsigned int v, int flags) +{ + return samdb_msg_add_int_flags(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags); +} + /* add a (signed) int64_t element to a message */ @@ -952,6 +968,68 @@ int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v); } +/* + append a int element to a message +*/ +int samdb_msg_append_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, + const char *attr_name, int v, int flags) +{ + const char *s = talloc_asprintf(mem_ctx, "%d", v); + if (s == NULL) { + return ldb_oom(sam_ldb); + } + return ldb_msg_append_string(msg, attr_name, s, flags); +} + +/* + * Append an unsigned int element to a message + * + * The issue here is that we have not yet first cast to int32_t explicitly, + * before we cast to an signed int to printf() into the %d or cast to a + * int64_t before we then cast to a long long to printf into a %lld. + * + * There are *no* unsigned integers in Active Directory LDAP, even the RID + * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities. + * (See the schema, and the syntax definitions in schema_syntax.c). + * + */ +int samdb_msg_append_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, + const char *attr_name, unsigned int v, int flags) +{ + return samdb_msg_append_int(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags); +} + +/* + append a (signed) int64_t element to a message +*/ +int samdb_msg_append_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, + const char *attr_name, int64_t v, int flags) +{ + const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v); + if (s == NULL) { + return ldb_oom(sam_ldb); + } + return ldb_msg_append_string(msg, attr_name, s, flags); +} + +/* + * Append an unsigned int64_t (uint64_t) element to a message + * + * The issue here is that we have not yet first cast to int32_t explicitly, + * before we cast to an signed int to printf() into the %d or cast to a + * int64_t before we then cast to a long long to printf into a %lld. + * + * There are *no* unsigned integers in Active Directory LDAP, even the RID + * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities. + * (See the schema, and the syntax definitions in schema_syntax.c). + * + */ +int samdb_msg_append_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, + const char *attr_name, uint64_t v, int flags) +{ + return samdb_msg_append_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v, flags); +} + /* add a samr_Password element to a message */ @@ -2780,15 +2858,8 @@ NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, tdo_msg->num_elements = 0; TALLOC_FREE(tdo_msg->elements); - ret = ldb_msg_add_empty(tdo_msg, "trustAuthIncoming", - LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ldb_transaction_cancel(ldb); - TALLOC_FREE(frame); - return NT_STATUS_NO_MEMORY; - } - ret = ldb_msg_add_value(tdo_msg, "trustAuthIncoming", - &new_val, NULL); + ret = ldb_msg_append_value(tdo_msg, "trustAuthIncoming", + &new_val, LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { ldb_transaction_cancel(ldb); TALLOC_FREE(frame); @@ -3153,6 +3224,7 @@ int dsdb_find_guid_by_dn(struct ldb_context *ldb, /* adds the given GUID to the given ldb_message. This value is added for the given attr_name (may be either "objectGUID" or "parentGUID"). + This function is used in processing 'add' requests. */ int dsdb_msg_add_guid(struct ldb_message *msg, struct GUID *guid, @@ -5637,7 +5709,8 @@ int dsdb_user_obj_set_defaults(struct ldb_context *ldb, } /** - * Sets 'sAMAccountType on user object based on userAccountControl + * Sets 'sAMAccountType on user object based on userAccountControl. + * This function is used in processing both 'add' and 'modify' requests. * @param ldb Current ldb_context * @param usr_obj ldb_message representing User object * @param user_account_control Value for userAccountControl flags @@ -5649,21 +5722,19 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message * { int ret; uint32_t account_type; - struct ldb_message_element *el; account_type = ds_uf2atype(user_account_control); if (account_type == 0) { ldb_set_errstring(ldb, "dsdb: Unrecognized account type!"); return LDB_ERR_UNWILLING_TO_PERFORM; } - ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj, - "sAMAccountType", - account_type); + ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj, + "sAMAccountType", + account_type, + LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(usr_obj, "sAMAccountType"); - el->flags = LDB_FLAG_MOD_REPLACE; if (account_type_p) { *account_type_p = account_type; @@ -5673,7 +5744,8 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message * } /** - * Determine and set primaryGroupID based on userAccountControl value + * Determine and set primaryGroupID based on userAccountControl value. + * This function is used in processing both 'add' and 'modify' requests. * @param ldb Current ldb_context * @param usr_obj ldb_message representing User object * @param user_account_control Value for userAccountControl flags @@ -5685,17 +5757,15 @@ int dsdb_user_obj_set_primary_group_id(struct ldb_context *ldb, struct ldb_messa { int ret; uint32_t rid; - struct ldb_message_element *el; rid = ds_uf2prim_group_rid(user_account_control); - ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj, - "primaryGroupID", rid); + ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj, + "primaryGroupID", rid, + LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(usr_obj, "primaryGroupID"); - el->flags = LDB_FLAG_MOD_REPLACE; if (group_rid_p) { *group_rid_p = rid; diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 0f221b794d4..aef2e284dc7 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -914,14 +914,8 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); } - ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor", - LDB_FLAG_MOD_REPLACE, - &sd_element); - if (ret != LDB_SUCCESS) { - return ldb_oom(ldb); - } - ret = ldb_msg_add_value(msg, "nTSecurityDescriptor", - sd, NULL); + ret = ldb_msg_append_value(msg, "nTSecurityDescriptor", + sd, LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ldb_oom(ldb); } diff --git a/source4/dsdb/samdb/ldb_modules/objectguid.c b/source4/dsdb/samdb/ldb_modules/objectguid.c index 093d6ed74ca..cfc89184ff6 100644 --- a/source4/dsdb/samdb/ldb_modules/objectguid.c +++ b/source4/dsdb/samdb/ldb_modules/objectguid.c @@ -41,7 +41,6 @@ */ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) { - struct ldb_message_element *el; char *s; int ret; @@ -54,16 +53,13 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) return LDB_ERR_OPERATIONS_ERROR; } - ret = ldb_msg_add_string(msg, attr, s); + /* always set as replace. This works because on add ops, the flag + is ignored */ + ret = ldb_msg_append_string(msg, attr, s, LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(msg, attr); - /* always set as replace. This works because on add ops, the flag - is ignored */ - el->flags = LDB_FLAG_MOD_REPLACE; - return LDB_SUCCESS; } @@ -73,23 +69,19 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) static int add_uint64_element(struct ldb_context *ldb, struct ldb_message *msg, const char *attr, uint64_t v) { - struct ldb_message_element *el; int ret; if (ldb_msg_find_element(msg, attr) != NULL) { return LDB_SUCCESS; } - ret = samdb_msg_add_uint64(ldb, msg, msg, attr, v); + /* always set as replace. This works because on add ops, the flag + is ignored */ + ret = samdb_msg_append_uint64(ldb, msg, msg, attr, v, LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(msg, attr); - /* always set as replace. This works because on add ops, the flag - is ignored */ - el->flags = LDB_FLAG_MOD_REPLACE; - return LDB_SUCCESS; } diff --git a/source4/dsdb/samdb/ldb_modules/partition_init.c b/source4/dsdb/samdb/ldb_modules/partition_init.c index 58c65ccedd0..484b5bffb27 100644 --- a/source4/dsdb/samdb/ldb_modules/partition_init.c +++ b/source4/dsdb/samdb/ldb_modules/partition_init.c @@ -742,10 +742,6 @@ int partition_create(struct ldb_module *module, struct ldb_request *req) } mod_msg->dn = ldb_dn_new(mod_msg, ldb, DSDB_PARTITION_DN); - ret = ldb_msg_add_empty(mod_msg, DSDB_PARTITION_ATTR, LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - return ret; - } casefold_dn = ldb_dn_get_casefold(dn); @@ -785,18 +781,16 @@ int partition_create(struct ldb_module *module, struct ldb_request *req) } partition_record = talloc_asprintf(mod_msg, "%s:%s", casefold_dn, filename); - ret = ldb_msg_add_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record); + ret = ldb_msg_append_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record, + LDB_FLAG_MOD_ADD); if (ret != LDB_SUCCESS) { return ret; } if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) { /* this new partition is a partial replica */ - ret = ldb_msg_add_empty(mod_msg, "partialReplica", LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - return ret; - } - ret = ldb_msg_add_fmt(mod_msg, "partialReplica", "%s", ldb_dn_get_linearized(dn)); + ret = ldb_msg_append_fmt(mod_msg, LDB_FLAG_MOD_ADD, + "partialReplica", "%s", ldb_dn_get_linearized(dn)); if (ret != LDB_SUCCESS) { return ret; } diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index 4949e691a86..a39550e9e85 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -3888,22 +3888,12 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are ldb_operr(ldb)); } - if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { + if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { talloc_free(ares); return ldb_module_done(ac->req, NULL, NULL, ldb_oom(ldb)); } - if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { - talloc_free(ares); - return ldb_module_done(ac->req, NULL, NULL, - ldb_oom(ldb)); - } - if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { - talloc_free(ares); - return ldb_module_done(ac->req, NULL, NULL, - ldb_oom(ldb)); - } - if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { + if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { talloc_free(ares); return ldb_module_done(ac->req, NULL, NULL, ldb_oom(ldb)); @@ -5161,16 +5151,10 @@ static int replmd_name_modify(struct replmd_replicated_request *ar, goto failed; } - if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { - goto failed; - } - if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { - goto failed; - } - if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { + if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { goto failed; } - if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { + if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { goto failed; } diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 24971d521aa..b89d93910fd 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -1103,14 +1103,11 @@ static int samldb_rodc_add(struct samldb_ctx *ac) return LDB_ERR_OTHER; found: - ret = ldb_msg_add_empty(ac->msg, "msDS-SecondaryKrbTgtNumber", - LDB_FLAG_INTERNAL_DISABLE_VALIDATION, NULL); - if (ret != LDB_SUCCESS) { - return ldb_operr(ldb); - } - ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, - "msDS-SecondaryKrbTgtNumber", krbtgt_number); + ldb_msg_remove_attr(ac->msg, "msDS-SecondaryKrbTgtNumber"); + ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, + "msDS-SecondaryKrbTgtNumber", krbtgt_number, + LDB_FLAG_INTERNAL_DISABLE_VALIDATION); if (ret != LDB_SUCCESS) { return ldb_operr(ldb); } @@ -1792,7 +1789,7 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) struct ldb_context *ldb = ldb_module_get_ctx(ac->module); void *skip_allocate_sids = ldb_get_opaque(ldb, "skip_allocate_sids"); - struct ldb_message_element *el, *el2; + struct ldb_message_element *el; struct dom_sid *sid; int ret; @@ -1926,23 +1923,17 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) /* "isCriticalSystemObject" might be set */ if (user_account_control & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) { - ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", - "TRUE"); + ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject", + "TRUE", LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el2 = ldb_msg_find_element(ac->msg, - "isCriticalSystemObject"); - el2->flags = LDB_FLAG_MOD_REPLACE; } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) { - ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", - "FALSE"); + ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject", + "FALSE", LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el2 = ldb_msg_find_element(ac->msg, - "isCriticalSystemObject"); - el2->flags = LDB_FLAG_MOD_REPLACE; } /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */ @@ -2018,14 +2009,13 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); return LDB_ERR_UNWILLING_TO_PERFORM; } - ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, - "sAMAccountType", - account_type); + ret = samdb_msg_add_uint_flags(ldb, ac->msg, ac->msg, + "sAMAccountType", + account_type, + LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el2 = ldb_msg_find_element(ac->msg, "sAMAccountType"); - el2->flags = LDB_FLAG_MOD_REPLACE; } break; } @@ -2945,26 +2935,23 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) } if (old_atype != new_atype) { - ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, - "sAMAccountType", new_atype); + ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, + "sAMAccountType", new_atype, + LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(ac->msg, "sAMAccountType"); - el->flags = LDB_FLAG_MOD_REPLACE; } /* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */ if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) { /* "lockoutTime" reset as per MS-SAMR 3.1.1.8.10 */ ldb_msg_remove_attr(ac->msg, "lockoutTime"); - ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime", - (NTTIME)0); + ret = samdb_msg_append_uint64(ldb, ac->msg, ac->msg, "lockoutTime", + (NTTIME)0, LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(ac->msg, "lockoutTime"); - el->flags = LDB_FLAG_MOD_REPLACE; } /* @@ -2975,14 +2962,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) * creating the attribute. */ if (old_is_critical != new_is_critical || old_atype != new_atype) { - ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", - new_is_critical ? "TRUE": "FALSE"); + ret = ldb_msg_append_string(ac->msg, "isCriticalSystemObject", + new_is_critical ? "TRUE": "FALSE", + LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(ac->msg, - "isCriticalSystemObject"); - el->flags = LDB_FLAG_MOD_REPLACE; } if (!ldb_msg_find_element(ac->msg, "primaryGroupID") && @@ -2995,14 +2980,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) } } - ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, - "primaryGroupID", new_pgrid); + ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, + "primaryGroupID", new_pgrid, + LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(ac->msg, - "primaryGroupID"); - el->flags = LDB_FLAG_MOD_REPLACE; } /* Propagate eventual "userAccountControl" attribute changes */ @@ -3205,13 +3188,12 @@ static int samldb_lockout_time(struct samldb_ctx *ac) /* lockoutTime == 0 resets badPwdCount */ ldb_msg_remove_attr(ac->msg, "badPwdCount"); - ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, - "badPwdCount", 0); + ret = samdb_msg_append_int(ldb, ac->msg, ac->msg, + "badPwdCount", 0, + LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(ac->msg, "badPwdCount"); - el->flags = LDB_FLAG_MOD_REPLACE; return LDB_SUCCESS; } @@ -3309,13 +3291,11 @@ static int samldb_group_type_change(struct samldb_ctx *ac) ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); return LDB_ERR_UNWILLING_TO_PERFORM; } - ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType", - account_type); + ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, "sAMAccountType", + account_type, LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(ac->msg, "sAMAccountType"); - el->flags = LDB_FLAG_MOD_REPLACE; return LDB_SUCCESS; } diff --git a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c index 64e05195798..5ad45f28f15 100644 --- a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +++ b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c @@ -294,14 +294,13 @@ static int tr_prepare_attributes(struct tr_context *ac) return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "reanimate: Unrecognized account type!"); } - ret = samdb_msg_add_uint(ldb, ac->mod_msg, ac->mod_msg, - "sAMAccountType", account_type); + ret = samdb_msg_append_uint(ldb, ac->mod_msg, ac->mod_msg, + "sAMAccountType", account_type, + LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "reanimate: Failed to add sAMAccountType to restored object."); } - el = ldb_msg_find_element(ac->mod_msg, "sAMAccountType"); - el->flags = LDB_FLAG_MOD_REPLACE; /* Default values set by Windows */ ret = samdb_find_or_add_attribute(ldb, ac->mod_msg, @@ -324,12 +323,11 @@ static int tr_prepare_attributes(struct tr_context *ac) return ret; } - ret = ldb_msg_add_string(ac->mod_msg, "objectCategory", value); + ret = ldb_msg_append_string(ac->mod_msg, "objectCategory", value, + LDB_FLAG_MOD_ADD); if (ret != LDB_SUCCESS) { return ret; } - el = ldb_msg_find_element(ac->mod_msg, "objectCategory"); - el->flags = LDB_FLAG_MOD_ADD; } return LDB_SUCCESS; diff --git a/source4/nbt_server/wins/winsdb.c b/source4/nbt_server/wins/winsdb.c index e4a7c2042ed..2a05e96bca4 100644 --- a/source4/nbt_server/wins/winsdb.c +++ b/source4/nbt_server/wins/winsdb.c @@ -102,13 +102,11 @@ uint64_t winsdb_set_maxVersion(struct winsdb_handle *h, uint64_t newMaxVersion) msg->dn = dn; - ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL); + ret = ldb_msg_append_string(msg, "objectClass", "winsMaxVersion", + LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) goto failed; - ret = ldb_msg_add_string(msg, "objectClass", "winsMaxVersion"); - if (ret != LDB_SUCCESS) goto failed; - ret = ldb_msg_add_empty(msg, "maxVersion", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) goto failed; - ret = ldb_msg_add_fmt(msg, "maxVersion", "%llu", (long long)newMaxVersion); + ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE, + "maxVersion", "%llu", (long long)newMaxVersion); if (ret != LDB_SUCCESS) goto failed; ret = ldb_modify(wins_db, msg); @@ -779,8 +777,7 @@ static struct ldb_message *winsdb_message(struct ldb_context *ldb, ret |= ldb_msg_add_winsdb_addr(msg, rec, "address", rec->addresses[i]); } if (rec->registered_by) { - ret |= ldb_msg_add_empty(msg, "registeredBy", 0, NULL); - ret |= ldb_msg_add_string(msg, "registeredBy", rec->registered_by); + ret |= ldb_msg_append_string(msg, "registeredBy", rec->registered_by, 0); } if (ret != LDB_SUCCESS) goto failed; return msg; diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 185e0044de1..575bf845539 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -1760,12 +1760,7 @@ static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx, goto done; } - ret = ldb_msg_add_empty(dest, attribute, flags, NULL); - if (ret != LDB_SUCCESS) { - return NT_STATUS_NO_MEMORY; - } - - ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value); + ret = samdb_msg_append_uint(sam_ldb, dest, dest, attribute, value, flags); if (ret != LDB_SUCCESS) { return NT_STATUS_NO_MEMORY; } @@ -1856,13 +1851,7 @@ static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx, continue; } - ret = ldb_msg_add_empty(msg, attribute, - LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - return NT_STATUS_NO_MEMORY; - } - - ret = ldb_msg_add_value(msg, attribute, &v, NULL); + ret = ldb_msg_append_value(msg, attribute, &v, LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { return NT_STATUS_NO_MEMORY; } @@ -2148,28 +2137,30 @@ static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call, } if (add_incoming || del_incoming) { - ret = ldb_msg_add_empty(msg, "trustAuthIncoming", - LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - return NT_STATUS_NO_MEMORY; - } if (add_incoming) { - ret = ldb_msg_add_value(msg, "trustAuthIncoming", - &trustAuthIncoming, NULL); + ret = ldb_msg_append_value(msg, "trustAuthIncoming", + &trustAuthIncoming, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } + } else { + ret = ldb_msg_add_empty(msg, "trustAuthIncoming", + LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { return NT_STATUS_NO_MEMORY; } } } if (add_outgoing || del_outgoing) { - ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", - LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - return NT_STATUS_NO_MEMORY; - } if (add_outgoing) { - ret = ldb_msg_add_value(msg, "trustAuthOutgoing", - &trustAuthOutgoing, NULL); + ret = ldb_msg_append_value(msg, "trustAuthOutgoing", + &trustAuthOutgoing, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } + } else { + ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", + LDB_FLAG_MOD_REPLACE, NULL); if (ret != LDB_SUCCESS) { return NT_STATUS_NO_MEMORY; } @@ -4617,14 +4608,8 @@ static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_stat goto done; } - ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo", - LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo", - &ft_blob, NULL); + ret = ldb_msg_append_value(msg, "msDS-TrustForestTrustInfo", + &ft_blob, LDB_FLAG_MOD_REPLACE); if (ret != LDB_SUCCESS) { status = NT_STATUS_NO_MEMORY; goto done; diff --git a/source4/winbind/idmap.c b/source4/winbind/idmap.c index c4039be473a..c6375f8357a 100644 --- a/source4/winbind/idmap.c +++ b/source4/winbind/idmap.c @@ -672,14 +672,8 @@ static NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, vals[1].data = (uint8_t *)hwm_string; vals[1].length = strlen(hwm_string); } else { - ret = ldb_msg_add_empty(hwm_msg, "xidNumber", LDB_FLAG_MOD_ADD, - NULL); - if (ret != LDB_SUCCESS) { - status = NT_STATUS_NONE_MAPPED; - goto failed; - } - - ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string); + ret = ldb_msg_append_string(hwm_msg, "xidNumber", hwm_string, + LDB_FLAG_MOD_ADD); if (ret != LDB_SUCCESS) { status = NT_STATUS_NONE_MAPPED; -- 2.25.1 From 9b481fafa14cdd55dfabf120ada8f2bc94ca5d86 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 14 Jun 2022 15:43:26 +1200 Subject: [PATCH 06/10] ldb: Release LDB 2.6.1 * CVE-2022-32746 Use-after-free occurring in database audit logging module (bug 15009) Signed-off-by: Andrew Bartlett --- lib/ldb/ABI/ldb-2.6.1.sigs | 291 ++++++++++++++++++++++++++++++ lib/ldb/ABI/pyldb-util-2.6.1.sigs | 3 + lib/ldb/wscript | 2 +- 3 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 lib/ldb/ABI/ldb-2.6.1.sigs create mode 100644 lib/ldb/ABI/pyldb-util-2.6.1.sigs diff --git a/lib/ldb/ABI/ldb-2.6.1.sigs b/lib/ldb/ABI/ldb-2.6.1.sigs new file mode 100644 index 00000000000..40388d9e330 --- /dev/null +++ b/lib/ldb/ABI/ldb-2.6.1.sigs @@ -0,0 +1,291 @@ +ldb_add: int (struct ldb_context *, const struct ldb_message *) +ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *) +ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...) +ldb_attr_casefold: char *(TALLOC_CTX *, const char *) +ldb_attr_dn: int (const char *) +ldb_attr_in_list: int (const char * const *, const char *) +ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *) +ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *) +ldb_base64_decode: int (char *) +ldb_base64_encode: char *(TALLOC_CTX *, const char *, int) +ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *) +ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val) +ldb_binary_encode_string: char *(TALLOC_CTX *, const char *) +ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *) +ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t) +ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t) +ldb_check_critical_controls: int (struct ldb_control **) +ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) +ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *) +ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **) +ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *) +ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *) +ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) +ldb_debug_add: void (struct ldb_context *, const char *, ...) +ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level) +ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...) +ldb_delete: int (struct ldb_context *, struct ldb_dn *) +ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...) +ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...) +ldb_dn_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val) +ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *) +ldb_dn_check_special: bool (struct ldb_dn *, const char *) +ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *) +ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *) +ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val) +ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *) +ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *) +ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *) +ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *) +ldb_dn_get_casefold: const char *(struct ldb_dn *) +ldb_dn_get_comp_num: int (struct ldb_dn *) +ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int) +ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int) +ldb_dn_get_extended_comp_num: int (struct ldb_dn *) +ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *) +ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int) +ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *) +ldb_dn_get_linearized: const char *(struct ldb_dn *) +ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *) +ldb_dn_get_rdn_name: const char *(struct ldb_dn *) +ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *) +ldb_dn_has_extended: bool (struct ldb_dn *) +ldb_dn_is_null: bool (struct ldb_dn *) +ldb_dn_is_special: bool (struct ldb_dn *) +ldb_dn_is_valid: bool (struct ldb_dn *) +ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *) +ldb_dn_minimise: bool (struct ldb_dn *) +ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *) +ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...) +ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int) +ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int) +ldb_dn_remove_extended_components: void (struct ldb_dn *) +ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *) +ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val) +ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *) +ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *) +ldb_dn_validate: bool (struct ldb_dn *) +ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *) +ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int) +ldb_errstring: const char *(struct ldb_context *) +ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **) +ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_filter_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *) +ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *) +ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_create_perms: unsigned int (struct ldb_context *) +ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_event_context: struct tevent_context *(struct ldb_context *) +ldb_get_flags: unsigned int (struct ldb_context *) +ldb_get_opaque: void *(struct ldb_context *, const char *) +ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *) +ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *) +ldb_global_init: int (void) +ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *) +ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *) +ldb_handle_use_global_event_context: void (struct ldb_handle *) +ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) +ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *) +ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *) +ldb_ldif_message_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *) +ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **) +ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *) +ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *) +ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *) +ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *) +ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **) +ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *) +ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *) +ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *) +ldb_load_modules: int (struct ldb_context *, const char **) +ldb_map_add: int (struct ldb_module *, struct ldb_request *) +ldb_map_delete: int (struct ldb_module *, struct ldb_request *) +ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *) +ldb_map_modify: int (struct ldb_module *, struct ldb_request *) +ldb_map_rename: int (struct ldb_module *, struct ldb_request *) +ldb_map_search: int (struct ldb_module *, struct ldb_request *) +ldb_match_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *) +ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) +ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *) +ldb_match_msg_objectclass: int (const struct ldb_message *, const char *) +ldb_mod_register_control: int (struct ldb_module *, const char *) +ldb_modify: int (struct ldb_context *, const struct ldb_message *) +ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *) +ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **) +ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int) +ldb_module_flags: uint32_t (struct ldb_context *) +ldb_module_get_ctx: struct ldb_context *(struct ldb_module *) +ldb_module_get_name: const char *(struct ldb_module *) +ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *) +ldb_module_get_private: void *(struct ldb_module *) +ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *) +ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **) +ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *) +ldb_module_next: struct ldb_module *(struct ldb_module *) +ldb_module_popt_options: struct poptOption **(struct ldb_context *) +ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **) +ldb_module_send_referral: int (struct ldb_request *, char *) +ldb_module_set_next: void (struct ldb_module *, struct ldb_module *) +ldb_module_set_private: void (struct ldb_module *, void *) +ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type) +ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *) +ldb_modules_load: int (const char *, const char *) +ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int) +ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **) +ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...) +ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *) +ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *) +ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *) +ldb_msg_add_string: int (struct ldb_message *, const char *, const char *) +ldb_msg_add_string_flags: int (struct ldb_message *, const char *, const char *, int) +ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **) +ldb_msg_append_fmt: int (struct ldb_message *, int, const char *, const char *, ...) +ldb_msg_append_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *, int) +ldb_msg_append_steal_string: int (struct ldb_message *, const char *, char *, int) +ldb_msg_append_steal_value: int (struct ldb_message *, const char *, struct ldb_val *, int) +ldb_msg_append_string: int (struct ldb_message *, const char *, const char *, int) +ldb_msg_append_value: int (struct ldb_message *, const char *, const struct ldb_val *, int) +ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *) +ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *) +ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) +ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *) +ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *) +ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *) +ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **) +ldb_msg_element_add_value: int (TALLOC_CTX *, struct ldb_message_element *, const struct ldb_val *) +ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *) +ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *) +ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *) +ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *) +ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double) +ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int) +ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t) +ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *) +ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int) +ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t) +ldb_msg_find_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t) +ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_t) +ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *) +ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *) +ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *) +ldb_msg_new: struct ldb_message *(TALLOC_CTX *) +ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **) +ldb_msg_remove_attr: void (struct ldb_message *, const char *) +ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *) +ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *) +ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *) +ldb_msg_sort_elements: void (struct ldb_message *) +ldb_next_del_trans: int (struct ldb_module *) +ldb_next_end_trans: int (struct ldb_module *) +ldb_next_init: int (struct ldb_module *) +ldb_next_prepare_commit: int (struct ldb_module *) +ldb_next_read_lock: int (struct ldb_module *) +ldb_next_read_unlock: int (struct ldb_module *) +ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *) +ldb_next_request: int (struct ldb_module *, struct ldb_request *) +ldb_next_start_trans: int (struct ldb_module *) +ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_options_copy: const char **(TALLOC_CTX *, const char **) +ldb_options_find: const char *(struct ldb_context *, const char **, const char *) +ldb_options_get: const char **(struct ldb_context *) +ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t) +ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *) +ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **) +ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *) +ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *) +ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *) +ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *) +ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t) +ldb_register_backend: int (const char *, ldb_connect_fn, bool) +ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *) +ldb_register_hook: int (ldb_hook_fn) +ldb_register_module: int (const struct ldb_module_ops *) +ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *) +ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *) +ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *) +ldb_req_get_custom_flags: uint32_t (struct ldb_request *) +ldb_req_is_untrusted: bool (struct ldb_request *) +ldb_req_location: const char *(struct ldb_request *) +ldb_req_mark_trusted: void (struct ldb_request *) +ldb_req_mark_untrusted: void (struct ldb_request *) +ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t) +ldb_req_set_location: void (struct ldb_request *, const char *) +ldb_request: int (struct ldb_context *, struct ldb_request *) +ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *) +ldb_request_done: int (struct ldb_request *, int) +ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *) +ldb_request_get_status: int (struct ldb_request *) +ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *) +ldb_request_set_state: void (struct ldb_request *, int) +ldb_reset_err_string: void (struct ldb_context *) +ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***) +ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *) +ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *) +ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *) +ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *, const char *, unsigned int, const struct ldb_schema_syntax *, struct ldb_schema_attribute *) +ldb_schema_attribute_remove: void (struct ldb_context *, const char *) +ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int) +ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *) +ldb_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *) +ldb_schema_set_override_indexlist: void (struct ldb_context *, bool) +ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...) +ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *) +ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *) +ldb_set_create_perms: void (struct ldb_context *, unsigned int) +ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *) +ldb_set_debug_stderr: int (struct ldb_context *) +ldb_set_default_dns: void (struct ldb_context *) +ldb_set_errstring: void (struct ldb_context *, const char *) +ldb_set_event_context: void (struct ldb_context *, struct tevent_context *) +ldb_set_flags: void (struct ldb_context *, unsigned int) +ldb_set_modules_dir: void (struct ldb_context *, const char *) +ldb_set_opaque: int (struct ldb_context *, const char *, void *) +ldb_set_require_private_event_context: void (struct ldb_context *) +ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int) +ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *) +ldb_set_utf8_default: void (struct ldb_context *) +ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t)) +ldb_setup_wellknown_attributes: int (struct ldb_context *) +ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *) +ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *) +ldb_strerror: const char *(int) +ldb_string_to_time: time_t (const char *) +ldb_string_utc_to_time: time_t (const char *) +ldb_timestring: char *(TALLOC_CTX *, time_t) +ldb_timestring_utc: char *(TALLOC_CTX *, time_t) +ldb_transaction_cancel: int (struct ldb_context *) +ldb_transaction_cancel_noerr: int (struct ldb_context *) +ldb_transaction_commit: int (struct ldb_context *) +ldb_transaction_prepare_commit: int (struct ldb_context *) +ldb_transaction_start: int (struct ldb_context *) +ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *) +ldb_unpack_data_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int) +ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *) +ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *) +ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *) +ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) +ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *) +ldb_val_string_cmp: int (const struct ldb_val *, const char *) +ldb_val_to_time: int (const struct ldb_val *, time_t *) +ldb_valid_attr_name: int (const char *) +ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list) +ldb_wait: int (struct ldb_handle *, enum ldb_wait_type) diff --git a/lib/ldb/ABI/pyldb-util-2.6.1.sigs b/lib/ldb/ABI/pyldb-util-2.6.1.sigs new file mode 100644 index 00000000000..164a806b2ff --- /dev/null +++ b/lib/ldb/ABI/pyldb-util-2.6.1.sigs @@ -0,0 +1,3 @@ +pyldb_Dn_FromDn: PyObject *(struct ldb_dn *) +pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **) +pyldb_check_type: bool (PyObject *, const char *) diff --git a/lib/ldb/wscript b/lib/ldb/wscript index 63d0ceaf234..60bb7cf48b3 100644 --- a/lib/ldb/wscript +++ b/lib/ldb/wscript @@ -2,7 +2,7 @@ APPNAME = 'ldb' # For Samba 4.17.x -VERSION = '2.6.0' +VERSION = '2.6.1' import sys, os -- 2.25.1 From 8de845d1c2c751386587e8d820384bef20f8b565 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Wed, 16 Feb 2022 17:03:10 +1300 Subject: [PATCH 07/10] CVE-2022-32745 s4/dsdb/samldb: Check for empty values array This avoids potentially trying to access the first element of an empty array. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 Signed-off-by: Joseph Sutton --- source4/dsdb/samdb/ldb_modules/samldb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index b89d93910fd..3ecbd00e68e 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -751,7 +751,7 @@ static int samldb_schema_add_handle_linkid(struct samldb_ctx *ac) return ret; } - if (el == NULL) { + if (el == NULL || el->num_values == 0) { return LDB_SUCCESS; } @@ -919,7 +919,7 @@ static int samldb_schema_add_handle_mapiid(struct samldb_ctx *ac) return ret; } - if (el == NULL) { + if (el == NULL || el->num_values == 0) { return LDB_SUCCESS; } -- 2.25.1 From ab8c0067bf046cad908df75b15c609341e937bf2 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 17 Feb 2022 11:11:53 +1300 Subject: [PATCH 08/10] CVE-2022-32745 s4/dsdb/util: Use correct value for loop count limit Currently, we can crash the server by sending a large number of values of a specific attribute (such as sAMAccountName) spread across a few message elements. If val_count is larger than the total number of elements, we get an access beyond the elements array. Similarly, we can include unrelated message elements prior to the message elements of the attribute in question, so that not all of the attribute's values are copied into the returned elements values array. This can cause the server to access uninitialised data, likely resulting in a crash or unexpected behaviour. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 Signed-off-by: Joseph Sutton --- source4/dsdb/samdb/ldb_modules/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c index 405febf0b3d..14947746837 100644 --- a/source4/dsdb/samdb/ldb_modules/util.c +++ b/source4/dsdb/samdb/ldb_modules/util.c @@ -1546,7 +1546,7 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, v = _el->values; - for (i = 0; i < val_count; i++) { + for (i = 0; i < msg->num_elements; i++) { if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { if ((operation == LDB_MODIFY) && (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) -- 2.25.1 From 72b7b07e617ebef4f533a5bc48a0b958645ab0cd Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 17 Feb 2022 11:13:38 +1300 Subject: [PATCH 09/10] CVE-2022-32745 s4/dsdb/util: Don't call memcpy() with a NULL pointer Doing so is undefined behaviour. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 Signed-off-by: Joseph Sutton --- source4/dsdb/samdb/ldb_modules/util.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c index 14947746837..35ae110b5ef 100644 --- a/source4/dsdb/samdb/ldb_modules/util.c +++ b/source4/dsdb/samdb/ldb_modules/util.c @@ -1548,15 +1548,19 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, for (i = 0; i < msg->num_elements; i++) { if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { + const struct ldb_message_element *tmp_el = &msg->elements[i]; if ((operation == LDB_MODIFY) && - (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) + (LDB_FLAG_MOD_TYPE(tmp_el->flags) == LDB_FLAG_MOD_DELETE)) { continue; } + if (tmp_el->values == NULL || tmp_el->num_values == 0) { + continue; + } memcpy(v, - msg->elements[i].values, - msg->elements[i].num_values); - v += msg->elements[i].num_values; + tmp_el->values, + tmp_el->num_values); + v += tmp_el->num_values; } } -- 2.25.1 From bb26e931ff73d3591df07a3c78901b1cb286d8c8 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 3 Jun 2022 16:16:31 +1200 Subject: [PATCH 10/10] CVE-2022-32745 s4/dsdb/util: Correctly copy values into message element To use memcpy(), we need to specify the number of bytes to copy, rather than the number of ldb_val structures. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 Signed-off-by: Joseph Sutton --- source4/dsdb/samdb/ldb_modules/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c index 35ae110b5ef..e7fe8f855df 100644 --- a/source4/dsdb/samdb/ldb_modules/util.c +++ b/source4/dsdb/samdb/ldb_modules/util.c @@ -1559,7 +1559,7 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, } memcpy(v, tmp_el->values, - tmp_el->num_values); + tmp_el->num_values * sizeof(*v)); v += tmp_el->num_values; } } -- 2.25.1