/*
 * XF-SPF, basic but fully function implementation of SPF checker to be
 * used with qmail-smtpd's SMTPEXTFORK patch. Please see README for details.
 */
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/nameser.h> /* DNS struct */
#include "xf-spf.h"
#include "syslog.h"

#include <spf2/spf.h>

int main()
{
	int	res = 0;
	int	i;
	int	xfspf_dbg = 0;

	char *remote_ip = NULL;
	char *remote_sender = NULL;
	char *heloehlo = NULL;
	char *rcptto = NULL;

	const char *envp;
	int spfbehavior;

	SPF_server_t		*spf_server = NULL;
	SPF_request_t		*spf_request = NULL;
	SPF_response_t		*spf_myres = NULL;
	SPF_response_t		*spf_myres2 = NULL; // para DNS secundario

int error(int res)
{
	if (spf_request)
		SPF_request_free(spf_request);
	if (spf_server)
		SPF_server_free(spf_server);
	exit(res);
}

int errcli()
{
	fprintf(stderr, "This program should not be run from the command line\n");
	error(NOTCLI);
}

	// getenv retorna char * entao, convertemos ponteiro pra inteiro e atribuimos
	if (!(envp = getenv("SPFBEHAVIOR"))) {
		loga("SPFBEHAVIOR enviroment var is not defined");
		error(XFPASS);
	} else
		spfbehavior = atoi(envp);

	// if spfbehavior is not 1-6, no more checks, let it pass
	if ((spfbehavior < 1) || (spfbehavior > 6)) error(XFPASS);

	if (!(remote_ip = getenv("TCPREMOTEIP"))) errcli();
	if (!(rcptto = getenv("REMOTERCPT"))) errcli();
	if (!(heloehlo = getenv("REMOTEHELO"))) errcli();
	if (!(remote_sender = getenv("REMOTEMF"))) remote_sender = "postmaster";

	spf_server = SPF_server_new(SPF_DNS_CACHE, xfspf_dbg);

	if (spf_server == NULL) {
		loga("SPF lib failed on spf_server creation");
		error(XFSPFERR);
	}

	spf_request = SPF_request_new(spf_server);

	if ( SPF_request_set_ipv4_str( spf_request, remote_ip ) ) {
		loga("SPF lib identified IP address as invalid");
		error(XFSPFERR);
	}

	if (heloehlo == NULL) {
		if (remote_sender != NULL) {
			if (strstr(remote_sender, "@") != NULL) {
				heloehlo = strdup(strstr(remote_sender, "@") + 1);

				if ( SPF_request_set_helo_dom( spf_request, heloehlo ) ) {
					loga("SPF lib identified HELO domain as invalid");
					error(XFSPFERR);
				}
			}
		}
	} else {
		if ( SPF_request_set_helo_dom( spf_request, heloehlo ) ) {
			loga("SPF lib identified HELO domain as invalid");
			error(XFSPFERR);
		}
	}

	if ( SPF_request_set_env_from( spf_request, remote_sender ) ) {
		loga("SPF lib identified envelope FROM address as invalid");
		error(XFSPFERR);
	}

	SPF_request_query_mailfrom(spf_request, &spf_myres);

	if (SPF_response_result(spf_myres) != SPF_RESULT_PASS) {
		SPF_request_query_rcptto(spf_request, &spf_myres2, rcptto);
		if (SPF_response_result(spf_myres2) == SPF_RESULT_PASS) {
		}
	}

	// Vamos liberar a memoria
	SPF_response_free(spf_myres);
	if (spf_myres2) SPF_response_free(spf_myres2);

	if (spfbehavior > 0)
		if (envp = SPF_response_get_received_spf(spf_myres))
			loga(envp);
#if LOGNSPFDOM == 1
		else
			loga("Received-SPF: none (domain does not have SPF record)");
#endif

	switch (res = SPF_response_result(spf_myres)) {
	  case SPF_RESULT_PASS:
	    break;
	  case SPF_RESULT_FAIL:
	    if (spfbehavior > 2) error(XFPERMF);
	    break;
	  case SPF_RESULT_SOFTFAIL:
	    if (spfbehavior > 3) error(XFPERMF);
	    break;
	  case SPF_RESULT_NEUTRAL:
	    if (spfbehavior > 4) error(XFPERMF);
	    break;
	  case SPF_RESULT_INVALID:
	    if (spfbehavior > 5) error(XFPERMF);
	    break;
	  case SPF_RESULT_TEMPERROR:
	    if (spfbehavior > 5) error(XFPERMF);
	    break;
	 case SPF_RESULT_PERMERROR:   
	    if (spfbehavior > 5) error(XFPERMF);
	    break;
	  case SPF_RESULT_NONE:
	    if (spfbehavior > 5) error(XFPERMF);
	    break;
	  default:
	    error(res);
	}
return(XFPASS);
}


syntax highlighted by Code2HTML, v. 0.9.1