Hello,

a new version of the patch, in accordance to RFC 5321 only accepting CRLF as line separator, and with usage of builtin struct member _crlf to remember CRLFs.

By the way, clamsmtp maintainers already integrated my patch into their package.

Regards
  Christoph
Index: proxsmtp-1.10/common/smtppass.c
===================================================================
--- proxsmtp-1.10.orig/common/smtppass.c	2018-02-16 13:34:32.445788258 +0100
+++ proxsmtp-1.10/common/smtppass.c	2018-02-16 14:28:03.119531212 +0100
@@ -1524,16 +1524,37 @@
 {
     int r, count = 0;
     const char* data;
+    int linestart;
+
+    linestart = 1;
 
     while((r = sp_read_data(ctx, &data)) != 0)
     {
-        if(r < 0)
-            return -1;  /* Message already printed */
+	if(r < 0)
+	 return -1;  /* Message already printed */
+
+    sp_messagex(ctx, LOG_DEBUG, "data is %d characters long", strlen(data));
+    sp_messagex(ctx, LOG_DEBUG, "r is %d", r);
 
-        count += r;
+	/* SMTP RFCs say that servers must remove leading dots at the beginning
+	 * of a line. We do that here.
+	 */
+
+	if (linestart && (data[0] == '.'))
+	{
+	    data++;
+	    r--;
+	}
+
+	if (data[r-1] == '\n')
+	 linestart = 1;
+	else
+	 linestart = 0;
 
-        if((r = sp_write_data(ctx, data, r)) < 0)
-            return -1;  /* Message already printed */
+	count += r;
+
+	if((r = sp_write_data(ctx, data, r)) < 0)
+	 return -1;  /* Message already printed */
     }
 
     /* End the caching */
@@ -1707,9 +1728,12 @@
     int ret = 0;
     char *line;
     char header[MAX_HEADER_LENGTH] = "";
-    size_t header_len, line_len;
+    size_t header_len;
     int header_prepend = 0;
     ssize_t rc;
+    size_t buf_len;
+    int linestart;
+    char *buf;
 
     ASSERT(ctx->cachename[0]);  /* Must still be around */
     ASSERT(!ctx->cachefile);    /* File must be closed */
@@ -1717,10 +1741,12 @@
     memset(header, 0, sizeof(header));
 
     /* Alloc line buffer */
-    line_len = SP_LINE_LENGTH;
-    if((line = (char *)malloc(line_len)) == NULL)
+    buf_len = SP_LINE_LENGTH;
+    if((buf = (char *)malloc(buf_len)) == NULL)
         RETURN(-1);
 
+    buf[0] = '.';
+
     /* Open the file */
     file = fopen(ctx->cachename, "r");
     if(file == NULL)
@@ -1766,17 +1792,23 @@
         header[0] = '\0';
     }
 
+    linestart = 1;
+
     /* Transfer actual file data */
-    while((rc = getline(&line, &line_len, file)) != -1)
+    while(line = (fgets(buf + 1, buf_len - 1, file)))
     {
-        /*
-         * If the line is <CRLF>.<CRLF> we need to change it so that
-         * it doesn't end the email. We do this by adding a space.
-         * This won't occur much in clamsmtpd, but proxsmtpd might
-         * have filters that accidentally put this in.
-         */
-        if(strcmp(line, "." CRLF) == 0)
-            strncpy(line, ". " CRLF, SP_LINE_LENGTH);
+	/* SMTP RFCs say that clients must prepend an additional dot
+	 * to every line starting with a dot. We do that here.
+	 */
+	if (linestart && (line[0] == '.'))
+	 line = buf;
+
+	rc = strlen(line);
+
+	if (line[rc-1] == '\n')
+	 linestart = 1;
+	else
+	 linestart = 0;
 
         if(header[0] != '\0')
         {
@@ -1818,10 +1850,10 @@
 
 cleanup:
 
-	if(line)
-		free(line);
-    if(file)
-        fclose(file); /* read-only so no error check */
+	if(buf)
+		free(buf);
+	if(file)
+		fclose(file); /* read-only so no error check */
 
     return ret;
 }

Reply via email to