static void pf_response(SPF_client_options_t *opts, SPF_response_t *spf_response, SPF_client_request_t *req) { char result[RESULTSIZE]; char spf_comment[RESULTSIZE]; switch (spf_response->result) { case SPF_RESULT_PASS: strcpy(result, POSTFIX_DUNNO); printf("action=PREPEND X-%s\n",SPF_response_get_received_spf(spf_response)); snprintf(spf_comment, RESULTSIZE, SPF_response_get_received_spf(spf_response)); break; case SPF_RESULT_FAIL: strcpy(result, POSTFIX_REJECT); snprintf(spf_comment, RESULTSIZE,"SPF Reject: %s", (spf_response->smtp_comment ? spf_response->smtp_comment : (spf_response->header_comment ? spf_response->header_comment : ""))); break; case SPF_RESULT_TEMPERROR: case SPF_RESULT_PERMERROR: case SPF_RESULT_INVALID: snprintf(result, RESULTSIZE, "450 temporary failure: %s", (spf_response->smtp_comment ? spf_response->smtp_comment : "")); spf_comment[0]='\0'; break; case SPF_RESULT_SOFTFAIL: case SPF_RESULT_NEUTRAL: case SPF_RESULT_NONE: default: strcpy(result, POSTFIX_DUNNO); printf("action=PREPEND X-%s\n",SPF_response_get_received_spf(spf_response)); snprintf(spf_comment, RESULTSIZE, SPF_response_get_received_spf(spf_response)); break; } result[RESULTSIZE - 1] = '\0'; if (opts->debug > 1) syslog(LOG_DEBUG, "<-- action=%s\n", result); if (strcmp(result,POSTFIX_REJECT) == 0) { printf("action=%s %s\n\n", result, spf_comment); } else { printf("action=%s\n\n", result); } fflush(stdout); if (opts->debug) syslog(LOG_INFO, "action=%s %s (ip=%s from=%s helo=%s to=%s)\n", result, spf_comment, req->ip, req->sender, req->helo, req->rcpt_to); }
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); }
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; }
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; }
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; }