From 159a3f448ad2caf9468921a4387c2dbafe09c3a3 Mon Sep 17 00:00:00 2001 From: John Denker Date: Tue, 31 Jul 2012 18:08:21 -0700 Subject: bring sepofra over from ~/hack/ --- tools/sepofra.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 tools/sepofra.c (limited to 'tools/sepofra.c') diff --git a/tools/sepofra.c b/tools/sepofra.c new file mode 100644 index 0000000..5072b36 --- /dev/null +++ b/tools/sepofra.c @@ -0,0 +1,178 @@ +#include +#include + +#include "sepofra.h" + + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +using namespace std; + +string domain_part(const string ema){ + size_t where = ema.find('@'); + if (where != ema.npos){ + return ema.substr(1+where); + } + return ema; +} + +string subdomain(const string ema){ + size_t where = ema.find('.'); + if (where != ema.npos){ + return ema.substr(1+where); + } + return ema; +} + +SPF_result_t sepofra::check1(const string host, + const string msg, const int debug){ + if (!host.length()) return SPF_RESULT_INVALID; + + authorities.push_back(host); + if (SPF_request_set_env_from( spf_request, + host.c_str() ) ) { + throw bad_thing (("Invalid " + msg + ": " + host).c_str()); + } + + if (spf_response) SPF_response_free(spf_response); + SPF_request_query_mailfrom(spf_request, &spf_response); + if (debug) dumpit(debug, spf_response, ""); + return SPF_response_result(spf_response); +} + + +void sepofra::check( + const string opt_ip, + const string opt_helo, + const string opt_mailfrom, + const string opt_rcpt_to, + const int opt_debug) +{ + SPF_server_t* spf_server = NULL; + sepofra rslt; + ip = opt_ip; + mailfrom = opt_mailfrom; + string mailfrom_domain = domain_part(opt_mailfrom); + string auth; + + do { + spf_server = SPF_server_new(SPF_DNS_CACHE, opt_debug); + if (spf_server == NULL) { + cerr << "SPF_server_new failed" << endl; + break; + } + + spf_request = SPF_request_new(spf_server); + if (spf_request == NULL) { + cerr << "SPF_request_new failed" << endl; + break; + } + + if ( SPF_request_set_ipv4_str( spf_request, opt_ip.c_str() ) ) { + cerr << "Invalid IP address: " << opt_ip << endl; + break; + } + + result = check1(opt_helo, "HELO domain", opt_debug); + if (result == SPF_RESULT_PASS) break; + if (result == SPF_RESULT_FAIL) break; + + result = check1(mailfrom, "MAILFROM domain", opt_debug); + if (result == SPF_RESULT_PASS) break; + if (result == SPF_RESULT_FAIL) break; + + result = check1(subdomain(opt_helo), "HELO subdomain", opt_debug); + if (result == SPF_RESULT_PASS) break; + if (result == SPF_RESULT_FAIL) break; + + result = check1(subdomain(mailfrom), "MAILFROM domain", opt_debug); + if (result == SPF_RESULT_PASS) break; + if (result == SPF_RESULT_FAIL) break; + + } while(0); + + if (spf_response) SPF_response_free(spf_response); + if (spf_request) SPF_request_free(spf_request); + if (spf_server) SPF_server_free(spf_server); + + return; +} + +string sepofra::explain() const { + if (result == SPF_RESULT_INVALID) return ""; +// now build a string + stringstream build; + string summary = SPF_strresult(result); + if (result != SPF_RESULT_PASS + && result != SPF_RESULT_FAIL) summary = "neutral"; + + char hostname[1+HOST_NAME_MAX]; + gethostname(hostname, 1+HOST_NAME_MAX); + build << "Received-SPF: "; + build << summary; + build << " (" << hostname; /* ) */ + build << ": sender " << ip; + if (result == SPF_RESULT_PASS){ + build << " is approved by {" + << authorities.back() + << "}"; + } else if (result == SPF_RESULT_FAIL){ + build << " is forbidden by {" + << authorities.back() + << "}"; + } else { + build << " is neither approved nor forbidden by {"; + int didsome(0); + for (list::const_iterator ptr = authorities.begin(); + ptr != authorities.end(); ptr++) { + if (didsome++) build << " "; + build << *ptr; + } + build << "}"; + } + /* ( */ build << ")"; + build << " client-ip=" << ip << ";"; + build << " envelope-from=" << mailfrom << ";"; + return build.str(); +} + +void dumpit(const int opt_debug, + SPF_response_t* spf_response, + const char* msg) { + int i; + printf("---- %s\n", msg); + if ( opt_debug > 0 ) { + printf ( "result = %s (%d)\n", + SPF_strresult(SPF_response_result(spf_response)), + SPF_response_result(spf_response)); + printf ( "err = %s (%d)\n", + SPF_strerror(SPF_response_errcode(spf_response)), + SPF_response_errcode(spf_response)); + for (i = 0; i < SPF_response_messages(spf_response); i++) { + SPF_error_t *err = SPF_response_message(spf_response, i); + printf ( "%s_msg = (%d) %s\n", + (SPF_error_errorp(err) ? "warn" : "err"), + SPF_error_code(err), + SPF_error_message(err)); + } + } + +#define VALID_STR(x) (x ? x : "") + + printf("Bottom line result: %s\n", + SPF_strresult( SPF_response_result(spf_response))); + + printf("Reason: %s\n", SPF_strreason(spf_response->reason)); + + printf("SMTP comment: %s\n", + VALID_STR(SPF_response_get_smtp_comment(spf_response))); + + printf("Header comment: %s\n", + VALID_STR(SPF_response_get_header_comment(spf_response))); + + printf("Received spf: %s\n", + VALID_STR(SPF_response_get_received_spf(spf_response))); + +} -- cgit v1.2.3