Re: [PATCH 0/2] Use base64 URL safe alphabet for message id generation.

2023-03-04 Thread Kevin J. McCarthy

On Sat, Mar 04, 2023 at 06:33:33PM +0100, Sebastian Andrzej Siewior wrote:

#2 of this mini series uses the safe dictionary for base64 encoding to
use for message-id generation. This bothered me for a while and then I
stumbled uppon issie #400 so it appears to not be just me.

#1 is rather unimportant but allows to decode this safe URL base64
encoded strings if ever needed.


Thank you Sebastian, and again my apologies to everyone for basically 
ignoring #400.


These patches look okay to me.  I've made a couple small indentation and 
spacing fixes to be in line with Mutt code, but otherwise they seem fine.


I'll take another look tomorrow and if I still don't see any issues will 
push to stable for a (well overdue) 2.2.10 release in the next week or 
so.


--
Kevin J. McCarthy
GPG Fingerprint: 8975 A9B3 3AA3 7910 385C  5308 ADEF 7684 8031 6BDA


signature.asc
Description: PGP signature


[PATCH 2/2] Use base64 URL safe alphabet for message id generation.

2023-03-04 Thread Sebastian Andrzej Siewior
The character '/' from base64 alphabet breaks web redirectors if the
message-id from an email is used as part of the URL for redirectors and/
or automatic pointers to an email.

Use the URL safe alphabet from RFC4648 section 5 for message id
generation.

Signed-off-by: Sebastian Andrzej Siewior 
---
 base64.c| 33 +++--
 messageid.c |  4 ++--
 mime.h  |  1 +
 protos.h|  1 +
 sendlib.c   |  9 +
 5 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/base64.c b/base64.c
index 290f384e16957..cc7106f4358b2 100644
--- a/base64.c
+++ b/base64.c
@@ -56,16 +56,15 @@ void mutt_buffer_to_base64 (BUFFER *out, const unsigned 
char *in, size_t len)
   mutt_buffer_fix_dptr (out);
 }
 
