コード例 #1
0
ファイル: spf.c プロジェクト: fanf2/exim
int spf_init(uschar *spf_helo_domain, uschar *spf_remote_addr) {

  spf_server = SPF_server_new(SPF_DNS_CACHE, 0);

  if ( spf_server == NULL ) {
    debug_printf("spf: SPF_server_new() failed.\n");
    return 0;
  }

  if (SPF_server_set_rec_dom(spf_server, CS primary_hostname)) {
    debug_printf("spf: SPF_server_set_rec_dom() failed.\n");
    spf_server = NULL;
    return 0;
  }

  spf_request = SPF_request_new(spf_server);

  if (SPF_request_set_ipv4_str(spf_request, CS spf_remote_addr)) {
    debug_printf("spf: SPF_request_set_ipv4_str() failed.\n");
    spf_server = NULL;
    spf_request = NULL;
    return 0;
  }

  if (SPF_request_set_helo_dom(spf_request, CS spf_helo_domain)) {
    debug_printf("spf: SPF_set_helo_dom() failed.\n");
    spf_server = NULL;
    spf_request = NULL;
    return 0;
  }

  return 1;
}
コード例 #2
0
ファイル: spf.c プロジェクト: Exim/exim
BOOL
spf_init(uschar *spf_helo_domain, uschar *spf_remote_addr)
{
spf_server = SPF_server_new(SPF_DNS_CACHE, 0);

if (!spf_server)
  {
  DEBUG(D_receive) debug_printf("spf: SPF_server_new() failed.\n");
  return FALSE;
  }

if (SPF_server_set_rec_dom(spf_server, CS primary_hostname))
  {
  DEBUG(D_receive) debug_printf("spf: SPF_server_set_rec_dom(\"%s\") failed.\n",
    primary_hostname);
  spf_server = NULL;
  return FALSE;
  }

spf_request = SPF_request_new(spf_server);

if (  SPF_request_set_ipv4_str(spf_request, CS spf_remote_addr)
   && SPF_request_set_ipv6_str(spf_request, CS spf_remote_addr)
   )
  {
  DEBUG(D_receive)
    debug_printf("spf: SPF_request_set_ipv4_str() and "
      "SPF_request_set_ipv6_str() failed [%s]\n", spf_remote_addr);
  spf_server = NULL;
  spf_request = NULL;
  return FALSE;
  }

if (SPF_request_set_helo_dom(spf_request, CS spf_helo_domain))
  {
  DEBUG(D_receive) debug_printf("spf: SPF_set_helo_dom(\"%s\") failed.\n",
    spf_helo_domain);
  spf_server = NULL;
  spf_request = NULL;
  return FALSE;
  }

return TRUE;
}
コード例 #3
0
ファイル: spf4r.c プロジェクト: caquino/spf4r
static VALUE
t_query (VALUE self, VALUE map)
{
	int retcode = SPF_RESULT_PASS;
	SPF_server_t *spf_server = NULL;
	SPF_request_t *spf_request = NULL;
	SPF_response_t *spf_response = NULL;
	SPF_response_t *spf_response_2mx = NULL;

	char * ip = STR2CSTR (rb_hash_aref (map,rb_str_new2 ("client_address")));
	char * helo = STR2CSTR (rb_hash_aref (map,rb_str_new2 ("helo_name")));
	char * sender = STR2CSTR (rb_hash_aref (map,rb_str_new2 ("sender")));
	char * recipient = STR2CSTR (rb_hash_aref (map,rb_str_new2 ("recipient")));

	spf_server = SPF_server_new (SPF_DNS_CACHE, 0);
	if (spf_server == NULL) rb_raise (rb_eRuntimeError,  "can't initialize SPF library");

	spf_request = SPF_request_new (spf_server);

	if (SPF_request_set_ipv4_str (spf_request, ip)) rb_raise (rb_eTypeError, "error, invalid IP address");

	if (SPF_request_set_helo_dom (spf_request, helo)) rb_raise (rb_eTypeError, "error, invalid helo domain");

	if (SPF_request_set_env_from (spf_request, sender)) rb_raise (rb_eTypeError, "error, invalid envelope from address");

	SPF_request_query_mailfrom (spf_request, &spf_response);

	if (SPF_response_result (spf_response) != SPF_RESULT_PASS)
	{
		SPF_request_query_rcptto (spf_request, &spf_response_2mx, recipient);

		if (SPF_response_result (spf_response_2mx) == SPF_RESULT_PASS)
		{
			return INT2NUM(SPF_RESULT_PASS);
		}

		retcode = SPF_response_result (spf_response);
	} 
	SPF_server_free(spf_server);

	return INT2NUM(retcode);
}
コード例 #4
0
ファイル: spf_stubs.c プロジェクト: andrenth/ocaml-spf
CAMLprim value
caml_spf_server_new(value debug_val, value dns_type_val)
{
    CAMLparam2(debug_val, dns_type_val);
    int debug;
    int dns_type;
    SPF_server_t *server;

    debug = (debug_val == Val_none) ? 0 : Bool_val(Some_val(debug_val));

    dns_type = dns_type_of_val(dns_type_val);
    if (dns_type == -1)
        spf_error("unknown DNS type");

    server = SPF_server_new(dns_type, debug);
    if (server == NULL)
        spf_error("cannot create SPF server");

    CAMLreturn((value)server);
}
コード例 #5
0
ファイル: spf.c プロジェクト: badzong/mopher
int
spf_init(void)
{
	char **k, **v;

	if((spf_server = SPF_server_new(SPF_DNS_CACHE, 0)) == NULL) {
		log_error("spf: init: SPF_server_new failed");
		return -1;
	}

	acl_symbol_register("spf", MS_OFF_ENVFROM, spf, AS_CACHE);
	acl_symbol_register("spf_reason", MS_OFF_ENVFROM, spf, AS_CACHE);

	for (k = spf_static_keys, v = spf_static_values; *k && *v; ++k, ++v)
	{
		acl_constant_register(VT_STRING, *k, *v, VF_KEEP);
	}


	return 0;
}
コード例 #6
0
ファイル: spf.c プロジェクト: Gnitset/.bah
int main()
{
	int spf;
	char *me, *remote, *helo, *sender, *spf_env;
	const char *header;
	SPF_server_t *spf_server;
	SPF_request_t *spf_request;
	SPF_response_t *spf_response;

	/**
	 * env variables
	 **/
	if (getenv("RELAYCLIENT") ||              /* known user */
	    !(spf_env = getenv("SPF"))) return 0; /* plugin disabled */

	spf = atoi(spf_env);
	if (spf < 1 || spf > 6) {
		if (spf > 6)
			fprintf(stderr, "spf: ERROR: invalid value (%d) of SPF variable\n", spf);
		return 0;
	}

	remote  = getenv("TCPREMOTEIP"); 
	me      = getenv("TCPLOCALHOST");
	if (!me) me = getenv("TCPLOCALIP");
	if (!remote || !me) { /* should never happen */
		fprintf(stderr, "spf: ERROR: can't get tcpserver variables\n");
		if(!remote) fprintf(stderr, "spf: can't read TCPREMOTEIP\n");
		else fprintf(stderr, "spf: can't read TCPLOCALHOST nor TCPLOCALIP\n");
		return 0;
	}

	sender = getenv("SMTPMAILFROM");
	if (!sender) { /* should never happen */
		fprintf(stderr, "spf: ERROR: can't get envelope sender address\n");
		fprintf(stderr, "spf: can't read SMTPMAILFROM\n");
		return 0;
	}
	if (!*sender) return 0; /* null sender mail */

	helo = getenv("SMTPHELOHOST");

	/**
	 * SPF
	 **/
	spf_server = SPF_server_new(SPF_DNS_CACHE, 0);
	if (!spf_server) {
		fprintf(stderr, "spf: ERROR: can't initialize libspf2\n");
		return 0;
	}
	spf_request = SPF_request_new(spf_server);
	if (!spf_request) {
		fprintf(stderr, "spf: ERROR: can't initialize libspf2\n");
		return 0;
	}

	if (SPF_request_set_ipv4_str(spf_request, remote)) {
		fprintf(stderr, "spf: can't parse TCPREMOTEIP\n");
		return 0;
	}

	SPF_server_set_rec_dom(spf_server, me);

	if (helo) SPF_request_set_helo_dom(spf_request, helo);
	SPF_request_set_env_from(spf_request, sender);

	/* Perform actual lookup */
	SPF_request_query_mailfrom(spf_request, &spf_response);

	/* check whether mail needn`t to be blocked */
	switch (SPF_response_result(spf_response)) {
		case SPF_RESULT_PASS:      break;
		case SPF_RESULT_FAIL:      if (spf > 0) { block(spf_response); return 0; } break;
		case SPF_RESULT_SOFTFAIL:  if (spf > 1) { block(spf_response); return 0; } break;
		case SPF_RESULT_NEUTRAL:   if (spf > 2) { block(spf_response); return 0; } break;
		case SPF_RESULT_NONE:      if (spf > 3) { block(spf_response); return 0; } break;
		case SPF_RESULT_TEMPERROR:
		case SPF_RESULT_PERMERROR: if (spf > 4) { block(spf_response); return 0; } break;
#if 0
		case SPF_RESULT_UNKNOWN:   if (spf > 5) { block(spf_response); return 0; } break;
		case SPF_RESULT_UNMECH:    break;
#else
					   // FIXME: UNKNOWN and UNMECH above map how?
					   // INVALID should not ever occur, it indicates a bug.
		case SPF_RESULT_INVALID:   if (spf > 5) { block(spf_response); return 0; } break;
#endif
	}

	/* add header */
	header = SPF_response_get_received_spf(spf_response);
	if (header)
		printf("H%s\n", header);
	else {
		fprintf(stderr, "spf: libspf2 library failed to produce Received-SPF header\n",
			SPF_strerror(SPF_response_errcode(spf_response)));
		/* Example taken from libspf2: */
/*
		fprintf ( stderr, "spf: diag: result = %s (%d)\n",
		SPF_strresult(SPF_response_result(spf_response)),
		SPF_response_result(spf_response));
		fprintf ( stderr, "spf: diag: 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);
			fprintf ( stderr, "spf: diag: %s_msg = (%d) %s\n",
				(SPF_error_errorp(err) ? "warn" : "err"),
				SPF_error_code(err),
				SPF_error_message(err));
		}
*/
	}

	SPF_response_free(spf_response);
	SPF_request_free(spf_request);
	SPF_server_free(spf_server);

	return 0;
}
コード例 #7
0
int main( int argc, char *argv[] )
{
	SPF_client_options_t	*opts;
	SPF_client_request_t	*req = NULL;

	SPF_server_t	*spf_server = NULL;
	SPF_request_t	*spf_request = NULL;
	SPF_response_t	*spf_response = NULL;
	SPF_response_t	*spf_response_2mx = NULL;
	SPF_errcode_t	 err;

	int  			 opt_keep_comments = 0;

#ifdef TO_MX
	char			*p, *p_end;
#endif

	int 			 request_limit=0;
	int				 major, minor, patch;

	int				 res = 0;
	int				 c;

	const char		*partial_result;
	char			*result = NULL;
	int				 result_len = 0;
	char			hostname[255];
	char			pf_result[100];
	struct hostent		*fullhostname;

        /* Figure out our name */
        progname = strrchr(argv[0], '/');
        if (progname != NULL)                                                 
                ++progname;
        else
                progname = argv[0];

	/*open syslog*/
	openlog(progname, LOG_PID|LOG_CONS|LOG_NDELAY|LOG_NOWAIT, LOG_MAIL);

	/* Redefine libSPF2 output routines to go to syslog */
	SPF_error_handler = SPF_error_syslog;
	SPF_warning_handler = SPF_warning_syslog;
	SPF_info_handler = SPF_info_syslog;
	SPF_debug_handler = SPF_debug_syslog;
	
	opts = (SPF_client_options_t *)malloc(sizeof(SPF_client_options_t));
	memset(opts, 0, sizeof(SPF_client_options_t));

	/*
	 * check the arguments
	 */

	for (;;) {
		int option_index;	/* Largely unused */

		c = getopt_long_only (argc, argv, "f:i:s:h:r:lt::gemcnd::kz:a:v",
				  long_options, &option_index);

		if (c == -1)
			break;

		switch (c) {
			case 'l':
				opts->localpolicy = optarg;
				break;

			case 't':
				if (optarg == NULL)
					opts->use_trusted = 1;
				else
					opts->use_trusted = atoi(optarg);
				break;

			case 'g':
				opts->fallback = optarg;
				break;

			case 'e':
				opts->explanation = optarg;
				break;

			case 'm':
				opts->max_lookup = atoi(optarg);
				break;

			case 'c':		/* "clean"		*/
				opts->sanitize = atoi(optarg);
				break;

			case 'n':		/* name of host doing SPF checking */
				opts->rec_dom = optarg;
				break;

			case 'a':
				unimplemented('a');
				break;

			case 'z':
				unimplemented('z');
				break;


			case 'v':
				fprintf( stderr, "policyd-spf-fs version information:\n" );
				fprintf( stderr, "policyd-spf-fs version: $Rev: 27 $\n");
				fprintf( stderr, "SPF test system version: %s\n",
				 SPF_TEST_VERSION );
				fprintf( stderr, "Compiled with SPF library version: %d.%d.%d\n",
				 SPF_LIB_VERSION_MAJOR, SPF_LIB_VERSION_MINOR,
				 SPF_LIB_VERSION_PATCH );
				SPF_get_lib_version( &major, &minor, &patch );
				fprintf( stderr, "Running with SPF library version: %d.%d.%d\n",
				 major, minor, patch );
				fprintf( stderr, "\n" );
				FAIL_ERROR;
				break;

			case 0:
			case '?':
				help();
				FAIL_ERROR;
				break;

			case 'k':
				opt_keep_comments = 1;
				break;

			case 'd':
				if (optarg == NULL)
					opts->debug = 1;
				else
					opts->debug = atoi( optarg );
				break;

			default:
				fprintf( stderr, "Error: getopt returned character code 0%o ??\n", c);
				FAIL_ERROR;
		}
	}

	if (optind != argc) {
		help();
		FAIL_ERROR;
	}

	if (!opts->rec_dom) {
  	  gethostname(hostname, 255);
	  fullhostname = gethostbyname(hostname);
	
	  if (opts->debug > 1)
	    syslog(LOG_DEBUG, "Hostname: %s\n",fullhostname->h_name);

	  opts->rec_dom = fullhostname->h_name;
	}

	/*
	 * set up the SPF configuration
	 */

	spf_server = SPF_server_new(SPF_DNS_CACHE, opts->debug > 2 ? opts->debug-2 : 0);

	if ( opts->rec_dom )
		SPF_server_set_rec_dom( spf_server, opts->rec_dom );
	if ( opts->sanitize )
		SPF_server_set_sanitize( spf_server, opts->sanitize );
	if ( opts->max_lookup )
		SPF_server_set_max_dns_mech(spf_server, opts->max_lookup);

	if (opts->localpolicy) {
		err = SPF_server_set_localpolicy( spf_server, opts->localpolicy, opts->use_trusted, &spf_response);
		if ( err ) {
			response_print_errors("Error setting local policy",
							spf_response, err);
			WARN_ERROR;
		}
		FREE_RESPONSE(spf_response);
	}


	if ( !opts->explanation ) {
	  opts->explanation = DEFAULT_EXPLANATION;
	}
	
	err = SPF_server_set_explanation( spf_server, opts->explanation, &spf_response );
	if ( err ) {
	  response_print_errors("Error setting default explanation",
	         spf_response, err);
	  WARN_ERROR;
	}
	FREE_RESPONSE(spf_response);

	/*
	 * process the SPF request
	 */

	request_limit=0;

	while ( request_limit < REQUEST_LIMIT ) {
		request_limit++;	                                
	        if (request_limit == 0) {
  		  free(req);
  		}
		req = (SPF_client_request_t *)malloc(sizeof(SPF_client_request_t));
		memset(req, 0, sizeof(SPF_client_request_t));
		
		if (read_request_from_pf(opts, req)) {
		  syslog(LOG_WARNING, "IO Closed while reading, exiting");
		  EXIT_OK;
		}
		
		if (opts->debug > 1)
			syslog(LOG_DEBUG, "Reincarnation %d\n", request_limit);


		/* We have to do this here else we leak on CONTINUE_ERROR */
		FREE_REQUEST(spf_request);
		FREE_RESPONSE(spf_response);

		spf_request = SPF_request_new(spf_server);

		if (SPF_request_set_ipv4_str(spf_request, req->ip) && SPF_request_set_ipv6_str(spf_request, req->ip)) {
			syslog(LOG_WARNING, "Invalid IP address.\n" );
			CONTINUE_ERROR;
		}

	  if (req->helo) {
		if (SPF_request_set_helo_dom( spf_request, req->helo ) ) {
			syslog(LOG_WARNING, "Invalid HELO domain.\n" );
			CONTINUE_ERROR;
		}
	  }

	  	if (strchr(req->sender, '@') > 0) {
  		  if (SPF_request_set_env_from( spf_request, req->sender ) ) {
			syslog(LOG_WARNING, "Invalid envelope from address.\n" );
			CONTINUE_ERROR;
		  }
		} else { /* This is something we can not check*/ 
                  CONTINUE_DUNNO("no valid email address found");
                }

		err = SPF_request_query_mailfrom(spf_request, &spf_response);
		if (opts->debug > 1) 
			response_print("Main query", spf_response);
		if (err) {
		  if (opts->debug > 1)
			response_print_errors("Failed to query MAIL-FROM",
							spf_response, err);

			CONTINUE_DUNNO("no SPF record found");
		}

		if (result != NULL)
			result[0] = '\0';
		APPEND_RESULT(SPF_response_result(spf_response));
		
#ifdef TO_MX /* This code returns usualy neutral and oferwrites a fail from the above spf code
                which is not what we like. So we disable it for the time deing ... */
                
		if (req->rcpt_to != NULL  && *req->rcpt_to != '\0' ) {
			p = req->rcpt_to;
			p_end = p + strcspn(p, ",;");

			/* This is some incarnation of 2mx mode. */
			while (SPF_response_result(spf_response)!=SPF_RESULT_PASS) {
				if (*p_end)
					*p_end = '\0';
				else
					p_end = NULL;	/* Note this is last rcpt */

				err = SPF_request_query_rcptto(spf_request,
								&spf_response_2mx, p);
				if (opts->debug > 1)
					response_print("2mx query", spf_response_2mx);
				if (err) {
					response_print_errors("Failed to query RCPT-TO",
									spf_response, err);
					CONTINUE_ERROR;
				}

				/* append the result */
				APPEND_RESULT(SPF_response_result(spf_response_2mx));

				spf_response = SPF_response_combine(spf_response,
								spf_response_2mx);

				if (!p_end)
					break;
				p = p_end + 1;
			}
		}
#endif /* TO_MX */
		/* We now have an option to call SPF_request_query_fallback */
		if (opts->fallback) {
			err = SPF_request_query_fallback(spf_request,
							&spf_response, opts->fallback);
			if (opts->debug > 1)
				response_print("fallback query", spf_response_2mx);
			if (err) {
				response_print_errors("Failed to query best-guess",
								spf_response, err);
				CONTINUE_ERROR;
			}

			/* append the result */
			APPEND_RESULT(SPF_response_result(spf_response_2mx));

			spf_response = SPF_response_combine(spf_response,
							spf_response_2mx);
		}

/*		printf( "R: %s\nSC: %s\nHC: %s\nRS: %s\n",
			result,
			X_OR_EMPTY(SPF_response_get_smtp_comment(spf_response)),
			X_OR_EMPTY(SPF_response_get_header_comment(spf_response)),
			X_OR_EMPTY(SPF_response_get_received_spf(spf_response))
			);
*/			
		pf_response(opts, spf_response, req);
			
		res = SPF_response_result(spf_response);

		fflush(stdout);
	}

  error:
	FREE(result, free);
	FREE_RESPONSE(spf_response);
	FREE_REQUEST(spf_request);
	FREE(spf_server, SPF_server_free);

	syslog(LOG_INFO, "Terminating with result %d, Reincarnation: %d\n", res, request_limit);
	return res;
}
コード例 #8
0
ファイル: check_spf.c プロジェクト: Gurut/gross
int
spfc(thread_pool_t *info, thread_ctx_t *thread_ctx, edict_t *edict)
{
	struct timespec ts, start, now, timeleft;
	chkresult_t *result;
	grey_tuple_t *request;
	SPF_server_t *spf_server = NULL;
	SPF_request_t *spf_request = NULL;
	SPF_response_t *spf_response = NULL;
	SPF_response_t *spf_response_2mx = NULL;
	const char *smtp_error;
	int ret;

	logstr(GLOG_DEBUG, "spfc called");

	request = (grey_tuple_t *)edict->job;
	assert(request);

	result = (chkresult_t *)Malloc(sizeof(chkresult_t));
	memset(result, 0, sizeof(*result));
	result->judgment = J_UNDEFINED;
        result->checkname = "spf";

	/* initialize if we are not yet initialized */
	if (NULL == thread_ctx->state) {
		/* Initialize */
		spf_server = SPF_server_new(SPF_DNS_CACHE, SPF_DEBUG_LEVEL);
		if (NULL == spf_server) {
			logstr(GLOG_ERROR, "SPF_server_new failed");
			goto FINISH;
		}
		thread_ctx->state = spf_server;
		thread_ctx->cleanup = &cleanup_spfc;
	} else {
		spf_server = (SPF_server_t *) thread_ctx->state;
	}

	/* Now we are ready to query */
	ret = SPF_server_set_explanation(spf_server,
		"Please see http://www.openspf.org/Why?id=%{S}&ip=%{C}", &spf_response);
	if (ret)
		logstr(GLOG_ERROR, "SPF: setting explanation failed");

	spf_request = SPF_request_new(spf_server);

	ret = SPF_request_set_ipv4_str(spf_request, request->client_address);
	if (ret) {
		logstr(GLOG_ERROR, "invalid IP address %s", request->client_address);
		goto CLEANUP;
	}

	if (request->helo_name) {
		ret = SPF_request_set_helo_dom(spf_request, request->helo_name);
		if (ret) {
			logstr(GLOG_ERROR, "invalid HELO domain: %s.", request->helo_name);
			goto CLEANUP;
		}
	}

	ret = SPF_request_set_env_from(spf_request, request->sender);
	if (ret) {
		logstr(GLOG_ERROR, "invalid envelope sender address %s", request->sender);
		goto CLEANUP;
	}

	ret = SPF_request_query_mailfrom(spf_request, &spf_response);
	switch (ret) {
	case SPF_E_SUCCESS:
	case SPF_E_NOT_SPF:
		break; 
	default:
		logstr(GLOG_ERROR, "spf: sender based query failed: %s", SPF_strerror(ret));
		goto CLEANUP;
	}

	/* XXX: do we need 2mx checks? */
	ret = SPF_response_result(spf_response);
	switch (ret) {
	case SPF_RESULT_FAIL:
		result->judgment = J_BLOCK;
		logstr(GLOG_DEBUG, "SPF: fail");
		smtp_error = SPF_response_get_smtp_comment(spf_response);
		if (smtp_error) 
			result->reason = strdup(smtp_error);
		else
			result->reason = strdup("SPF: policy violation: (no message available)");
		break;
	case SPF_RESULT_SOFTFAIL:
		result->judgment = J_SUSPICIOUS;
		logstr(GLOG_DEBUG, "SPF softfail");
		result->weight = 1;	/* FIXME: configurable */
		break;
	case SPF_RESULT_PASS:
		result->judgment = J_UNDEFINED;
		logstr(GLOG_DEBUG, "SPF: pass");
		break;
	case SPF_RESULT_NEUTRAL:
		result->judgment = J_UNDEFINED;
		logstr(GLOG_DEBUG, "SPF: neutral");
		break;
	case SPF_RESULT_NONE:
		result->judgment = J_UNDEFINED;
		logstr(GLOG_DEBUG, "SPF: no record");
		break;
	default:
		logstr(GLOG_DEBUG, "Unexpected SPF result (%d)", ret);
	}

      CLEANUP:
	if (spf_request)
		SPF_request_free(spf_request);
	if (spf_response)
		SPF_response_free(spf_response);
      FINISH:

	send_result(edict, result);

	logstr(GLOG_DEBUG, "spfc returning");
	request_unlink(request);

	return 0;
}
コード例 #9
0
static int verify_data(spctx_t* ctx)
{
    char ebuf[256];
    int n;
    SPF_request_t *spf_request = NULL;
    char * xforwardaddr = NULL;
    char * xforwardhelo = NULL;
    
    if(spf_server == NULL)
    {
	/* redirect errors */
	SPF_error_handler = SPF_error_syslog; 
	SPF_warning_handler = SPF_warning_syslog; 
	SPF_info_handler = SPF_info_syslog; 
	SPF_debug_handler = SPF_debug_syslog;
      
        spf_server = SPF_server_new(SPF_DNS_CACHE, 1);
	if (spf_server == NULL) 
	    return -1;	  
    }
    
    /* trim string */
    if(ctx->xforwardaddr)
	xforwardaddr = trim_space(ctx->xforwardaddr);
    if(ctx->xforwardhelo)
	xforwardhelo = trim_space(ctx->xforwardhelo);
    
    sp_messagex(ctx, LOG_DEBUG, "New connection: ADDR %s - MAIL FROM %s - XF-ADDR %s - XF-HELO %s", 
		ctx->client.peername, ctx->sender, xforwardaddr, xforwardhelo);
    
    spf_request = SPF_request_new(spf_server);
    if( xforwardaddr )
      SPF_request_set_ipv4_str( spf_request, xforwardaddr );
    else if ( ctx->client.peername )
      SPF_request_set_ipv4_str( spf_request, ctx->client.peername );
    if( xforwardhelo )
      SPF_request_set_helo_dom( spf_request, xforwardhelo );
    if( ctx->sender )
      SPF_request_set_env_from( spf_request, ctx->sender );

    SPF_response_t *spf_response = NULL;
    SPF_request_query_mailfrom(spf_request, &spf_response);
    
    char hostname[100];
    strncpy(hostname, SPF_request_get_rec_dom(spf_request), 99);
    
    char *result_spf = NULL;
    switch(SPF_response_result(spf_response))
    {     
      case SPF_RESULT_NONE: 	
	sp_messagex(ctx, LOG_DEBUG, "No SPF policy found for %s", ctx->sender); 
	result_spf = "none";
	break;
	
      case SPF_RESULT_NEUTRAL: 
        result_spf = "neutral";
	sp_messagex(ctx, LOG_DEBUG, "SPF: NEUTRAL for %s", ctx->sender); 
	break;

      case SPF_RESULT_SOFTFAIL:
	result_spf = "softfail";
	sp_messagex(ctx, LOG_DEBUG, "SPF: SOFTFAIL for %s", ctx->sender); 
	break;
	
      case SPF_RESULT_PASS:
	result_spf = "pass";
	sp_messagex(ctx, LOG_DEBUG, "SPF: PASS for %s", ctx->sender); 
        break;
	
      case SPF_RESULT_FAIL:
	buffer_reject_message("550 SPF Reject", ebuf, sizeof(ebuf));
        buffer_reject_message(SPF_response_get_smtp_comment(spf_response), ebuf, sizeof(ebuf));
        final_reject_message(ebuf, sizeof(ebuf));
	sp_messagex(ctx, LOG_DEBUG, "SPF FAIL for %s, ignore message", ctx->sender); 

	SPF_response_free(spf_response);
	SPF_request_free(spf_request);

	if(sp_fail_data(ctx, ebuf) == -1)
            return -1;	
	else
	    return 0;
	break;
      
      case SPF_RESULT_TEMPERROR:
      case SPF_RESULT_PERMERROR:
      case SPF_RESULT_INVALID:
	buffer_reject_message("450 temporary failure", ebuf, sizeof(ebuf));
        final_reject_message(ebuf, sizeof(ebuf));
	sp_messagex(ctx, LOG_DEBUG, "TEMP ERROR or INVALID RECORD in SPF for %s", ctx->sender); 
 
	SPF_response_free(spf_response);
	SPF_request_free(spf_request);

        if(sp_fail_data(ctx, ebuf) == -1)
            return -1;	
	else
	    return 0;
	break;
    };
    char auth_result_spf[1025];
    snprintf(auth_result_spf, 1024, "spf=%s smtp.mailfrom=%s", result_spf, ctx->sender);
   
    SPF_response_free(spf_response);
    SPF_request_free(spf_request);
    
    
    
    /* Tell client to start sending data */
    if(sp_start_data (ctx) < 0)
        return -1; /* Message already printed */

    /* Setup DKIM verifier */
    DKIMContext ctxt;
    DKIMVerifyOptions vopts = {0};
    vopts.nCheckPractices = 1;
    vopts.pfnSelectorCallback = NULL; //SelectorCallback;

    n = DKIMVerifyInit( &ctxt, &vopts );

    /* Read data into verifier */
    int len = -1;
    const char *buffer = 0;
    do
    {
        len = sp_read_data(ctx, &buffer);
        if(len == -1)
            return -1;
        if(len > 0)
        {
            DKIMVerifyProcess( &ctxt, buffer, len );
	    sp_write_data( ctx, buffer, len );
        }

    } while(len > 0);
    sp_write_data( ctx, NULL, 0 );

    /* Verify DKIM */
    n = DKIMVerifyResults( &ctxt );
    
    /* Get verification details */
    int nSigCount = 0;
    DKIMVerifyDetails* pDetails;
    char szPolicy[512];

    DKIMVerifyGetDetails(&ctxt, &nSigCount, &pDetails, szPolicy );

    /* Proxy based on verification results */
    char auth_result_dkim[1025];
    if(nSigCount == 0)
    {
        sp_messagex(ctx, LOG_DEBUG, "No DKIM signature, passthrough");
	snprintf(auth_result_dkim, 1024, "dkim=none");
    }
    else if (n == DKIM_SUCCESS || n == DKIM_PARTIAL_SUCCESS)
    {
        sp_messagex(ctx, LOG_DEBUG, "DKIM verification: Success, adding header information");
	
	int strpos = 0;
	int i=0;
	for(; i<nSigCount; ++i)
	{
	    snprintf(&auth_result_dkim[strpos], 1024 - strpos, 
		     "%sdkim=%s header.d=%s", (i>0 ? ";\n" : ""),
		     (pDetails[i].nResult == DKIM_SUCCESS ? "pass" : "fail"),
		     pDetails[i].szSignatureDomain);
	    strpos = strlen(auth_result_dkim);
	}
	
    } else {
        sp_messagex(ctx, LOG_DEBUG, "DKIM verification: Failed, report error and ignore message.");

        buffer_reject_message("550 DKIM Signature failed verification (http://www.dkim.org/info/dkim-faq.html)", ebuf, sizeof(ebuf));
        final_reject_message(ebuf, sizeof(ebuf));

        DKIMVerifyFree( &ctxt );

        if(sp_fail_data(ctx, ebuf) == -1)
            return -1;
	else
	    return 0;
    }
    DKIMVerifyFree( &ctxt );

    char auth_results_header[1025];
    snprintf(auth_results_header, 1024, "Authentication-Results: %s;\n %s;\n %s;", 
	     hostname, auth_result_spf, auth_result_dkim);
    
    if( sp_done_data(ctx, auth_results_header) == -1)
        return -1;

    return 0;  
}