changeset 832:dc8136010a35

Add rejection of posts and obstruction of subscriptions.
author Ben Schmidt
date Mon, 23 Jan 2012 17:02:18 +1100
parents f7295507141c
children a1ba22fc5a36
files ChangeLog man/mlmmj-sub.1 src/listcontrol.c src/mlmmj-process.c src/mlmmj-sub.c
diffstat 5 files changed, 136 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Jan 23 16:28:05 2012 +1100
+++ b/ChangeLog	Mon Jan 23 17:02:18 2012 +1100
@@ -1,3 +1,4 @@
+ o Add rejection of posts and obstruction of subscriptions.
  o Avoid bogus error messages when logging that the list address has been
    found in To: or CC: headers.
  o Escape dashes in man pages.
--- a/man/mlmmj-sub.1	Mon Jan 23 16:28:05 2012 +1100
+++ b/man/mlmmj-sub.1	Mon Jan 23 17:02:18 2012 +1100
@@ -20,7 +20,7 @@
 .HP
 \fB\-L\fR: Full path to list directory
 .HP
-\fB\-m\fR: Subscriber moderation string
+\fB\-m\fR: Moderation string
 .HP
 \fB\-n\fR: Subscribe to nomail version of the list
 .HP
--- a/src/listcontrol.c	Mon Jan 23 16:28:05 2012 +1100
+++ b/src/listcontrol.c	Mon Jan 23 17:02:18 2012 +1100
@@ -62,6 +62,10 @@
 	CTRL_CONFUNSUB_NOMAIL,
 	CTRL_CONFUNSUB,
 	CTRL_BOUNCES,
+	CTRL_RELEASE,
+	CTRL_REJECT,
+	CTRL_PERMIT,
+	CTRL_OBSTRUCT,
 	CTRL_MODERATE,
 	CTRL_HELP,
 	CTRL_FAQ,
@@ -92,6 +96,10 @@
 	{ "confunsub-nomail",   1 },
 	{ "confunsub",          1 },
 	{ "bounces",            1 },
+	{ "release",            1 },
+	{ "reject",             1 },
+	{ "permit",             1 },
+	{ "obstruct",           1 },
 	{ "moderate",           1 },
 	{ "help",               0 },
 	{ "faq",                0 },
