Merge branch 'router_dynamic_modules'
[exim.git] / src / src / dkim.c
index 0c5e84788872ae7f359ce65e329fd93b3cacbd3f..68f074889619362fced3f60a92010ada365e45d9 100644 (file)
@@ -2,9 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2020 - 2024 */
 /* Copyright (c) University of Cambridge, 1995 - 2018 */
 /* Copyright (c) University of Cambridge, 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 - 2021*/
 /* See the file NOTICE for conditions of use and distribution. */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 /* Code for DKIM support. Other DKIM relevant code is in
    receive.c, transport.c and transports/smtp.c */
 
 /* Code for DKIM support. Other DKIM relevant code is in
    receive.c, transport.c and transports/smtp.c */
@@ -50,7 +51,7 @@ dkim_exim_query_dns_txt(const uschar * name)
 dns_answer * dnsa = store_get_dns_answer();
 dns_scan dnss;
 rmark reset_point = store_mark();
 dns_answer * dnsa = store_get_dns_answer();
 dns_scan dnss;
 rmark reset_point = store_mark();
-gstring * g = string_get_tainted(256, TRUE);
+gstring * g = string_get_tainted(256, GET_TAINTED);
 
 lookup_dnssec_authenticated = NULL;
 if (dns_lookup(dnsa, name, T_TXT, NULL) != DNS_SUCCEED)
 
 lookup_dnssec_authenticated = NULL;
 if (dns_lookup(dnsa, name, T_TXT, NULL) != DNS_SUCCEED)
@@ -82,7 +83,7 @@ for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
       return string_from_gstring(g);
       }
 
       return string_from_gstring(g);
       }
 
-    g->ptr = 0;                /* overwrite previous record */
+    gstring_reset(g);          /* overwrite previous record */
     }
 
 bad:
     }
 
 bad:
@@ -288,7 +289,7 @@ else
       break;
     }
 
       break;
     }
 
-log_write(0, LOG_MAIN, "%s", string_from_gstring(logmsg));
+log_write(0, LOG_MAIN, "%Y", logmsg);
 return;
 }
 
 return;
 }
 
@@ -341,8 +342,8 @@ for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
   if (sig->domain)   g = string_append_listele(g, ':', sig->domain);
   if (sig->identity) g = string_append_listele(g, ':', sig->identity);
   }
   if (sig->domain)   g = string_append_listele(g, ':', sig->domain);
   if (sig->identity) g = string_append_listele(g, ':', sig->identity);
   }
-
-if (g) dkim_signers = g->s;
+gstring_release_unused(g);
+dkim_signers = string_from_gstring(g);
 
 out:
 store_pool = dkim_verify_oldpool;
 
 out:
 store_pool = dkim_verify_oldpool;
@@ -357,7 +358,8 @@ dkim_acl_call(uschar * id, gstring ** res_ptr,
 {
 int rc;
 DEBUG(D_receive)
 {
 int rc;
 DEBUG(D_receive)
-  debug_printf("calling acl_smtp_dkim for dkim_cur_signer='%s'\n", id);
+  debug_printf("calling acl_smtp_dkim for identity '%s' domain '%s' sel '%s'\n",
+             id, dkim_signing_domain, dkim_signing_selector);
 
 rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, user_msgptr, log_msgptr);
 dkim_exim_verify_log_sig(dkim_cur_sig);
 
 rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, user_msgptr, log_msgptr);
 dkim_exim_verify_log_sig(dkim_cur_sig);
@@ -368,6 +370,7 @@ return rc;
 
 
 /* For the given identity, run the DKIM ACL once for each matching signature.
 
 
 /* For the given identity, run the DKIM ACL once for each matching signature.
+If none match, run it once.
 
 Arguments
  id            Identity to look for in dkim signatures
 
 Arguments
  id            Identity to look for in dkim signatures
@@ -424,7 +427,8 @@ for (pdkim_signature * 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);
 
-    if ((rc = dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr)) != OK)
+    if (  (rc = dkim_acl_call(id, res_ptr, user_msgptr, log_msgptr)) != OK
+       || dkim_verify_minimal && Ustrcmp(dkim_verify_status, "pass") == 0)
       return rc;
     }
 
       return rc;
     }
 
@@ -623,6 +627,7 @@ if (dkim->dot_stuffed)
 
 store_pool = POOL_MAIN;
 
 
 store_pool = POOL_MAIN;
 
+GET_OPTION("dkim_domain");
 if ((s = dkim->dkim_domain) && !(dkim_domain = expand_cstring(s)))
   /* expansion error, do not send message. */
   { errwhen = US"dkim_domain"; goto expand_bad; }
 if ((s = dkim->dkim_domain) && !(dkim_domain = expand_cstring(s)))
   /* expansion error, do not send message. */
   { errwhen = US"dkim_domain"; goto expand_bad; }
@@ -651,6 +656,7 @@ if (dkim_domain)
   /* Set $dkim_selector expansion variable to each selector in list,
   for this domain. */
 
   /* Set $dkim_selector expansion variable to each selector in list,
   for this domain. */
 
+  GET_OPTION("dkim_selector");
   if (!(dkim_sel = expand_string(dkim->dkim_selector)))
     { errwhen = US"dkim_selector"; goto expand_bad; }
 
   if (!(dkim_sel = expand_string(dkim->dkim_selector)))
     { errwhen = US"dkim_selector"; goto expand_bad; }
 
@@ -668,6 +674,7 @@ if (dkim_domain)
 
     /* Get canonicalization to use */
 
 
     /* Get canonicalization to use */
 
+    GET_OPTION("dkim_canon");
     dkim_canon_expanded = dkim->dkim_canon
       ? expand_string(dkim->dkim_canon) : US"relaxed";
     if (!dkim_canon_expanded)  /* expansion error, do not send message. */
     dkim_canon_expanded = dkim->dkim_canon
       ? expand_string(dkim->dkim_canon) : US"relaxed";
     if (!dkim_canon_expanded)  /* expansion error, do not send message. */
@@ -685,6 +692,7 @@ if (dkim_domain)
       pdkim_canon = PDKIM_CANON_RELAXED;
       }
 
       pdkim_canon = PDKIM_CANON_RELAXED;
       }
 
