summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <sebastian@breakpoint.cc>2023-03-04 18:33:35 +0100
committerKevin McCarthy <kevin@8t8.us>2023-03-04 18:11:15 -0800
commit5df86199463b5cf893fb6a37457fa02804d3b02a (patch)
tree3e3bc9bdf4449d94bfbc3c19d608e1673be9d224
parentcecddeac3be3d37a3418f01a02c9c0fbdd9f6d8c (diff)
Use base64 URL safe alphabet for message id generation.
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 <sebastian@breakpoint.cc>
-rw-r--r--base64.c33
-rw-r--r--messageid.c4
-rw-r--r--mime.h1
-rw-r--r--protos.h1
-rw-r--r--sendlib.c9
5 files changed, 36 insertions, 12 deletions
diff --git a/base64.c b/base64.c
index 290f384e..5757b785 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 e4ac4410..d96a5d44 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 c162ee2b..1a876ae2 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 a055d1a2..d760c7d1 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 d9429c2e..c2283972 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 (BODY *a, FILE *fpin);
static void encode_quoted (FGETCONV * fc, FILE *fout, int istext)