-/* raw bytes to null-terminated base 64 string */
-void mutt_to_base64 (unsigned char *out, const unsigned char *in, size_t len,
-size_t olen)
+static void to_base64 (unsigned char *out, const unsigned char *in, size_t len,
+size_t olen, const char *dict)
 {
   while (len >= 3 && olen > 4)
   {
-*out++ = B64Chars[in[0] >> 2];
-*out++ = B64Chars[((in[0] << 4) & 0x30) | (in[1] >> 4)];
-*out++ = B64Chars[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
-*out++ = B64Chars[in[2] & 0x3f];
+*out++ = dict[in[0] >> 2];
+*out++ = dict[((in[0] << 4) & 0x30) | (in[1] >> 4)];
+*out++ = dict[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
+*out++ = dict[in[2] & 0x3f];
 olen  -= 4;
 len   -= 3;
 in+= 3;
@@ -76,15 +75,29 @@ void mutt_to_base64 (unsigned char *out, const unsigned 
char *in, size_t len,
   {
 unsigned char fragment;
 
-*out++ = B64Chars[in[0] >> 2];
+*out++ = dict[in[0] >> 2];
 fragment = (in[0] << 4) & 0x30;
 if (len > 1)
   fragment |= in[1] >> 4;
-*out++ = B64Chars[fragment];
-*out++ = (len < 2) ? '=' : B64Chars[(in[1] << 2) & 0x3c];
+*out++ = dict[fragment];
+*out++ = (len < 2) ? '=' : dict[(in[1] << 2) & 0x3c];
 *out++ = '=';
   }
   *out = '\0';
+
+}
+
+/* raw bytes to null-terminated base 64 string */
+void mutt_to_base64 (unsigned char *out, const unsigned char *in, size_t len,
+size_t olen)
+{
+   to_base64(out, in, len, olen, B64Chars);
+}
+
+void mutt_to_base64_safeurl (unsigned char *out, const unsigned char *in,
+size_t len, size_t olen)
+{
+   to_base64(out, in, len, olen, B64Chars_urlsafe);
 }
 
 int mutt_buffer_from_base64 (BUFFER *out, const char *in)
diff --git a/messageid.c b/messageid.c
index e4ac441002626..d96a5d4467102 100644
--- a/messageid.c
+++ b/messageid.c
@@ -49,7 +49,7 @@ static const char *id_format_str (char *dest, size_t destlen, 
size_t col,
   {
 case 'r':
   mutt_random_bytes ((char *)r_raw, sizeof(r_raw));
-  mutt_to_base64 (r_out, r_raw, sizeof(r_raw), sizeof(r_out));
+  mutt_to_base64_safeurl (r_out, r_raw, sizeof(r_raw), sizeof(r_out));
   mutt_format_s (dest, destlen, fmt, (const char *)r_out);
   break;
 
@@ -65,7 +65,7 @@ static const char *id_format_str (char *dest, size_t destlen, 
size_t col,
   for (int i = 0; i < 4; i++)
 z_raw[i] = (uint8_t) (id_data->now >> (3-i)*8u);
   mutt_random_bytes ((char *)z_raw + 4, sizeof(z_raw) - 4);
-  mutt_to_base64 (z_out, z_raw, sizeof(z_raw), sizeof(z_out));
+  mutt_to_base64_safeurl (z_out, z_raw, sizeof(z_raw), sizeof(z_out));
   mutt_format_s (dest, destlen, fmt, (const char *)z_out);
   break;
 
diff --git a/mime.h b/mime.h
index c162ee2b5a2b6..1a876ae27749c 100644
--- a/mime.h
+++ b/mime.h
@@ -63,6 +63,7 @@ enum
 extern const int Index_hex[];
 extern const int Index_64[];
 extern const char B64Chars[];
+extern const char B64Chars_urlsafe[];
 #endif
 
 #define hexval(c) Index_hex[(unsigned int)(c)]
diff --git a/protos.h b/protos.h
index a055d1a2ca266..d760c7d137ed5 100644
--- a/protos.h
+++ b/protos.h
@@ -432,6 +432,7 @@ int safe_symlink (const char *, const char *);
 
 /* base64.c */
 void mutt_to_base64 (unsigned char*, const unsigned char*, size_t, size_t);
+void mutt_to_base64_safeurl (unsigned char*, const unsigned char*, size_t, 
size_t);
 int mutt_from_base64 (char*, const char*, size_t);
 void mutt_buffer_to_base64 (BUFFER *, const unsigned char *, size_t);
 int mutt_buffer_from_base64 (BUFFER *, const char *);
diff --git a/sendlib.c b/sendlib.c
index d9429c2e62629..c2283972f1d33 100644
--- a/sendlib.c
+++ b/sendlib.c
@@ -84,6 +84,15 @@ const char B64Chars[64] = {
   '8', '9', '+', '/'
 };
 
+/* RFC4648 section 5 Base 64 Encoding with URL and Filename Safe Alphabet */
+const char B64Chars_urlsafe[64] = {
+  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
+  't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+  '8', '9', '-', '_'
+};
+
 static void transform_to_7bit 

[PATCH 1/2] base64val: Add support to decode base64 safe URL.

2023-03-04 Thread Sebastian Andrzej Siewior
In the base64 safe URL dictionary the characters '+' and '/' are
replaced by '-' and '_'.
Add the characters to Index_64 to allow decoding if needed.

Signed-off-by: Sebastian Andrzej Siewior 
---
 handler.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/handler.c b/handler.c
index 697c87e2b0992..cedf352ae1e5b 100644
--- a/handler.c
+++ b/handler.c
@@ -58,10 +58,10 @@ const int Index_hex[128] = {
 const int Index_64[128] = {
   -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
   -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-  -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+  -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,62,-1,63,
   52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
   -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
-  15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+  15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,63,
   -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
   41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
 };
-- 
2.39.2



[PATCH 0/2] Use base64 URL safe alphabet for message id generation.

2023-03-04 Thread Sebastian Andrzej Siewior
Hi,

#2 of this mini series uses the safe dictionary for base64 encoding to
use for message-id generation. This bothered me for a while and then I
stumbled uppon issie #400 so it appears to not be just me.

#1 is rather unimportant but allows to decode this safe URL base64
encoded strings if ever needed.

Sebastian