Index: acl.c =================================================================== RCS file: /milter-greylist/milter-greylist/acl.c,v retrieving revision 1.113 diff -u -r1.113 acl.c --- acl.c 16 Jun 2015 12:27:29 -0000 1.113 +++ acl.c 28 Sep 2015 18:55:48 -0000 @@ -2273,6 +2273,7 @@ mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } + priv->priv_sr.sr_addheader_index = ap->ap_addheader_index; } if (ap->ap_addfooter) { priv->priv_sr.sr_addfooter = strdup(ap->ap_addfooter); @@ -2418,6 +2419,7 @@ ap.ap_msg = acl->a_msg; ap.ap_report = acl->a_report; ap.ap_addheader = acl->a_addheader; + ap.ap_addheader_index = acl->a_addheader_index; ap.ap_addfooter = acl->a_addfooter; ap.ap_subjtag = acl->a_subjtag; ap.ap_maxpeek = acl->a_maxpeek; @@ -2790,8 +2792,13 @@ mystrlcat(entrystr, tempstr, len); } if (acl->a_addheader) { - snprintf(tempstr, sizeof(tempstr), - "[addheader \"%s\"] ", acl->a_addheader); + if (acl->a_addheader_index >= 0) + snprintf(tempstr, sizeof(tempstr), + "[addheader \"%s\" %d] ", + acl->a_addheader, acl->a_addheader_index); + else + snprintf(tempstr, sizeof(tempstr), + "[addheader \"%s\"] ", acl->a_addheader); mystrlcat(entrystr, tempstr, len); } if (acl->a_addfooter) { @@ -3070,8 +3077,9 @@ } void -acl_add_addheader(hdr) +acl_add_addheader(hdr, index) char *hdr; + int index; { if (gacl->a_addheader) { mg_log(LOG_ERR, @@ -3084,9 +3092,11 @@ "malloc failed in ACL line %d", conf_line); exit(EX_OSERR); } + + gacl->a_addheader_index = index; if (conf.c_debug || conf.c_acldebug) - mg_log(LOG_DEBUG, "load acl addheader \"%s\"", hdr); + mg_log(LOG_DEBUG, "load acl addheader \"%s\" %d", hdr, index); return; } Index: acl.h =================================================================== RCS file: /milter-greylist/milter-greylist/acl.h,v retrieving revision 1.55 diff -u -r1.55 acl.h --- acl.h 16 Jun 2015 12:27:29 -0000 1.55 +++ acl.h 28 Sep 2015 18:55:48 -0000 @@ -183,6 +183,7 @@ char *ap_msg; char *ap_report; char *ap_addheader; + int ap_addheader_index; char *ap_addfooter; char *ap_subjtag; int ap_maxpeek; @@ -290,6 +291,7 @@ char *a_msg; char *a_report; char *a_addheader; + int a_addheader_index; char *a_addfooter; char *a_subjtag; int a_maxpeek; @@ -317,7 +319,7 @@ void acl_add_ecode(char *); void acl_add_msg(char *); void acl_add_report(char *); -void acl_add_addheader(char *); +void acl_add_addheader(char *, int); void acl_add_addfooter(char *); void acl_add_subjtag(char *); void acl_add_maxpeek(int); @@ -407,9 +409,9 @@ #define EXF_HELO (1LL << 26) #define EXF_LDAPCHECK (1LL << 27) #define EXF_NOLOG (1LL << 28) -#define EXF_DKIM (1LL << 28) #define EXF_P0F (1LL << 29) #define EXF_SA (1LL << 30) #define EXF_TARPIT (1LL << 31) #define EXF_MX (1LL << 32) /* Need long long (64b) */ +#define EXF_DKIM (1LL << 33) #endif /* _ACL_H_ */ Index: conf_yacc.y =================================================================== RCS file: /milter-greylist/milter-greylist/conf_yacc.y,v retrieving revision 1.126 diff -u -r1.126 conf_yacc.y --- conf_yacc.y 16 Jun 2015 12:27:29 -0000 1.126 +++ conf_yacc.y 28 Sep 2015 18:55:48 -0000 @@ -1213,7 +1213,14 @@ addheader_value: ADDHEADER QSTRING { char hdr[QSTRLEN + 1]; - acl_add_addheader(quotepath(hdr, $2, QSTRLEN)); + acl_add_addheader( + quotepath(hdr, $2, QSTRLEN), -1); + } + | ADDHEADER QSTRING TNUMBER { + char hdr[QSTRLEN + 1]; + + acl_add_addheader( + quotepath(hdr, $2, QSTRLEN), atoi($3)); } ; addfooter_value: ADDFOOTER QSTRING { Index: dkimcheck.c =================================================================== RCS file: /milter-greylist/milter-greylist/dkimcheck.c,v retrieving revision 1.8 diff -u -r1.8 dkimcheck.c --- dkimcheck.c 4 Oct 2013 08:03:42 -0000 1.8 +++ dkimcheck.c 28 Sep 2015 18:55:48 -0000 @@ -67,56 +67,6 @@ #include "dkimcheck.h" static DKIM_LIB *dkim_ptr = NULL; -static sfsistat dkimcheck_error(struct mlfi_priv *); - -static sfsistat -dkimcheck_error(priv) - struct mlfi_priv *priv; -{ - sfsistat retval; - - switch (priv->priv_dkimstat) { - case DKIM_STAT_OK: - retval = SMFIS_CONTINUE; - break; - - case DKIM_STAT_NOSIG: - mg_log(LOG_DEBUG, "DKIM failed: %s", - dkim_getresultstr(priv->priv_dkimstat)); - - retval = SMFIS_CONTINUE; - break; - - case DKIM_STAT_KEYFAIL: - case DKIM_STAT_CBTRYAGAIN: - mg_log(LOG_WARNING, "DKIM failed: %s", - dkim_getresultstr(priv->priv_dkimstat)); - - retval = SMFIS_TEMPFAIL; - break; - - case DKIM_STAT_INTERNAL: - mg_log(LOG_WARNING, "DKIM failed: %s", - dkim_getresultstr(priv->priv_dkimstat)); - - exit(EX_OSERR); - break; - - default: - mg_log(LOG_ERR, "DKIM failed: %s", - dkim_getresultstr(priv->priv_dkimstat)); - - retval = SMFIS_CONTINUE; - break; - } - - if (priv->priv_dkimstat != DKIM_STAT_OK) { - (void)dkim_free(priv->priv_dkim); - priv->priv_dkim = NULL; - } - - return retval; -} void dkimcheck_init(void) @@ -232,18 +182,16 @@ priv->priv_dkimstat = dkim_header(priv->priv_dkim, header, len); free(header); - return dkimcheck_error(priv); + return SMFIS_CONTINUE; } sfsistat dkimcheck_eoh(priv) struct mlfi_priv *priv; { - if (priv->priv_dkim == NULL) - return SMFIS_CONTINUE; - - priv->priv_dkimstat = dkim_eoh(priv->priv_dkim); - return dkimcheck_error(priv); + if ((priv->priv_dkim != NULL) && (priv->priv_dkimstat == DKIM_STAT_OK)) + priv->priv_dkimstat = dkim_eoh(priv->priv_dkim); + return SMFIS_CONTINUE; } sfsistat @@ -252,11 +200,9 @@ size_t size; struct mlfi_priv *priv; { - if (priv->priv_dkim == NULL) - return SMFIS_CONTINUE; - - priv->priv_dkimstat = dkim_body(priv->priv_dkim, chunk, size); - return dkimcheck_error(priv); + if ((priv->priv_dkim != NULL) && (priv->priv_dkimstat == DKIM_STAT_OK)) + priv->priv_dkimstat = dkim_body(priv->priv_dkim, chunk, size); + return SMFIS_CONTINUE; } sfsistat @@ -265,11 +211,9 @@ { bool testkey; - if (priv->priv_dkim == NULL) - return SMFIS_CONTINUE; - - priv->priv_dkimstat = dkim_eom(priv->priv_dkim, &testkey); - return dkimcheck_error(priv); + if ((priv->priv_dkim != NULL) && (priv->priv_dkimstat == DKIM_STAT_OK)) + priv->priv_dkimstat = dkim_eom(priv->priv_dkim, &testkey); + return SMFIS_CONTINUE; } int @@ -280,53 +224,52 @@ struct mlfi_priv *priv; { enum spf_status stat; - int result; if (stage != AS_DATA) { mg_log(LOG_ERR, "dkim clause called at non DATA stage"); exit(EX_SOFTWARE); } - stat = ad ? *(enum spf_status *)ad : MGSPF_PASS; + switch (priv->priv_dkimstat) { + case DKIM_STAT_OK: + strcpy(priv->priv_dkim_result, "pass"); + stat = MGSPF_PASS; + break; - switch (stat) { - case MGSPF_PASS: - result = (priv->priv_dkimstat == DKIM_STAT_OK); + case DKIM_STAT_BADSIG: + case DKIM_STAT_REVOKED: + case DKIM_STAT_CBREJECT: + strcpy(priv->priv_dkim_result, "fail"); + stat = MGSPF_FAIL; break; - case MGSPF_FAIL: - switch (priv->priv_dkimstat) { - case DKIM_STAT_BADSIG: - case DKIM_STAT_NOKEY: - case DKIM_STAT_REVOKED: - case DKIM_STAT_CBREJECT: - result = 1; - break; - default: - result = 0; - } + case DKIM_STAT_NOKEY: + case DKIM_STAT_SYNTAX: + case DKIM_STAT_INVALID: + case DKIM_STAT_NOTIMPLEMENT: + case DKIM_STAT_CBERROR: + case DKIM_STAT_CBINVALID: + strcpy(priv->priv_dkim_result, "permerror"); + stat = MGSPF_ERROR; break; - case MGSPF_ERROR: - switch (priv->priv_dkimstat) { - case DKIM_STAT_SYNTAX: - case DKIM_STAT_INVALID: - case DKIM_STAT_NOTIMPLEMENT: - case DKIM_STAT_CBERROR: - case DKIM_STAT_MULTIDNSREPLY: - result = 1; - break; - default: - result = 0; - } + case DKIM_STAT_NORESOURCE: + case DKIM_STAT_INTERNAL: + case DKIM_STAT_CBTRYAGAIN: + case DKIM_STAT_KEYFAIL: + case DKIM_STAT_MULTIDNSREPLY: + strcpy(priv->priv_dkim_result, "temperror"); + stat = MGSPF_ERROR; break; - case MGSPF_NONE: - result = (priv->priv_dkimstat == DKIM_STAT_NOSIG); + case DKIM_STAT_NOSIG: + strcpy(priv->priv_dkim_result, "none"); + stat = MGSPF_NONE; break; - case MGSPF_UNKNOWN: - result = (priv->priv_dkimstat == DKIM_STAT_CANTVRFY); + case DKIM_STAT_CANTVRFY: + strcpy(priv->priv_dkim_result, "neutral"); + stat = MGSPF_UNKNOWN; break; default: @@ -335,7 +278,7 @@ break; } - return result; + return (stat == ad ? *(enum spf_status *)ad : MGSPF_PASS); } char * Index: greylist.conf.5 =================================================================== RCS file: /milter-greylist/milter-greylist/greylist.conf.5,v retrieving revision 1.127 diff -u -r1.127 greylist.conf.5 --- greylist.conf.5 16 Jun 2015 12:27:29 -0000 1.127 +++ greylist.conf.5 28 Sep 2015 18:55:48 -0000 @@ -389,7 +389,10 @@ This quoted string is a RFC822 header that gets added to the message. Format string substitution is supported. No check is done for header length standard compliance, so make sure the substituted string is -shorter than 2048 characters. +shorter than 2048 characters. Headers are appended to the bottom, +unless an optional index integer (>=0) is specified after the quoted +string; in this case the header will be inserted at this index point +from the top. .TP .I addfooter Append a footer to the message. Usual escape sequences such as \\n can @@ -1509,6 +1512,20 @@ .I %P{mail} Note that this copes very badly with multivalued properties. .TP +.I %Qd +DKIM query result (pass, fail, etc.), if built with DKIM support. +.TP +.I %Qs +SPF query result (pass, (soft)fail, etc.), if built with SPF support. +.TP +.I %QA +Authentication results summary, suitable for Authentication-Results +header. Will included formatted query results from DKIM and SPF if checked. +.TP +.I %QS +SPF result, suitable for Received-SPF header. Available when +compiled with libspf2. +.TP .I %% a single % character .PP Index: milter-greylist.c =================================================================== RCS file: /milter-greylist/milter-greylist/milter-greylist.c,v retrieving revision 1.277 diff -u -r1.277 milter-greylist.c --- milter-greylist.c 26 Apr 2014 15:03:33 -0000 1.277 +++ milter-greylist.c 28 Sep 2015 18:55:49 -0000 @@ -424,9 +424,17 @@ #ifdef USE_GEOIP geoip_set_ccode(priv); #endif +#ifdef HAVE_SPF2 + priv->priv_spf_header = NULL; +#endif +#if (defined(HAVE_SPF) || defined(HAVE_SPF_ALT) || \ + defined(HAVE_SPF2_10) || defined(HAVE_SPF2)) + priv->priv_spf_result[0] = '\0'; +#endif #ifdef USE_DKIM priv->priv_dkim = NULL; priv->priv_dkimstat = DKIM_STAT_OK; + priv->priv_dkim_result[0] = '\0'; #endif #ifdef USE_P0F priv->priv_p0f = NULL; @@ -1247,7 +1255,12 @@ } else { *hdrvalue = '\0'; hdrvalue += strlen(sep); - smfi_addheader(ctx, hdrname, hdrvalue); + if (priv->priv_sr.sr_addheader_index >= 0) + smfi_insheader( + ctx, priv->priv_sr.sr_addheader_index, + hdrname, hdrvalue); + else + smfi_addheader(ctx, hdrname, hdrvalue); } free(hdrname); @@ -1386,6 +1399,10 @@ ADD_REASON(whystr, "Sender passed SPF test"); priv->priv_last_whitelist &= ~EXF_SPF; } + if (priv->priv_last_whitelist & EXF_DKIM) { + ADD_REASON(whystr, "Sender passed DKIM test"); + priv->priv_last_whitelist &= ~EXF_DKIM; + } if (priv->priv_last_whitelist & EXF_NONIP) { #ifdef AF_INET6 ADD_REASON(whystr, @@ -1486,7 +1503,12 @@ } else { *hdrvalue = '\0'; hdrvalue += strlen(sep); - smfi_addheader(ctx, hdrname, hdrvalue); + if (priv->priv_sr.sr_addheader_index >= 0) + smfi_insheader( + ctx, priv->priv_sr.sr_addheader_index, + hdrname, hdrvalue); + else + smfi_addheader(ctx, hdrname, hdrvalue); } free(hdrname); @@ -1556,6 +1578,10 @@ if (priv->priv_p0f != NULL) free(priv->priv_p0f); #endif +#ifdef HAVE_SPF2 + if (priv->priv_spf_header != NULL) + free(priv->priv_spf_header); +#endif #ifdef USE_DKIM dkimcheck_free(priv); #endif @@ -3120,7 +3146,104 @@ mystrncat(&outstr, tzstr, &outmaxlen, cv); break; } - + case 'Q': { /* "Query" results */ + fstr_len = 2; + switch(*(ptok + 1)) { + case 's': /* SPF result */ +#if (defined(HAVE_SPF) || defined(HAVE_SPF_ALT) || \ + defined(HAVE_SPF2_10) || defined(HAVE_SPF2)) + if (priv->priv_spf_result[0]) + mystrncat(&outstr, + priv->priv_spf_result, + &outmaxlen, cv); +#else + fstr_len = 0; +#endif + break; + case 'd': /* DKIM result */ +#ifdef USE_DKIM + if (priv->priv_dkim_result[0]) + mystrncat(&outstr, + priv->priv_dkim_result, + &outmaxlen, cv); +#else + fstr_len = 0; +#endif + break; + case 'A': { /* Authentication-Results header value */ + char host[ADDRLEN + 1]; + char output[HDRLEN + 1]; + char *fqdn; + int cx; + + fqdn = smfi_getsymval(priv->priv_ctx, "{j}"); + if (fqdn == NULL) { + mg_log(LOG_DEBUG, + "smfi_getsymval failed for {j}"); + gethostname(host, ADDRLEN); + fqdn = host; + } + + cx = snprintf(output, HDRLEN, "%s", fqdn); + +#if (defined(HAVE_SPF) || defined(HAVE_SPF_ALT) || \ + defined(HAVE_SPF2_10) || defined(HAVE_SPF2)) + if ((cx < HDRLEN) && priv->priv_spf_result[0]) { + char tmpfrom[ + strlen(priv->priv_from) - 1]; + + memcpy(tmpfrom, + priv->priv_from + 1, + sizeof(tmpfrom) - 1); + tmpfrom[sizeof(tmpfrom) - 1] = '\0'; + + cx += snprintf(output+cx, HDRLEN-cx, + ";\r\n\tspf=%s smtp.mailfrom=%s", + priv->priv_spf_result, tmpfrom); + } +#endif +#ifdef USE_DKIM + if ((cx < HDRLEN) && + priv->priv_dkim_result[0]) { + DKIM_SIGINFO *sig=NULL; + unsigned const char *domain; + cx += snprintf(output+cx, HDRLEN-cx, + ";\r\n\tdkim=%s", + priv->priv_dkim_result); + + if (priv->priv_dkim != NULL) + sig = dkim_getsignature( + priv->priv_dkim); + if ((cx < HDRLEN) && (sig != NULL) && + ((domain = dkim_sig_getdomain(sig)) + != NULL)) + cx += snprintf(output+cx, + HDRLEN-cx, " header.d=%s", + domain); + } +#endif + if ((cx < HDRLEN) && (cx == strlen(fqdn))) + snprintf(output+cx, HDRLEN-cx, + "; none"); + mystrncat(&outstr, output, &outmaxlen, cv); + break; + } + case 'S': /* Received-SPF header value */ +#ifdef HAVE_SPF2 + if (priv->priv_spf_header != NULL) + mystrncat(&outstr, + priv->priv_spf_header, + &outmaxlen, cv); +#else + fstr_len = 0; +#endif + break; + default: + fstr_len = 0; + break; + } + break; + } case 'C': { /* Country code from GeoIP */ #ifdef USE_GEOIP if (priv->priv_ccode != NULL) Index: milter-greylist.h =================================================================== RCS file: /milter-greylist/milter-greylist/milter-greylist.h,v retrieving revision 1.97 diff -u -r1.97 milter-greylist.h --- milter-greylist.h 17 Dec 2014 08:36:43 -0000 1.97 +++ milter-greylist.h 28 Sep 2015 18:55:49 -0000 @@ -168,6 +168,7 @@ char *sr_report; char *sr_report_x; char *sr_addheader; + int sr_addheader_index; char *sr_addfooter; char *sr_subjtag; sfsistat sr_retcode; @@ -219,9 +220,17 @@ #ifdef USE_DNSRBL LIST_HEAD(, dnsrbl_list) priv_dnsrbl; #endif +#ifdef HAVE_SPF2 + char *priv_spf_header; +#endif +#if (defined(HAVE_SPF) || defined(HAVE_SPF_ALT) || \ + defined(HAVE_SPF2_10) || defined(HAVE_SPF2)) + char priv_spf_result[10]; +#endif #ifdef USE_DKIM DKIM *priv_dkim; DKIM_STAT priv_dkimstat; + char priv_dkim_result[10]; #endif #ifdef USE_P0F char *priv_p0f; Index: spf.c =================================================================== RCS file: /milter-greylist/milter-greylist/spf.c,v retrieving revision 1.38 diff -u -r1.38 spf.c --- spf.c 4 Oct 2013 08:01:10 -0000 1.38 +++ spf.c 28 Sep 2015 18:55:49 -0000 @@ -96,7 +96,6 @@ int result = 0; struct timeval tv1, tv2, tv3; enum spf_status status; - char *statestr = ""; if (conf.c_debug) gettimeofday(&tv1, NULL); @@ -116,45 +115,46 @@ p->RES = SPF_policy_main(p); status = ad ? *(enum spf_status *)ad : MGSPF_PASS; - switch (status) { - case MGSPF_PASS: - result = (p->RES == SPF_PASS); - statestr = "pass"; - break; - case MGSPF_FAIL: - result = (p->RES == SPF_H_FAIL); - statestr = "fail"; - break; - case MGSPF_SOFTFAIL: - result = (p->RES == SPF_S_FAIL); - statestr = "softfail"; - break; - case MGSPF_NEUTRAL: - result = (p->RES == SPF_NEUTRAL); - statestr = "neutral"; - break; - case MGSPF_UNKNOWN: - result = (p->RES == SPF_UNKNOWN || p->RES == SPF_UNMECH); - statestr = "unknown"; - break; - case MGSPF_ERROR: - result = (p->RES == SPF_ERROR); - statestr = "error"; - break; - case MGSPF_NONE: - result = (p->RES == SPF_NONE); - statestr = "none"; + switch (p->RES) { + case SPF_PASS: + result = (status == MGSPF_PASS); + strcpy(priv->priv_spf_result, "pass"); + break; + case SPF_H_FAIL: + result = (status == MGSPF_FAIL); + strcpy(priv->priv_spf_result, "fail"); + break; + case SPF_S_FAIL: + result = (status == MGSPF_SOFTFAIL); + strcpy(priv->priv_spf_result, "softfail"); + break; + case SPF_NEUTRAL: + result = (status == MGSPF_NEUTRAL); + strcpy(priv->priv_spf_result, "neutral"); + break; + case SPF_UNKNOWN: + case SPF_UNMECH: + result = (status == MGSPF_UNKNOWN); + strcpy(priv->priv_spf_result, "unknown"); + break; + case SPF_ERROR: + result = (status == MGSPF_ERROR); + strcpy(priv->priv_spf_result, "error"); + break; + case SPF_NONE: + result = (status == MGSPF_NONE); + strcpy(priv->priv_spf_result, "none"); break; default: - mg_log(LOG_ERR, "Internal error: unexpected spf_status %d", - " spf raw result %d", status, p->RES); + mg_log(LOG_ERR, "Internal error: unexpected spf result %d", + " spf test code %d", p->RES, status); exit(EX_SOFTWARE); break; } if (conf.c_debug) - mg_log(LOG_DEBUG, "SPF return code %d (test %s, result %d)", - p->RES, statestr, result); + mg_log(LOG_DEBUG, "SPF return %s (test code %d, result %d)", + priv->priv_spf_result, status, result); SPF_close(p); @@ -211,7 +211,6 @@ struct timeval tv1, tv2, tv3; size_t len; enum spf_status status; - char *statestr = ""; if (conf.c_debug) gettimeofday(&tv1, NULL); @@ -271,45 +270,46 @@ #endif status = ad ? *(enum spf_status *)ad : MGSPF_PASS; - switch (status) { - case MGSPF_PASS: - result = (out.result == SPF_RESULT_PASS); - statestr = "pass"; - break; - case MGSPF_FAIL: - result = (out.result == SPF_RESULT_FAIL); - statestr = "fail"; - break; - case MGSPF_SOFTFAIL: - result = (out.result == SPF_RESULT_SOFTFAIL); - statestr = "softfail"; - break; - case MGSPF_NEUTRAL: - result = (out.result == SPF_RESULT_NEUTRAL); - statestr = "neutral"; - break; - case MGSPF_UNKNOWN: - result = (out.result == SPF_RESULT_UNKNOWN); - statestr = "unknown"; - break; - case MGSPF_ERROR: - result = (out.result == SPF_RESULT_ERROR); - statestr = "error"; - break; - case MGSPF_NONE: - result = (out.result == SPF_RESULT_NONE); - statestr = "none"; + switch (out.result) { + case SPF_RESULT_PASS: + result = (status == MGSPF_PASS); + strcpy(priv->priv_spf_result, "pass"); + break; + case SPF_RESULT_FAIL: + result = (status == MGSPF_FAIL); + strcpy(priv->priv_spf_result, "fail"); + break; + case SPF_RESULT_SOFTFAIL: + result = (status == MGSPF_SOFTFAIL); + strcpy(priv->priv_spf_result, "softfail"); + break; + case SPF_RESULT_NEUTRAL: + result = (status == MGSPF_NEUTRAL); + strcpy(priv->priv_spf_result, "neutral"); + break; + case SPF_RESULT_UNKNOWN: + result = (status == MGSPF_UNKNOWN); + strcpy(priv->priv_spf_result, "unknown"); + break; + case SPF_RESULT_ERROR: + result = (status == MGSPF_ERROR); + strcpy(priv->priv_spf_result, "error"); + break; + case SPF_RESULT_NONE: + result = (status == MGSPF_NONE); + strcpy(priv->priv_spf_result, "none"); break; default: - mg_log(LOG_ERR, "Internal error: unexpected spf_status %d", - " spf_alt/spf_2_10 raw result %d", status, out.result); + mg_log(LOG_ERR, + "Internal error: unexpected spf_alt/spf_2_10 result %d", + " spf test code %d", out.result, status); exit(EX_SOFTWARE); break; } if (conf.c_debug) - mg_log(LOG_DEBUG, "SPF return code %d (test %s, result %d)", - out.result, statestr, result); + mg_log(LOG_DEBUG, "SPF return %s (test code %d, result %d)", + priv->priv_spf_result, out.result, result); SPF_free_output(&out); out3: @@ -340,6 +340,7 @@ struct mlfi_priv *priv; { struct sockaddr *sa = SA(&priv->priv_addr); + char *fqdn; char *helo = priv->priv_helo; char *fromp = priv->priv_from; SPF_server_t *spf_server; @@ -350,7 +351,6 @@ struct timeval tv1, tv2, tv3; size_t len; enum spf_status status; - char *statestr = ""; if (conf.c_debug) gettimeofday(&tv1, NULL); @@ -365,6 +365,11 @@ goto out2; } + /* Local machine FQDN */ + fqdn = smfi_getsymval(priv->priv_ctx, "{j}"); + if (fqdn != NULL && SPF_server_set_rec_dom(spf_server, fqdn) != 0) + mg_log(LOG_WARNING, "SPF_server_set_rec_dom failed"); + /* * Get the IP address */ @@ -415,46 +420,53 @@ res = SPF_response_result(spf_response); status = ad ? *(enum spf_status *)ad : MGSPF_PASS; - switch (status) { - case MGSPF_PASS: - result = (res == SPF_RESULT_PASS); - statestr = "pass"; - break; - case MGSPF_FAIL: - result = (res == SPF_RESULT_FAIL); - statestr = "fail"; - break; - case MGSPF_SOFTFAIL: - result = (res == SPF_RESULT_SOFTFAIL); - statestr = "softfail"; - break; - case MGSPF_NEUTRAL: - result = (res == SPF_RESULT_NEUTRAL); - statestr = "neutral"; - break; - case MGSPF_UNKNOWN: - result = - (res == SPF_RESULT_PERMERROR || res == SPF_RESULT_INVALID); - statestr = "unknown"; - break; - case MGSPF_ERROR: - result = (res == SPF_RESULT_TEMPERROR); - statestr = "error"; - break; - case MGSPF_NONE: - result = (res == SPF_RESULT_NONE); - statestr = "none"; + switch (res) { + case SPF_RESULT_PASS: + result = (status == MGSPF_PASS); + strcpy(priv->priv_spf_result, "pass"); + break; + case SPF_RESULT_FAIL: + result = (status == MGSPF_FAIL); + strcpy(priv->priv_spf_result, "fail"); + break; + case SPF_RESULT_SOFTFAIL: + result = (status == MGSPF_SOFTFAIL); + strcpy(priv->priv_spf_result, "softfail"); + break; + case SPF_RESULT_NEUTRAL: + result = (status == MGSPF_NEUTRAL); + strcpy(priv->priv_spf_result, "neutral"); + break; + case SPF_RESULT_INVALID: + result = (status == MGSPF_UNKNOWN); + strcpy(priv->priv_spf_result, "unknown"); + break; + case SPF_RESULT_PERMERROR: + result = (status == MGSPF_ERROR); + strcpy(priv->priv_spf_result, "permerror"); + break; + case SPF_RESULT_TEMPERROR: + result = (status == MGSPF_ERROR); + strcpy(priv->priv_spf_result, "temperror"); + break; + case SPF_RESULT_NONE: + result = (status == MGSPF_NONE); + strcpy(priv->priv_spf_result, "none"); break; default: - mg_log(LOG_ERR, "Internal error: unexpected spf_status %d", - " spf2 raw result %d", status, res); + mg_log(LOG_ERR, "Internal error: unexpected spf2 result %d", + " spf test code %d", res, status); exit(EX_SOFTWARE); break; } if (conf.c_debug) - mg_log(LOG_DEBUG, "SPF return code %d (test %s, result %d)", - res, statestr, result); + mg_log(LOG_DEBUG, "SPF return %s (test code %d, result %d)", + priv->priv_spf_result, res, result); + + if (priv->priv_spf_header != NULL) + free(priv->priv_spf_header); + priv->priv_spf_header = strdup(spf_response->received_spf_value); SPF_response_free(spf_response); out3: