]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
CVE-2026-58221: s4:dsdb: provide dsdb_audit_{log_attributes,operation_human_readable...
authorStefan Metzmacher <metze@samba.org>
Mon, 29 Jun 2026 17:09:28 +0000 (19:09 +0200)
committerBjoern Jacke <bjacke@samba.org>
Tue, 28 Jul 2026 15:56:37 +0000 (15:56 +0000)
They are useful outside of audit_log.c soon.

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

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
source4/dsdb/samdb/ldb_modules/audit_log.c
source4/dsdb/samdb/ldb_modules/audit_util.c
source4/dsdb/samdb/ldb_modules/tests/test_audit_log.c

index c944a84b36080495c17107de0ef1d52fef1d58c7..3aad76a914a2e7c8ee40870234f1ec3013333fb8 100644 (file)
@@ -867,185 +867,6 @@ static char *password_change_human_readable(
        TALLOC_FREE(ctx);
        return log_entry;
 }
-/*
- * @brief Generate a human readable string, detailing attributes in a message
- *
- * For modify operations each attribute is prefixed with the action.
- * Normal values are enclosed in []
- * Base64 values are enclosed in {}
- * Truncated values are indicated by three trailing dots "..."
- *
- * @param[in]  ldb       the ldb_context
- * @param[out] buffer    the attributes will be appended to the buffer.
- *                       assumed to have been allocated via talloc.
- * @param[in]  operation the operation type
- * @param[in]  message   the message to process
- *
- * @return a pointer to buffer
- *
- */
-static char *log_attributes(
-       struct ldb_context *ldb,
-       char *buffer,
-       enum ldb_request_type operation,
-       const struct ldb_message *message)
-{
-       size_t i, j;
-       for (i=0;i<message->num_elements;i++) {
-               if (i > 0) {
-                       buffer = talloc_asprintf_append_buffer(buffer, " ");
-               }
-
-               if (message->elements[i].name == NULL) {
-                       ldb_debug(
-                               ldb,
-                               LDB_DEBUG_ERROR,
-                               "Error: Invalid element name (NULL) at "
-                               "position %zu", i);
-                       return NULL;
-               }
-
-               if (operation == LDB_MODIFY) {
-                       const char *action =NULL;
-                       action = dsdb_audit_get_modification_action(
-                               message->elements[i].flags);
-                       buffer = talloc_asprintf_append_buffer(
-                               buffer,
-                               "%s: %s ",
-                               action,
-                               message->elements[i].name);
-               } else {
-                       buffer = talloc_asprintf_append_buffer(
-                               buffer,
-                               "%s ",
-                               message->elements[i].name);
-               }
-
-               if (dsdb_audit_redact_attribute(message->elements[i].name)) {
-                       /*
-                        * Do not log the value of any secret or password
-                        * attributes
-                        */
-                       buffer = talloc_asprintf_append_buffer(
-                               buffer,
-                               "[REDACTED SECRET ATTRIBUTE]");
-                       continue;
-               }
-
-               for (j=0;j<message->elements[i].num_values;j++) {
-                       struct ldb_val v;
-                       bool use_b64_encode = false;
-                       size_t length;
-                       if (j > 0) {
-                               buffer = talloc_asprintf_append_buffer(
-                                       buffer,
-                                       " ");
-                       }
-
-                       v = message->elements[i].values[j];
-                       length = MIN(MAX_LENGTH, v.length);
-                       use_b64_encode = ldb_should_b64_encode(ldb, &v);
-                       if (use_b64_encode) {
-                               const char *encoded = ldb_base64_encode(
-                                       buffer,
-                                       (char *)v.data,
-                                       length);
-                               buffer = talloc_asprintf_append_buffer(
-                                       buffer,
-                                       "{%s%s}",
-                                       encoded,
-                                       (v.length > MAX_LENGTH ? "..." : ""));
-                       } else {
-                               buffer = talloc_asprintf_append_buffer(
-                                       buffer,
-                                       "[%*.*s%s]",
-                                       (int)length,
-                                       (int)length,
-                                       (char *)v.data,
-                                       (v.length > MAX_LENGTH ? "..." : ""));
-                       }
-               }
-       }
-       return buffer;
-}
-
-/*
- * @brief generate a human readable log entry detailing an ldb operation.
- *
- * Generate a human readable log entry detailing an ldb operation.
- *
- * @param[in] mem_ctx the talloc context owning the returned string.
- * @param[in] module  the ldb module
- * @param[in] request the request
- * @param[in] reply   the result of the operation
- *
- * @return the log entry.
- *
- */
-static char *operation_human_readable(
-       TALLOC_CTX *mem_ctx,
-       struct ldb_module *module,
-       const struct ldb_request *request,
-       const struct ldb_reply *reply)
-{
-       struct ldb_context *ldb = NULL;
-       const char *remote_host = NULL;
-       const struct tsocket_address *remote = NULL;
-       const struct dom_sid *sid = NULL;
-       struct dom_sid_buf user_sid;
-       const char *timestamp = NULL;
-       const char *op_name = NULL;
-       char *log_entry = NULL;
-       const char *dn = NULL;
-       const char *new_dn = NULL;
-       const struct ldb_message *message = NULL;
-
-       TALLOC_CTX *ctx = talloc_new(NULL);
-
-       ldb = ldb_module_get_ctx(module);
-
-       remote_host = dsdb_audit_get_remote_host(ldb, ctx);
-       remote = dsdb_audit_get_remote_address(ldb);
-       if (remote != NULL && dsdb_audit_is_system_session(module)) {
-               sid = dsdb_audit_get_actual_sid(ldb);
-       } else {
-               sid = dsdb_audit_get_user_sid(module);
-       }
-       timestamp = audit_get_timestamp(ctx);
-       op_name = dsdb_audit_get_operation_name(request);
-       dn = dsdb_audit_get_primary_dn(request);
-       new_dn = dsdb_audit_get_secondary_dn(request);
-
-       message = dsdb_audit_get_message(request);
-
-       log_entry = talloc_asprintf(
-               mem_ctx,
-               "[%s] at [%s] status [%s] "
-               "remote host [%s] SID [%s] DN [%s]",
-               op_name,
-               timestamp,
-               ldb_strerror(reply->error),
-               remote_host,
-               dom_sid_str_buf(sid, &user_sid),
-               dn);
-       if (new_dn != NULL) {
-               log_entry = talloc_asprintf_append_buffer(
-                       log_entry,
-                       " New DN [%s]",
-                       new_dn);
-       }
-       if (message != NULL) {
-               log_entry = talloc_asprintf_append_buffer(log_entry,
-                                                         " attributes [");
-               log_entry = log_attributes(ldb,
-                                          log_entry,
-                                          request->operation,
-                                          message);
-               log_entry = talloc_asprintf_append_buffer(log_entry, "]");
-       }
-       TALLOC_FREE(ctx);
-       return log_entry;
-}
 
 /*
  * @brief generate a human readable log entry detailing a replicated update
@@ -1213,7 +1034,7 @@ static void log_standard_operation(
 
        if (CHECK_DEBUGLVLC(DBGC_DSDB_AUDIT, OPERATION_LOG_LVL)) {
                char *entry = NULL;
-               entry = operation_human_readable(
+               entry = dsdb_audit_operation_human_readable(
                        ctx,
                        module,
                        request,
index 11e1b75561627977f0b4aebac63308087f8852ba..33910d7c9a8993f36ce56feecfb4b99cc30898b9 100644 (file)
@@ -716,3 +716,183 @@ failure:
        DBG_ERR("Unable to create ldb attributes JSON audit message\n");
        return attributes;
 }
+
+/*
+ * @brief Generate a human readable string, detailing attributes in a message
+ *
+ * For modify operations each attribute is prefixed with the action.
+ * Normal values are enclosed in []
+ * Base64 values are enclosed in {}
+ * Truncated values are indicated by three trailing dots "..."
+ *
+ * @param[in]  ldb       the ldb_context
+ * @param[out] buffer    the attributes will be appended to the buffer.
+ *                       assumed to have been allocated via talloc.
+ * @param[in]  operation the operation type
+ * @param[in]  message   the message to process
+ *
+ * @return a pointer to buffer
+ *
+ */
+char *dsdb_audit_log_attributes(
+       struct ldb_context *ldb,
+       char *buffer,
+       enum ldb_request_type operation,
+       const struct ldb_message *message)
+{
+       size_t i, j;
+       for (i=0;i<message->num_elements;i++) {
+               if (i > 0) {
+                       buffer = talloc_asprintf_append_buffer(buffer, " ");
+               }
+
+               if (message->elements[i].name == NULL) {
+                       ldb_debug(
+                               ldb,
+                               LDB_DEBUG_ERROR,
+                               "Error: Invalid element name (NULL) at "
+                               "position %zu", i);
+                       return NULL;
+               }
+
+               if (operation == LDB_MODIFY) {
+                       const char *action =NULL;
+                       action = dsdb_audit_get_modification_action(
+                               message->elements[i].flags);
+                       buffer = talloc_asprintf_append_buffer(
+                               buffer,
+                               "%s: %s ",
+                               action,
+                               message->elements[i].name);
+               } else {
+                       buffer = talloc_asprintf_append_buffer(
+                               buffer,
+                               "%s ",
+                               message->elements[i].name);
+               }
+
+               if (dsdb_audit_redact_attribute(message->elements[i].name)) {
+                       /*
+                        * Do not log the value of any secret or password
+                        * attributes
+                        */
+                       buffer = talloc_asprintf_append_buffer(
+                               buffer,
+                               "[REDACTED SECRET ATTRIBUTE]");
+                       continue;
+               }
+
+               for (j=0;j<message->elements[i].num_values;j++) {
+                       struct ldb_val v;
+                       bool use_b64_encode = false;
+                       size_t length;
+                       if (j > 0) {
+                               buffer = talloc_asprintf_append_buffer(
+                                       buffer,
+                                       " ");
+                       }
+
+                       v = message->elements[i].values[j];
+                       length = MIN(MAX_LENGTH, v.length);
+                       use_b64_encode = ldb_should_b64_encode(ldb, &v);
+                       if (use_b64_encode) {
+                               const char *encoded = ldb_base64_encode(
+                                       buffer,
+                                       (char *)v.data,
+                                       length);
+                               buffer = talloc_asprintf_append_buffer(
+                                       buffer,
+                                       "{%s%s}",
+                                       encoded,
+                                       (v.length > MAX_LENGTH ? "..." : ""));
+                       } else {
+                               buffer = talloc_asprintf_append_buffer(
+                                       buffer,
+                                       "[%*.*s%s]",
+                                       (int)length,
+                                       (int)length,
+                                       (char *)v.data,
+                                       (v.length > MAX_LENGTH ? "..." : ""));
+                       }
+               }
+       }
+       return buffer;
+}
+
+/*
+ * @brief generate a human readable log entry detailing an ldb operation.
+ *
+ * Generate a human readable log entry detailing an ldb operation.
+ *
+ * @param[in] mem_ctx the talloc context owning the returned string.
+ * @param[in] module  the ldb module
+ * @param[in] request the request
+ * @param[in] reply   the result of the operation
+ *
+ * @return the log entry.
+ *
+ */
+char *dsdb_audit_operation_human_readable(
+       TALLOC_CTX *mem_ctx,
+       struct ldb_module *module,
+       const struct ldb_request *request,
+       const struct ldb_reply *reply)
+{
+       struct ldb_context *ldb = NULL;
+       const char *remote_host = NULL;
+       const struct tsocket_address *remote = NULL;
+       const struct dom_sid *sid = NULL;
+       struct dom_sid_buf user_sid;
+       const char *timestamp = NULL;
+       const char *op_name = NULL;
+       char *log_entry = NULL;
+       const char *dn = NULL;
+       const char *new_dn = NULL;
+       const struct ldb_message *message = NULL;
+
+       TALLOC_CTX *ctx = talloc_new(NULL);
+
+       ldb = ldb_module_get_ctx(module);
+
+       remote_host = dsdb_audit_get_remote_host(ldb, ctx);
+       remote = dsdb_audit_get_remote_address(ldb);
+       if (remote != NULL && dsdb_audit_is_system_session(module)) {
+               sid = dsdb_audit_get_actual_sid(ldb);
+       } else {
+               sid = dsdb_audit_get_user_sid(module);
+       }
+       timestamp = audit_get_timestamp(ctx);
+       op_name = dsdb_audit_get_operation_name(request);
+       dn = dsdb_audit_get_primary_dn(request);
+       new_dn = dsdb_audit_get_secondary_dn(request);
+
+       message = dsdb_audit_get_message(request);
+
+       log_entry = talloc_asprintf(
+               mem_ctx,
+               "[%s] at [%s] status [%s] "
+               "remote host [%s] SID [%s] DN [%s]",
+               op_name,
+               timestamp,
+               ldb_strerror(reply->error),
+               remote_host,
+               dom_sid_str_buf(sid, &user_sid),
+               dn);
+       if (new_dn != NULL) {
+               log_entry = talloc_asprintf_append_buffer(
+                       log_entry,
+                       " New DN [%s]",
+                       new_dn);
+       }
+       if (message != NULL) {
+               log_entry = talloc_asprintf_append_buffer(log_entry,
+                                                         " attributes [");
+               log_entry = dsdb_audit_log_attributes(ldb,
+                                                     log_entry,
+                                                     request->operation,
+                                                     message);
+               log_entry = talloc_asprintf_append_buffer(log_entry, "]");
+       }
+       TALLOC_FREE(ctx);
+       return log_entry;
+}
index 2862fa25f3f969fd272306cb4523824dafda7c86..6e7ceaf0cdcfcc53d93c768690ea0ce583fe75b2 100644 (file)
@@ -1615,7 +1615,7 @@ static void test_replicated_update_json(void **state)
 }
 
 /*
- * minimal unit test of operation_human_readable, that ensures that all the
+ * minimal unit test of dsdb_audit_operation_human_readable, that ensures that all the
  * expected attributes and objects are in the json object.
  */
 static void test_operation_hr_empty(void **state)
