From: Ben Schmidt Date: Mon, 23 Jan 2012 06:02:18 +0000 (+1100) Subject: Add rejection of posts and obstruction of subscriptions. X-Git-Tag: RELEASE_1_2_18a1~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6734768b0a4c469ae2defdfd6b84e0a1687f1186;p=thirdparty%2Fmlmmj.git Add rejection of posts and obstruction of subscriptions. --- diff --git a/ChangeLog b/ChangeLog index 6b926686..ab168b59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 --git a/man/mlmmj-sub.1 b/man/mlmmj-sub.1 index c958ac5f..5c7fb741 100644 --- a/man/mlmmj-sub.1 +++ b/man/mlmmj-sub.1 @@ -20,7 +20,7 @@ mlmmj-sub \- subscribe address to a mailinglist run by mlmmj .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 --git a/src/listcontrol.c b/src/listcontrol.c index 931dab18..52f57283 100644 --- a/src/listcontrol.c +++ b/src/listcontrol.c @@ -62,6 +62,10 @@ enum ctrl_e { 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 @@ static struct ctrl_command ctrl_commands[] = { { "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 @@ int listcontrol(struct email_container *fromemails, const char *listdir, 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 @@ int listcontrol(struct email_container *fromemails, const char *listdir, 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 @@ int listcontrol(struct email_container *fromemails, const char *listdir, 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 @@ int listcontrol(struct email_container *fromemails, const char *listdir, 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 --git a/src/mlmmj-process.c b/src/mlmmj-process.c index 5a45ece6..a8894c9b 100644 --- a/src/mlmmj-process.c +++ b/src/mlmmj-process.c @@ -96,7 +96,7 @@ static void newmoderated(const char *listdir, const char *mailfilename, 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 @@ static void newmoderated(const char *listdir, const char *mailfilename, 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 @@ static void newmoderated(const char *listdir, const char *mailfilename, 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 --git a/src/mlmmj-sub.c b/src/mlmmj-sub.c index 811db7a1..506b7d4d 100644 --- a/src/mlmmj-sub.c +++ b/src/mlmmj-sub.c @@ -74,8 +74,8 @@ void moderate_sub(const char *listdir, const char *listaddr, 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 @@ void moderate_sub(const char *listdir, const char *listaddr, break; } - 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); - while(fd < 0 && errno == EEXIST) { - myfree(modfilename); - 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); + if (fd < 0) { + if (errno == EEXIST) { + myfree(cookie); + myfree(modfilename); + continue; + } + log_error(LOG_ARGS, "could not create %s" + "ignoring request: %s", str); + exit(EXIT_FAILURE); + } + break; } - if(fd < 0) { - log_error(LOG_ARGS, "could not create %s" - "ignoring request: %s", str); - exit(EXIT_FAILURE); - } + if(writen(fd, str, strlen(str)) < 0) { log_error(LOG_ARGS, "could not write to %s" "ignoring request: %s", str); @@ -144,13 +143,14 @@ void moderate_sub(const char *listdir, const char *listaddr, 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 @@ void moderate_sub(const char *listdir, const char *listaddr, 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); @@ -241,8 +242,11 @@ void getaddrandtype(const char *listdir, const char *modstr, { 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) {