From cbbd45a9700a660bcc4e2f762f5004c2aa2b1078 Mon Sep 17 00:00:00 2001 From: John Denker Date: Tue, 17 Jul 2012 14:33:26 -0700 Subject: implement "-addr" option in mail-scan --- tools/makefile | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/makefile') diff --git a/tools/makefile b/tools/makefile index 7f5dcef..e092702 100644 --- a/tools/makefile +++ b/tools/makefile @@ -14,6 +14,9 @@ progs = pido hi-q skrewt hi-test mail-scan all: $(progs) +mail-scan: mail-scan.o + $(CC) $< -lboost_regex -o $@ + install: install $(progs) /var/qmail/bin/ cp filters.conf aufilters.conf /var/qmail/control/ -- cgit v1.2.3 From 8fe5ccdb4ee79b4d287b82e80004e1acc9ee4b94 Mon Sep 17 00:00:00 2001 From: John Denker Date: Thu, 19 Jul 2012 14:10:35 -0700 Subject: teach hi-q to have a "mode" word at the front of each line --- tools/aufilters.conf | 2 +- tools/filters.conf | 6 ++-- tools/hi-q.c | 82 ++++++++++++++++++++++++++++++++-------------------- tools/hi-test.conf | 9 ++++-- tools/hi-test2.conf | 6 ++-- tools/makefile | 2 -- 6 files changed, 63 insertions(+), 44 deletions(-) (limited to 'tools/makefile') diff --git a/tools/aufilters.conf b/tools/aufilters.conf index 2eea3fd..e166133 100644 --- a/tools/aufilters.conf +++ b/tools/aufilters.conf @@ -1,2 +1,2 @@ # configuration file for hi-q (authorized users) - /var/qmail/bin/qmail-queue +qq /var/qmail/bin/qmail-queue diff --git a/tools/filters.conf b/tools/filters.conf index 169f74d..8bc2efe 100644 --- a/tools/filters.conf +++ b/tools/filters.conf @@ -1,4 +1,4 @@ # configuration file for hi-q - /var/qmail/bin/skrewt - /usr/local/bin/spamc -Y 0 -s 1000000 - /var/qmail/bin/qmail-queue +black /var/qmail/bin/skrewt +black /usr/local/bin/spamc -Y 0 -s 1000000 +qq /var/qmail/bin/qmail-queue diff --git a/tools/hi-q.c b/tools/hi-q.c index 81e717a..6140206 100644 --- a/tools/hi-q.c +++ b/tools/hi-q.c @@ -134,6 +134,39 @@ int xclose(int arg){ extern char** environ; +typedef enum {gray, black, qq, fail} moder; + +class jobber{ +public: + moder mode; + vector cmd; + + jobber(const moder _mode, const vector _cmd) + : mode(_mode), cmd(_cmd) + {} + + jobber(const string _mode, const vector _cmd) + : mode(fail), cmd(_cmd){ + setmode(_mode); + } + + jobber() + : mode(fail), cmd(0) + {} + + void setmode(const string _mode) { + if (0) {} + else if (_mode == "gray") mode = gray; + else if (_mode == "grey") mode = gray; // variant spelling + else if (_mode == "black") mode = black; + else if (_mode == "qq") mode = qq; + else { + cerr << "jobber: bad mode: " << _mode << endl; + mode = fail; + } + } +}; + int main(int argc, char** argv) { int verbose(0); int kidstatus; @@ -141,27 +174,8 @@ int main(int argc, char** argv) { int rslt; int loose_end = 0; -#ifdef SpareStuff - char* slurp2_args[] = {"/home/jsd/hack/slurp2", 0}; - char* echo_args[] = {"/bin/echo", "hi there", 0}; - char* wc_args[] = {"/usr/bin/wc", 0}; - char* cat_args[] = {"/bin/cat", 0}; - char* spama_args[] = {"/usr/local/bin/spamassassin", "-e", 0}; - char* spamc_args[] = {"/usr/local/bin/spamc", "-Z", "7", 0}; - char* qq_args[] = {"/var/qmail/bin/qmail-queue", 0}; - - - - const char** joblist[] = { - cat_args, - slurp2_args, - 0 // required: zero terminates the list - }; - -#endif - typedef vector VS; - vector filter; + vector filter; string conf_var = "HI_Q_CONF"; char* auth = getenv("QMAIL_AUTHORIZED"); if (auth && *auth) conf_var = "HI_Q_AUCONF"; @@ -199,15 +213,19 @@ int main(int argc, char** argv) { string line; if (!getline(conf, line).good()) break; istringstream parse(line); - vector job; + jobber job; while (parse.good()){ string token; parse >> token; if (parse.fail()) break; if (token[0] == '#') break; - job.push_back(token); + job.cmd.push_back(token); + } + if (job.cmd.size()) { + job.setmode(job.cmd.front()); + job.cmd.erase(job.cmd.begin()); } - if (job.size()) filter.push_back(job); + if (job.cmd.size()) filter.push_back(job); } unsigned int nkids = filter.size(); @@ -218,8 +236,8 @@ int main(int argc, char** argv) { if (0 && verbose) for (unsigned int ii = 0; ii < nkids; ii++) { cerr << "hi-q filter[" << ii << "] :; "; - for (VS::const_iterator token = filter[ii].begin(); - token != filter[ii].end(); token++){ + for (VS::const_iterator token = filter[ii].cmd.begin(); + token != filter[ii].cmd.end(); token++){ cerr << *token << " "; } cerr << endl; @@ -351,10 +369,10 @@ int main(int argc, char** argv) { // (except last kid reads fd1 as well as fd0). //// probe_fd(); - int ntok = filter[ii].size(); + int ntok = filter[ii].cmd.size(); const char* prog[1+ntok]; for (int jj = 0; jj < ntok; jj++){ - prog[jj] = filter[ii][jj].c_str(); + prog[jj] = filter[ii].cmd[jj].c_str(); } prog[ntok] = 0; close(resync[rEnd]); @@ -417,8 +435,8 @@ int main(int argc, char** argv) { cerr << "hi-q filter[" << ii << "] " << kidpid[ii] << " :; "; - for (VS::const_iterator token = filter[ii].begin(); - token != filter[ii].end(); token++){ + for (VS::const_iterator token = filter[ii].cmd.begin(); + token != filter[ii].cmd.end(); token++){ cerr << *token << " "; } cerr << endl; @@ -477,7 +495,7 @@ int main(int argc, char** argv) { if (sts == 1) { cerr << "hi-q says: kid[" << kidno << "]" << " pid " << argbest_blame - << " i.e. '" << filter[kidno][0] << "'" + << " i.e. '" << filter[kidno].cmd[0] << "'" << " reports spam." << endl; panic(ex_spam); } @@ -515,13 +533,13 @@ int main(int argc, char** argv) { if (WIFEXITED(kidstatus)) { int sts = WEXITSTATUS(kidstatus); cerr << "hi-q says: qq program " << kidpid[nkids-1] - << " i.e. '" << filter[nkids-1][0] << "'" + << " i.e. '" << filter[nkids-1].cmd[0] << "'" << " returned status " << sts << endl; return sts; } else if (WIFSIGNALED(kidstatus)) { cerr << "hi-q says: qq program " << kidpid[nkids-1] - << " i.e. '" << filter[nkids-1][0] << "'" + << " i.e. '" << filter[nkids-1].cmd[0] << "'" << " was killed by signal " << WTERMSIG(kidstatus) << endl; return ex_syserr; diff --git a/tools/hi-test.conf b/tools/hi-test.conf index 630e2bb..d400373 100644 --- a/tools/hi-test.conf +++ b/tools/hi-test.conf @@ -1,3 +1,6 @@ -hi-test x0 -snooze 10 -hi-test x1 -snooze 1 -exit 1 -kill -hi-test x2 -snooze 10 +# comment + +# another comment, with blank line between +black hi-test x0 -snooze 10 +black hi-test x1 -snooze 1 -exit 1 -kill +qq hi-test x2 -snooze 10 diff --git a/tools/hi-test2.conf b/tools/hi-test2.conf index 2dbad3b..df047ab 100644 --- a/tools/hi-test2.conf +++ b/tools/hi-test2.conf @@ -1,3 +1,3 @@ -hi-test x0 -snooze 10 -hi-test x2 -snooze 10 -hi-test x1 -snooze 1 -exit 3 +grey hi-test x0 -snooze 10 +gray hi-test x2 -snooze 10 +qq hi-test x1 -snooze 1 -exit 3 diff --git a/tools/makefile b/tools/makefile index e092702..bb91f37 100644 --- a/tools/makefile +++ b/tools/makefile @@ -28,8 +28,6 @@ install: chmod u+s /var/qmail/rbin/checkpassword cp smtp.conf /etc/stunnel/ cp pop3.conf /etc/stunnel/ - chmod 640 /var/qmail/control/*.crtkey - chown qmaild /var/qmail/control/*.crtkey install qmail-tls-check_certs /var/qmail/bin/ install spamassassin /etc/init.d/ install qmail /etc/init.d/ -- cgit v1.2.3 From a356f2e89ba2bc25207f2d9605a1d6bcca15d6d7 Mon Sep 17 00:00:00 2001 From: John Denker Date: Thu, 19 Jul 2012 14:56:22 -0700 Subject: log some interesting variables --- tools/hi-q.c | 19 ++++++++++++++----- tools/hi-test.c | 11 ++++++++++- tools/makefile | 5 ++++- 3 files changed, 28 insertions(+), 7 deletions(-) (limited to 'tools/makefile') diff --git a/tools/hi-q.c b/tools/hi-q.c index 6140206..2ddc448 100644 --- a/tools/hi-q.c +++ b/tools/hi-q.c @@ -120,11 +120,16 @@ void usage() { // we have data coming in on fd 0. // and envelope / control information coming in on fd 1. +string progname; +pid_t mypid; + void dump(const string var){ char* str = getenv(var.c_str()); - if (str) cerr << "hi-q: " << var - << " is set to '" << str << "'" << endl; - else cerr << "hi-q: " << var << " is not set." << endl; + cerr << progname + << "[" << mypid << "] " + << var; + if (str) cerr << " is set to '" << str << "'" << endl; + else cerr << " is not set." << endl; } int xclose(int arg){ @@ -149,7 +154,7 @@ public: : mode(fail), cmd(_cmd){ setmode(_mode); } - + jobber() : mode(fail), cmd(0) {} @@ -168,6 +173,10 @@ public: }; int main(int argc, char** argv) { + progname = *argv; + mypid = getpid(); + dump("TCPREMOTEIP"); + dump("TCPREMOTEHOST"); int verbose(0); int kidstatus; @@ -534,7 +543,7 @@ int main(int argc, char** argv) { int sts = WEXITSTATUS(kidstatus); cerr << "hi-q says: qq program " << kidpid[nkids-1] << " i.e. '" << filter[nkids-1].cmd[0] << "'" - << " returned status " << sts + << " returned status " << sts << endl; return sts; } else if (WIFSIGNALED(kidstatus)) { diff --git a/tools/hi-test.c b/tools/hi-test.c index 0c9a35f..47128a9 100644 --- a/tools/hi-test.c +++ b/tools/hi-test.c @@ -41,13 +41,22 @@ void exeunt(const int sts){ using namespace std; +string progname; + +void dump(const string var){ + char* str = getenv(var.c_str()); + cerr << progname << ": " << var; + if (str) cerr << " is set to '" << str << "'" << endl; + else cerr << " is not set." << endl; +} + int main(int _argc, const char** _argv){ int snooze(0); int status(0); int killmode(0); int argc(_argc); const char **argv(_argv); - string progname(*argv); argv++; argc--; + progname = *argv; argv++; argc--; while (argc) { string arg(*argv); argv++; argc--; diff --git a/tools/makefile b/tools/makefile index bb91f37..04b9d21 100644 --- a/tools/makefile +++ b/tools/makefile @@ -6,7 +6,7 @@ CC= /usr/bin/g++ -Wall -g -I $(HOME)/lib/include .PHONY : shipit clean list-src ALWAYS foo dirs setup imgs \ - zip wc html all hacha hevea tcprules + zip wc html all hacha hevea tcprules logmark .SECONDARY : # do not remove any intermediate files @@ -37,6 +37,9 @@ install: /etc/tcpserver/smtp.rules : ./mk_smtp_rules $@ +logmark: + logger -t jsd -p mail.info ========================= + ALWAYS: @echo ... -- cgit v1.2.3 From 379794ea0d610165e75fca2c71e7161d66e0c10d Mon Sep 17 00:00:00 2001 From: John Denker Date: Thu, 19 Jul 2012 15:20:43 -0700 Subject: add greylist --- tools/greylist.c | 5 +++++ tools/hi-test2.conf | 2 +- tools/makefile | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 tools/greylist.c (limited to 'tools/makefile') diff --git a/tools/greylist.c b/tools/greylist.c new file mode 100644 index 0000000..fa7d701 --- /dev/null +++ b/tools/greylist.c @@ -0,0 +1,5 @@ + + +int main(){ + return 0; +} diff --git a/tools/hi-test2.conf b/tools/hi-test2.conf index df047ab..c7312fb 100644 --- a/tools/hi-test2.conf +++ b/tools/hi-test2.conf @@ -1,3 +1,3 @@ grey hi-test x0 -snooze 10 -gray hi-test x2 -snooze 10 +gray greylist x2 -snooze 10 qq hi-test x1 -snooze 1 -exit 3 diff --git a/tools/makefile b/tools/makefile index 04b9d21..8837952 100644 --- a/tools/makefile +++ b/tools/makefile @@ -10,7 +10,7 @@ CC= /usr/bin/g++ -Wall -g -I $(HOME)/lib/include .SECONDARY : # do not remove any intermediate files -progs = pido hi-q skrewt hi-test mail-scan +progs = pido hi-q skrewt hi-test mail-scan greylist all: $(progs) -- cgit v1.2.3 From 945767f12154698fab3e7e370486a5e9b09276e9 Mon Sep 17 00:00:00 2001 From: John Denker Date: Thu, 19 Jul 2012 20:58:24 -0700 Subject: add "Scan" function to greylist --- tools/greylist.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++---------- tools/makefile | 3 ++ 2 files changed, 77 insertions(+), 15 deletions(-) (limited to 'tools/makefile') diff --git a/tools/greylist.c b/tools/greylist.c index d769ff4..3ba502d 100644 --- a/tools/greylist.c +++ b/tools/greylist.c @@ -1,5 +1,6 @@ #include /* for exit(), getenv() */ #include +#include #include #include /* for stat() */ @@ -11,8 +12,16 @@ #include /* for creat() */ #include /* for gettimeofday() */ +// requires apt-get install libboost-filesystem-dev: +#include + using namespace std; +const int minute(60); +const int hour(60*minute); +const int day(24*hour); + +const int minimum_age(5*minute); const int sa_good = 0; const int bug_bait_grey = 1; // qmail_queue and spamc have similar interpretations here: @@ -30,27 +39,26 @@ void dump(const string var){ else cerr << " is not set." << endl; } -const string dirname("/var/qmail/greylist"); // int stat(const char *path, struct stat *buf); // int fstat(int fd, struct stat *buf); // int lstat(const char *path, struct stat *buf); -const int minute(60); -const int hour(60*minute); -const int day(24*hour); class whatsit{ public: + string dirname; string progname; pid_t mypid; timeval now; + string ipbase; string ipname; + string hostname; int mod_age; int ac_age; - whatsit(const string name) - : progname(name), mypid(getpid()) + whatsit(const string name, const string _dirname) + : dirname(_dirname), progname(name), mypid(getpid()), mod_age(0), ac_age(0) { gettimeofday(&now, NULL); } @@ -59,10 +67,49 @@ public: void update(const string msg, const timeval new_mod, const timeval new_ac); }; +void scan(const string p){ + timeval now; + gettimeofday(&now, NULL); + using namespace boost::filesystem; + + if (is_directory(p)) { + for (directory_iterator itr(p); itr!=directory_iterator(); ++itr) { + string basename = itr->path().filename(); + cout << setw(20) << basename << ' '; // display filename only + if (is_regular_file(itr->status())) { +// cout << " [" << file_size(itr->path()) << ']'; + struct stat mystat; + string fn = p + "/" + basename; + int rslt = stat(fn.c_str(), &mystat); + if (rslt != 0){ + cerr << progname << ": stat failed for '" + << fn << "' : "; + perror(0); + } + int mod_age = now.tv_sec - mystat.st_mtime; + int ac_age = now.tv_sec - mystat.st_atime; + cout << setw(10) << mod_age + << " " << setw(10) << ac_age; + if (mod_age < minimum_age) { + cout << " young"; + } else if (mod_age == ac_age) { + cout << " never used"; + } + } + cout << '\n'; + } + } + else { + // starting point is not a directory: + cout << (exists(p) ? "Found: " : "Not found: ") << p << '\n'; + } +} + void whatsit::update(const string msg, const timeval new_mod, const timeval new_ac){ cerr << progname << ": " - << msg << ": " << ipname - << " mod_age: " << mod_age + << msg << ": " << ipbase; + if (hostname.length()) cerr << " " << hostname; + cerr << " mod_age: " << mod_age << " ac_age: " << ac_age << endl; timeval upd[2] = { @@ -73,12 +120,22 @@ void whatsit::update(const string msg, const timeval new_mod, const timeval new_ utimes(ipname.c_str(), upd); } -int main(int argc, char** argv){ - -// dump("TCPREMOTEIP"); -// dump("TCPREMOTEHOST"); +int main(int _argc, char** _argv){ + int argc(_argc); + char** argv(_argv); + const string dirname("/var/qmail/greylist"); + whatsit foo(argv[0], dirname); argc--; argv++; + while (argc > 0) { + string arg = argv[0]; argc--; argv++; + if (arg == "-scan") { + scan(dirname); + return 0; + } + else { + cerr << "Unrecognized arg, ignored: " << arg << endl; + } + } - whatsit foo(argv[0]); return foo.doit(); } @@ -88,7 +145,9 @@ int whatsit::doit(){ cerr << progname << ": TCPREMOTEIP not set???" << endl; exit(sa_syserr); } - string ipbase = ipvar; + ipbase = ipvar; + char* hostvar = getenv("TCPREMOTEHOST"); + if (hostvar) hostname = hostvar; // see if our directory exists: struct stat dirstat; @@ -134,7 +193,7 @@ int whatsit::doit(){ 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 < 5*minute) { + if (mod_age < minimum_age) { update("early bird", mod_orig, now); return(bug_bait_grey); } diff --git a/tools/makefile b/tools/makefile index 8837952..97c345c 100644 --- a/tools/makefile +++ b/tools/makefile @@ -14,6 +14,9 @@ progs = pido hi-q skrewt hi-test mail-scan greylist all: $(progs) +greylist: greylist.c + $(CC) $< -lboost_filesystem-mt -o $@ + mail-scan: mail-scan.o $(CC) $< -lboost_regex -o $@ -- cgit v1.2.3 From 9280a33c63250b841e8a51d4ef3aac2148b4bc12 Mon Sep 17 00:00:00 2001 From: John Denker Date: Fri, 20 Jul 2012 05:43:54 -0700 Subject: 5 minutes is not enough --- qmail.c | 2 +- tools/greylist.c | 2 +- tools/makefile | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'tools/makefile') diff --git a/qmail.c b/qmail.c index 476c788..a8ddef8 100644 --- a/qmail.c +++ b/qmail.c @@ -122,7 +122,7 @@ struct qmail *qq; case 65: /* fall through */ case 66: /* fall through */ case 62: return "Zqq trouble creating files in queue (#4.3.0)"; - case 70: return "Zgreylisting in progress; please try again in 00:05:00 (#4.3.0)"; + case 70: return "Zgreylisting in progress; please try again in 00:15:00 (#4.3.0)"; case 71: return "Zmail server temporarily rejected message (#4.3.0)"; case 72: return "Zconnection to mail server timed out (#4.4.1)"; case 73: return "Zconnection to mail server rejected (#4.4.1)"; diff --git a/tools/greylist.c b/tools/greylist.c index 1e62e93..525fc9b 100644 --- a/tools/greylist.c +++ b/tools/greylist.c @@ -22,7 +22,7 @@ const int minute(60); const int hour(60*minute); const int day(24*hour); -const int minimum_age(5*minute); +const int minimum_age(15*minute); const int maximum_age(32*day); const int probation(4*hour); const int sa_good = 0; diff --git a/tools/makefile b/tools/makefile index 97c345c..3e599b8 100644 --- a/tools/makefile +++ b/tools/makefile @@ -43,6 +43,11 @@ install: logmark: logger -t jsd -p mail.info ========================= +todo: + echo zap -- kill program group \ + extended error codes from skrewt, greylist \ + extended error codes [-x] from spamc + ALWAYS: @echo ... -- cgit v1.2.3 From abcd53ddce872e3f331d8a6d7c1ff44c070b91b0 Mon Sep 17 00:00:00 2001 From: John Denker Date: Fri, 20 Jul 2012 09:20:36 -0700 Subject: greylist will now zap its program-group --- tools/greylist.c | 46 +++++++++++++++++++++++++++++++++++----------- tools/hi-test2.conf | 2 +- tools/makefile | 2 +- 3 files changed, 37 insertions(+), 13 deletions(-) (limited to 'tools/makefile') diff --git a/tools/greylist.c b/tools/greylist.c index 525fc9b..910b40c 100644 --- a/tools/greylist.c +++ b/tools/greylist.c @@ -11,7 +11,8 @@ #include /* for ofstream() */ #include /* for creat() */ #include /* for gettimeofday() */ -#include +#include /* for stringstream */ +#include /* for kill(), SIGUSR1 */ // requires apt-get install libboost-filesystem-dev: #include @@ -43,10 +44,32 @@ void dump(const string var){ } - // int stat(const char *path, struct stat *buf); - // int fstat(int fd, struct stat *buf); - // int lstat(const char *path, struct stat *buf); +//////////////// +// little utility to help with argument parsing: +// +int prefix(const string shorter, const string longer){ + return shorter == longer.substr(0, shorter.length()); +} + +void exeunt(const int sts){ + if (sts == sa_good) exit(sts); + + const char* foo = getenv("HI_Q_GROUP"); + if (!foo) exit(sts); + +// No point in signalling ourself: + sighandler_t rslt = signal(SIGUSR1, SIG_IGN); + if (rslt == SIG_ERR) { + cerr << "error setting signal" << endl; + } + int k = kill(-atoi(foo), SIGUSR1); + if (k) { + cerr << "kill failed on group " << atoi(foo) << " ... "; + perror(0); + } + exit(sts); +} class whatsit{ public: @@ -161,7 +184,8 @@ int main(int _argc, char** _argv){ return 0; } else { - cerr << "Unrecognized arg, ignored: " << arg << endl; + cerr << "Unrecognized arg: " << arg << endl; + exeunt(sa_syserr); } } @@ -172,7 +196,7 @@ int whatsit::doit(){ char* ipvar = getenv("TCPREMOTEIP"); if (!ipvar) { cerr << progname << ": TCPREMOTEIP not set???" << endl; - exit(sa_syserr); + exeunt(sa_syserr); } ipbase = ipvar; char* hostvar = getenv("TCPREMOTEHOST"); @@ -194,7 +218,7 @@ int whatsit::doit(){ << ": mkdir failed for '" << dirname << "' : "; perror(0); - exit(sa_syserr); + exeunt(sa_syserr); } } @@ -216,7 +240,7 @@ int whatsit::doit(){ } close(fd); update("new customer", now, now); - return(bug_bait_grey); + exeunt(bug_bait_grey); } // here if stat succeeded mod_age = now.tv_sec - ipstat.st_mtime; @@ -224,16 +248,16 @@ int whatsit::doit(){ timeval mod_orig = {ipstat.st_mtime, 0}; if (mod_age < minimum_age) { update("early bird", mod_orig, now); - return(bug_bait_grey); + exeunt(bug_bait_grey); } if (mod_age - ac_age < minimum_age // early bird, or completely unused && mod_age > probation) { // did not diligently resubmit update("disprobation", now, now); - return(bug_bait_grey); + exeunt(bug_bait_grey); } if (ac_age > maximum_age) { update("too old, starting over", now, now); - return(bug_bait_grey); + exeunt(bug_bait_grey); } // if all checks are passed, must be OK: update("returning customer", mod_orig, now); diff --git a/tools/hi-test2.conf b/tools/hi-test2.conf index c7312fb..3c1422c 100644 --- a/tools/hi-test2.conf +++ b/tools/hi-test2.conf @@ -1,3 +1,3 @@ grey hi-test x0 -snooze 10 -gray greylist x2 -snooze 10 +gray greylist qq hi-test x1 -snooze 1 -exit 3 diff --git a/tools/makefile b/tools/makefile index 3e599b8..cf62473 100644 --- a/tools/makefile +++ b/tools/makefile @@ -44,7 +44,7 @@ logmark: logger -t jsd -p mail.info ========================= todo: - echo zap -- kill program group \ + echo zap penalize greylist status of spam \ extended error codes from skrewt, greylist \ extended error codes [-x] from spamc -- cgit v1.2.3 From bcce618000e74f0d36780b48c3c49f4a9b5914e5 Mon Sep 17 00:00:00 2001 From: John Denker Date: Sat, 21 Jul 2012 11:16:12 -0700 Subject: check DNS consistency --- tools/greylist.c | 51 ++++++++++++++++++++++++++++++++++++--------------- tools/makefile | 8 +++++--- 2 files changed, 41 insertions(+), 18 deletions(-) (limited to 'tools/makefile') diff --git a/tools/greylist.c b/tools/greylist.c index f9a4ebc..863a2fe 100644 --- a/tools/greylist.c +++ b/tools/greylist.c @@ -20,6 +20,8 @@ #include /* for getaddrinfo() */ #include /* for getaddrinfo() */ #include /* for memset() */ +#include /* for inet_ntop() */ + using namespace std; @@ -294,7 +296,7 @@ int main(int _argc, char** _argv){ // (b) move all the DNS checking to a separate module int dns = foo.check_dns(); - if (dns == ex_syserr) return dns; + if (dns == ex_syserr || dns == ex_spam) return dns; exeunt(sts); } @@ -373,15 +375,26 @@ int whatsit::doit(const int penalty){ typedef vector VU; -class VUx : public VU { +class VUx{ public: - sa_family_t fam; + VU addr; + sa_family_t fam; + string str(); }; +string VUx::str(){ + char msgbuf[INET6_ADDRSTRLEN]; + const char* rslt = inet_ntop(fam, &addr[0], + msgbuf, sizeof(msgbuf)); + if (!rslt) rslt = ""; + return rslt; +} + VUx parse_sockaddr(const sockaddr* ai_addr) { void* numericAddress; VUx rslt; int addrsize; + rslt.addr = VU(0); rslt.fam = ((sockaddr *)ai_addr)->sa_family; switch (rslt.fam) { case AF_INET: @@ -397,8 +410,7 @@ VUx parse_sockaddr(const sockaddr* ai_addr) { return rslt; } unsigned char* foo = (unsigned char*) numericAddress; - (VU)rslt = VU(foo, foo+addrsize); - cerr << "asdf " << rslt.size() << " ... " << VU(foo, foo+addrsize).size() << endl; + rslt.addr = VU(foo, foo+addrsize); return rslt; } @@ -443,7 +455,7 @@ int whatsit::check_dns(){ return ex_syserr; } - VU ipAddr = parse_sockaddr(ipresult->ai_addr); + VUx ipAddr = parse_sockaddr(ipresult->ai_addr); error = getaddrinfo(hostvar, NULL, &hints, &result); if (error) { cerr << "error in getaddrinfo for " << hostvar @@ -454,18 +466,27 @@ int whatsit::check_dns(){ // loop over all returned results and check for a match. vector checked_hosts; for (res = result; res != NULL; res = res->ai_next){ - VU hostAddr = parse_sockaddr(res->ai_addr); -#if 0 - char msgbuf[INET6_ADDRSTRLEN]; - const char* rslt = inet_ntop(fam, numericAddress, - msgbuf, sizeof(msgbuf)); -#endif - if (!diff(hostAddr, ipAddr)) { - cerr << "match! " << ipAddr.size() << endl; + VUx hostAddr = parse_sockaddr(res->ai_addr); + + if (!diff(hostAddr.addr, ipAddr.addr)) { + ///// cerr << "match! " << ipAddr.addr.size() << endl; goto done; } } - cerr << "no match" << endl; + cerr << "(warning) DNS inconsistency: " + << ipAddr.str() << " does not match"; + for (res = result; res != NULL; res = res->ai_next){ + cerr << " " << parse_sockaddr(res->ai_addr).str(); + } + cerr << endl; +#if 1 + // temporary ... just a warning + return 0; +#else + return ex_spam; +#endif + + done: return 0; } diff --git a/tools/makefile b/tools/makefile index cf62473..1f878f0 100644 --- a/tools/makefile +++ b/tools/makefile @@ -44,9 +44,11 @@ logmark: logger -t jsd -p mail.info ========================= todo: - echo zap penalize greylist status of spam \ - extended error codes from skrewt, greylist \ - extended error codes [-x] from spamc + echo \ + pass message-ID to greylist program \ + ... also provide a way for certain recipients to bypass some checks \ + ... both will require major restructuring, "cat" process \ + ..... ALWAYS: @echo ... -- cgit v1.2.3 From 46cb697732ea2c2c4a68358109a58232ef2666e7 Mon Sep 17 00:00:00 2001 From: John Denker Date: Sat, 21 Jul 2012 11:43:00 -0700 Subject: dns inconsistency is just a warning for the moment --- tools/greylist.c | 22 ++++++++++------------ tools/makefile | 1 + 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'tools/makefile') diff --git a/tools/greylist.c b/tools/greylist.c index 863a2fe..95a4f0b 100644 --- a/tools/greylist.c +++ b/tools/greylist.c @@ -436,6 +436,8 @@ int whatsit::check_dns(){ struct addrinfo *res; addrinfo hints; int error; + int ex_dnserr(ex_syserr); + ex_dnserr = 0; // temporarily just a warning /* resolve the domain name into a list of addresses */ memset(&hints, 0, sizeof(struct addrinfo)); @@ -448,11 +450,11 @@ int whatsit::check_dns(){ if (error) { cerr << "error in getaddrinfo for " << ipvar << " : " << gai_strerror(error) << endl; - return ex_syserr; + return ex_dnserr; } if (!ipresult) { cerr << "should never happen (addr with no addrs?)" << endl; - return ex_syserr; + return ex_dnserr; } VUx ipAddr = parse_sockaddr(ipresult->ai_addr); @@ -460,7 +462,7 @@ int whatsit::check_dns(){ if (error) { cerr << "error in getaddrinfo for " << hostvar << " : " << gai_strerror(error) << endl; - return ex_syserr; + return ex_dnserr; } // loop over all returned results and check for a match. @@ -473,19 +475,15 @@ int whatsit::check_dns(){ goto done; } } - cerr << "(warning) DNS inconsistency: " - << ipAddr.str() << " does not match"; + if (!ex_dnserr) cerr << "(warning) "; + cerr << "DNS inconsistency: " + << ipAddr.str() << " --> " + << hostvar << " ==>"; for (res = result; res != NULL; res = res->ai_next){ cerr << " " << parse_sockaddr(res->ai_addr).str(); } cerr << endl; -#if 1 - // temporary ... just a warning - return 0; -#else - return ex_spam; -#endif - + return ex_dnserr; done: return 0; diff --git a/tools/makefile b/tools/makefile index 1f878f0..6fa9636 100644 --- a/tools/makefile +++ b/tools/makefile @@ -48,6 +48,7 @@ todo: pass message-ID to greylist program \ ... also provide a way for certain recipients to bypass some checks \ ... both will require major restructuring, "cat" process \ + ... IPv6 reverse-DNS recors \ ..... ALWAYS: -- cgit v1.2.3 From 8ce08aca2410c795dfc46f37dc27402ff6de5dd1 Mon Sep 17 00:00:00 2001 From: John Denker Date: Sat, 21 Jul 2012 15:53:08 -0700 Subject: ignore penalty features for the moment --- tools/greylist.c | 4 ++++ tools/hi-q.c | 22 ++++++++++++++-------- tools/makefile | 3 ++- 3 files changed, 20 insertions(+), 9 deletions(-) (limited to 'tools/makefile') diff --git a/tools/greylist.c b/tools/greylist.c index 95a4f0b..063c3d0 100644 --- a/tools/greylist.c +++ b/tools/greylist.c @@ -68,6 +68,10 @@ int prefix(const string shorter, const string longer){ void exeunt(const int sts){ if (sts == ex_good) exit(sts); +#ifndef PENALIZE_SPAMMERS + if (sts == ex_penaltybox) exit(sts); +#endif + const char* foo = getenv("HI_Q_GROUP"); if (!foo) exit(sts); diff --git a/tools/hi-q.c b/tools/hi-q.c index 6aaf302..8766b08 100644 --- a/tools/hi-q.c +++ b/tools/hi-q.c @@ -158,7 +158,7 @@ int fork_and_wait(const jobber job){ int sts = WEXITSTATUS(kidstatus); if (sts != ex_good && sts != ex_spam) { cerr << "hi-q: job " << prog[0] - << " unexpectedly returns status: " << sts + << " unexpectedly returns status: " << sts << endl; exit(sts); } @@ -179,7 +179,7 @@ int fork_and_wait(const jobber job){ int fork_and_wait(vector post){ for(vector::const_iterator foo = post.begin(); foo != post.end(); foo++) { - int rslt = fork_and_wait(*foo); + int rslt = fork_and_wait(*foo); if (rslt) return rslt; } return 0; @@ -590,7 +590,7 @@ bar // do not decrement the "alive" counter // since that only applies to non-special kids if (WIFEXITED(kidstatus)) { - cerr << "hi-q: special kid exited early, status " + cerr << "hi-q: special kid exited early, status " << WEXITSTATUS(kidstatus) << " with " << alive << " kids still alive" << endl; @@ -599,10 +599,10 @@ bar int sig = WTERMSIG(kidstatus); if (sig == SIGUSR1) {/* normal, no logging required */} else { - cerr << "hi-q: special kid killed by signal " + cerr << "hi-q: special kid killed by signal " << sig << endl; // this is not normal - return(ex_syserr); + return(ex_syserr); } } else { /* paused, not dead */ @@ -612,7 +612,13 @@ bar // here if somekid is not the special kid if (WIFEXITED(kidstatus)) { alive--; - if (WEXITSTATUS(kidstatus)) { + int sts = WEXITSTATUS(kidstatus); +#ifndef PENALIZE_SPAMMERS + // ignore penalties for the moment + // to see whether there are any false positives + if (sts == ex_penaltybox) sts = ex_good; +#endif + if (sts) { argbest_blame = somekid; best_blame = kidstatus; break; @@ -694,7 +700,7 @@ bar if (WIFEXITED(kidstatus)) { int sts = WEXITSTATUS(kidstatus); cerr << progid - << " says: qq program" + << " says: qq program" << " i.e. " << basename(filter[nkids-1].cmd[0]) << "[" << kidpid[nkids-1] << "]" << " returned status " << sts @@ -702,7 +708,7 @@ bar return sts; } else if (WIFSIGNALED(kidstatus)) { cerr << progid - << " says: qq program" + << " says: qq program" << " i.e. " << basename(filter[nkids-1].cmd[0]) << "[" << kidpid[nkids-1] << "]" << " was killed by signal " << WTERMSIG(kidstatus) diff --git a/tools/makefile b/tools/makefile index 6fa9636..9059a2f 100644 --- a/tools/makefile +++ b/tools/makefile @@ -49,7 +49,8 @@ todo: ... also provide a way for certain recipients to bypass some checks \ ... both will require major restructuring, "cat" process \ ... IPv6 reverse-DNS recors \ - ..... + ... "clean up bad DNS reports nnnn --> () ==> ()" \ + ..... ALWAYS: @echo ... -- cgit v1.2.3 From abb71cf6b1145588827d04de4da3bb48ecb06965 Mon Sep 17 00:00:00 2001 From: John Denker Date: Sun, 22 Jul 2012 14:43:07 -0700 Subject: set program gid (not just egid) the way mailman likes it --- tools/makefile | 22 ++++++++++++++++------ tools/wripper.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 tools/wripper.c (limited to 'tools/makefile') diff --git a/tools/makefile b/tools/makefile index 9059a2f..43418ce 100644 --- a/tools/makefile +++ b/tools/makefile @@ -10,18 +10,24 @@ CC= /usr/bin/g++ -Wall -g -I $(HOME)/lib/include .SECONDARY : # do not remove any intermediate files -progs = pido hi-q skrewt hi-test mail-scan greylist +qprogs = pido hi-q skrewt hi-test mail-scan greylist wripper -all: $(progs) +all: $(qprogs) wripper -greylist: greylist.c +greylist: greylist.o $(CC) $< -lboost_filesystem-mt -o $@ +wripper: wripper.o + $(CC) $< -o $@ + chgrp daemon $@ + chmod g+s $@ + mail-scan: mail-scan.o $(CC) $< -lboost_regex -o $@ install: - install $(progs) /var/qmail/bin/ + install $(qprogs) /var/qmail/bin/ + install -gdaemon -m2755 wripper /usr/lib/mailman/mail/ cp filters.conf aufilters.conf /var/qmail/control/ install -m700 -d /var/qmail/rbin chown qmaild /var/qmail/rbin @@ -43,14 +49,18 @@ install: logmark: logger -t jsd -p mail.info ========================= -todo: +# Command to let everybody out of the penalty box: +parole: + greylist -scan |grep penalty | while read addr rest ; do TCPREMOTEIP=$addr greylist -p 1 -v ; done + +todo: echo \ pass message-ID to greylist program \ ... also provide a way for certain recipients to bypass some checks \ ... both will require major restructuring, "cat" process \ ... IPv6 reverse-DNS recors \ ... "clean up bad DNS reports nnnn --> () ==> ()" \ - ..... + ..... ALWAYS: @echo ... diff --git a/tools/wripper.c b/tools/wripper.c new file mode 100644 index 0000000..2a19c8b --- /dev/null +++ b/tools/wripper.c @@ -0,0 +1,53 @@ +////////////// + +using namespace std; +#include +#include +#include +#include +#include /* for perror() */ + +string dirname(const string path){ + size_t where = path.rfind("/"); + if (where == string::npos) return "."; + return path.substr(0, where); +} + +int main(int argc, char** argv){ + int uid=getuid(); + int euid=geteuid(); + int gid=getgid(); + int egid=getegid(); + int sts; + int verbosity(0); + + if (verbosity) cout << "uid: " << uid + << " euid: " << euid + << " gid: " << gid + << " egid: " << egid + << endl; + + sts = setreuid(euid, euid); + if (sts){ + cerr << "wripper: setreuid failed: "; + perror(0); + } + + sts = setregid(egid, egid); + if (sts){ + cerr << "wripper: setregid failed: "; + perror(0); + } + + if (verbosity) cout << "uid: " << getuid() + << " euid: " << geteuid() + << " gid: " << getgid() + << " egid: " << getegid() + << endl; + + string path = dirname(*argv) + "/mailman"; + *argv = (char*) path.c_str(); + execv(*argv, argv); + cerr << "wripper: exec failed for '" << *argv << "' : "; + perror(0); +} -- cgit v1.2.3 From 8f18b37fd5a46d28544a4f31465c47428a43398b Mon Sep 17 00:00:00 2001 From: John Denker Date: Sun, 22 Jul 2012 19:13:11 -0700 Subject: create the "bash-c" program, so as to make it easy to write self-executing scripts --- .gitignore | 3 +++ tools/bash-c.c | 36 ++++++++++++++++++++++++++++++++++++ tools/hi-test.conf | 2 +- tools/hi-test2.conf | 10 ++++++---- tools/hi-test3.conf | 2 +- tools/makefile | 5 ++++- tools/t-bash-c | 3 +++ 7 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 tools/bash-c.c mode change 100644 => 100755 tools/hi-test.conf mode change 100644 => 100755 tools/hi-test2.conf create mode 100755 tools/t-bash-c (limited to 'tools/makefile') diff --git a/.gitignore b/.gitignore index ca1ef6d..574561f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.rej *.logg *#[0-9]* +\#*# has?????.h auto-gid @@ -158,3 +159,5 @@ auto_uids.c control.tar.gz data.tar.gz dummy-mail-transfer-agent_all.deb +bash-c +wripper diff --git a/tools/bash-c.c b/tools/bash-c.c new file mode 100644 index 0000000..6b2844d --- /dev/null +++ b/tools/bash-c.c @@ -0,0 +1,36 @@ +////////////// + +using namespace std; +#include +#include +#include +#include +#include /* for perror() */ +#include /* for exit() */ + + +string dirname(const string path){ + size_t where = path.rfind("/"); + if (where == string::npos) return "."; + return path.substr(0, where); +} + +int main(int argc, char** argv){ + int verbosity(0); + + char* nargv[1+argc]; + for (int ii = 1; ii <= argc; ii++){ + if (verbosity) { + if (argv[ii] == 0) cout << "zero" << endl; + else cout << "[" << argv[ii] << "]" << endl; + } + nargv[1+ii] = argv[ii]; + } + nargv[1] = (char*)"-c"; + nargv[0] = (char*)"/home/jsd/bin/ECHO"; + nargv[0] = (char*)"/bin/bash"; + + execv(*nargv, nargv); + cerr << "bash-c: exec failed for '" << *nargv << "' : "; + perror(0); +} diff --git a/tools/hi-test.conf b/tools/hi-test.conf old mode 100644 new mode 100755 index aa6a1cf..f692f37 --- a/tools/hi-test.conf +++ b/tools/hi-test.conf @@ -1,4 +1,4 @@ -# comment +#! /usr/local/bin/bash-c set -x ; Date: Mon, 23 Jul 2012 08:43:49 -0700 Subject: the usual automatic dependency-finder --- tools/makefile | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'tools/makefile') diff --git a/tools/makefile b/tools/makefile index 5dc7952..08bf17c 100644 --- a/tools/makefile +++ b/tools/makefile @@ -10,12 +10,33 @@ CC= /usr/bin/g++ -Wall -g -I $(HOME)/lib/include .SECONDARY : # do not remove any intermediate files -qprogs = pido hi-q skrewt hi-test mail-scan greylist wripper +# sources for main programs that go in /var/qmail/bin +qmain = pido.c hi-q.c skrewt.c hi-test.c mail-scan.c greylist.c wripper.c +qprogs = $(qmain:%.c=%) -moreprogs = wripper bash-c +# sources for other main programs: +moremain = wripper.c bash-c.c +moreprogs = $(moremain:%.c=%) + +nonmain = + +sources = $(qmain) $(moremain) $(nonmain) + +beware_other = checkpassword.c spamc.c + +## dependency-finding scheme (with local mods) based on: +## http://www.gnu.org/manual/make-3.77/html_mono/make.html#SEC42 +## (see also include statement at end of this makefile) +%.d : %.c + @$(SHELL) -ec '$(CXX) -MM $(CXXFLAGS) $< \ + | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \ + [ -s $@ ] || rm -f $@' all: $(qprogs) $(moreprogs) +show: + : --- $(qprogs) +++ $(moreprogs) + greylist: greylist.o $(CC) $< -lboost_filesystem-mt -o $@ @@ -70,3 +91,5 @@ ALWAYS: ##?? include $(chapters:.htm=.d) ##?? include $(fancy:%.htm=aux/%.fig) + +include $(sources:.c=.d) -- cgit v1.2.3 From 02bfae1f87c4693eb00bf943fb24886a5ac47a09 Mon Sep 17 00:00:00 2001 From: John Denker Date: Tue, 24 Jul 2012 11:29:56 -0700 Subject: improve compatibility across boost versions; allow use by non-superuser --- tools/makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'tools/makefile') diff --git a/tools/makefile b/tools/makefile index 08bf17c..76df23b 100644 --- a/tools/makefile +++ b/tools/makefile @@ -38,12 +38,13 @@ show: : --- $(qprogs) +++ $(moreprogs) greylist: greylist.o - $(CC) $< -lboost_filesystem-mt -o $@ + $(CC) $< -lboost_filesystem-mt -lboost_system -o $@ + +# $(CC) $< -lboost_filesystem -o $@ wripper: wripper.o $(CC) $< -o $@ - chgrp daemon $@ - chmod g+s $@ + chgrp daemon $@ && chmod g+s $@ || true mail-scan: mail-scan.o $(CC) $< -lboost_regex -o $@ -- cgit v1.2.3