@@ -1645,7 +1645,7 @@ static void test_operation_hr_empty(void **state)
        reply = talloc_zero(ctx, struct ldb_reply);
        reply->error = LDB_SUCCESS;
 
-       line = operation_human_readable(ctx, module, req, reply);
+       line = dsdb_audit_operation_human_readable(ctx, module, req, reply);
        assert_non_null(line);
 
        /*
@@ -1740,7 +1740,7 @@ static void test_operation_hr(void **state)
        reply = talloc_zero(ctx, struct ldb_reply);
        reply->error = LDB_SUCCESS;
 
-       line = operation_human_readable(ctx, module, req, reply);
+       line = dsdb_audit_operation_human_readable(ctx, module, req, reply);
        assert_non_null(line);
 
        /*
@@ -1851,7 +1851,7 @@ static void test_as_system_operation_hr(void **state)
        reply = talloc_zero(ctx, struct ldb_reply);
        reply->error = LDB_SUCCESS;
 
-       line = operation_human_readable(ctx, module, req, reply);
+       line = dsdb_audit_operation_human_readable(ctx, module, req, reply);
        assert_non_null(line);
 
        /*
@@ -2162,7 +2162,7 @@ static void test_log_attributes(void **state)
        buf = talloc_zero(ctx, char);
        msg = talloc_zero(ctx, struct ldb_message);
 
-       str = log_attributes(ctx, buf, LDB_ADD, msg);
+       str = dsdb_audit_log_attributes(ctx, buf, LDB_ADD, msg);
        assert_string_equal("", str);
 
        TALLOC_FREE(str);
@@ -2175,7 +2175,7 @@ static void test_log_attributes(void **state)
        msg = talloc_zero(ctx, struct ldb_message);
        ldb_msg_add_string(msg, "clearTextPassword", "secret");
 
-       str = log_attributes(ctx, buf, LDB_ADD, msg);
+       str = dsdb_audit_log_attributes(ctx, buf, LDB_ADD, msg);
        assert_string_equal(
                "clearTextPassword [REDACTED SECRET ATTRIBUTE]",
                str);
@@ -2185,7 +2185,7 @@ static void test_log_attributes(void **state)
         * action will be unknown as there are no ACL's set
         */
        buf = talloc_zero(ctx, char);
