summaryrefslogtreecommitdiffstats
path: root/system/clamsmtp/patches/leading_dots.patch
blob: 983247146fc767cb4bc61950bb01b79c5a209679 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
--- clamsmtp-1.10.orig/common/smtppass.c
+++ clamsmtp-1.10/common/smtppass.c
@@ -1389,16 +1389,34 @@ int sp_cache_data(spctx_t* ctx)
 {
     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 */
+
+	/* 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 (ctx->_crlf)
+	 linestart = 1;
+	else
+	 linestart = 0;	
             
-        count += r;
+	count += r;
             
-        if((r = sp_write_data(ctx, data, r)) < 0)
-            return -1;  /* Message already printed */
+	if((r = sp_write_data(ctx, data, r)) < 0)
+	 return -1;  /* Message already printed */
     }
     
     /* End the caching */
@@ -1572,9 +1590,12 @@ int sp_done_data(spctx_t* ctx, const cha
     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 */
@@ -1582,10 +1603,12 @@ int sp_done_data(spctx_t* ctx, const cha
     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)
@@ -1631,17 +1654,24 @@ int sp_done_data(spctx_t* ctx, const cha
         header[0] = '\0';
     }
 
-    /* Transfer actual file data */    
-    while((rc = getline(&line, &line_len, file)) != -1)
+    /* Transfer actual file data */
+    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 (strstr(line, CRLF))
+	 linestart = 1;
+	else
+	 linestart = 0;
+
+	if(strcmp(line, "." CRLF) == 0)
+	 strncpy(line, ". " CRLF, SP_LINE_LENGTH);
       
         if(header[0] != '\0')
         {
@@ -1683,10 +1713,10 @@ int sp_done_data(spctx_t* ctx, const cha
         
 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;
 }