Browse code

Experimental mode: Reduce the number of SPF DNS queries

git-svn: trunk@3150

Nigel Horne authored on 2007/07/15 22:21:50
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Sun Jul 15 13:27:46 BST 2007 (njh)
2
+----------------------------------
3
+  * clamav-milter:	Experimental mode: Reduce the number of SPF DNS queries
4
+
1 5
 Sun Jul 15 10:26:49 BST 2007 (njh)
2 6
 ----------------------------------
3 7
   * clamav-milter:	Experimental mode: Handle A: MX: INCLUDE: in SPF
... ...
@@ -567,7 +567,7 @@ static	table_t	*mx(const char *host, table_t *t);
567 567
 #ifdef	HAVE_RESOLV_H
568 568
 static	table_t	*resolve(const char *host, table_t *t);
569 569
 #ifdef	CL_EXPERIMENTAL
570
-static	void	spf(struct privdata *privdata);
570
+static	int	spf(struct privdata *privdata);
571 571
 static	void	spf_ip(char *ip, int zero, void *v);
572 572
 #endif
573 573
 #endif
... ...
@@ -2891,14 +2891,6 @@ clamfi_envfrom(SMFICTX *ctx, char **argv)
2891 2891
 	if(hflag)
2892 2892
 		privdata->headers = header_list_new();
2893 2893
 
2894
-#ifdef	CL_EXPERIMENTAL
2895
-	/*
2896
-	 * FIXME: This should only be done when a phish is found. It's done
2897
-	 *	on every email for now to test the SPF code
2898
-	 */
2899
-	spf(privdata);
2900
-#endif	/*CL_EXPERIMENTAL*/
2901
-
2902 2894
 	return SMFIS_CONTINUE;
2903 2895
 }
2904 2896
 
... ...
@@ -3457,14 +3449,11 @@ clamfi_eom(SMFICTX *ctx)
3457 3457
 	 * exceeded
3458 3458
 	 */
3459 3459
 #ifdef	CL_EXPERIMENTAL
3460
-	/*
3461
-	 * FIXME: SPF lookup should only be done when a phish is found, see
3462
-	 *	above
3463
-	 */
3464
-	if(privdata->spf_ok && (strstr(mess, "FOUND") != NULL) && (strstr(mess, "Phishing") != NULL)) {
3465
-		logg(_("%s: Ignoring phish false positive\n"), sendmailId);
3466
-		strcpy(mess, "OK");
3467
-	}
3460
+	if((strstr(mess, "FOUND") != NULL) && (strstr(mess, "Phishing") != NULL))
3461
+		if(spf(privdata)) {
3462
+			logg(_("%s: Ignoring phish false positive\n"), sendmailId);
3463
+			strcpy(mess, "OK");
3464
+		}
3468 3465
 #endif
