From 65a7d8c381dfb4788ecd5c40a28365acb1f377e1 Mon Sep 17 00:00:00 2001 From: Nigel Metheringham Date: Tue, 12 Feb 2008 12:52:51 +0000 Subject: [PATCH] Integrated SPF Best Guess. Fixes: bug #521 --- doc/doc-txt/ChangeLog | 6 +++++- doc/doc-txt/NewStuff | 9 +++++++- doc/doc-txt/experimental-spec.txt | 36 ++++++++++++++++++++++++++++++- src/src/acl.c | 19 ++++++++++++++-- src/src/expand.c | 3 ++- src/src/globals.c | 3 ++- src/src/globals.h | 3 ++- src/src/readconf.c | 5 ++++- src/src/spf.c | 13 ++++++++--- src/src/spf.h | 8 +++++-- 10 files changed, 91 insertions(+), 14 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 3d939c718..6c84133b4 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.543 2008/02/06 18:57:46 fanf2 Exp $ +$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.544 2008/02/12 12:52:51 nm4 Exp $ Change log file for Exim from version 4.21 ------------------------------------------- @@ -29,6 +29,10 @@ TF/03 Bugzilla 615: When checking the local_parts router precondition does not use the address's named list lookup cache, since this contains cached lookups for the whole local part. +NM/05 Bugzilla 521: Integrated SPF Best Guess support contributed by + Robert Millan. Documentation is in experimental-spec.txt + + Exim version 4.69 ----------------- diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index e18d215aa..1470efc92 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/NewStuff,v 1.157 2007/08/23 11:01:49 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/NewStuff,v 1.158 2008/02/12 12:52:51 nm4 Exp $ New Features in Exim -------------------- @@ -8,6 +8,13 @@ Before a formal release, there may be quite a lot of detail so that people can test from the snapshots or the CVS before the documentation is updated. Once the documentation is updated, this file is reduced to a short list. +Version 4.70 +------------ + + 1. Preliminary SPF Best Guess support. Documentation for this is in + experimental-spec.txt. + + Version 4.68 ------------ diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 15fd247ae..4175173c3 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/experimental-spec.txt,v 1.10 2008/01/16 09:36:19 tom Exp $ +$Cambridge: exim/doc/doc-txt/experimental-spec.txt,v 1.11 2008/02/12 12:52:51 nm4 Exp $ From time to time, experimental features may be added to Exim. While a feature is experimental, there will be a build-time @@ -799,6 +799,9 @@ variables. draft, this header must be added at the top of the header list. Please see section 10 on how you can do this. + Note: in case of "Best-guess" (see below), the convention is + to put this string in a header called X-SPF-Guess: instead. + $spf_result This contains the outcome of the SPF check in string form, one of pass, fail, softfail, none, neutral, err_perm or @@ -808,6 +811,37 @@ variables. This contains a string that can be used in a SMTP response to the calling party. Useful for "fail". +In addition to SPF, you can also perform checks for so-called +"Best-guess". Strictly speaking, "Best-guess" is not standard +SPF, but it is supported by the same framework that enables SPF +capability. Refer to http://www.openspf.org/FAQ/Best_guess_record +for a description of what it means. + +To access this feature, simply use the spf_guess condition in place +of the spf one. For example: + +/* ----------------- +deny message = $sender_host_address doesn't look trustworthy to me + spf_guess = fail +--------------------- */ + +In case you decide to reject messages based on this check, you +should note that although it uses the same framework, "Best-guess" +is NOT SPF, and therefore you should not mention SPF at all in your +reject message. + +When the spf_guess condition has run, it sets up the same expansion +variables as when spf condition is run, described above. + +Additionally, since Best-guess is not standarized, you may redefine +what "Best-guess" means to you by redefining spf_guess variable in +global config. For example, the following: + +/* ----------------- +spf_guess = v=spf1 a/16 mx/16 ptr ?all +--------------------- */ + +would relax host matching rules to a broader network range. 4. SRS (Sender Rewriting Scheme) Support diff --git a/src/src/acl.c b/src/src/acl.c index e0f01694b..fcafc6b58 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/acl.c,v 1.81 2008/01/17 13:03:35 tom Exp $ */ +/* $Cambridge: exim/src/src/acl.c,v 1.82 2008/02/12 12:52:51 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -102,6 +102,7 @@ enum { ACLC_ACL, #endif #ifdef EXPERIMENTAL_SPF ACLC_SPF, + ACLC_SPF_GUESS, #endif ACLC_VERIFY }; @@ -165,6 +166,7 @@ static uschar *conditions[] = { #endif #ifdef EXPERIMENTAL_SPF US"spf", + US"spf_guess", #endif US"verify" }; @@ -300,6 +302,7 @@ static uschar cond_expand_at_top[] = { #endif #ifdef EXPERIMENTAL_SPF TRUE, /* spf */ + TRUE, /* spf_guess */ #endif TRUE /* verify */ }; @@ -363,6 +366,7 @@ static uschar cond_modifiers[] = { #endif #ifdef EXPERIMENTAL_SPF FALSE, /* spf */ + FALSE, /* spf_guess */ #endif FALSE /* verify */ }; @@ -547,6 +551,14 @@ static unsigned int cond_forbids[] = { (1<next) #ifdef EXPERIMENTAL_SPF case ACLC_SPF: - rc = spf_process(&arg, sender_address); + rc = spf_process(&arg, sender_address, SPF_PROCESS_NORMAL); + break; + case ACLC_SPF_GUESS: + rc = spf_process(&arg, sender_address, SPF_PROCESS_GUESS); break; #endif diff --git a/src/src/expand.c b/src/src/expand.c index beb72aa67..b2d0fb4ae 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/expand.c,v 1.92 2008/01/17 13:03:35 tom Exp $ */ +/* $Cambridge: exim/src/src/expand.c,v 1.93 2008/02/12 12:52:51 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -575,6 +575,7 @@ static var_entry var_table[] = { { "spam_score_int", vtype_stringptr, &spam_score_int }, #endif #ifdef EXPERIMENTAL_SPF + { "spf_guess", vtype_stringptr, &spf_guess }, { "spf_header_comment", vtype_stringptr, &spf_header_comment }, { "spf_received", vtype_stringptr, &spf_received }, { "spf_result", vtype_stringptr, &spf_result }, diff --git a/src/src/globals.c b/src/src/globals.c index e7efebffa..93f74910c 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.c,v 1.80 2008/01/17 13:03:35 tom Exp $ */ +/* $Cambridge: exim/src/src/globals.c,v 1.81 2008/02/12 12:52:51 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -1136,6 +1136,7 @@ uschar *spam_score = NULL; uschar *spam_score_int = NULL; #endif #ifdef EXPERIMENTAL_SPF +uschar *spf_guess = US"v=spf1 a/24 mx/24 ptr ?all"; uschar *spf_header_comment = NULL; uschar *spf_received = NULL; uschar *spf_result = NULL; diff --git a/src/src/globals.h b/src/src/globals.h index 4172c7355..ac425ed98 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.h,v 1.61 2008/01/17 13:03:35 tom Exp $ */ +/* $Cambridge: exim/src/src/globals.h,v 1.62 2008/02/12 12:52:51 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -705,6 +705,7 @@ extern uschar *spam_score; /* the spam score (float) */ extern uschar *spam_score_int; /* spam_score * 10 (int) */ #endif #ifdef EXPERIMENTAL_SPF +extern uschar *spf_guess; /* spf best-guess record */ extern uschar *spf_header_comment; /* spf header comment */ extern uschar *spf_received; /* Received-SPF: header */ extern uschar *spf_result; /* spf result in string form */ diff --git a/src/src/readconf.c b/src/src/readconf.c index 0a577f7db..2e65cd970 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/readconf.c,v 1.34 2008/01/17 13:03:35 tom Exp $ */ +/* $Cambridge: exim/src/src/readconf.c,v 1.35 2008/02/12 12:52:51 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -356,6 +356,9 @@ static optionlist optionlist_config[] = { { "smtp_return_error_details",opt_bool, &smtp_return_error_details }, #ifdef WITH_CONTENT_SCAN { "spamd_address", opt_stringptr, &spamd_address }, +#endif +#ifdef EXPERIMENTAL_SPF + { "spf_guess", opt_stringptr, &spf_guess }, #endif { "split_spool_directory", opt_bool, &split_spool_directory }, { "spool_directory", opt_stringptr, &spool_directory }, diff --git a/src/src/spf.c b/src/src/spf.c index 0d2316e2e..532f81422 100644 --- a/src/src/spf.c +++ b/src/src/spf.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/spf.c,v 1.7 2007/05/17 19:55:10 tom Exp $ */ +/* $Cambridge: exim/src/src/spf.c,v 1.8 2008/02/12 12:52:51 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -73,7 +73,7 @@ int spf_init(uschar *spf_helo_domain, uschar *spf_remote_addr) { context (if any), retrieves the result, sets up expansion strings and evaluates the condition outcome. */ -int spf_process(uschar **listptr, uschar *spf_envelope_sender) { +int spf_process(uschar **listptr, uschar *spf_envelope_sender, int action) { int sep = 0; uschar *list = *listptr; uschar *spf_result_id; @@ -93,7 +93,10 @@ int spf_process(uschar **listptr, uschar *spf_envelope_sender) { } /* get SPF result */ - SPF_request_query_mailfrom(spf_request, &spf_response); + if (action == SPF_PROCESS_FALLBACK) + SPF_request_query_fallback(spf_request, &spf_response, 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); @@ -106,6 +109,10 @@ int spf_process(uschar **listptr, uschar *spf_envelope_sender) { /* 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) { diff --git a/src/src/spf.h b/src/src/spf.h index 3e014bdaf..455fbbfd9 100644 --- a/src/src/spf.h +++ b/src/src/spf.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/spf.h,v 1.6 2005/06/27 15:28:45 tom Exp $ */ +/* $Cambridge: exim/src/src/spf.h,v 1.7 2008/02/12 12:52:51 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -26,6 +26,10 @@ typedef struct spf_result_id { /* prototypes */ int spf_init(uschar *,uschar *); -int spf_process(uschar **, uschar *); +int spf_process(uschar **, uschar *, int); + +#define SPF_PROCESS_NORMAL 0 +#define SPF_PROCESS_GUESS 1 +#define SPF_PROCESS_FALLBACK 2 #endif -- 2.30.2