DKIM: call ACL once for each signature matching the identity from dkim_verify_signers...
authorJeremy Harris <jgh146exb@wizmail.org>
Wed, 8 Nov 2017 10:43:28 +0000 (10:43 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Wed, 8 Nov 2017 11:08:10 +0000 (11:08 +0000)
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/src/dkim.c
src/src/dkim.h
src/src/receive.c
test/log/4524

index 1a7a7baa638558da5b2c2485912d485bb6f6cec2..cfee04ccd59fc90c52fe9cbf1d2fff9b326d25d4 100644 (file)
@@ -38708,6 +38708,11 @@ dkim_verify_signers = $sender_address_domain:$dkim_signers
 If a domain or identity is listed several times in the (expanded) value of
 &%dkim_verify_signers%&, the ACL is only called once for that domain or identity.
 
 If a domain or identity is listed several times in the (expanded) value of
 &%dkim_verify_signers%&, the ACL is only called once for that domain or identity.
 
+.new
+If multiple signatures match a domain (or identity), the ACL is called once
+for each matching signature.
+.wen
+
 
 Inside the &%acl_smtp_dkim%&, the following expansion variables are
 available (from most to least important):
 
 Inside the &%acl_smtp_dkim%&, the following expansion variables are
 available (from most to least important):
index 4b3d64e0cbed168d1424c5b98d3f6630c2089356..fd188a00a2e6dcdd1aaeaaa8ac07c22aa45720e5 100644 (file)
@@ -182,6 +182,10 @@ JH/31 Fix CHUNKING code to properly flush the unwanted chunk after an error.
       Previously only that bufferd was discarded, resulting in SYMTP command
       desynchronisation.
 
       Previously only that bufferd was discarded, resulting in SYMTP command
       desynchronisation.
 
+JH/32 DKIM: when a message has multiple signatures matching an identity given
+      in dkim_verify_signers, run the dkim acl once for each.  Previously only
+      one run was done.  Bug 2189.
+
 
 Exim version 4.89
 -----------------
 
 Exim version 4.89
 -----------------
index 528ce82c42989dd9e79f0fce17da4803612ef182..396e5b905082f012eb69fc173f990388c831bf01 100644 (file)
@@ -235,14 +235,6 @@ return;
 }
 
 
 }
 
 
-/* Log a line for "the current" signature */
-void
-dkim_exim_verify_log_item(void)
-{
-dkim_exim_verify_log_sig(dkim_cur_sig);
-}
-
-
 /* Log a line for each signature */
 void
 dkim_exim_verify_log_all(void)
 /* Log a line for each signature */
 void
 dkim_exim_verify_log_all(void)
@@ -303,37 +295,72 @@ store_pool = dkim_verify_oldpool;
 }
 
 
 }
 
 
-void
-dkim_exim_acl_setup(uschar * id)
+
+/* Args as per dkim_exim_acl_run() below */
+static int
+dkim_acl_call(uschar * id, gstring ** res_ptr,
+  uschar ** user_msgptr, uschar ** log_msgptr)
+{
+int rc;
+DEBUG(D_receive)
+  debug_printf("calling acl_smtp_dkim for dkim_cur_signer='%s'\n", id);
+
+rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, user_msgptr, log_msgptr);
+dkim_exim_verify_log_sig(dkim_cur_sig);
+*res_ptr = string_append_listele(*res_ptr, ':', dkim_verify_status);
+return rc;
+}
+
+
+
+/* For the given identity, run the DKIM ACL once for each matching signature.
+
+Arguments
+ id            Identity to look for in dkim signatures
+ res_ptr       ptr to growable string-list of status results,
+               appended to per ACL run
+ user_msgptr   where to put a user error (for SMTP response)
+ log_msgptr    where to put a logging message (not for SMTP response)
+
+Returns:       OK         access is granted by an ACCEPT verb
+               DISCARD    access is granted by a DISCARD verb
+               FAIL       access is denied
+               FAIL_DROP  access is denied; drop the connection
+               DEFER      can't tell at the moment
+               ERROR      disaster
+*/
+
+int
+dkim_exim_acl_run(uschar * id, gstring ** res_ptr,
+  uschar ** user_msgptr, uschar ** log_msgptr)
 {
 pdkim_signature * sig;
 uschar * cmp_val;
 {
 pdkim_signature * sig;
 uschar * cmp_val;
+int rc = -1;
 
 dkim_verify_status = US"none";
 dkim_verify_reason = US"";
 
 dkim_verify_status = US"none";
 dkim_verify_reason = US"";
-dkim_cur_sig = NULL;
 dkim_cur_signer = id;
 
 if (dkim_disable_verify || !id || !dkim_verify_ctx)
 dkim_cur_signer = id;
 
 if (dkim_disable_verify || !id || !dkim_verify_ctx)
-  return;
+  return OK;
 
 
-/* Find signature to run ACL on */
+/* Find signatures to run ACL on */
 
 for (sig = dkim_signatures; sig; sig = sig->next)
   if (  (cmp_val = Ustrchr(id, '@') != NULL ? US sig->identity : US sig->domain)
      && strcmpic(cmp_val, id) == 0
      )
     {
 
 for (sig = dkim_signatures; sig; sig = sig->next)
   if (  (cmp_val = Ustrchr(id, '@') != NULL ? US sig->identity : US sig->domain)
      && strcmpic(cmp_val, id) == 0
      )
     {
-    dkim_cur_sig = sig;
-
     /* The "dkim_domain" and "dkim_selector" expansion variables have
     /* The "dkim_domain" and "dkim_selector" expansion variables have
-       related globals, since they are used in the signing code too.
-       Instead of inventing separate names for verification, we set
-       them here. This is easy since a domain and selector is guaranteed
-       to be in a signature. The other dkim_* expansion items are
-       dynamically fetched from dkim_cur_sig at expansion time (see
-       function below). */
+    related globals, since they are used in the signing code too.
+    Instead of inventing separate names for verification, we set
+    them here. This is easy since a domain and selector is guaranteed
+    to be in a signature. The other dkim_* expansion items are
+    dynamically fetched from dkim_cur_sig at expansion time (see
+    function below). */
 
 
+    dkim_cur_sig = sig;
     dkim_signing_domain = US sig->domain;
     dkim_signing_selector = US sig->selector;
     dkim_key_length = sig->sighash.len * 8;
     dkim_signing_domain = US sig->domain;
     dkim_signing_selector = US sig->selector;
     dkim_key_length = sig->sighash.len * 8;
@@ -343,8 +370,18 @@ for (sig = dkim_signatures; sig; sig = sig->next)
 
     dkim_verify_status = dkim_exim_expand_query(DKIM_VERIFY_STATUS);
     dkim_verify_reason = dkim_exim_expand_query(DKIM_VERIFY_REASON);
 
     dkim_verify_status = dkim_exim_expand_query(DKIM_VERIFY_STATUS);
     dkim_verify_reason = dkim_exim_expand_query(DKIM_VERIFY_REASON);
-    return;
+    
+    if ((rc = dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr)) != OK)
+      return rc;
     }
     }
+
+if (rc != -1)
+  return rc;
+
+/* No matching sig found.  Call ACL once anyway. */
+
+dkim_cur_sig = NULL;
+return dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr);
 }
 
 
 }
 
 
