smtp: Fixed sending of double CRLF caused by first in EOB
authorSteve Holme <steve_holme@hotmail.com>
Sat, 4 May 2013 08:52:09 +0000 (09:52 +0100)
committerSteve Holme <steve_holme@hotmail.com>
Sat, 4 May 2013 09:00:33 +0000 (10:00 +0100)
If the mail sent during the transfer contains a terminating <CRLF> then
we should not send the first <CRLF> of the EOB as specified in RFC-5321.

Additionally don't send the <CRLF> if there is "no mail data" as the
DATA command already includes it.

14 files changed:
lib/smtp.c
lib/smtp.h
tests/data/test1320
tests/data/test1406
tests/data/test900
tests/data/test901
tests/data/test902
tests/data/test903
tests/data/test904
tests/data/test905
tests/data/test906
tests/data/test907
tests/data/test908
tests/data/test909

index e33999d581cac448179925f4c2790d56a53dac91..ae63e7bebdfc9aa4c6231427c32b71ef6102e855 100644 (file)
@@ -1455,6 +1455,9 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
   CURLcode result = CURLE_OK;
   struct SessionHandle *data = conn->data;
   struct SMTP *smtp = data->state.proto.smtp;
+  struct pingpong *pp = &conn->proto.smtpc.pp;
+  const char *eob;
+  size_t len;
   ssize_t bytes_written;
 
   (void)premature;
@@ -1471,25 +1474,27 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
     result = status;         /* use the already set error code */
   }
   else if(!data->set.connect_only) {
-    struct smtp_conn *smtpc = &conn->proto.smtpc;
-    struct pingpong *pp = &smtpc->pp;
+    /* Calculate the EOB taking into account any terminating CRLF from the 
+       previous line of the email or the CRLF of the DATA command when there
+       is "no mail data". RFC-5321, sect. 4.1.1.4. */
+    eob = SMTP_EOB;
+    len = SMTP_EOB_LEN;
+    if(smtp->trailing_crlf || !conn->data->set.infilesize) {
+      eob += 2;
+      len -= 2;
+    }
 
     /* Send the end of block data */
-    result = Curl_write(conn,
-                        conn->writesockfd,  /* socket to send to */
-                        SMTP_EOB,           /* buffer pointer */
-                        SMTP_EOB_LEN,       /* buffer size */
-                        &bytes_written);    /* actually sent away */
-
+    result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written);
     if(result)
       return result;
 
-    if(bytes_written != SMTP_EOB_LEN) {
+    if(bytes_written != len) {
       /* The whole chunk was not sent so keep it around and adjust the
          pingpong structure accordingly */
-      pp->sendthis = strdup(SMTP_EOB);
-      pp->sendsize = SMTP_EOB_LEN;
-      pp->sendleft = SMTP_EOB_LEN - bytes_written;
+      pp->sendthis = strdup(eob);
+      pp->sendsize = len;
+      pp->sendleft = len - bytes_written;
     }
     else
       /* Successfully sent so adjust the response timeout relative to now */
@@ -1812,8 +1817,15 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
   /* This loop can be improved by some kind of Boyer-Moore style of
      approach but that is saved for later... */
   for(i = 0, si = 0; i < nread; i++) {
-    if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i])
+    if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) {
       smtp->eob++;
+
+      /* Is the EOB potentially the terminating CRLF? */
+      if(2 == smtp->eob || SMTP_EOB_LEN == smtp->eob)
+        smtp->trailing_crlf = TRUE;
+      else
+        smtp->trailing_crlf = FALSE;
+    }
     else if(smtp->eob) {
       /* A previous substring matched so output that first */
       memcpy(&data->state.scratch[si], SMTP_EOB, smtp->eob);
@@ -1824,6 +1836,9 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
         smtp->eob = 1;
       else
         smtp->eob = 0;
+
+      /* Reset the trailing CRLF flag as there was more data */
+      smtp->trailing_crlf = FALSE;
     }
 
     /* Do we have a match for CRLF. as per RFC-2821, sect. 4.5.2 */