-       str = log_attributes(ctx, buf, LDB_MODIFY, msg);
+       str = dsdb_audit_log_attributes(ctx, buf, LDB_MODIFY, msg);
        assert_string_equal(
                "unknown: clearTextPassword [REDACTED SECRET ATTRIBUTE]",
                str);
@@ -2200,7 +2200,7 @@ static void test_log_attributes(void **state)
        msg = talloc_zero(ctx, struct ldb_message);
        ldb_msg_add_string(msg, "attribute", "value");
 
-       str = log_attributes(ctx, buf, LDB_ADD, msg);
+       str = dsdb_audit_log_attributes(ctx, buf, LDB_ADD, msg);
        assert_string_equal(
                "attribute [value]",
                str);
@@ -2216,7 +2216,7 @@ static void test_log_attributes(void **state)
        msg = talloc_zero(ctx, struct ldb_message);
        ldb_msg_add_string(msg, "attribute", "value");
 
-       str = log_attributes(ctx, buf, LDB_MODIFY, msg);
+       str = dsdb_audit_log_attributes(ctx, buf, LDB_MODIFY, msg);
        assert_string_equal(
                "unknown: attribute [value]",
                str);
@@ -2234,7 +2234,7 @@ static void test_log_attributes(void **state)
        ldb_msg_add_string(msg, "attribute02", "value02");
        ldb_msg_add_string(msg, "attribute02", "value03");
 
