Browse Source

Plan 9 from Bell Labs 2004-01-28

David du Colombier 18 years ago
parent
commit
389d76096c
3 changed files with 68 additions and 49 deletions
  1. 2 2
      dist/replica/plan9.db
  2. 2 0
      dist/replica/plan9.log
  3. 64 47
      sys/src/cmd/upas/smtp/greylist.c

+ 2 - 2
dist/replica/plan9.db

@@ -375,7 +375,7 @@
 386/bin/rx - 775 sys sys 1071245345 80158
 386/bin/sam - 775 sys sys 1064598302 156664
 386/bin/scat - 775 sys sys 1071245346 282545
-386/bin/scp - 775 sys sys 1069592375 151684
+386/bin/scp - 775 sys sys 1075184164 151804
 386/bin/scuzz - 775 sys sys 1064598306 110748
 386/bin/sed - 775 sys sys 1064598306 88194
 386/bin/seq - 775 sys sys 1064598307 38429
@@ -10868,7 +10868,7 @@ sys/src/cmd/upas/send/skipequiv.c - 664 sys sys 944961322 1747
 sys/src/cmd/upas/send/translate.c - 664 sys sys 944961322 804
 sys/src/cmd/upas/send/tryit - 664 sys sys 944961322 584
 sys/src/cmd/upas/smtp - 20000000775 sys sys 988250017 0
-sys/src/cmd/upas/smtp/greylist.c - 664 sys sys 1071335923 5588
+sys/src/cmd/upas/smtp/greylist.c - 664 sys sys 1075211327 6300
 sys/src/cmd/upas/smtp/mkfile - 664 sys sys 1067722781 746
 sys/src/cmd/upas/smtp/mxdial.c - 664 sys sys 1055703150 4887
 sys/src/cmd/upas/smtp/rfc822.y - 664 sys sys 1064589606 13417

+ 2 - 0
dist/replica/plan9.log

@@ -13784,3 +13784,5 @@
 1075098663 2 c 386/bin/upas/nedmail - 775 sys sys 1075097690 154056
 1075098663 3 a 386/bin/upas/unesc - 775 sys sys 1075097691 133345
 1075131067 0 c sys/src/cmd/ssh/scp.c - 664 sys sys 1075130172 13886
+1075185075 0 c 386/bin/scp - 775 sys sys 1075184164 151804
+1075212079 0 c sys/src/cmd/upas/smtp/greylist.c - 664 sys sys 1075211327 6300

+ 64 - 47
sys/src/cmd/upas/smtp/greylist.c

@@ -4,6 +4,13 @@
 #include <ctype.h>
 #include <ip.h>
 
+typedef struct {
+	int	existed;	/* these two are distinct to cope with errors */
+	int	created;
+	int	noperm;
+	long	mtime;		/* mod time, iff it already existed */
+} Greysts;
+
 /*
  * There's a bit of a problem with yahoo; they apparently have a vast
  * pool of machines that all run the same queue(s), so a 451 retry can
@@ -73,18 +80,6 @@ onwhitelist(void)
 	return line != nil;
 }
 
-static int
-tryaddgrey(char *file)
-{
-	int fd = create(file, OWRITE|OEXCL, 0444);
-
-	if (fd >= 0) {
-		close(fd);
-		return 1;
-	}
-	return 0;
-}
-
 static int mkdirs(char *);
 
 /*
@@ -133,29 +128,61 @@ mkdirs(char *path)
 	return 0;
 }
 
-/* true if we added it and it wasn't already present */
-static int
-addgreylist(char *file)
+static long
+getmtime(char *file)
 {
-	if (tryaddgrey(file))
-		return 1;
+	long mtime = -1;
+	Dir *ds = dirstat(file);
 
-	/* make presumed-missing intermediate directories */
-	if (mkpdirs(file) < 0)
-		return 0;
+	if (ds != nil) {
+		mtime = ds->mtime;
+		free(ds);
+	}
+	return mtime;
+}
 