index 7a03e51ced194f8f586ce19d92ce5aae0353c9d1..4aff0c5f92eb08cb49c3259efa0324a43afb4d54 100644 (file)
@@ -62,6 +62,7 @@ struct SMTP {
   struct curl_slist *rcpt; /* Recipient list */
   size_t eob;              /* Number of bytes of the EOB (End Of Body) that
                               have been received so far */
+  bool trailing_crlf;      /* Specifies if the tailing CRLF is present */
 };
 
 /* smtp_conn is used for struct connection-oriented data in the connectdata
index f1c7328e659b486ccf5b338d5e5ca3568f4dd64d..15ec7bb6c2f6b39cf836f9670c15ae71f27e9c70 100644 (file)
@@ -58,7 +58,6 @@ From: different
 To: another\r
 \r
 body\r
-\r
 .\r
 </upload>
 <proxy>
index b7727edfd6b56e5c1505f805b8498148989b2409..6245c513eb8c9b3689824f4057800a7bd45c8f40 100644 (file)
@@ -49,7 +49,6 @@ From: different
 To: another\r
 \r
 body\r
-\r
 .\r
 </upload>
 <file name="log/test1406.c" mode="text">
index e71fa94fdb9fa96d19a206041c08f776cfb7b6ed..749a9657438ac061a49353ca5846de40c5c496ea 100644 (file)
@@ -46,7 +46,6 @@ From: different
 To: another\r
 \r
 body\r
-\r
 .\r
 </upload>
 </verify>
index cc3409990846dc7c51368992fd34301bcc5c5d54..ed24518241a3b924af33d9b79981de303889e046 100644 (file)
@@ -57,7 +57,6 @@ To: another
 ..\r
 \r
 body\r
-\r
 .\r
 </upload>
 </verify>
index c3b9fb44235c8e9c8296b522b5294c1cc39dd936..4da1b991293fddcacbcb23e1d277b720bb5e3df7 100644 (file)
@@ -52,7 +52,6 @@ From: different
 To: another\r
 \r
 body\r
-\r
 .\r
 </upload>
 </verify>
index defadf903616d6420d9e2915c5aa05ad4931ed22..157bd48cbe566f2716ac5d11d3912cf5daf4b5a7 100644 (file)
@@ -49,7 +49,6 @@ QUIT
 </protocol>
 <upload>
 mail body\r
-\r
 .\r
 </upload>
 </verify>
index 19e6f222623c995ac4492e992f26b0ecf83d772a..1a23f4157c331c84b38550d2f6735dbed1df75be 100644 (file)
@@ -50,7 +50,6 @@ QUIT
 </protocol>
 <upload>
 mail body\r
-\r
 .\r
 </upload>
 </verify>
index 451a73d49eb67edb62896bddec685ba8d046274e..fccd84baeab1286cca5b37be7e8589234269ad36 100644 (file)
@@ -52,7 +52,6 @@ QUIT
 </protocol>
 <upload>
 mail body\r
-\r
 .\r
 </upload>
 </verify>
index 80c1e7ee617470845ec796278ea3cd6a4d29b5d5..1f88990fd024fa7526fee8b04c7b344b3678f2c1 100644 (file)
@@ -45,7 +45,6 @@ From: different
 To: another\r
 \r
 body\r
-\r
 .\r
 </upload>
 </verify>
index 45e453db0b2be4c740c86ee548bd16b761077416..511d51970ef160b57890cd49c0e5e86e7bac350a 100644 (file)
@@ -47,7 +47,6 @@ QUIT
 </protocol>
 <upload>
 mail body\r
-\r
 .\r
 </upload>
 </verify>
index c1689287f8b2aeb72ffa1cdf6c59b62012c4f6a7..61d56c5e04dedd5313fc0f764092c40a0b723faf 100644 (file)
@@ -48,7 +48,6 @@ QUIT
 </protocol>
 <upload>
 mail body\r
-\r
 .\r
 </upload>
 </verify>
index 89c8b0fb8c68f9c86ef4c0ed489427d5631830a3..2fc1f191d97a7d9eb5fdde12ab67a95fa7e4cb62 100644 (file)
@@ -50,7 +50,6 @@ From: different
 To: another\r
 \r
 body\r
-\r
 .\r
 </upload>
 </verify>