summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Denker <jsd@av8n.com>2012-11-24 11:53:34 -0800
committerJohn Denker <jsd@av8n.com>2012-11-24 11:53:34 -0800
commita80d71e7dc3b46980b9f91c9238599fee26cc1b2 (patch)
tree9831468092f614ad0d735aa2655eb39f07d0745d
parent348bd85500f5cb5dc4b239e98d9459dbe71f96bc (diff)
working toward identifying the "owning domain"
-rw-r--r--tools/libskrewt.c86
-rw-r--r--tools/libskrewt.h39
-rw-r--r--tools/makefile3
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)