]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
pop3: satisfy some strict parsing rules in RFC 1939
authorPhil Carmody <phil@dovecot.fi>
Fri, 15 Aug 2014 12:02:59 +0000 (15:02 +0300)
committerPhil Carmody <phil@dovecot.fi>
Fri, 15 Aug 2014 12:02:59 +0000 (15:02 +0300)
"Commands in the POP3 consist of a case-insensitive keyword, possibly
 followed by one or more arguments.  All commands are terminated by a
 CRLF pair.  Keywords and arguments consist of printable ASCII
 characters.  Keywords and arguments are each separated by a single
 SPACE character."

"A server MUST respond to an unrecognized, unimplemented, or
 syntactically invalid command by responding with a negative status
 indicator."

Therefore the following commands must be rejected:
LIST 2600Hz
LIST 99 red balloons
TOP 1 2 buckle-my-shoe

Signed-off-by: Phil Carmody <phil@dovecot.fi>
src/pop3/pop3-commands.c

index 20fc89f55a0a7e387e88a7974ac4554387406f78..dade32e1e3baf9f2cf453cf221409f8255e192ed 100644 (file)
@@ -26,7 +26,7 @@ static uint32_t msgnum_to_seq(struct client *client, uint32_t msgnum)
 }
 
 static const char *get_msgnum(struct client *client, const char *args,
-                             unsigned int *msgnum)
+                             unsigned int *msgnum, bool thenspace)
 {
        unsigned int num;
 
@@ -40,6 +40,11 @@ static const char *get_msgnum(struct client *client, const char *args,
                                 "-ERR Message number too large: %s", args);
                return NULL;
        }
+       if (*args != (thenspace ? ' ' : '\0')) {
+               client_send_line(client,
+                                "-ERR Noise after message number: %s", args);
+               return NULL;
+       }
        if (num == 0 || num > client->messages_count) {
                client_send_line(client,
                                 "-ERR There's no message %u.", num);
@@ -62,7 +67,7 @@ static const char *get_msgnum(struct client *client, const char *args,
 }
 
 static const char *get_size(struct client *client, const char *args,
-                           uoff_t *size)
+                           uoff_t *size, bool thenspace)
 {
        uoff_t num;
 
@@ -76,6 +81,10 @@ static const char *get_size(struct client *client, const char *args,
                                 args);
                return NULL;
        }
+       if (*args != (thenspace ? ' ' : '\0')) {
+               client_send_line(client, "-ERR Noise after size: %s", args);
+               return NULL;
+       }
 
        while (*args == ' ') args++;
 
@@ -93,7 +102,7 @@ static int cmd_dele(struct client *client, const char *args)
 {
        unsigned int msgnum;
 
-       if (get_msgnum(client, args, &msgnum) == NULL)
+       if (get_msgnum(client, args, &msgnum, FALSE) == NULL)
                return -1;
 
        if (!client->deleted) {
@@ -155,7 +164,7 @@ static int cmd_list(struct client *client, const char *args)
        } else {
                unsigned int msgnum;
 
-               if (get_msgnum(client, args, &msgnum) == NULL)
+               if (get_msgnum(client, args, &msgnum, FALSE) == NULL)
                        return -1;
 
                client_send_line(client, "+OK %u %"PRIuUOFF_T, msgnum+1,
@@ -470,7 +479,7 @@ static int cmd_retr(struct client *client, const char *args)
 {
        unsigned int msgnum;
 
-       if (get_msgnum(client, args, &msgnum) == NULL)
+       if (get_msgnum(client, args, &msgnum, FALSE) == NULL)
                return -1;
 
        if (client->lowest_retr_pop3_msn > msgnum+1 ||
@@ -534,10 +543,10 @@ static int cmd_top(struct client *client, const char *args)
        unsigned int msgnum;
        uoff_t max_lines;
 
-       args = get_msgnum(client, args, &msgnum);
+       args = get_msgnum(client, args, &msgnum, TRUE);
        if (args == NULL)
                return -1;
-       if (get_size(client, args, &max_lines) == NULL)
+       if (get_size(client, args, &max_lines, FALSE) == NULL)
                return -1;
 
        client->top_count++;
@@ -860,7 +869,7 @@ static int cmd_uidl(struct client *client, const char *args)
        } else {
                unsigned int msgnum;
 
-               if (get_msgnum(client, args, &msgnum) == NULL)
+               if (get_msgnum(client, args, &msgnum, FALSE) == NULL)
                        return -1;
 
                seq = msgnum_to_seq(client, msgnum);