summaryrefslogtreecommitdiff
path: root/tools/sepofra.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/sepofra.c')
-rw-r--r--tools/sepofra.c178
1 files changed, 178 insertions, 0 deletions
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 <iostream>
+#include <sstream>
+
+#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<string>::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)));
+
+}