-       str = log_attributes(ctx, buf, LDB_MODIFY, msg);
+       str = dsdb_audit_log_attributes(ctx, buf, LDB_MODIFY, msg);
        assert_string_equal(
                "unknown: attribute01 [value01] "
                "unknown: attribute02 [value02] [value03]",
@@ -2251,7 +2251,7 @@ static void test_log_attributes(void **state)
        msg = talloc_zero(ctx, struct ldb_message);
        ldb_msg_add_string(msg, "attribute", "value\n");
 
-       str = log_attributes(ctx, buf, LDB_ADD, msg);
+       str = dsdb_audit_log_attributes(ctx, buf, LDB_ADD, msg);
        assert_string_equal("attribute {dmFsdWUK}", str);
 
        TALLOC_FREE(str);
@@ -2268,7 +2268,7 @@ static void test_log_attributes(void **state)
        memset(lv, 'x', MAX_LENGTH+1);
        ldb_msg_add_string(msg, "attribute", lv);
 
-       str = log_attributes(ctx, buf, LDB_ADD, msg);
+       str = dsdb_audit_log_attributes(ctx, buf, LDB_ADD, msg);
        snprintf(ex, sizeof(ex), "attribute [%.*s...]", MAX_LENGTH, lv);
        assert_string_equal(ex, str);