summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Denker <jsd@av8n.com>2012-07-20 22:18:31 -0700
committerJohn Denker <jsd@av8n.com>2012-07-29 15:32:35 -0700
commit60ebe6c00a2868e6bb69ef30cf04e5568276808b (patch)
tree68234b25e80f1f838ecc39676518cd59c9592a3b
parent4e298a27d17d0d0a4181b302b4237363396eb0ed (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.conf6
-rw-r--r--tools/greylist.c82
-rw-r--r--tools/hi-q.c21
-rw-r--r--tools/hi-test2.conf2
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 !