275 lines
7.9 KiB
Diff
275 lines
7.9 KiB
Diff
From df487eb2d713e817660dd3b56bb26ba715fadfea Mon Sep 17 00:00:00 2001
|
|
From: Joseph Sutton <josephsutton@catalyst.net.nz>
|
|
Date: Wed, 16 Feb 2022 16:30:03 +1300
|
|
Subject: [PATCH] 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 <josephsutton@catalyst.net.nz>
|
|
---
|
|
common/ldb_msg.c | 165 ++++++++++++++++++++++++++++++++++++++-
|
|
include/ldb.h | 24 ++++++
|
|
2 files changed, 185 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/common/ldb_msg.c b/common/ldb_msg.c
|
|
index 44d3b29e9a7..9cd7998e21c 100644
|
|
--- a/common/ldb_msg.c
|
|
+++ b/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/include/ldb.h b/include/ldb.h
|
|
index 129beefeaf5..63d8aedd672 100644
|
|
--- a/include/ldb.h
|
|
+++ b/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
|