changeset 842:c6fe438f3e60

Fix access logic so subonlypost doesn't override a send access rule.
author Ben Schmidt
date Tue, 24 Jan 2012 04:08:24 +1100
parents fabf3a96132f
children 2ea56ea4bd34
files ChangeLog README.access TUNABLES src/mlmmj-process.c
diffstat 4 files changed, 91 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Jan 24 15:43:53 2012 +1100
+++ b/ChangeLog	Tue Jan 24 04:08:24 2012 +1100
@@ -1,3 +1,4 @@
+ o Fix access logic so subonlypost doesn't override a send access rule.
  o Make +unsubscribe remove the requester from all versions of the list.
  o Make mlmmj-unsub default to removing the requester from all versions of the
    list.
--- a/README.access	Tue Jan 24 15:43:53 2012 +1100
+++ b/README.access	Tue Jan 24 04:08:24 2012 +1100
@@ -28,7 +28,7 @@
 rules.
 
 The action "send" will send the mail unconditionally. It will not be
-moderated.
+moderated, nor subject to subonlypost, nor modnonsubposts.
 
 The action "deny" will not send the mail to the mailing list, but will send a
 rejection mail to the sender.
@@ -42,7 +42,7 @@
            function as moderators in listdir/control/moderators
 
 
-The flow through the access system is like this:
+The flow through the access system is something like this:
 
                deny       +------+
        +----------------->| deny |
@@ -58,12 +58,15 @@
     +--------+            +------+ confirm   +------+
        |  |                   ^                ^  ^
        |  |                   | yes            |  |
-       |  |    allow      +------------+ no    |  |
-       |  +-------------->| moderation |-------+  |
-       |                  +------------+          |
+       |  |    allow      +--------------+ no  |  |
+       |  +-------------->| moderation * |-----+  |
+       |                  +--------------+        |
        |       send                               |
        +------------------------------------------+
 
+* modnonsubposts is also processed here, and subonlypost (the flow
+  may be to deny or discard for subonlypost without modnonsubposts).
+
 
 First a simple example. This rule set will reject any mail that is NOT plain
 text, or has a subject that contains "BayStar", and allow anything else:
--- a/TUNABLES	Tue Jan 24 15:43:53 2012 +1100
+++ b/TUNABLES	Tue Jan 24 04:08:24 2012 +1100
@@ -47,8 +47,8 @@
 
  · modnonsubposts		(boolean)
 
-   When this file is present and subonlypost is enabled, all postings from
-   people who are not subscribed to the list will be moderated.
+   When this file is present, all postings from people who are not subscribed
+   to the list will be moderated.
 
  · prefix			(normal)
 