@@ -106,7 +114,8 @@
 		const char *mlmmjbounce, const char *mailname)
 {
 	char *bouncenr, *tmpstr;
-	char *param = NULL, *conffilename, *moderatefilename, *omitfilename;
+	char *param = NULL, *conffilename, *moderatefilename, *gatekeepfilename;
+	char *omitfilename;
 	char *omit = NULL;
 	char *c, *archivefilename, *sendfilename;
 	const char *subswitch;
@@ -612,31 +621,31 @@
 		exit(EXIT_FAILURE);
 		break;
 
-	/* listname+moderate-COOKIE@domain.tld */
+	/* listname+release-COOKIE@domain.tld */
+	case CTRL_RELEASE:
+	/* DEPRECATED: listname+moderate-COOKIE@domain.tld */
+	/* DEPRECATED: listname+moderate-subscribeCOOKIE@domain.tld */
 	case CTRL_MODERATE:
-		/* TODO Add accept/reject parameter to moderate */
-		moderatefilename = concatstr(3, listdir, "/moderation/", param);
-
-		/* Subscriber moderation */
+		/* Subscriber moderation; DEPRECATED */
 		if(strncmp(param, "subscribe", 9) == 0) {
-			log_oper(listdir, OPLOGFNAME, "%s moderated %s",
-				fromemails->emaillist[0], moderatefilename);
-			execlp(mlmmjsub, mlmmjsub,
-					"-L", listdir,
-					"-m", param,
-					"-c", (char *)NULL);
+			tmpstr = mystrdup(param + 9);
+			myfree(param);
+			param = tmpstr;
+			goto permit;
 		}
 
-		sendfilename = concatstr(2, moderatefilename, ".sending");
+		moderatefilename = concatstr(3, listdir, "/moderation/", param);
 		if(stat(moderatefilename, &stbuf) < 0) {
 			myfree(moderatefilename);
 			/* no mail to moderate */
 			errno = 0;
-			log_error(LOG_ARGS, "A moderate request was"
+			log_error(LOG_ARGS, "A release request was"
 				" sent with a mismatching cookie."
 				" Ignoring mail");
 			return -1;
 		}
+
+		sendfilename = concatstr(2, moderatefilename, ".sending");
 		/* Rename it to avoid mail being sent twice */
 		if(rename(moderatefilename, sendfilename) < 0) {
 			log_error(LOG_ARGS, "Could not rename to .sending");
@@ -658,9 +667,11 @@
 			myfree(omitfilename);
 		}
 
-		log_oper(listdir, OPLOGFNAME, "%s moderated %s",
-				fromemails->emaillist[0], moderatefilename);
 		myfree(moderatefilename);
+
+		log_oper(listdir, OPLOGFNAME, "%s released %s",
+				fromemails->emaillist[0], param);
+
 		if (omit != NULL)
 			execlp(mlmmjsend, mlmmjsend,
 					"-L", listdir,
@@ -675,6 +686,80 @@
 		exit(EXIT_FAILURE);
 		break;
 
+	/* listname+reject-COOKIE@domain.tld */
+	case CTRL_REJECT:
+		moderatefilename = concatstr(3, listdir, "/moderation/", param);
+		if(stat(moderatefilename, &stbuf) < 0) {
+			myfree(moderatefilename);
+			/* no mail to moderate */
+			errno = 0;
+			log_error(LOG_ARGS, "A reject request was"
+				" sent with a mismatching cookie."
+				" Ignoring mail");
+			return -1;
+		}
+		log_oper(listdir, OPLOGFNAME, "%s rejected %s",
+			fromemails->emaillist[0], param);
+		myfree(param);
+		if (unlink(moderatefilename) != 0) {
+			log_error(LOG_ARGS, "Could not unlink %s",
+					moderatefilename);
+			myfree(moderatefilename);
+			exit(EXIT_FAILURE);
+		}
+		myfree(moderatefilename);
+		break;
+
+	/* listname+permit-COOKIE@domain.tld */
+	case CTRL_PERMIT:
+permit:
+		gatekeepfilename = concatstr(3, listdir,
+				"/moderation/subscribe", param);
+		if(stat(gatekeepfilename, &stbuf) < 0) {
+			myfree(gatekeepfilename);
+			/* no mail to moderate */
+			errno = 0;
+			log_error(LOG_ARGS, "A permit request was"
+				" sent with a mismatching cookie."
+				" Ignoring mail");
+			return -1;
+		}
+		log_oper(listdir, OPLOGFNAME, "%s permitted %s",
+			fromemails->emaillist[0], param);
+		execlp(mlmmjsub, mlmmjsub,
+				"-L", listdir,
+				"-m", param,
+				"-c", (char *)NULL);
+		log_error(LOG_ARGS, "execlp() of '%s' failed",
+					mlmmjsub);
+		exit(EXIT_FAILURE);
+		break;
+
+	/* listname+obstruct-COOKIE@domain.tld */
+	case CTRL_OBSTRUCT:
+		gatekeepfilename = concatstr(3, listdir,
+				"/moderation/subscribe", param);
+		if(stat(gatekeepfilename, &stbuf) < 0) {
+			myfree(gatekeepfilename);
+			/* no mail to moderate */
+			errno = 0;
+			log_error(LOG_ARGS, "An obstruct request was"
+				" sent with a mismatching cookie."
+				" Ignoring mail");
+			return -1;
+		}
+		log_oper(listdir, OPLOGFNAME, "%s obstructed %s",
+			fromemails->emaillist[0], param);
+		myfree(param);
+		if (unlink(gatekeepfilename) != 0) {
+			log_error(LOG_ARGS, "Could not unlink %s",
+					gatekeepfilename);
+			myfree(gatekeepfilename);
+			exit(EXIT_FAILURE);
+		}
+		myfree(gatekeepfilename);
+		break;
+
 	/* listname+help@domain.tld */
 	case CTRL_HELP:
 		if(!strchr(fromemails->emaillist[0], '@')) {
--- a/src/mlmmj-process.c	Mon Jan 23 16:28:05 2012 +1100
+++ b/src/mlmmj-process.c	Mon Jan 23 17:02:18 2012 +1100
@@ -96,7 +96,7 @@
 	text *txt;
 	memory_lines_state *mls;
 	char *queuefilename = NULL, *moderatorsfilename, *efromismod = NULL;
-	char *mailbasename = mybasename(mailfilename), *tmp, *to;
+	char *mailbasename = mybasename(mailfilename), *tmp, *to, *reject;
 	int moderatorsfd, foundaddr = 0, notifymod = 0, status;
 	pid_t childpid, pid;
 #if 0
@@ -138,7 +138,9 @@
 	myfree(moderators);
 
 	listdelim = getlistdelim(listdir);
-	replyto = concatstr(6, listname, listdelim, "moderate-", mailbasename,
+	replyto = concatstr(6, listname, listdelim, "release-", mailbasename,
+			    "@", listfqdn);
+	reject = concatstr(6, listname, listdelim, "reject-", mailbasename,
 			    "@", listfqdn);
 
 	from = concatstr(4, listname, listdelim, "owner@", listfqdn);
@@ -155,6 +157,7 @@
 	register_unformatted(txt, "posteraddr", posteraddr);
 	register_unformatted(txt, "moderateaddr", replyto); /* DEPRECATED */
 	register_unformatted(txt, "releaseaddr", replyto);
+	register_unformatted(txt, "rejectaddr", reject);
 	register_unformatted(txt, "moderators", "%moderators%"); /* DEPRECATED */
 	register_formatted(txt, "moderators",
 			rewind_memory_lines, get_memory_line, mls);
--- a/src/mlmmj-sub.c	Mon Jan 23 16:28:05 2012 +1100
+++ b/src/mlmmj-sub.c	Mon Jan 23 17:02:18 2012 +1100
@@ -74,8 +74,8 @@
 	text *txt;
 	memory_lines_state *mls;
 	char *a = NULL, *queuefilename, *from, *listname, *listfqdn, *str;
-	char *modfilename, *randomstr, *mods, *to, *replyto, *moderators = NULL;
-	char *modfilebase;
+	char *modfilename, *mods, *to, *replyto, *moderators = NULL;
+	char *cookie, *obstruct;
 	struct strlist *submods;
 	pid_t childpid, pid;
 
@@ -93,25 +93,24 @@
 			break;
 	}
 	
-	randomstr = random_str();
+	for (;;) {
+		cookie = random_str();
 	modfilename = concatstr(3, listdir, "/moderation/subscribe",
-			randomstr);
-	myfree(randomstr);
-
+				cookie);
 	fd = open(modfilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
-	while(fd < 0 && errno == EEXIST) {
+		if (fd < 0) {
+			if (errno == EEXIST) {
+				myfree(cookie);
 		myfree(modfilename);
-		randomstr = random_str();
-		modfilename = concatstr(3, listdir, "/moderation/subscribe",
-				randomstr);
-		myfree(randomstr);
-		fd = open(modfilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
+				continue;
 	}
-	if(fd < 0) {
 		log_error(LOG_ARGS, "could not create %s"
 				"ignoring request: %s", str);
 		exit(EXIT_FAILURE);
 	}
+		break;
+	}
+
 	if(writen(fd, str, strlen(str)) < 0) {
 		log_error(LOG_ARGS, "could not write to %s"
 				"ignoring request: %s", str);
@@ -144,13 +143,14 @@
 	listdelim = getlistdelim(listdir);
 	listfqdn = genlistfqdn(listaddr);
 	listname = genlistname(listaddr);
-	modfilebase = mybasename(modfilename);
 
 	from = concatstr(4, listname, listdelim, "owner@", listfqdn);
 	to = concatstr(3, listname, "-moderators@", listfqdn);
-	replyto = concatstr(6, listname, listdelim, "moderate-", modfilebase,
+	replyto = concatstr(6, listname, listdelim, "permit-", cookie,
 			"@", listfqdn);
-	myfree(modfilebase);
+	obstruct = concatstr(6, listname, listdelim, "obstruct-", cookie,
+			"@", listfqdn);
+	myfree(cookie);
 	for(i = 0; i < submods->count; i++) {
 		printf("%s", submods->strs[i]);
 		str = moderators;
@@ -166,7 +166,8 @@
 	register_unformatted(txt, "subaddr", subaddr);
 	register_unformatted(txt, "moderateaddr", replyto); /* DEPRECATED */
 	register_unformatted(txt, "permitaddr", replyto);
-	register_unformatted(txt, "moderators", "%gatekeepers"); /* DEPRECATED */
+	register_unformatted(txt, "obstructaddr", obstruct);
+	register_unformatted(txt, "moderators", "%gatekeepers%"); /* DEPRECATED */
 	register_formatted(txt, "gatekeepers",
 			rewind_memory_lines, get_memory_line, mls);
 	queuefilename = prepstdreply(txt, listdir, "$listowner$", to, replyto);
@@ -242,7 +243,10 @@
 	int fd;
 	char *readaddr, *readtype, *modfilename;
 		
-	modfilename = concatstr(3, listdir, "/moderation/", modstr);
+	if (strncmp(modstr, "subscribe", 9) == 0)
+			modstr += 9;
+
+	modfilename = concatstr(3, listdir, "/moderation/subscribe", modstr);
 
 	fd = open(modfilename, O_RDONLY);
 	if(fd < 0) {