chiark / gitweb /
Confirmation strings are now invariant under URL-encoding. They are still
authorrjk@greenend.org.uk <>
Mon, 31 Dec 2007 11:46:17 +0000 (11:46 +0000)
committerrjk@greenend.org.uk <>
Mon, 31 Dec 2007 11:46:17 +0000 (11:46 +0000)
base64-encoded but using a slightly different set of symbols to MIME.

lib/base64.c
lib/base64.h
server/server.c

index c657cde063ecbfedf652603ec2f8414b49f3397d..7ba47300d9c5c13b20431cedfc750623564fe16b 100644 (file)
 #include "vector.h"
 
 static const char mime_base64_table[] =
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 
 /** @brief Convert MIME base64
  * @param s base64 data
  * @param nsp Where to store length of converted data
+ * @param table Table of characters to use
  * @return Decoded data
  *
  * See <a href="http://tools.ietf.org/html/rfc2045#section-6.8">RFC
  * 2045 s6.8</a>.
  */
 char *mime_base64(const char *s, size_t *nsp) {
+  return generic_base64(s, nsp, mime_base64_table);
+}
+
+/** @brief Convert base64
+ * @param s base64 data
+ * @param nsp Where to store length of converted data
+ * @return Decoded data
+ *
+ * @p table should consist of 65 characters.  The first 64 will be used to
+ * represents the 64 digits and the 65th will be used as padding at the end
+ * (i.e. the role of '=' in RFC2045 base64).
+ */
+char *generic_base64(const char *s, size_t *nsp, const char *table) {
   struct dynstr d;
   const char *t;
   int b[4], n, c;
@@ -51,15 +65,15 @@ char *mime_base64(const char *s, size_t *nsp) {
   dynstr_init(&d);
   n = 0;
   while((c = (unsigned char)*s++)) {
-    if((t = strchr(mime_base64_table, c))) {
-      b[n++] = t - mime_base64_table;
+    if((t = strchr(table, c))) {
+      b[n++] = t - table;
       if(n == 4) {
        dynstr_append(&d, (b[0] << 2) + (b[1] >> 4));
        dynstr_append(&d, (b[1] << 4) + (b[2] >> 2));
        dynstr_append(&d, (b[2] << 6) + b[3]);
        n = 0;
       }
-    } else if(c == '=') {
+    } else if(c == table[64]) {
       if(n >= 2) {
        dynstr_append(&d, (b[0] << 2) + (b[1] >> 4));
        if(n == 3)
@@ -74,7 +88,7 @@ char *mime_base64(const char *s, size_t *nsp) {
   return d.vec;
 }
 
-/** @brief Convert a binary string to base64
+/** @brief Convert a binary string to MIME base64
  * @param s Bytes to convert
  * @param ns Number of bytes to convert
  * @return Encoded data
@@ -85,34 +99,50 @@ char *mime_base64(const char *s, size_t *nsp) {
  * 2045 s6.8</a>.
  */
 char *mime_to_base64(const uint8_t *s, size_t ns) {
+  return generic_to_base64(s, ns, mime_base64_table);
+}
+
+/** @brief Convert a binary string to base64
+ * @param s Bytes to convert
+ * @param ns Number of bytes to convert
+ * @param table Table of characters to use
+ * @return Encoded data
+ *
+ * This function does not attempt to split up lines.
+ *
+ * @p table should consist of 65 characters.  The first 64 will be used to
+ * represents the 64 digits and the 65th will be used as padding at the end
+ * (i.e. the role of '=' in RFC2045 base64).
+ */
+char *generic_to_base64(const uint8_t *s, size_t ns, const char *table) {
   struct dynstr d[1];
 
   dynstr_init(d);
   while(ns >= 3) {
     /* Input bytes with output bits: AAAAAABB BBBBCCCC CCDDDDDD */
     /* Output bytes with input bits: 000000 001111 111122 222222 */
-    dynstr_append(d, mime_base64_table[s[0] >> 2]);
-    dynstr_append(d, mime_base64_table[((s[0] & 3) << 4)
+    dynstr_append(d, table[s[0] >> 2]);
+    dynstr_append(d, table[((s[0] & 3) << 4)
                                       + (s[1] >> 4)]);
-    dynstr_append(d, mime_base64_table[((s[1] & 15) << 2)
+    dynstr_append(d, table[((s[1] & 15) << 2)
                                       + (s[2] >> 6)]);
-    dynstr_append(d, mime_base64_table[s[2] & 63]);
+    dynstr_append(d, table[s[2] & 63]);
     ns -= 3;
     s += 3;
   }
   if(ns > 0) {
-    dynstr_append(d, mime_base64_table[s[0] >> 2]);
+    dynstr_append(d, table[s[0] >> 2]);
     switch(ns) {
     case 1:
-      dynstr_append(d, mime_base64_table[(s[0] & 3) << 4]);
-      dynstr_append(d, '=');
-      dynstr_append(d, '=');
+      dynstr_append(d, table[(s[0] & 3) << 4]);
+      dynstr_append(d, table[64]);
+      dynstr_append(d, table[64]);
       break;
     case 2:
-      dynstr_append(d, mime_base64_table[((s[0] & 3) << 4)
+      dynstr_append(d, table[((s[0] & 3) << 4)
                                         + (s[1] >> 4)]);
-      dynstr_append(d, mime_base64_table[(s[1] & 15) << 2]);
-      dynstr_append(d, '=');
+      dynstr_append(d, table[(s[1] & 15) << 2]);
+      dynstr_append(d, table[64]);
       break;
     }
   }
index a2c20e67f2938552686ab50f15d03192db2db52b..0beb53496560e7710401d5936e00f05745645af6 100644 (file)
@@ -25,7 +25,9 @@
 #define BASE64_H
 
 char *mime_base64(const char *s, size_t *nsp);
+char *generic_base64(const char *s, size_t *nsp, const char *table);
 char *mime_to_base64(const uint8_t *s, size_t ns);
+char *generic_to_base64(const uint8_t *s, size_t ns, const char *table);
 
 #endif /* BASE64_H */
 
index a7fad016992e5be6508b7184c8dbf42ed5f127d3..1e7c22fcc88d0166d71507c299833152130d61f0 100644 (file)
@@ -1154,6 +1154,16 @@ static int c_users(struct conn *c,
   return 1;                            /* completed */
 }
 
+/** @brief Base64 mapping table for confirmation strings
+ *
+ * This is used with generic_to_base64() and generic_base64().  We cannot use
+ * the MIME table as that contains '+' and '=' which get quoted when
+ * URL-encoding.  (The CGI still does the URL encoding but it is desirable to
+ * avoid it being necessary.)
+ */
+static const char confirm_base64_table[] =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/.*";
+
 static int c_register(struct conn *c,
                      char **vec,
                      int attribute((unused)) nvec) {
@@ -1166,7 +1176,8 @@ static int c_register(struct conn *c,
   buf = xmalloc_noptr(bufsize);
   offset = byte_snprintf(buf, bufsize, "%s;", vec[0]);
   gcry_randomize(buf + offset, CONFIRM_SIZE, GCRY_STRONG_RANDOM);
-  cs = mime_to_base64((uint8_t *)buf, offset + CONFIRM_SIZE);
+  cs = generic_to_base64((uint8_t *)buf, offset + CONFIRM_SIZE,
+                        confirm_base64_table);
   if(trackdb_adduser(vec[0], vec[1], config->default_rights, vec[2], cs))
     sink_writes(ev_writer_sink(c->w), "550 Cannot create user\n");
   else
@@ -1187,7 +1198,7 @@ static int c_confirm(struct conn *c,
     sink_writes(ev_writer_sink(c->w), "530 Authentication failure\n");
     return 1;
   }
-  if(!(user = mime_base64(vec[0], &nuser))
+  if(!(user = generic_base64(vec[0], &nuser, confirm_base64_table))
      || !(sep = memchr(user, ';', nuser))) {
     sink_writes(ev_writer_sink(c->w), "550 Malformed confirmation string\n");
     return 1;