]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Feature] Sync UUID v7 random portion with Log-Tag header
authorVsevolod Stakhov <vsevolod@rspamd.com>
Sat, 14 Feb 2026 19:17:22 +0000 (19:17 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Sat, 14 Feb 2026 19:17:22 +0000 (19:17 +0000)
When an MTA provides a Log-Tag header that overrides the pool UID,
patch the task UUID's random portion (bytes 8-15) to stay in sync.
Uses a fast hash of the tag to derive the bytes while preserving
the UUID v7 variant bits.

src/libserver/protocol.c
src/libutil/util.c
src/libutil/util.h

index a50f0aedaec1f5cac138320f93cf88795c238b10..092c4855dddce6fe5fcbf317a78e1ca388ce8891 100644 (file)
@@ -528,6 +528,8 @@ rspamd_protocol_set_log_tag(struct rspamd_task *task,
                int len = MIN(tag_len, sizeof(task->task_pool->tag.uid) - 1);
                memcpy(task->task_pool->tag.uid, tag, len);
                task->task_pool->tag.uid[len] = '\0';
+               /* Keep UUID random portion in sync with the new log tag */
+               rspamd_uuid_v7_patch_uid(task->task_uuid, tag, tag_len);
        }
 }
 
index 9c1ea18fe9cd2cc7355493919e96cdb81dc716f9..7714195c4b5c9215eba6e43236130f1426318757 100644 (file)
@@ -1667,6 +1667,25 @@ int rspamd_uuid_v7(char uuid_out[37], char *opt_uid_buf, gsize uid_buflen, doubl
        return 0;
 }
 
+void rspamd_uuid_v7_patch_uid(char uuid[37], const char *tag, gsize tag_len)
+{
+       uint8_t bytes[8];
+       char hex[16];
+
+       /* Hash the tag to get 8 bytes for UUID positions 8-15 */
+       uint64_t h = rspamd_cryptobox_fast_hash(tag, tag_len, 0x7569645f763700ULL);
+       memcpy(bytes, &h, sizeof(h));
+
+       /* Preserve variant bits: byte 8 must have top 2 bits = 10 */
+       bytes[0] = 0x80 | (bytes[0] & 0x3f);
+
+       /* Hex-encode and patch into UUID string:
+        * positions 19-22 = bytes 8-9, positions 24-35 = bytes 10-15 */
+       rspamd_encode_hex_buf(bytes, 8, hex, sizeof(hex));
+       memcpy(uuid + 19, hex, 4);
+       memcpy(uuid + 24, hex + 4, 12);
+}
+
 int rspamd_shmem_mkstemp(char *pattern)
 {
        int fd = -1;
index 34b7a685abbba4206588e29bf2f5a76ce1a30d03..0cff29b72478653b11c94f5a5e0e32b1389bbecb 100644 (file)
@@ -390,6 +390,15 @@ void rspamd_random_hex(char *buf, uint64_t len);
  */
 int rspamd_uuid_v7(char uuid_out[37], char *opt_uid_buf, gsize uid_buflen, double timestamp);
 
+/**
+ * Patch UUID v7 random portion (bytes 8-15) to match a new log tag.
+ * Hashes the tag to derive bytes, preserves timestamp and version/variant bits.
+ * @param uuid UUID string to patch in place (36 chars + NUL)
+ * @param tag new log tag value
+ * @param tag_len length of tag
+ */
+void rspamd_uuid_v7_patch_uid(char uuid[37], const char *tag, gsize tag_len);
+
 /**
  * Returns
  * @param pattern pattern to create (should end with some number of X symbols), modified by this function