]> granicus.if.org Git - mutt/commitdiff
Validate msgid in APOP authentication. Closes #2846
authorBrendan Cully <brendan@kublai.com>
Mon, 2 Apr 2007 22:20:58 +0000 (15:20 -0700)
committerBrendan Cully <brendan@kublai.com>
Mon, 2 Apr 2007 22:20:58 +0000 (15:20 -0700)
pop_auth.c
rfc822.c
rfc822.h

index 930f571344bcdedb2c1746160dfa61f79d4c8f85..c77c630db2590233b884073c5d44bfc4f2db9f69 100644 (file)
@@ -183,6 +183,13 @@ static pop_auth_res_t pop_auth_apop (POP_DATA *pop_data, const char *method)
   if (!pop_data->timestamp)
     return POP_A_UNAVAIL;
 
+  if (rfc822_valid_msgid (pop_data->timestamp) < 0)
+  {
+    mutt_error _("POP timestamp is invalid!");
+    mutt_sleep (2);
+    return POP_A_UNAVAIL;
+  }
+
   mutt_message _("Authenticating (APOP)...");
 
   /* Compute the authentication hash to send to the server */
index 7d9e4bb8cc8e2b61d7526620086adfbf273ba512..7b05e3039b4d3bb859e41ebc9af152cd7f5493a2 100644 (file)
--- a/rfc822.c
+++ b/rfc822.c
@@ -792,6 +792,52 @@ ADDRESS *rfc822_append (ADDRESS **a, ADDRESS *b)
   return tmp;
 }
 
+/* incomplete. Only used to thwart the APOP MD5 attack (#2846). */
+int rfc822_valid_msgid (const char *msgid)
+{
+  /* msg-id         = "<" addr-spec ">"
+   * addr-spec      = local-part "@" domain
+   * local-part     = word *("." word)
+   * word           = atom / quoted-string
+   * atom           = 1*<any CHAR except specials, SPACE and CTLs>
+   * CHAR           = ( 0.-127. )
+   * specials       = "(" / ")" / "<" / ">" / "@"
+                    / "," / ";" / ":" / "\" / <">
+                   / "." / "[" / "]"
+   * SPACE          = ( 32. )
+   * CTLS           = ( 0.-31., 127.)
+   * quoted-string  = <"> *(qtext/quoted-pair) <">
+   * qtext          = <any CHAR except <">, "\" and CR>
+   * CR             = ( 13. )
+   * quoted-pair    = "\" CHAR
+   * domain         = sub-domain *("." sub-domain)
+   * sub-domain     = domain-ref / domain-literal
+   * domain-ref     = atom
+   * domain-literal = "[" *(dtext / quoted-pair) "]"
+   */
+
+  char* dom;
+  unsigned int l, i;
+
+  if (!msgid || !*msgid)
+    return -1;
+
+  l = mutt_strlen (msgid);
+  if (l < 5) /* <atom@atom> */
+    return -1;
+  if (msgid[0] != '<' || msgid[l-1] != '>')
+    return -1;
+  if (!(dom = strrchr (msgid, '@')))
+    return -1;
+
+  /* TODO: complete parser */
+  for (i = 0; i < l; i++)
+    if ((unsigned char)msgid[i] > 127)
+      return -1;
+
+  return 0;
+}
+
 #ifdef TESTING
 int safe_free (void **p)       /* __SAFE_FREE_CHECKED__ */
 {
index 3c8d176570df2c212f67fa69d02940ad0bfa4b8b..5cabdf3147dcaa102c213bb55aeee42e08e7f7a9 100644 (file)
--- a/rfc822.h
+++ b/rfc822.h
@@ -52,6 +52,7 @@ int rfc822_write_address (char *, size_t, ADDRESS *, int);
 void rfc822_write_address_single (char *, size_t, ADDRESS *, int);
 void rfc822_free_address (ADDRESS **addr);
 void rfc822_cat (char *, size_t, const char *, const char *);
+int rfc822_valid_msgid (const char *msgid);
 
 extern int RFC822Error;
 extern const char *RFC822Errors[];