# HG changeset patch # User Ben Schmidt # Date 1327298538 -39600 # Node ID dc8136010a356419d4ccaa36e431d0d95e30145a # Parent f7295507141c2e209642787724fd2b006dd9213f Add rejection of posts and obstruction of subscriptions. diff -r f7295507141c -r dc8136010a35 ChangeLog --- 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. diff -r f7295507141c -r dc8136010a35 man/mlmmj-sub.1 --- 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 diff -r f7295507141c -r dc8136010a35 src/listcontrol.c --- 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], '@')) { diff -r f7295507141c -r dc8136010a35 src/mlmmj-process.c --- 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); diff -r f7295507141c -r dc8136010a35 src/mlmmj-sub.c --- 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) {