3469 3466
 	if(strstr(mess, "ERROR") != NULL) {
3470 3467
 		if(strstr(mess, "Size limit reached") != NULL) {
... ...
@@ -6134,8 +6123,11 @@ resolve(const char *host, table_t *t)
6134 6134
  * TODO: ptr
6135 6135
  * TODO: IPv6?
6136 6136
  * TODO: cache queries
6137
+ *
6138
+ * Return 1 if SPF says this email is from a legitimate source
6139
+ *	0 for fail or unknown
6137 6140
  */
6138
-static void
6141
+static int
6139 6142
 spf(struct privdata *privdata)
6140 6143
 {
6141 6144
 	char *host, *ptr;
... ...
@@ -6149,27 +6141,27 @@ spf(struct privdata *privdata)
6149 6149
 	char buf[BUFSIZ];
6150 6150
 
6151 6151
 	if(privdata->ip[0] == '\0')
6152
-		return;
6152
+		return 0;
6153 6153
 	if(strcmp(privdata->ip, "127.0.0.1") == 0) {
6154 6154
 		/* Loopback always pass SPF */
6155 6155
 		privdata->spf_ok = 1;
6156
-		return;
6156
+		return 1;
6157 6157
 	}
6158 6158
 	if(isLocal(privdata->ip)) {
6159 6159
 		/* Local addresses always pass SPF */
6160 6160
 		privdata->spf_ok = 1;
6161
-		return;
6161
+		return 1;
6162 6162
 	}
6163 6163
 
6164 6164
 	if(privdata->from == NULL)
6165
-		return;
6165
+		return 0;
6166 6166
 	if((host = strchr(privdata->from, '@')) == NULL)
6167
-		return;
6167
+		return 0;
6168 6168
 
6169 6169
 	host = cli_strdup(++host);
6170 6170
 
6171 6171
 	if(host == NULL)
6172
-		return;
6172
+		return 0;
6173 6173
 
6174 6174
 	ptr = strchr(host, '>');
6175 6175
 
... ...
@@ -6179,12 +6171,12 @@ spf(struct privdata *privdata)
6179 6179
 	len = res_query(host, C_IN, T_TXT, (u_char *)&q, sizeof(q));
6180 6180
 	if(len < 0) {
6181 6181
 		free(host);
6182
-		return;	/* Host has no TXT records */
6182
+		return 0;	/* Host has no TXT records */
6183 6183
 	}
6184 6184
 
6185 6185
 	if((unsigned int)len > sizeof(q)) {
6186 6186
 		free(host);
6187
-		return;
6187
+		return 0;
6188 6188
 	}
6189 6189
 
6190 6190
 	hp = &(q.h);
... ...
@@ -6194,7 +6186,7 @@ spf(struct privdata *privdata)
6194 6194
 	for(i = ntohs(hp->qdcount); i--; p += len + QFIXEDSZ)
6195 6195
 		if((len = dn_skipname(p, end)) < 0) {
6196 6196
 			free(host);
6197
-			return;
6197
+			return 0;
6198 6198
 		}
6199 6199
 
6200 6200
 	i = ntohs(hp->ancount);
... ...
@@ -6206,7 +6198,7 @@ spf(struct privdata *privdata)
6206 6206
 
6207 6207
 		if((len = dn_expand(q.u, end, p, buf, sizeof(buf) - 1)) < 0) {
6208 6208
 			free(host);
6209
-			return;
6209
+			return 0;
6210 6210
 		}
6211 6211
 		p += len;
6212 6212
 		GETSHORT(type, p);
... ...
@@ -6224,7 +6216,7 @@ spf(struct privdata *privdata)
6224 6224
 			char *record;
6225 6225
 			struct in_addr remote_ip;	/* IP connecting to us */
6226 6226
 
6227
-			logg("%s(%s): SPF record %s\n",
6227
+			logg("#%s(%s): SPF record %s\n",
6228 6228
 				host, privdata->ip, txt);
6229 6229
 #ifdef HAVE_INET_NTOP
6230 6230
 			/* IPv4 address ? */
... ...
@@ -6267,7 +6259,7 @@ spf(struct privdata *privdata)
6267 6267
 #endif
6268 6268
 					mask = MAKEMASK(preflen);
6269 6269
 					if((ntohl(remote_ip.s_addr) & mask) == (ntohl(spf_range.s_addr) & mask)) {
6270
-						logg("SPF ip4 pass\n");
6270
+						logg("#SPF ip4 pass\n");
6271 6271
 						privdata->spf_ok = 1;
6272 6272
 					}
6273 6273
 				} else if(strcmp(record, "mx") == 0) {
... ...
@@ -6335,6 +6327,8 @@ spf(struct privdata *privdata)
6335 6335
 		p += len;
6336 6336
 	}
6337 6337
 	free(host);
6338
+
6339
+	return privdata->spf_ok;
6338 6340
 }
6339 6341
 
6340 6342
 static void
... ...
@@ -6343,7 +6337,7 @@ spf_ip(char *ip, int zero, void *v)
6343 6343
 	struct privdata *privdata = (struct privdata *)v;
6344 6344
 
6345 6345
 	if(strcmp(ip, privdata->ip) == 0) {
6346
-		logg("SPF mx/a pass %s\n", ip);
6346
+		logg("#SPF mx/a pass %s\n", ip);
6347 6347
 		privdata->spf_ok = 1;
6348 6348
 	}
6349 6349
 }