diff options
author | John Denker <jsd@av8n.com> | 2012-11-24 11:53:34 -0800 |
---|---|---|
committer | John Denker <jsd@av8n.com> | 2012-11-24 11:53:34 -0800 |
commit | a80d71e7dc3b46980b9f91c9238599fee26cc1b2 (patch) | |
tree | 9831468092f614ad0d735aa2655eb39f07d0745d | |
parent | 348bd85500f5cb5dc4b239e98d9459dbe71f96bc (diff) |
working toward identifying the "owning domain"
-rw-r--r-- | tools/libskrewt.c | 86 | ||||
-rw-r--r-- | tools/libskrewt.h | 39 | ||||
-rw-r--r-- | tools/makefile | 3 |
3 files changed, 89 insertions, 39 deletions
diff --git a/tools/libskrewt.c b/tools/libskrewt.c index b41d7d0..3c820f1 100644 --- a/tools/libskrewt.c +++ b/tools/libskrewt.c @@ -64,7 +64,7 @@ int skrewt::krunch_rfrom(){ << word << "'" << endl; return ex_syserr; } - parse >> proximta_rDNS; + parse >> proximta_rDNS.name; for (;;) { // loop over words in this record parse >> word; size_t len = word.length(); @@ -75,8 +75,8 @@ int skrewt::krunch_rfrom(){ } if (word == "by") break; if (word == "(HELO" /*)*/) { - parse >> proximta_HELO; - proximta_HELO = rtrim(proximta_HELO, "()"); + parse >> proximta_HELO.name; + proximta_HELO.name = rtrim(proximta_HELO.name, "()"); continue; } if (word[0] != '(' || word[len-1] != ')') { @@ -92,8 +92,8 @@ int skrewt::krunch_rfrom(){ } } // provide some kind of default? maybe not. - if (0) if (proximta_HELO == "") { - proximta_HELO = proximta_rDNS + " (+-)"; + if (0) if (proximta_HELO.name == "") { + proximta_HELO.name = proximta_rDNS.name + " (+-)"; } return 0; @@ -178,7 +178,7 @@ int skrewt::headers(istream& xin){ } else if (headword == "to") { to = rest; } else if (headword == "return-path") { - return_path = rest; + return_path.name = rest; } else if (headword == "message-id") { message_id = rest; } @@ -214,6 +214,30 @@ int skrewt::dump_bigbuf(std::ostream& xout){ return 0; } +void check_name(name_tester& fqdn, const string ip) { + if (ip == "") { + cerr << "SPF: should never happen: email with no IP?" <<endl; + fqdn.spf = fqdn.map2ip = neutral; + return; + } + sepofra my_spf; + try { + my_spf.check(ip, + fqdn.name, + "junk", + "morejunk", 0/* verbosity */); + cerr << progid << " " << my_spf.explain() << endl; +// keep a copy of the result: + fqdn.spf = neutral; + if (my_spf.result == SPF_RESULT_PASS) fqdn.spf = pass; + if (my_spf.result == SPF_RESULT_FAIL) fqdn.spf = fail; + /* anything else, such as soft_fail, is treated as neutral */ + } catch (bad_thing foo) { + cerr << "Caught bad thing: " << foo.what() << endl; + return; + } +} + int skrewt::interstage(){ if (saw_blank_line) {/* ignore */} // Note that the headers are in reverse-chronological order. @@ -221,36 +245,31 @@ int skrewt::interstage(){ // at the time skrewt normally runs, since it is upstream // of qmail-queue. cerr << progid << " Return-path: " - << (return_path.length() ? return_path : "[not set yet]") <<endl; + << (return_path.name.length() ? return_path.name : "[not set yet]") <<endl; { // parse the 'Received: from' line: cerr << progid << " Received: " << received_from <<endl; int rslt = krunch_rfrom(); if (rslt) return rslt; - cerr << progid << " === rDNS: " << proximta_rDNS << endl; - cerr << progid << " === HELO: " << proximta_HELO << endl; + if (proximta_AuthUser == "") { +// FIXME: also check return-path aka envelope-from + check_name(proximta_HELO, proximta_IP); + check_name(proximta_rDNS, proximta_IP); + } + + cerr << progid << " === rDNS: " << proximta_rDNS.name + << " " << decode_test_state[proximta_rDNS.spf] + << " " << decode_test_state[proximta_rDNS.map2ip] + << endl; + cerr << progid << " === HELO: " << proximta_HELO.name + << " " << decode_test_state[proximta_HELO.spf] + << " " << decode_test_state[proximta_HELO.map2ip] + << endl; cerr << progid << " === IP: " << proximta_IP << endl; cerr << progid << " === Mid '" << message_id << "'" << endl; cerr << progid << " === AuthUser: " << proximta_AuthUser << endl; } - if (proximta_AuthUser == "") - if (proximta_IP != "") { - sepofra my_spf; - try { - my_spf.check(proximta_IP, - proximta_HELO, - return_path, - "junk", 0/* verbosity */); - cerr << progid << " " << my_spf.explain() << endl; -// keep a copy of the result: - spf_result = my_spf.result; - } catch (bad_thing foo) { - cerr << "Caught bad thing: " << foo.what() << endl; - return ex_syserr; - } - } - // The logic here is: In order: // 1:: If whitelisted, accept. No greylisting, no spam-checking. // 2:: If blacklisted, reject. No greylisting, no spam-checking. @@ -408,6 +427,21 @@ void dump(const list<conner> sitch){ cerr << endl; } +// constructor + +skrewt::skrewt() + : spf_result(SPF_RESULT_INVALID), + boundary("x-xx-x"), msgsize(0), saw_blank_line(0), recno(0), + maxsize(1000*1000), error_exit(0), mid_required(0), + headerbuf(0), bigbuf(0), + lookahead(1, "") +{ +// expand the macro in a way that will initialize the decoder table: +# define foo(name) decode_test_state[name] = #name; + test_state_macro +# undef foo +} + int skrewt::body(std::istream& xin, std::ostream& xout){ list<conner> sitch; if (content_type.length()) { diff --git a/tools/libskrewt.h b/tools/libskrewt.h index 34cdfd3..2360b15 100644 --- a/tools/libskrewt.h +++ b/tools/libskrewt.h @@ -5,6 +5,28 @@ #include "qq_exit_codes.h" // a bit of a kludge extern std::string progid; +#define test_state_macro \ +foo(untested) \ +foo(pass) \ +foo(neutral) \ +foo(fail) + +// expand the codes to make some <const int> names: +#define foo(name) name, +typedef enum { + test_state_macro +} test_state; +#undef foo + +class name_tester { +public: + std::string name; // typically a FQDN + test_state spf; + test_state map2ip; + name_tester() : name(""), spf(untested), map2ip(untested) + {} +}; + class xstr { public: int err; @@ -16,12 +38,12 @@ public: class skrewt{ public: std::string received_from; // envelope HELO among other things - std::string proximta_HELO; - std::string proximta_rDNS; + name_tester proximta_HELO; + name_tester proximta_rDNS; std::string proximta_IP; std::string proximta_AuthUser; SPF_result_t spf_result; - std::string return_path; // envelope MAIL FROM + name_tester return_path; // envelope MAIL FROM std::string boundary; std::string to; std::string from; @@ -39,16 +61,9 @@ public: std::vector<std::string> headerbuf; std::vector<std::string> bigbuf; xstr lookahead; + std::map<test_state,std::string> decode_test_state; - // constructor - skrewt() - : spf_result(SPF_RESULT_INVALID), - boundary("x-xx-x"), msgsize(0), saw_blank_line(0), recno(0), - maxsize(1000*1000), error_exit(0), mid_required(0), - headerbuf(0), bigbuf(0), - lookahead(1, "") - {} - + skrewt(); // constructor xstr getRecord(std::istream& xin); xstr getLine(std::istream& xin); int headers(std::istream& xin); diff --git a/tools/makefile b/tools/makefile index 2373125..7d0afbf 100644 --- a/tools/makefile +++ b/tools/makefile @@ -29,7 +29,8 @@ qprogs = $(qmain:%.c=%) moremain = wripper.c bash-c.c ltgrey.c fixown.c pipette.c moreprogs = $(moremain:%.c=%) -nonmain = libltgrey.c +# sources for libraries +nonmain = libltgrey.c libskrewt.c sources = $(qmain) $(moremain) $(nonmain) |