Example #1
0
CAMLprim value
caml_spf_request_query_mailfrom(value req_val)
{
    CAMLparam1(req_val);
    CAMLlocal3(ret, cmt, res);
    const char *s;
    SPF_request_t *req = (SPF_request_t *)req_val;
    SPF_response_t *resp;
    SPF_result_t result;

    caml_enter_blocking_section();
    SPF_request_query_mailfrom(req, &resp);
    caml_leave_blocking_section();

    ret = caml_alloc(5, 0);

    result = SPF_response_result(resp);
    res = caml_alloc(1, tag_of_result(result));

    switch (result) {
    case SPF_RESULT_FAIL:
    case SPF_RESULT_SOFTFAIL:
    case SPF_RESULT_NEUTRAL:
        cmt = caml_alloc(2, 0);
        Store_field(cmt, 0,
                    caml_copy_string(SPF_response_get_smtp_comment(resp)));
        Store_field(cmt, 1,
                    caml_copy_string(SPF_response_get_explanation(resp)));
        res = caml_alloc(1, tag_of_result(result));
        Store_field(res, 0, cmt);
        Store_field(ret, 0, res);
        break;
    case SPF_RESULT_INVALID:
    case SPF_RESULT_PASS:
    case SPF_RESULT_TEMPERROR:
    case SPF_RESULT_PERMERROR:
    case SPF_RESULT_NONE:
        Store_field(ret, 0, Val_int(tag_of_result(result)));
        break;
    }

    Store_field(ret, 1, Val_int(SPF_response_reason(resp)));

/* For buggy libspf2 - avoid a segfault */
#define BUG_HEADER_COMMENT "internal error"
#define BUG_RECEIVED_SPF_VALUE "none (" BUG_HEADER_COMMENT ")"
#define BUG_RECEIVED_SPF "Received-SPF: " BUG_RECEIVED_SPF_VALUE

    s = SPF_response_get_received_spf(resp);
    Store_field(ret, 2, caml_copy_string(s ? s : BUG_RECEIVED_SPF));
    s = SPF_response_get_received_spf_value(resp);
    Store_field(ret, 3, caml_copy_string(s ? s : BUG_RECEIVED_SPF_VALUE));
    s = SPF_response_get_header_comment(resp);
    Store_field(ret, 4, caml_copy_string(s ? s : BUG_HEADER_COMMENT));

    SPF_response_free(resp);

    CAMLreturn(ret);
}
Example #2
0
File: spf.c Project: Exim/exim
int
spf_process(const uschar **listptr, uschar *spf_envelope_sender, int action)
{
int sep = 0;
const uschar *list = *listptr;
uschar *spf_result_id;
int rc = SPF_RESULT_PERMERROR;

if (!(spf_server && spf_request))
  /* no global context, assume temp error and skip to evaluation */
  rc = SPF_RESULT_PERMERROR;

else if (SPF_request_set_env_from(spf_request, CS spf_envelope_sender))
  /* Invalid sender address. This should be a real rare occurrence */
  rc = SPF_RESULT_PERMERROR;

else
  {
  /* get SPF result */
  if (action == SPF_PROCESS_FALLBACK)
    {
    SPF_request_query_fallback(spf_request, &spf_response, CS spf_guess);
    spf_result_guessed = TRUE;
    }
  else
    SPF_request_query_mailfrom(spf_request, &spf_response);

  /* set up expansion items */
  spf_header_comment     = US SPF_response_get_header_comment(spf_response);
  spf_received           = US SPF_response_get_received_spf(spf_response);
  spf_result             = US SPF_strresult(SPF_response_result(spf_response));
  spf_smtp_comment       = US SPF_response_get_smtp_comment(spf_response);

  rc = SPF_response_result(spf_response);
  }

/* We got a result. Now see if we should return OK or FAIL for it */
DEBUG(D_acl) debug_printf("SPF result is %s (%d)\n", SPF_strresult(rc), rc);

if (action == SPF_PROCESS_GUESS && (!strcmp (SPF_strresult(rc), "none")))
  return spf_process(listptr, spf_envelope_sender, SPF_PROCESS_FALLBACK);

while ((spf_result_id = string_nextinlist(&list, &sep, NULL, 0)))
  {
  BOOL negate, result;

  if ((negate = spf_result_id[0] == '!'))
    spf_result_id++;

  result = Ustrcmp(spf_result_id, spf_result_id_list[rc].name) == 0;
  if (negate != result) return OK;
  }

/* no match */
return FAIL;
}
Example #3
0
File: spf.c Project: Gnitset/.bah
void block(SPF_response_t *spf_response)
{
	const char *explain;
	explain = SPF_response_get_smtp_comment(spf_response);

	if (explain) {
		printf("E550 %s (#5.7.1)\n", explain);
		fprintf(stderr, "spf: blocked with: %s\n", explain);
	} else {
		printf("E550 Blocked with SPF (#5.7.1)\n");
		fprintf(stderr, "spf: WARNING: no explanation for blocked mail!\n");
	}
}
Example #4
0
File: spf.c Project: fanf2/exim
int spf_process(uschar **listptr, uschar *spf_envelope_sender, int action) {
  int sep = 0;
  uschar *list = *listptr;
  uschar *spf_result_id;
  uschar spf_result_id_buffer[128];
  int rc = SPF_RESULT_PERMERROR;

  if (!(spf_server && spf_request)) {
    /* no global context, assume temp error and skip to evaluation */
    rc = SPF_RESULT_PERMERROR;
    goto SPF_EVALUATE;
  };

  if (SPF_request_set_env_from(spf_request, CS spf_envelope_sender)) {
    /* Invalid sender address. This should be a real rare occurence */
    rc = SPF_RESULT_PERMERROR;
    goto SPF_EVALUATE;
  }

  /* get SPF result */
  if (action == SPF_PROCESS_FALLBACK)
    SPF_request_query_fallback(spf_request, &spf_response, CS spf_guess);
  else
    SPF_request_query_mailfrom(spf_request, &spf_response);

  /* set up expansion items */
  spf_header_comment     = (uschar *)SPF_response_get_header_comment(spf_response);
  spf_received           = (uschar *)SPF_response_get_received_spf(spf_response);
  spf_result             = (uschar *)SPF_strresult(SPF_response_result(spf_response));
  spf_smtp_comment       = (uschar *)SPF_response_get_smtp_comment(spf_response);

  rc = SPF_response_result(spf_response);

  /* We got a result. Now see if we should return OK or FAIL for it */
  SPF_EVALUATE:
  debug_printf("SPF result is %s (%d)\n", SPF_strresult(rc), rc);

  if (action == SPF_PROCESS_GUESS && (!strcmp (SPF_strresult(rc), "none")))
    return spf_process(listptr, spf_envelope_sender, SPF_PROCESS_FALLBACK);

  while ((spf_result_id = string_nextinlist(&list, &sep,
                                     spf_result_id_buffer,
                                     sizeof(spf_result_id_buffer))) != NULL) {
    int negate = 0;
    int result = 0;

    /* Check for negation */
    if (spf_result_id[0] == '!') {
      negate = 1;
      spf_result_id++;
    };

    /* Check the result identifier */
    result = Ustrcmp(spf_result_id, spf_result_id_list[rc].name);
    if (!negate && result==0) return OK;
    if (negate && result!=0) return OK;
  };

  /* no match */
  return FAIL;
}
Example #5
0
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;
}
Example #6
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;  
}