Mercurial > hg > mlmmj
changeset 626:a07129231d84
cleaned up do_access() and added more logging
author | mortenp |
---|---|
date | Wed, 21 Feb 2007 09:45:14 +1100 |
parents | 745b09e3f8bc |
children | 4ee0e692bb1c |
files | src/mlmmj-process.c |
diffstat | 1 files changed, 75 insertions(+), 92 deletions(-) [+] |
line wrap: on
line diff
--- a/src/mlmmj-process.c Sat Feb 03 01:16:00 2007 +1100 +++ b/src/mlmmj-process.c Wed Feb 21 09:45:14 2007 +1100 @@ -60,11 +60,10 @@ }; -struct rule_list { - regex_t regexp; - unsigned int not; - enum action act; - struct rule_list *next; +static char *action_strs[] = { + "allowed", + "denied", + "moderated" }; @@ -154,147 +153,130 @@ } -static void free_rules(struct rule_list *rule) +static enum action do_access(struct strlist *rule_strs, struct strlist *hdrs, + const char *from, const char *listdir) { - struct rule_list *next; - - while (rule) { - next = rule->next; - regfree(&rule->regexp); - myfree(rule); - rule = next; - } -} - - -static enum action do_access(struct strlist *rule_strs, struct strlist *hdrs) -{ - int i; + int i, j; unsigned int match; - unsigned int rule_nr; - struct rule_list *head = NULL; - struct rule_list *rule, *new_rule; char *rule_ptr; char errbuf[128]; int err; - enum action ret; + enum action act; + unsigned int not; + regex_t regexp; + char *hdr; - /* They're going in backwards later on, so loop from the end here - * to get it right - */ - for (i=rule_strs->count-1; i>=0; i--) { - new_rule = mymalloc(sizeof(struct rule_list)); - - /* linked list */ - new_rule->next = head; - head = new_rule; + for (i=0; i<rule_strs->count; i++) { rule_ptr = rule_strs->strs[i]; + if (strncmp(rule_ptr, "allow", 5) == 0) { rule_ptr += 5; - new_rule->act = ALLOW; + act = ALLOW; } else if (strncmp(rule_ptr, "deny", 4) == 0) { rule_ptr += 4; - new_rule->act = DENY; + act = DENY; } else if (strncmp(rule_ptr, "moderate", 8) == 0) { rule_ptr += 8; - new_rule->act = MODERATE; + act = MODERATE; } else { errno = 0; - log_error(LOG_ARGS, "Unable to parse rule #%d!" - " Denying post to list", i); - free_rules(head); + log_error(LOG_ARGS, "Unable to parse rule #%d \"%s\":" + " Missing action keyword. Denying post from \"%s\"", + i, rule_strs->strs[i], from); + log_oper(listdir, OPLOGFNAME, "Unable to parse rule #%d \"%s\":" + " Missing action keyword. Denying post from \"%s\"", + i, rule_strs->strs[i], from); return DENY; } if (*rule_ptr == ' ') { rule_ptr++; } else if (*rule_ptr == '\0') { - /* We had a single allow/deny so match everything */ - *(--rule_ptr) = '.'; + /* the rule is a keyword and no regexp */ + log_oper(listdir, OPLOGFNAME, "mlmmj-process: access -" + " A mail from \"%s\" was %s by rule #%d \"%s\"", + from, action_strs[act], i, rule_strs->strs[i]); + return act; } else { /* we must have space or end of string */ errno = 0; - log_error(LOG_ARGS, "Unable to parse rule #%d!" - " Denying post to list", i); - free_rules(head); + log_error(LOG_ARGS, "Unable to parse rule #%d \"%s\":" + " Invalid character after action keyword." + " Denying post from \"%s\"", i, rule_strs->strs[i], from); + log_oper(listdir, OPLOGFNAME, "Unable to parse rule #%d \"%s\":" + " Invalid character after action keyword." + " Denying post from \"%s\"", i, rule_strs->strs[i], from); return DENY; } if (*rule_ptr == '!') { rule_ptr++; - new_rule->not = 1; + not = 1; } else { - new_rule->not = 0; + not = 0; } /* remove unanchored ".*" from beginning of regexp to stop the * regexp matching to loop so long time it seems like it's * hanging */ + if (strncmp(rule_ptr, "^.*", 3) == 0) { + rule_ptr += 3; + } + while (strncmp(rule_ptr, ".*", 2) == 0) { + rule_ptr += 2; + } - if (strlen(rule_ptr) > 2 && !strncmp(rule_ptr, ".*", 2)) - memmove(rule_ptr, rule_ptr + 2, strlen(rule_ptr) - 1); - - if ((err = regcomp(&new_rule->regexp, rule_ptr, + if ((err = regcomp(®exp, rule_ptr, REG_EXTENDED | REG_NOSUB | REG_ICASE))) { - regerror(err, &new_rule->regexp, errbuf, - sizeof(errbuf)); + regerror(err, ®exp, errbuf, sizeof(errbuf)); + regfree(®exp); errno = 0; - log_error(LOG_ARGS, "regcomp() failed for rule #%d!" + log_error(LOG_ARGS, "regcomp() failed for rule #%d \"%s\"" " (message: '%s') (expression: '%s')" - " Denying post to list", - i, errbuf, rule_ptr); - free_rules(head); + " Denying post from \"%s\"", + i, rule_strs->strs[i], errbuf, rule_ptr, from); + log_oper(listdir, OPLOGFNAME, "regcomp() failed for rule" + " #%d \"%s\" (message: '%s') (expression: '%s')" + " Denying post from \"%s\"", + i, rule_strs->strs[i], errbuf, rule_ptr, from); return DENY; } -#if 0 - printf("rule #%d: %s if%s match '%s'\n", i, - (new_rule->act == ALLOW) ? "allow" : "deny", - (new_rule->not) ? " not" : "", - rule_ptr); -#endif - - } - - rule = head; - for (rule_nr=0; rule; rule_nr++) { match = 0; - for (i=0; i<hdrs->count; i++) { - if (regexec(&rule->regexp, hdrs->strs[i], 0, NULL, 0) + for (j=0; j<hdrs->count; j++) { + if (regexec(®exp, hdrs->strs[j], 0, NULL, 0) == 0) { match = 1; break; } } - if (match != rule->not) { - char *logstr; + + regfree(®exp); - errno = 0; - switch(rule->act) { - case ALLOW: - logstr = "allowed"; - break; - case MODERATE: - logstr = "moderated"; - break; - default: - case DENY: - logstr = "denied"; - break; + if (match != not) { + if (match) { + hdr = mystrdup(hdrs->strs[j]); + chomp(hdr); + log_oper(listdir, OPLOGFNAME, "mlmmj-process: access -" + " A mail from \"%s\" with header \"%s\" was %s by" + " rule #%d \"%s\"", from, hdr, action_strs[act], + i, rule_strs->strs[i]); + myfree(hdr); + } else { + log_oper(listdir, OPLOGFNAME, "mlmmj-process: access -" + " A mail from \"%s\" was %s by rule #%d \"%s\"" + " because no header matched.", from, + action_strs[act], i, rule_strs->strs[i]); + } + return act; } - log_error(LOG_ARGS, "A mail was %s by rule #%d", - logstr, rule_nr); - ret = rule->act; - free_rules(head); - return ret; } - rule = rule->next; - } - - free_rules(head); + log_oper(listdir, OPLOGFNAME, "mlmmj-process: access -" + " A mail from \"%s\" didn't match any rules, and" + " was denied by default.", from); return DENY; } @@ -812,7 +794,8 @@ enum action accret; /* Don't send a mail about denial to the list, but silently * discard and exit. Also do this in case it's turned off */ - accret = do_access(access_rules, &allheaders); + accret = do_access(access_rules, &allheaders, + fromemails.emaillist[0], listdir); if (accret == DENY) { if ((strcasecmp(listaddr, fromemails.emaillist[0]) == 0) || noaccessdenymails) {