[Patch] Improve generation of obfuscated message-id



Hi all,

a while ago we introduced obfuscated message-id headers (see bugzilla #738155 and related messages in the 
balsa list).

The message-id now is basically a base64-encoded hash value, which may contain the '+' and '/' characters 
explicitly allowed by RFC 5322.  However, I noticed that if a DSN is requested, some MTA's seem to use this 
message-id verbatim as ENVID parameter (see RFC 3461).  In this parameter, though, the '+' character is /not/ 
allowed and must be escaped.  As a result, the receiving MTA /may/ reject the message if the ENVID contains 
an unescaped +.

Although this is a bug in the sending MTA, IMO it would be better to adjust the way the message-id is 
created.  The attached patch uses the first 240 bits (30 bytes) of the random hash to create a somewhat 
formatted, base32-encoded message-id (see e.g. in this message).

Opinions?

I wish you all a merry Christmas!

Cheers,
Albrecht.
diff --git a/libbalsa/send.c b/libbalsa/send.c
index d38a00b..01487ce 100644
--- a/libbalsa/send.c
+++ b/libbalsa/send.c
@@ -1953,6 +1953,18 @@ libbalsa_message_postpone(LibBalsaMessage * message,
 }
 
 
+static inline gchar
+base32_char(guint8 val)
+{
+       val &= 0x1f;
+       if (val <= 25) {
+               return val + 'A';
+       } else {
+               return val + '2' - 26;
+       }
+}
+
+
 /* Create a message-id and set it on the mime message.
  */
 static void
@@ -1970,6 +1982,8 @@ libbalsa_set_message_id(GMimeMessage * mime_message)
     guint8 buffer[32];
     gsize buflen;
     gchar *message_id;
+    guint8 *src;
+    gchar *dst;
 
     g_mutex_lock(&mutex);
     if (rand == NULL) {
@@ -1994,15 +2008,28 @@ libbalsa_set_message_id(GMimeMessage * mime_message)
     g_hmac_unref(msg_id_hash);
     g_mutex_unlock(&mutex);
 
-    /* create a msg id string
-     * Note: RFC 5322, sect. 3.6.4 explicitly allows the form
-     *    dot-atom-text "@" dot-atom-text
-     * where dot-atom-text may include all base64 (RFC 1421) chars,
-     * including '+' and '/' */
-    message_id = g_base64_encode(buffer, buflen);
-    memmove(message_id + 23, message_id + 22, strlen(message_id) - 23);
-    message_id[22] = '@';
-
+    /* create a msg id string as base32-encoded string from the first
+     * 30 bytes of the hashed result, and separate the groups by '.'
+     * or '@' */
+    message_id = dst = g_malloc0(54U); /* = (32 / 5) * 9 */
+    src = buffer;
+       while (buflen >= 5U) {
+               *dst++ = base32_char(src[0] >> 3);
+               *dst++ = base32_char((src[0] << 2) + (src[1] >> 6));
+               *dst++ = base32_char(src[1] >> 1);
+               *dst++ = base32_char((src[1] << 4) + (src[2] >> 4));
+               *dst++ = base32_char((src[2] << 1) + (src[3] >> 7));
+               *dst++ = base32_char(src[3] >> 2);
+               *dst++ = base32_char((src[3] << 3) + (src[4] >> 5));
+               *dst++ = base32_char(src[4]);
+               src = &src[5];
+               buflen -= 5U;
+               if (dst == &message_id[(54U / 2U) - 1U]) {
+                       *dst++ = '@';
+               } else if (buflen >= 5U) {
+                       *dst++ = '.';
+               }
+       }
     g_mime_message_set_message_id(mime_message, message_id);
     g_free(message_id);
 }

Attachment: pgpJBEgiQDpj1.pgp
Description: PGP signature



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]