Integrated SPF Best Guess. Fixes: bug #521
authorNigel Metheringham <nigel@exim.org>
Tue, 12 Feb 2008 12:52:51 +0000 (12:52 +0000)
committerNigel Metheringham <nigel@exim.org>
Tue, 12 Feb 2008 12:52:51 +0000 (12:52 +0000)
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
doc/doc-txt/experimental-spec.txt
src/src/acl.c
src/src/expand.c
src/src/globals.c
src/src/globals.h
src/src/readconf.c
src/src/spf.c
src/src/spf.h

index 3d939c71879927e913a7c33d398f9fd076e1bb42..6c84133b4ed578089e702f5b4998ef89d3926c56 100644 (file)
@@ -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
 -------------------------------------------
 
 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.
 
       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
 -----------------
 
 Exim version 4.69
 -----------------
index e18d215aac21a0df22d56fee9f9c3fc4fbd5af88..1470efc92f381d5b7238c11e990c83e8d6fb8b98 100644 (file)
@@ -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
 --------------------
 
 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.
 
 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
 ------------
 
 Version 4.68
 ------------
 
index 15fd247ae42eb8588ed78b0db26785b4c0f12b96..4175173c320d5cf1113133a8dd7117807a152e54 100644 (file)
@@ -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
 
 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.
 
   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
   $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".
 
   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
 
 
 4. SRS (Sender Rewriting Scheme) Support
index e0f01694b96ce2f3a8be57a1a2cb3b3f54c81ec0..fcafc6b5812dfdb18cdb29eb644b5214ae0931d5 100644 (file)
@@ -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    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -102,6 +102,7 @@ enum { ACLC_ACL,
 #endif
 #ifdef EXPERIMENTAL_SPF
        ACLC_SPF,
 #endif
 #ifdef EXPERIMENTAL_SPF
        ACLC_SPF,
+       ACLC_SPF_GUESS,
 #endif
        ACLC_VERIFY };
 
 #endif
        ACLC_VERIFY };
 
@@ -165,6 +166,7 @@ static uschar *conditions[] = {
 #endif
 #ifdef EXPERIMENTAL_SPF
   US"spf",
 #endif
 #ifdef EXPERIMENTAL_SPF
   US"spf",
+  US"spf_guess",
 #endif
   US"verify" };
 
 #endif
   US"verify" };
 
@@ -300,6 +302,7 @@ static uschar cond_expand_at_top[] = {
 #endif
 #ifdef EXPERIMENTAL_SPF
   TRUE,    /* spf */
 #endif
 #ifdef EXPERIMENTAL_SPF
   TRUE,    /* spf */
+  TRUE,    /* spf_guess */
 #endif
   TRUE     /* verify */
 };
 #endif
   TRUE     /* verify */
 };
@@ -363,6 +366,7 @@ static uschar cond_modifiers[] = {
 #endif
 #ifdef EXPERIMENTAL_SPF
   FALSE,   /* spf */
 #endif
 #ifdef EXPERIMENTAL_SPF
   FALSE,   /* spf */
+  FALSE,   /* spf_guess */
 #endif
   FALSE    /* verify */
 };
 #endif
   FALSE    /* verify */
 };
@@ -547,6 +551,14 @@ static unsigned int cond_forbids[] = {
     (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY)|
     (1<<ACL_WHERE_NOTSMTP)|
     (1<<ACL_WHERE_NOTSMTP_START),
     (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY)|
     (1<<ACL_WHERE_NOTSMTP)|
     (1<<ACL_WHERE_NOTSMTP_START),
+
+  (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)|      /* spf_guess */
+    (1<<ACL_WHERE_HELO)|
+    (1<<ACL_WHERE_MAILAUTH)|
+    (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+    (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY)|
+    (1<<ACL_WHERE_NOTSMTP)|
+    (1<<ACL_WHERE_NOTSMTP_START),
   #endif
 
   /* Certain types of verify are always allowed, so we let it through
   #endif
 
   /* Certain types of verify are always allowed, so we let it through
@@ -3134,7 +3146,10 @@ for (; cb != NULL; cb = cb->next)
 
     #ifdef EXPERIMENTAL_SPF
     case ACLC_SPF:
 
     #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
 
     break;
     #endif
 
index beb72aa678470696e617dcc3fc874598c6ee3477..b2d0fb4aee9804da5b6b7bbb6ce66c6a74761ba4 100644 (file)
@@ -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    *
 
 /*************************************************
 *     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
   { "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 },
   { "spf_header_comment",  vtype_stringptr,   &spf_header_comment },
   { "spf_received",        vtype_stringptr,   &spf_received },
   { "spf_result",          vtype_stringptr,   &spf_result },
index e7efebffa519556a34915cb8785aa8441b89ae14..93f74910c77ffd45d1c0b9cbc18046b22f273e29 100644 (file)
@@ -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    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1136,6 +1136,7 @@ uschar *spam_score             = NULL;
 uschar *spam_score_int         = NULL;
 #endif
 #ifdef EXPERIMENTAL_SPF
 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;
 uschar *spf_header_comment     = NULL;
 uschar *spf_received           = NULL;
 uschar *spf_result             = NULL;
index 4172c7355981b5704aa00904bb5784bd66afe801..ac425ed9812d5f4c9da9eb148dad1135ac909814 100644 (file)
@@ -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    *
 
 /*************************************************
 *     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 *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 */
 extern uschar *spf_header_comment;     /* spf header comment */
 extern uschar *spf_received;           /* Received-SPF: header */
 extern uschar *spf_result;             /* spf result in string form */
index 0a577f7db6290b7a68c377e4a1c9bad28fc5c21a..2e65cd970fa257332f228944bf560c33f74aaba0 100644 (file)
@@ -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    *
 
 /*************************************************
 *     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 },
   { "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 },
 #endif
   { "split_spool_directory",    opt_bool,        &split_spool_directory },
   { "spool_directory",          opt_stringptr,   &spool_directory },
index 0d2316e2e88064ce2f284dc532e4e5c3e7e29288..532f814221bb2e00b49f11e55e3057966adedc68 100644 (file)
@@ -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    *
 
 /*************************************************
 *     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. */
 
    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;
   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 */
   }
 
   /* 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);
 
   /* 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);
   /* 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) {
   while ((spf_result_id = string_nextinlist(&list, &sep,
                                      spf_result_id_buffer,
                                      sizeof(spf_result_id_buffer))) != NULL) {
index 3e014bdafe30ae5587e7d314633d900c3d0badb0..455fbbfd939c2da14a4c571f29c3f6c2652504a2 100644 (file)
@@ -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    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -26,6 +26,10 @@ typedef struct spf_result_id {
 
 /* prototypes */
 int spf_init(uschar *,uschar *);
 
 /* 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
 
 #endif