+    GET_OPTION("dkim_sign_headers");
     if (  dkim->dkim_sign_headers
        && !(dkim_sign_headers_expanded = expand_string(dkim->dkim_sign_headers)))
       { errwhen = US"dkim_sign_header"; goto expand_bad; }
     if (  dkim->dkim_sign_headers
        && !(dkim_sign_headers_expanded = expand_string(dkim->dkim_sign_headers)))
       { errwhen = US"dkim_sign_header"; goto expand_bad; }
@@ -692,6 +700,7 @@ if (dkim_domain)
 
     /* Get private key to use. */
 
 
     /* Get private key to use. */
 
+    GET_OPTION("dkim_private_key");
     if (!(dkim_private_key_expanded = expand_string(dkim->dkim_private_key)))
       { errwhen = US"dkim_private_key"; goto expand_bad; }
 
     if (!(dkim_private_key_expanded = expand_string(dkim->dkim_private_key)))
       { errwhen = US"dkim_private_key"; goto expand_bad; }
 
@@ -706,21 +715,28 @@ if (dkim_domain)
             expand_file_big_buffer(dkim_private_key_expanded)))
       goto bad;
 
             expand_file_big_buffer(dkim_private_key_expanded)))
       goto bad;
 
+    GET_OPTION("dkim_hash");
     if (!(dkim_hash_expanded = expand_string(dkim->dkim_hash)))
       { errwhen = US"dkim_hash"; goto expand_bad; }
 
     if (!(dkim_hash_expanded = expand_string(dkim->dkim_hash)))
       { errwhen = US"dkim_hash"; goto expand_bad; }
 
+    GET_OPTION("dkim_identity");
     if (dkim->dkim_identity)
       if (!(dkim_identity_expanded = expand_string(dkim->dkim_identity)))
        { errwhen = US"dkim_identity"; goto expand_bad; }
       else if (!*dkim_identity_expanded)
        dkim_identity_expanded = NULL;
 
     if (dkim->dkim_identity)
       if (!(dkim_identity_expanded = expand_string(dkim->dkim_identity)))
        { errwhen = US"dkim_identity"; goto expand_bad; }
       else if (!*dkim_identity_expanded)
        dkim_identity_expanded = NULL;
 
+    GET_OPTION("dkim_timestamps");
     if (dkim->dkim_timestamps)
       if (!(dkim_timestamps_expanded = expand_string(dkim->dkim_timestamps)))
        { errwhen = US"dkim_timestamps"; goto expand_bad; }
       else
     if (dkim->dkim_timestamps)
       if (!(dkim_timestamps_expanded = expand_string(dkim->dkim_timestamps)))
        { errwhen = US"dkim_timestamps"; goto expand_bad; }
       else
-       xval = (tval = (unsigned long) time(NULL))
-             + strtoul(CCS dkim_timestamps_expanded, NULL, 10);
+        {
+        tval = (unsigned long) time(NULL);
+        xval = strtoul(CCS dkim_timestamps_expanded, NULL, 10);
+        if (xval > 0)
+          xval += tval;
+        }
 
     if (!(sig = pdkim_init_sign(&dkim_sign_ctx, dkim_signing_domain,
                          dkim_signing_selector,
 
     if (!(sig = pdkim_init_sign(&dkim_sign_ctx, dkim_signing_domain,
                          dkim_signing_selector,
@@ -740,6 +756,9 @@ if (dkim_domain)
     if (!pdkim_set_sig_bodyhash(&dkim_sign_ctx, sig))
       goto bad;
 
     if (!pdkim_set_sig_bodyhash(&dkim_sign_ctx, sig))
       goto bad;
 
+    dkim_signing_record = string_append_listele(dkim_signing_record, ':', dkim_signing_domain);
+    dkim_signing_record = string_append_listele(dkim_signing_record, ':', dkim_signing_selector);
+
     if (!dkim_sign_ctx.sig)            /* link sig to context chain */
       dkim_sign_ctx.sig = sig;
     else
     if (!dkim_sign_ctx.sig)            /* link sig to context chain */
       dkim_sign_ctx.sig = sig;
     else
@@ -821,7 +840,7 @@ authres_dkim(gstring * g)
 {
 int start = 0;         /* compiler quietening */
 
 {
 int start = 0;         /* compiler quietening */
 
-DEBUG(D_acl) start = g->ptr;
+DEBUG(D_acl) start = gstring_length(g);
 
 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
   {
 
 for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
   {
@@ -883,10 +902,10 @@ for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)
   }
 
 DEBUG(D_acl)
   }
 
 DEBUG(D_acl)
-  if (g->ptr == start)
-    debug_printf("DKIM: no authres\n");
+  if (gstring_length(g) == start)
+    debug_printf("DKIM:\tno authres\n");
   else
   else
-    debug_printf("DKIM: authres '%.*s'\n", g->ptr - start - 3, g->s + start + 3);
+    debug_printf("DKIM:\tauthres '%.*s'\n", g->ptr - start - 3, g->s + start + 3);
 return g;
 }
 
 return g;
 }