--- a/src/mlmmj-process.c	Tue Jan 24 15:43:53 2012 +1100
+++ b/src/mlmmj-process.c	Tue Jan 24 04:08:24 2012 +1100
@@ -416,13 +416,11 @@
 
 int main(int argc, char **argv)
 {
-	int i, j, opt, noprocess = 0, moderated = 0;
+	int i, j, opt, noprocess = 0, moderated = 0, send = 0;
 	enum modreason modreason;
 	int hdrfd, footfd, rawmailfd, donemailfd, omitfd;
-	int subonlypost = 0, addrtocc = 1, intocc = 0, modnonsubposts = 0;
+	int addrtocc = 1, intocc = 0;
 	int maxmailsize = 0;
-	int notoccdenymails = 0, noaccessdenymails = 0, nosubonlydenymails = 0;
-	int nomaxmailsizedenymails = 0;
 	int notmetoo = 0;
 	char *listdir = NULL, *mailfile = NULL, *headerfilename = NULL;
 	char *footerfilename = NULL, *donemailname = NULL;
@@ -751,8 +749,7 @@
 
 		if(st.st_size > maxmailsize) {
 
-			nomaxmailsizedenymails = statctrl(listdir, "nomaxmailsizedenymails");
-			if (nomaxmailsizedenymails) {
+			if (statctrl(listdir, "nomaxmailsizedenymails")) {
 				errno = 0;
 				log_error(LOG_ARGS, "Discarding %s due to"
 						" size limit (%d bytes too big)",
@@ -849,14 +846,12 @@
 	for(i = 0; i < alternates->count; i++)
 		myfree(alternates->strs[i]);
 
-	notoccdenymails = statctrl(listdir, "notoccdenymails");
-
 	if(addrtocc && !intocc) {
 		/* Don't send a mail about denial to the list, but silently
 		 * discard and exit. Also don't in case of it being turned off
 		 */
 		if ((strcasecmp(listaddr, posteraddr) == 0) ||
-				notoccdenymails) {
+				statctrl(listdir, "notoccdenymails")) {
 			log_error(LOG_ARGS, "Discarding %s because list"
 					" address was not in To: or Cc:,"
 					" and From: was the list or"
@@ -898,85 +893,6 @@
 		exit(EXIT_FAILURE);
 	}
 
-	subonlypost = statctrl(listdir, "subonlypost");
-	if(subonlypost) {
-		/* Don't send a mail about denial to the list, but silently
-		 * discard and exit. */
-		if (strcasecmp(listaddr, posteraddr) == 0) {
-			log_error(LOG_ARGS, "Discarding %s because"
-					" subonlypost was set and From: was"
-					" the list address",
-					mailfile);
-			myfree(listaddr);
-			unlink(donemailname);
-			myfree(donemailname);
-			exit(EXIT_SUCCESS);
-		}
-		if(is_subbed(listdir, posteraddr) == SUB_NONE) {
-			modnonsubposts = statctrl(listdir,
-					"modnonsubposts");
-			if(modnonsubposts) {
-				moderated = 1;
-				modreason = MODNONSUBPOSTS;
-				goto startaccess;
-			}
-
-			nosubonlydenymails = statctrl(listdir,
-					"nosubonlydenymails");
-
-			if(nosubonlydenymails) {
-				log_error(LOG_ARGS, "Discarding %s because"
-						" subonlypost and"
-						" nosubonlydenymails was set",
-						mailfile);
-				myfree(listaddr);
-				unlink(donemailname);
-				myfree(donemailname);
-				exit(EXIT_SUCCESS);
-			}
-			listdelim = getlistdelim(listdir);
-			listname = genlistname(listaddr);
-			listfqdn = genlistfqdn(listaddr);
-			fromaddr = concatstr(4, listname, listdelim,
-					"bounces-help@", listfqdn);
-			txt = open_text(listdir, "deny", "post",
-					"subonlypost", NULL, "subonlypost");
-			MY_ASSERT(txt);
-			register_unformatted(txt, "subject", subject);
-			register_unformatted(txt, "posteraddr", posteraddr);
-			register_originalmail(txt, donemailname);
-			queuefilename = prepstdreply(txt, listdir,
-					"$listowner$", posteraddr, NULL);
-			MY_ASSERT(queuefilename)
-			close_text(txt);
-			myfree(listaddr);
-			myfree(listdelim);
-			myfree(listname);
-			myfree(listfqdn);
-			unlink(donemailname);
-			myfree(donemailname);
-			execlp(mlmmjsend, mlmmjsend,
-					"-l", "1",
-					"-T", posteraddr,
-					"-F", fromaddr,
-					"-m", queuefilename, (char *)NULL);
-
-			log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend);
-			exit(EXIT_FAILURE);
-		}
-	}
-
-startaccess:
-
-	if(!moderated) {
-		if(statctrl(listdir, "moderated")) {
-			moderated = 1;
-			modreason = MODERATED;
-		}
-	}
-
-	noaccessdenymails = statctrl(listdir, "noaccessdenymails");
-
 	access_rules = ctrlvalues(listdir, "access");
 	if (access_rules) {
 		enum action accret;
@@ -986,7 +902,7 @@
 					posteraddr, listdir);
 		if (accret == DENY) {
 			if ((strcasecmp(listaddr, posteraddr) == 0) ||
-					noaccessdenymails) {
+				    statctrl(listdir, "noaccessdenymails")) {
 				log_error(LOG_ARGS, "Discarding %s because"
 						" it was denied by an access"
 						" rule, and From: was the list"
@@ -1048,12 +964,81 @@
 			myfree(discardname);
                 	exit(EXIT_SUCCESS);
 		} else if (accret == SEND) {
-			moderated = 0;
+			send = 1;
 		} else if (accret == ALLOW) {
 			/* continue processing as normal */
 		}
 	}
 
+	if(!send && (statctrl(listdir, "subonlypost") ||
+			statctrl(listdir, "modnonsubposts"))) {
+		/* Don't send a mail about denial to the list, but silently
+		 * discard and exit. */
+		if (strcasecmp(listaddr, posteraddr) == 0) {
+			log_error(LOG_ARGS, "Discarding %s because"
+					" subonlypost was set and From: was"
+					" the list address",
+					mailfile);
+			myfree(listaddr);
+			unlink(donemailname);
+			myfree(donemailname);
+			exit(EXIT_SUCCESS);
+		}
+		if(is_subbed(listdir, posteraddr) == SUB_NONE) {
+			if(statctrl(listdir, "modnonsubposts")) {
+				moderated = 1;
+				modreason = MODNONSUBPOSTS;
+			} else {
+				if(statctrl(listdir, "nosubonlydenymails")) {
+				    log_error(LOG_ARGS, "Discarding %s because"
+					    " subonlypost and"
+					    " nosubonlydenymails was set",
+					    mailfile);
+				    myfree(listaddr);
+				    unlink(donemailname);
+				    myfree(donemailname);
+				    exit(EXIT_SUCCESS);
+				}
+				listdelim = getlistdelim(listdir);
+				listname = genlistname(listaddr);
+				listfqdn = genlistfqdn(listaddr);
+				fromaddr = concatstr(4, listname, listdelim,
+					"bounces-help@", listfqdn);
+				txt = open_text(listdir, "deny", "post",
+					"subonlypost", NULL, "subonlypost");
+				MY_ASSERT(txt);
+				register_unformatted(txt, "subject", subject);
+				register_unformatted(txt, "posteraddr", posteraddr);
+				register_originalmail(txt, donemailname);
+				queuefilename = prepstdreply(txt, listdir,
+					"$listowner$", posteraddr, NULL);
+				MY_ASSERT(queuefilename)
+				close_text(txt);
+				myfree(listaddr);
+				myfree(listdelim);
+				myfree(listname);
+				myfree(listfqdn);
+				unlink(donemailname);
+				myfree(donemailname);
+				execlp(mlmmjsend, mlmmjsend,
+					"-l", "1",
+					"-T", posteraddr,
+					"-F", fromaddr,
+					"-m", queuefilename, (char *)NULL);
+
+				log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend);
+				exit(EXIT_FAILURE);
+			}
+		}
+	}
+
+	if(!send && !moderated) {
+		if(statctrl(listdir, "moderated")) {
+			moderated = 1;
+			modreason = MODERATED;
+		}
+	}
+
 	notmetoo = statctrl(listdir, "notmetoo");
 
 	if(moderated) {