From b5c06cd72be5ee4d0ebdf381c0b40825dcfa4a0b Mon Sep 17 00:00:00 2001 From: Brendan Cully <brendan@kublai.com> Date: Mon, 2 Apr 2007 15:20:58 -0700 Subject: [PATCH] Validate msgid in APOP authentication. Closes #2846 --- pop_auth.c | 7 +++++++ rfc822.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ rfc822.h | 1 + 3 files changed, 54 insertions(+) diff --git a/pop_auth.c b/pop_auth.c index 930f5713..c77c630d 100644 --- a/pop_auth.c +++ b/pop_auth.c @@ -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 */ diff --git a/rfc822.c b/rfc822.c index 7d9e4bb8..7b05e303 100644 --- 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__ */ { diff --git a/rfc822.h b/rfc822.h index 3c8d1765..5cabdf31 100644 --- 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[]; -- 2.40.0