index f32aa663531f96bb91a43e19cb5921ac503b2e63..c48241ce2daf6d51930aa2ec15b55ff2170140bd 100644 (file)
@@ -10,9 +10,8 @@ gstring * dkim_exim_sign(int, off_t, uschar *, struct ob_dkim *, const uschar **
 void    dkim_exim_verify_init(BOOL);
 void    dkim_exim_verify_feed(uschar *, int);
 void    dkim_exim_verify_finish(void);
 void    dkim_exim_verify_init(BOOL);
 void    dkim_exim_verify_feed(uschar *, int);
 void    dkim_exim_verify_finish(void);
-void    dkim_exim_verify_log_item(void);
 void    dkim_exim_verify_log_all(void);
 void    dkim_exim_verify_log_all(void);
-void    dkim_exim_acl_setup(uschar *);
+int     dkim_exim_acl_run(uschar *, gstring **, uschar **, uschar **);
 uschar *dkim_exim_expand_query(int);
 
 #define DKIM_ALGO               1
 uschar *dkim_exim_expand_query(int);
 
 #define DKIM_ALGO               1
index 8aa890bd00ad6afaf3a4532e554a45164f7b100b..e7e518a921b3c3e6d42ac16ff978ac9f18b52940 100644 (file)
@@ -3444,19 +3444,9 @@ else
 
            seen_items = string_catn(seen_items, ":", 1);
            }
 
            seen_items = string_catn(seen_items, ":", 1);
            }
-
          seen_items = string_cat(seen_items, item);
 
          seen_items = string_cat(seen_items, item);
 
-         dkim_exim_acl_setup(item);
-         DEBUG(D_receive)
-           debug_printf("calling acl_smtp_dkim for dkim_cur_signer='%s'\n",
-             item);
-
-         rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim,
-               &user_msg, &log_msg);
-         dkim_exim_verify_log_item();
-         results = string_append_listele(results, ':', dkim_verify_status);
-
+         rc = dkim_exim_acl_run(item, &results, &user_msg, &log_msg);
          if (rc != OK)
            {
            DEBUG(D_receive)
          if (rc != OK)
            {
            DEBUG(D_receive)
index 9176461320a41511ed1380914faed0f8bbfe9cc4..1eaac2f1b8659416c9efad51ec9b25dc07a12ce0 100644 (file)
@@ -7,8 +7,10 @@
 1999-03-02 09:44:33 rcpt acl: macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
 1999-03-02 09:44:33 10HmaY-0005vi-00 dkim_acl: signer: test.ex bits: 512 h=From:To:Subject
 1999-03-02 09:44:33 10HmaY-0005vi-00 DKIM: d=test.ex s=ses c=relaxed/relaxed a=rsa-sha256 b=512 [verification succeeded]
 1999-03-02 09:44:33 rcpt acl: macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
 1999-03-02 09:44:33 10HmaY-0005vi-00 dkim_acl: signer: test.ex bits: 512 h=From:To:Subject
 1999-03-02 09:44:33 10HmaY-0005vi-00 DKIM: d=test.ex s=ses c=relaxed/relaxed a=rsa-sha256 b=512 [verification succeeded]
-1999-03-02 09:44:33 10HmaY-0005vi-00 dkim_acl: signer: test.dkim.dom.ain bits: 512 h=
-1999-03-02 09:44:33 10HmaY-0005vi-00 data acl: dkim status pass:none
+1999-03-02 09:44:33 10HmaY-0005vi-00 dkim_acl: signer: test.ex bits: 1024 h=From:To:Subject
+1999-03-02 09:44:33 10HmaY-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded]
+1999-03-02 09:44:33 10HmaY-0005vi-00 dkim_acl: signer: test.dkim.dom.ain bits: 1024 h=
+1999-03-02 09:44:33 10HmaY-0005vi-00 data acl: dkim status pass:pass:none
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex
 1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <c@test.ex> R=server_dump
 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex
 1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <c@test.ex> R=server_dump
 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed