diff options
| author | John Denker <jsd@av8n.com> | 2012-07-20 22:18:31 -0700 | 
|---|---|---|
| committer | John Denker <jsd@av8n.com> | 2012-07-20 22:18:31 -0700 | 
| commit | 7c1ce87457e0eb69f7b9989c8538a169b6744d23 (patch) | |
| tree | 92bc230551433de150caf51ef9245c16e2613f34 | |
| parent | e6056a8ac7a8e843549e163a29d5545f6c97b8f7 (diff) | |
implement penaltybox return-code (exit status)
also make sure DNS checking doesn't interfere with more
basic duties such as keeping the greylist database updated
| -rw-r--r-- | tools/filters.conf | 6 | ||||
| -rw-r--r-- | tools/greylist.c | 82 | ||||
| -rw-r--r-- | tools/hi-q.c | 21 | ||||
| -rw-r--r-- | tools/hi-test2.conf | 2 | 
4 files changed, 72 insertions, 39 deletions
| diff --git a/tools/filters.conf b/tools/filters.conf index 9342441..f5b35f5 100644 --- a/tools/filters.conf +++ b/tools/filters.conf @@ -1,7 +1,7 @@  # configuration file for hi-q  series  /var/qmail/bin/skrewt -stub    /var/qmail/bin/greylist -sa      /usr/local/bin/spamc -Y 0 -s 1000000 +stub    /var/qmail/bin/greylist -check -v +sa      /usr/local/bin/spamc -Y 0 -s 1000000 -x  qq      /var/qmail/bin/qmail-queue -postspam /var/qmail/bin/greylist -suffix (post) -penalize 86400 +postspam /var/qmail/bin/greylist -suffix (post) -penalize 86400 -v diff --git a/tools/greylist.c b/tools/greylist.c index 465a78e..c5c891f 100644 --- a/tools/greylist.c +++ b/tools/greylist.c @@ -31,6 +31,7 @@ const int probation(4*hour);  #define foo(name, num) const int ex_ ## name = num  #define bar foo(good, 0) ;\  foo(spam, 21) ;\ +foo(penaltybox, 22) ;\  foo(greylisting, 70) ;\  foo(syserr, 71) ;\  foo(comerr, 74) ; @@ -90,9 +91,12 @@ public:    int ac_age;    string suffix;    string progid; +  int verbosity;    whatsit(const string name, const string _dirname) -  : dirname(_dirname), progname(name), mypid(getpid()), mod_age(0), ac_age(0) +  : dirname(_dirname), progname(name), mypid(getpid()), +    mod_age(0), ac_age(0), +    verbosity(0)    {      gettimeofday(&now, NULL);    } @@ -103,9 +107,15 @@ public:    void bind();  }; +string basename(const string path){ +  size_t where = path.rfind("/"); +  if (where != string::npos) return path.substr(1+where); +  return path; +} +  void whatsit::bind(){    stringstream foo; -  foo << progname << suffix  +  foo << basename(progname) << suffix       << "[" << mypid << "]";    progid = foo.str();  } @@ -166,6 +176,7 @@ void scan(const string progid, const string p, const int copies=1){            if (mod_age != ac_age) cout << "!";          } else if (mod_age < minimum_age) {            cout << " young"; +          if (mod_age != ac_age) cout << "!";          } else if (mod_age == ac_age) {            cout << " unused";          } else if (mod_age > maximum_age) { @@ -185,12 +196,15 @@ void scan(const string progid, const string p, const int copies=1){  void whatsit::update(const string msg, const timeval new_mod,       const timeval new_ac, const int penalty){ -  cerr << progid << ": " -       << msg << ": " << ipbase; -  if (hostname.length()) cerr <<  " " << hostname; -  cerr << "  mod_age: " << time_out(mod_age) -          << "  ac_age: " << time_out(ac_age) -          << endl; +  if (verbosity){ +    cerr << progid << ": "; +    if (penalty) cerr << " penalty+"; +    cerr << msg << ": " << ipbase; +    if (hostname.length()) cerr <<  " " << hostname; +    cerr << "  mod_age: " << time_out(mod_age) +            << "  ac_age: " << time_out(ac_age) +            << endl; +  }    timeval pen_mod(new_mod);    if (penalty) {      pen_mod = now; @@ -213,12 +227,17 @@ int main(int _argc, char** _argv){    int scanmode(0);    int copies(1);    int penalty(0); +  int check(0);    while (argc > 0) {      string arg = argv[0]; argc--; argv++;      if (prefix(arg, "-scan")) {        scanmode++;      } else if (prefix(arg, "-copy"))  {        copies++; +    } else if (prefix(arg, "-verbose"))  { +      foo.verbosity++; +    } else if (prefix(arg, "-check"))  { +      check++;      } else if (prefix(arg, "-penalize")          || prefix(arg, "-penalty"))  {        if (!argc){ @@ -244,7 +263,22 @@ int main(int _argc, char** _argv){      return 0;    } -  return foo.doit(penalty); +  int sts = foo.doit(penalty); + +// perform some extra checks. +// Probably a better design would be to +//  a) make more thorough DNS checks, and +//  b) move all the DNS checking to a separate module +  if (check){ +    char* hostvar = getenv("TCPREMOTEHOST"); +    if (!hostvar) { +      cerr << foo.progid +        << " from " << foo.ipbase +        << " ... TCPREMOTEHOST not set???" << endl; +      exeunt(ex_spam); +    } +  } +  exeunt(sts);  }  int whatsit::doit(const int penalty){ @@ -254,18 +288,11 @@ int whatsit::doit(const int penalty){        << " TCPREMOTEIP not set???" << endl;      // should never happen      // although you can make it happen using a weird test-harness -    exeunt(ex_syserr); +    return(ex_syserr);    }    ipbase = ipvar;    char* hostvar = getenv("TCPREMOTEHOST"); -  if (!hostvar) { -    cerr << progid -      << " from " << ipbase -      << " ... TCPREMOTEHOST not set???" << endl; -    exeunt(ex_spam); -  } else { -    hostname = hostvar; -  } +  if (hostvar) hostname = hostvar;  // see if our directory exists:    struct stat dirstat; @@ -283,7 +310,7 @@ int whatsit::doit(const int penalty){          << ": mkdir failed for '"          << dirname << "' : ";        perror(0); -      exeunt(ex_syserr); +      return(ex_syserr);      }    } @@ -304,33 +331,34 @@ int whatsit::doit(const int penalty){        perror(0);      }      close(fd); -    update("new customer", now, now); -    exeunt(ex_greylisting); +    update("new customer", now, now, penalty); +    return(ex_greylisting);    } -// here if stat succeeded + +// now for really checking the greylist status:    mod_age = now.tv_sec - ipstat.st_mtime;    ac_age = now.tv_sec - ipstat.st_atime;    timeval mod_orig = {ipstat.st_mtime, 0};    if (mod_age < 0) {      update("penalty box", mod_orig, now, penalty); -    exeunt(ex_spam); +    return(ex_penaltybox);    }    if (mod_age < ac_age){      update("paroled spammer", now, now, penalty); -    exeunt(ex_greylisting); +    return(ex_greylisting);    }    if (mod_age < minimum_age) {      update("early bird", mod_orig, now, penalty); -    exeunt(ex_greylisting); +    return(ex_greylisting);    }    if (mod_age - ac_age < minimum_age    // early bird, or completely unused      && mod_age > probation) {           // did not diligently resubmit      update("disprobation", now, now, penalty); -    exeunt(ex_greylisting); +    return(ex_greylisting);    }    if (ac_age > maximum_age) {      update("too old, starting over", now, now, penalty); -    exeunt(ex_greylisting); +    return(ex_greylisting);    }  // if all checks are passed, must be OK:    update("returning customer", mod_orig, now, penalty); diff --git a/tools/hi-q.c b/tools/hi-q.c index 26e67a7..6aaf302 100644 --- a/tools/hi-q.c +++ b/tools/hi-q.c @@ -30,6 +30,7 @@ using namespace std;  #define bar \  foo(good, 0) ;\  foo(spam, 21) ;\ +foo(penaltybox, 22) ;\  foo(permerr, 31) ;\  foo(greylisting, 70) ;\  foo(syserr, 71) ;\ @@ -188,6 +189,7 @@ void exeunt(const int sts) {    // FIXME: stop other children    //xxxx cerr << "hi-q: exeunt called with " << sts << endl;    if (sts == ex_spam) fork_and_wait(post); +  if (sts == ex_penaltybox) exit(ex_spam);    exit(sts);  } @@ -274,15 +276,18 @@ int xclose(int arg){  extern char** environ; +string basename(const string path){ +  size_t where = path.rfind("/"); +  if (where != string::npos) return path.substr(1+where); +  return path; +} +  int main(int argc, char** argv) {    {      progname = *argv;      mypid = getpid(); -    string shortname = progname; -    size_t where = shortname.rfind("/"); -    if (where != string::npos) shortname = shortname.substr(1+where);      stringstream binder; -    binder << shortname << "[" << mypid << "]"; +    binder << basename(progname) << "[" << mypid << "]";      progid = binder.str();    } @@ -658,7 +663,7 @@ bar        }        cerr << progid           << " concludes: kid[" << kidno << "]" -         << " i.e. " << filter[kidno].cmd[0]  +         << " i.e. " << basename(filter[kidno].cmd[0])           << "[" <<  argbest_blame << "]"           << " reports " << exword << endl;        exeunt(excode); @@ -666,7 +671,7 @@ bar        int sig = WTERMSIG(best_blame);        cerr << progid           << " concludes: kid[" << kidno << "]" -         << " i.e. " << filter[kidno].cmd[0]  +         << " i.e. " << basename(filter[kidno].cmd[0])           << "[" <<  argbest_blame << "]"               << " was killed by signal " << sig               << endl; @@ -690,7 +695,7 @@ bar          int sts = WEXITSTATUS(kidstatus);          cerr << progid                  << " says: qq program"  -                << " i.e. " << filter[nkids-1].cmd[0]  +                << " i.e. " << basename(filter[nkids-1].cmd[0])                  << "[" <<  kidpid[nkids-1] << "]"                  << " returned status " << sts                  << endl; @@ -698,7 +703,7 @@ bar        } else if (WIFSIGNALED(kidstatus)) {          cerr << progid                  << " says: qq program"  -                << " i.e. " << filter[nkids-1].cmd[0]  +                << " i.e. " << basename(filter[nkids-1].cmd[0])                  << "[" <<  kidpid[nkids-1] << "]"                  << " was killed by signal " << WTERMSIG(kidstatus)                  << endl; diff --git a/tools/hi-test2.conf b/tools/hi-test2.conf index 90997b4..370ba77 100644 --- a/tools/hi-test2.conf +++ b/tools/hi-test2.conf @@ -1,6 +1,6 @@  stub    hi-test x0 -snooze 2  stub    hi-test x0 -snooze 1 -exit 0 -stub    greylist -suffix (sfx) +stub    greylist -suffix (sfx) -v -p 10  qq      hi-test x1 -snooze 3 -exit 3  postspam /bin/echo post spam ! | 
