On Wed, Jun 16, 2010 at 11:49:22AM -0500, Patrick Goetz wrote:
> On 06/15/2010 06:36 PM, Bron Gondwana wrote:
> >>
> >>~/imap/imapparse.c
> >>line 53:
> >>-    MAXLITERAL = INT_MAX / 20
> >>+    MAXLITERAL = INT_MAX / 10
> >
> >Hmm - and still untouched in my latest codebase too.  We've got a
> >configurable maximum line length now.
> >
> >That's basically what - 100M, changed up to 200M?  Or am I out by an order
> >of magnitude or so?  Maximum size for a single email.
> >
> >I'd be happy to apply it (and also to replication...) - I don't see the
> >danger with either option, but it will block super-large emails.
> >
> 
> Wouldn't the len*10 here:
>        len = len*10 + c - '0';
>             if (len > MAXLITERAL || len < 0) {
>
> imply that it's actually changing a 10.7MB max size to 21.4MB?

No.  That's a skanky integer parser.  "len" is the integer value of
the number that's been read so far, the *10 was the previously read
character.  I guess that to avoid overflow, you need to limit what
you can read here... hmm.  I think that function could do with a
rewrite actually.
 
> In any case, since most people use email as a defacto file sharing
> system, this should be a run-time option, if possible.  On my
> postfix server at work we had message_size_limit set to 50MB (or
> something like this) and my own spouse got burned by this when some
> consultant tried to email her a large attachment containing some
> work-related videos.  I got the "so and so says he's trying to send
> me some files and the message keeps bouncing" call, which is how I
> discovered the message_size_limit setting in main.cf in the first
> place.
> 
> So, eventually MAXLITERAL should also be configurable, if possible,
> but for now we can probably let the debian *2 size limit patch
> stand?

I've attached the patch I just put into future branch.  It makes it
configurable.  But the more I think about it, the more I think the
whole concept is actually broken.  I'm probably going to just remove
the limit and change how we read the number!

Bron.
diff --git a/imap/imapparse.c b/imap/imapparse.c
index 3e1ec54..43a00e6 100644
--- a/imap/imapparse.c
+++ b/imap/imapparse.c
@@ -52,10 +52,6 @@
 #include "global.h"
 #include "exitcodes.h"
 
-enum {
-    MAXLITERAL = INT_MAX / 20
-};
-
 void freebuf(struct buf *buf)
 {
     if (buf->s) {
@@ -199,10 +195,10 @@ int getxstring(struct protstream *pin, struct protstream *pout,
 	while ((c = prot_getc(pin)) != EOF && isdigit(c)) {
 	    sawdigit = 1;
 	    len = len*10 + c - '0';
-            if (len > MAXLITERAL || len < 0) {
-                /* we overflowed */
-                fatal("literal too big", EC_IOERR);
-            }
+	    if (len > config_maxliteral || len < 0) {
+		/* we overflowed */
+		fatal("literal too big", EC_IOERR);
+	    }
 	}
 	if (c == '+') {
 	    isnowait++;
diff --git a/imap/sync_support.c b/imap/sync_support.c
index ca4934d..23272d0 100644
--- a/imap/sync_support.c
+++ b/imap/sync_support.c
@@ -91,10 +91,6 @@
 
 const char *lastkey = NULL;
 
-enum {
-    MAXLITERAL = INT_MAX / 20
-};
-
 char *sync_encode_options(int options)
 {
     static char buf[4];
diff --git a/lib/imapoptions b/lib/imapoptions
index 5215ec2..cd7a494 100644
--- a/lib/imapoptions
+++ b/lib/imapoptions
@@ -617,6 +617,11 @@ Blank lines and lines beginning with ``#'' are ignored.
    the lines in the header will be skipped.  This is to avoid malformed
    messages causing giant cache records */
 
+{ "maxliteral", INT_MAX / 10, INT }
+/* Maximum size of a literal value.  This sets the maximum possible size
+   for an email.  The default is INT_MAX/10 or about 210Mb on a standard
+   32 bit system */
+
 { "maxmessagesize", 0, INT }
 /* Maximum incoming LMTP message size.  If non-zero, lmtpd will reject
    messages larger than \fImaxmessagesize\fR bytes.  If set to 0, this
diff --git a/lib/libconfig.c b/lib/libconfig.c
index 1c59ce6..ccea820 100644
--- a/lib/libconfig.c
+++ b/lib/libconfig.c
@@ -81,6 +81,7 @@ int config_hashimapspool;	  /* f */
 enum enum_value config_virtdomains;	          /* f */
 enum enum_value config_mupdate_config;	/* IMAP_ENUM_MUPDATE_CONFIG_STANDARD */
 int config_auditlog;
+int config_maxliteral;
 int config_maxword;
 int config_maxquoted;
 
@@ -330,6 +331,7 @@ void config_read(const char *alt_config)
     }
 
     /* set some limits */
+    config_maxliteral = config_getint(IMAPOPT_MAXLITERAL);
     config_maxquoted = config_getint(IMAPOPT_MAXQUOTED);
     config_maxword = config_getint(IMAPOPT_MAXWORD);
 }
diff --git a/lib/libconfig.h b/lib/libconfig.h
index de40784..d70ce31 100644
--- a/lib/libconfig.h
+++ b/lib/libconfig.h
@@ -79,6 +79,7 @@ extern int config_implicitrights;
 extern enum enum_value config_virtdomains;
 extern enum enum_value config_mupdate_config;
 extern int config_auditlog;
+extern int config_maxliteral;
 extern int config_maxquoted;
 extern int config_maxword;
 
diff --git a/tools/config2header b/tools/config2header
index 97ebec3..50a4085 100755
--- a/tools/config2header
+++ b/tools/config2header
@@ -125,6 +125,7 @@ print CFILE <<EOF
 #include <syslog.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 #include "imapopts.h"
 
 struct imapopt_s imapopts[] =

Reply via email to