diff options
-rw-r--r-- | tools/libltgrey.c | 136 | ||||
-rw-r--r-- | tools/libltgrey.h | 23 | ||||
-rw-r--r-- | tools/ltgrey.c | 43 |
3 files changed, 132 insertions, 70 deletions
diff --git a/tools/libltgrey.c b/tools/libltgrey.c index d4ec0da..1bf7e9f 100644 --- a/tools/libltgrey.c +++ b/tools/libltgrey.c @@ -73,6 +73,15 @@ void exeunt(const int sts){ #include "utils.h" #include "qq_exit_codes.h" +// constructor +whatsit::whatsit(const std::string name, const std::string _parent_dir) +: parent_dir(_parent_dir), progname(name), mypid(getpid()), + mod_age(0), ac_age(0), + verbosity(0) +{ + gettimeofday(&now, NULL); +} + void whatsit::dump(const string var){ char* str = getenv(var.c_str()); cerr << progname @@ -88,13 +97,14 @@ int whatsit::setup(){ << "[" << mypid << "]"; progid = foo.str(); - ipvar = getenv("TCPREMOTEIP"); - if (ipvar) ipbase = ipvar; - hostvar = getenv("TCPREMOTEHOST"); - if (hostvar) hostname = hostvar; return 0; } +#if 1 +void whatsit::update(const string msg, const timeval new_mod, + const timeval new_ac, const int penalty, const int stain){ +} +#else void whatsit::update(const string msg, const timeval new_mod, const timeval new_ac, const int penalty, const int stain){ if (verbosity){ @@ -128,36 +138,51 @@ void whatsit::update(const string msg, const timeval new_mod, if (utimes(ipname.c_str(), upd)) cerr << "oops" << endl; } +#endif -int whatsit::doit(const int penalty, const int stain){ - - if (!ipvar) { - cerr << progid - << " TCPREMOTEIP not set???" << endl; - // should never happen - // although you can make it happen using a weird test-harness - return(ex_syserr); - } - +int whatsit::maybe_mkdir(const string somedir, const string msg){ // see if our directory exists: struct stat dirstat; - int rslt = stat(dirname.c_str(), &dirstat); + int rslt = stat(somedir.c_str(), &dirstat); if (rslt != 0){ if (errno != ENOENT) { - cerr << progid << ": stat failed for '" - << dirname << "' : "; + cerr << progid << " stat failed for " + << msg + << " '" << somedir << "' : "; perror(0); } - rslt = mkdir(dirname.c_str(), 0755); + rslt = mkdir(somedir.c_str(), 0755); if (rslt != 0) { cerr << progid << "uid " << getuid() - << ": mkdir failed for '" - << dirname << "' : "; + << " mkdir failed for " + << msg + << "' " << somedir << "' : "; perror(0); return(ex_syserr); } } + return 0; +} + +#if 1 +int whatsit::doit(const int penalty, const int stain){ + return ex_syserr; +} + +#else +int whatsit::doit(const int penalty, const int stain){ + if (!ipvar) { + cerr << progid + << " TCPREMOTEIP not set???" << endl; + // should never happen + // although you can make it happen using a weird test-harness + return(ex_syserr); + } + + maybe_mkdir(parent_dir, "parent dir"); + maybe_mkdir(parent_dir + "/quarante", "quarantine dir"); + maybe_mkdir(parent_dir + "/repute", "reputation dir"); ipname = dirname + "/" + ipbase; struct stat ipstat; @@ -210,6 +235,7 @@ int whatsit::doit(const int penalty, const int stain){ update("returning customer", mod_orig, now, penalty, stain); return 0; } +#endif typedef vector<unsigned char> VU; @@ -260,29 +286,35 @@ int diff(const VU aaa, const VU bbb){ return 0; } -int whatsit::check_dns(){ +int whatsit::check_dns(const char* ipvar, const char* namevar){ + if (!ipvar) { + cerr << progid << " check_dns: no addr specified." << endl; + return ex_syserr; + } string addr("()"), host("()"); vector<string> checked; - int sts = check_dns_sub(addr, host, checked); - if (sts == 0) return sts; - if (sts != ex_badDNS) return sts; // possible ex_syserr + int rslt = check_dns_sub(ipvar, namevar, addr, host, checked); + int sts = rslt; #if 1 sts = 0; // demote badDNS to just a warning #endif - cerr << progid; - if (!sts) cerr << " (warning)"; - cerr << " DNS inconsistency: " - << addr << " --> " - << host << " ==>"; - if (!checked.size()) cerr << " ()"; - else for (vector<string>::const_iterator chk = checked.begin(); - chk != checked.end(); chk++) cerr << " " << *chk; - cerr << endl; - + if (rslt || verbosity) { + cerr << progid; + if (rslt && !sts) cerr << " (warning)"; + if (rslt) cerr << " DNS inconsistency: "; + else cerr << " DNS OK: "; + cerr << addr << " --> " + << host << " ==>"; + if (!checked.size()) cerr << " ()"; + else for (vector<string>::const_iterator chk = checked.begin(); + chk != checked.end(); chk++) cerr << " " << *chk; + cerr << endl; + } return sts; } -int whatsit::check_dns_sub(string &addr, string &host, vector<string> &checked){ +int whatsit::check_dns_sub(const char* ipvar, const char* namevar, + string &addr, string &host, vector<string> &checked){ struct addrinfo *result; struct addrinfo *ipresult; @@ -296,6 +328,8 @@ int whatsit::check_dns_sub(string &addr, string &host, vector<string> &checked){ hints.ai_protocol = IPPROTO_TCP; #endif +// convert address-as-string to address-as-bits. +// also get information about family error = getaddrinfo(ipvar, NULL, &hints, &ipresult); if (error == EAI_NONAME) return ex_badDNS; if (error) { // some unexpected error @@ -309,14 +343,38 @@ int whatsit::check_dns_sub(string &addr, string &host, vector<string> &checked){ cerr << "should never happen (addr with no addrs?)" << endl; return ex_syserr; } + +// reconvert from bits to string + family info VUx ipAddr = parse_sockaddr(ipresult->ai_addr); addr = ipAddr.str(); - char* hostvar = getenv("TCPREMOTEHOST"); - if (hostvar) host = hostvar; - else return(ex_badDNS); + if (namevar) { + // inverse lookup already done + host = namevar; + } else { + // namevar not specified; do inverse lookup on our own + + char hostname[NI_MAXHOST] = ""; + char service[NI_MAXHOST] = ""; + +#ifdef convert_bits_to_string + const char* rslt = inet_ntop(ipAddr.fam, &ipAddr.addr[0], + msgbuf, sizeof(msgbuf)); + if (rslt) fprintf(stdout, "%s addrsize: %2d --> ", + msgbuf, addrsize); +#endif + error = getnameinfo(ipresult->ai_addr, ipresult->ai_addrlen, + hostname, NI_MAXHOST, service, NI_MAXHOST, 0); + if (error != 0) { + cerr << progid << " reverse DNS lookup failed: " + << gai_strerror(error) << endl; + return (ex_badDNS); + } + namevar = hostname; // a char*, used below + host = hostname; // a string, returned to caller + } - error = getaddrinfo(hostvar, NULL, &hints, &result); + error = getaddrinfo(namevar, NULL, &hints, &result); if (error == EAI_NONAME) return ex_badDNS; if (error) { cerr << progid diff --git a/tools/libltgrey.h b/tools/libltgrey.h index 585ec01..6f516b4 100644 --- a/tools/libltgrey.h +++ b/tools/libltgrey.h @@ -4,35 +4,26 @@ class whatsit{ public: - std::string dirname; + std::string parent_dir; std::string progname; pid_t mypid; timeval now; - char* ipvar; - char* hostvar; - std::string ipbase; - std::string ipname; - std::string hostname; int mod_age; int ac_age; std::string suffix; std::string progid; int verbosity; - whatsit(const std::string name, const std::string _dirname) - : dirname(_dirname), progname(name), mypid(getpid()), - mod_age(0), ac_age(0), - verbosity(0) - { - gettimeofday(&now, NULL); - } + whatsit(const std::string name, const std::string _parent_dir); int doit(const int penalty, const int stain); // access comes after modification: void update(const std::string msg, const timeval new_mod, const timeval new_ac, const int penalty, const int stain); int setup(); - int check_dns(); - int check_dns_sub(std::string &addr, std::string &host, - std::vector<std::string> &checked); + int check_dns(const char* ipvar, const char* namevar); + int check_dns_sub(const char* ipvar, const char* namevar, + std::string &addr, std::string &host, + std::vector<std::string> &checked); void dump(const std::string var); + int maybe_mkdir(const std::string somedir, const std::string msg); }; diff --git a/tools/ltgrey.c b/tools/ltgrey.c index afdb4c1..c9f384f 100644 --- a/tools/ltgrey.c +++ b/tools/ltgrey.c @@ -14,17 +14,24 @@ string progname; // forward reference: void scan(const string progid, const string p, const int copies=1); + int main(int _argc, char** _argv){ + char* namevar; + std::string hostname; + char* ipvar; + std::string ipbase; + std::string ipname; + mypid = getpid(); int argc(_argc); char** argv(_argv); - const string dirname("/var/qmail/greylist"); - whatsit foo(argv[0], dirname); argc--; argv++; + const string parent_dir("/var/qmail/ltgrey"); + whatsit foo(argv[0], parent_dir); argc--; argv++; int scanmode(0); int copies(1); int penalty(0); int stain(0); - int check(0); + int dnscheck(0); while (argc > 0) { string arg = argv[0]; argc--; argv++; if (prefix(arg, "-scan")) { @@ -33,8 +40,8 @@ int main(int _argc, char** _argv){ copies++; } else if (prefix(arg, "-verbose")) { foo.verbosity++; - } else if (prefix(arg, "-check")) { - check++; + } else if (prefix(arg, "-dnscheck")) { + dnscheck++; } else if (prefix(arg, "-penalize") || prefix(arg, "-penalty")) { if (!argc){ @@ -61,23 +68,29 @@ int main(int _argc, char** _argv){ } if (foo.setup()) return ex_syserr; +// dnscheck mode ... +// Probably a better design would be to +// (a) make more thorough DNS checks, and +// (b) move all the DNS checking to a separate module + + ipvar = getenv("TCPREMOTEIP"); + if (ipvar) ipbase = ipvar; + namevar = getenv("TCPREMOTEHOST"); + if (namevar) hostname = namevar; + + if (dnscheck) { + exeunt(foo.check_dns(ipvar, namevar)); + } + if (scanmode) { + string dirname = parent_dir + "/quarante"; scan(foo.progid, dirname, copies); return 0; } int sts = foo.doit(penalty, stain); - if (sts == ex_syserr) return sts; - if (!check) return ex_good; - -// check mode ... 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 + return sts; - int dns = foo.check_dns(); - if (dns == ex_syserr || dns == ex_spam) return dns; - exeunt(sts); } ////////////////////////////////////////////////////////////////////// |