-	/* retry the greylist entry */
-	if (tryaddgrey(file))
-		return 1;
+static void
+tryaddgrey(char *file, Greysts *gsp)
+{
+	int fd = create(file, OWRITE|OEXCL, 0444|DMEXCL);
 
-	/* it's in the list now, we're a 2nd conn., so add to whitelist */
-	return 0;
+	gsp->created = (fd >= 0);
+	if (fd >= 0) {
+		close(fd);
+		gsp->existed = 0;  /* just created; couldn't have existed */
+	} else {
+		/*
+		 * why couldn't we create file? it must have existed
+		 * (or we were denied perm on parent dir.).
+		 * if it existed, fill in gsp->mtime; otherwise
+		 * make presumed-missing intermediate directories.
+		 */
+		gsp->existed = access(file, AEXIST) >= 0;
+		if (gsp->existed)
+			gsp->mtime = getmtime(file);
+		else if (mkpdirs(file) < 0)
+			gsp->noperm = 1;
+	}
+}
+
+static void
+addgreylist(char *file, Greysts *gsp)
+{
+	tryaddgrey(file, gsp);
+	if (!gsp->created && !gsp->existed && !gsp->noperm)
+		/* retry the greylist entry with parent dirs created */
+		tryaddgrey(file, gsp);
 }
 
 static int
-recentcall(long mtime)
+recentcall(Greysts *gsp)
 {
-	return time(0) - mtime <= Nonspammax;
+	long delay = time(0) - gsp->mtime;
+
+	if (!gsp->existed)
+		return 0;
+	/* reject immediate call-back; spammers are doing that now */
+	return delay >= 30 && delay <= Nonspammax;
 }
 
 /*
@@ -174,11 +201,10 @@ recentcall(long mtime)
 static int
 isrcptrecent(char *rcpt)
 {
-	int wasongrey;
-	long calltm = 0;
 	char *user;
 	char file[256];
-	Dir *ds;
+	Greysts gs;
+	Greysts *gsp = &gs;
 
 	if (rcpt[0] == '\0' || strchr(rcpt, '/') != nil ||
 	    strcmp(rcpt, ".") == 0 || strcmp(rcpt, "..") == 0)
@@ -191,31 +217,22 @@ isrcptrecent(char *rcpt)
 	else
 		user++;
 
+	/* check & try to update the grey list entry */
 	snprint(file, sizeof file, "/mail/grey/%s/%s/%s",
 		nci->lsys, nci->rsys, user);
-	ds = dirstat(file);
-	if (ds != nil)
-		wasongrey = 1;
-	else {
-		wasongrey = !addgreylist(file);
-		ds = dirstat(file);
-	}
-
-	if (ds != nil) {
-		calltm = ds->mtime;
-		free(ds);
-	}
+	memset(gsp, 0, sizeof *gsp);
+	addgreylist(file, gsp);
 
 	/* if on greylist already and prior call was recent, add to whitelist */
-	if (wasongrey && recentcall(calltm)) {
+	if (gsp->existed && recentcall(gsp)) {
 		syslog(0, "smtpd",
 			"%s/%s was grey; adding IP to white", nci->rsys, rcpt);
 		return 1;
-	} else if (wasongrey)
-		syslog(0, "smtpd", "call for %s/%s was too long ago",
+	} else if (gsp->existed)
+		syslog(0, "smtpd", "call for %s/%s was seconds ago or long ago",
 			nci->rsys, rcpt);
 	else
-		syslog(0, "smtpd", "no registered call for %s/%s",
+		syslog(0, "smtpd", "no call registered for %s/%s; registering",
 			nci->rsys, rcpt);
 	return 0;
 }
@@ -235,7 +252,7 @@ vfysenderhostok(void)
 
 	/* if on greylist already and prior call was recent, add to whitelist */
 	if (recent) {
-		int fd = create(whitelist, OWRITE, 0444|DMAPPEND);
+		int fd = create(whitelist, OWRITE, 0666|DMAPPEND);
 
 		if (fd >= 0) {
 			seek(fd, 0, 2);			/* paranoia */