summaryrefslogtreecommitdiff
path: root/tools/greylist.c
diff options
context:
space:
mode:
authorJohn Denker <jsd@av8n.com>2012-07-21 05:18:31 (GMT)
committerJohn Denker <jsd@av8n.com>2012-07-21 05:18:31 (GMT)
commit7c1ce87457e0eb69f7b9989c8538a169b6744d23 (patch)
tree92bc230551433de150caf51ef9245c16e2613f34 /tools/greylist.c
parente6056a8ac7a8e843549e163a29d5545f6c97b8f7 (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
Diffstat (limited to 'tools/greylist.c')
-rw-r--r--tools/greylist.c82
1 files changed, 55 insertions, 27 deletions
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);