More checks on header line length during reception
[exim.git] / src / src / dkim.c
index d223f9e62e2d0d545c7a34926d3677460806e0f0..5209cd983ceb27d16a8e4c097fcc7ba8d2428083 100644 (file)
@@ -33,6 +33,8 @@ pdkim_ctx *dkim_verify_ctx = NULL;
 pdkim_signature *dkim_cur_sig = NULL;
 static const uschar * dkim_collect_error = NULL;
 
+#define DKIM_MAX_SIGNATURES 20
+
 
 
 /*XXX the caller only uses the first record if we return multiple.
@@ -114,7 +116,7 @@ if (dkim_verify_ctx)
 /* Create new context */
 
 dkim_verify_ctx = pdkim_init_verify(&dkim_exim_query_dns_txt, dot_stuffing);
-dkim_collect_input = !!dkim_verify_ctx;
+dkim_collect_input = dkim_verify_ctx ? DKIM_MAX_SIGNATURES : 0;
 dkim_collect_error = NULL;
 
 /* Start feed up with any cached data */
@@ -136,7 +138,7 @@ if (  dkim_collect_input
   dkim_collect_error = pdkim_errstr(rc);
   log_write(0, LOG_MAIN,
             "DKIM: validation error: %.100s", dkim_collect_error);
-  dkim_collect_input = FALSE;
+  dkim_collect_input = 0;
   }
 store_pool = dkim_verify_oldpool;
 }
@@ -190,19 +192,18 @@ if (!(s = sig->domain)) s = US"<UNSET>";
 logmsg = string_append(logmsg, 2, "d=", s);
 if (!(s = sig->selector)) s = US"<UNSET>";
 logmsg = string_append(logmsg, 2, " s=", s);
-logmsg = string_append(logmsg, 7,
-  " c=", sig->canon_headers == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
-  "/",   sig->canon_body    == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
-  " a=", dkim_sig_to_a_tag(sig),
-string_sprintf(" b=" SIZE_T_FMT,
-               (int)sig->sighash.len > -1 ? sig->sighash.len * 8 : 0));
+logmsg = string_fmt_append(logmsg, " c=%s/%s a=%s b=" SIZE_T_FMT,
+         sig->canon_headers == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
+         sig->canon_body    == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
+         dkim_sig_to_a_tag(sig),
+         (int)sig->sighash.len > -1 ? sig->sighash.len * 8 : (size_t)0);
 if ((s= sig->identity)) logmsg = string_append(logmsg, 2, " i=", s);
-if (sig->created > 0) logmsg = string_cat(logmsg,
-                             string_sprintf(" t=%lu", sig->created));
-if (sig->expires > 0) logmsg = string_cat(logmsg,
-                             string_sprintf(" x=%lu", sig->expires));
-if (sig->bodylength > -1) logmsg = string_cat(logmsg,
-                             string_sprintf(" l=%lu", sig->bodylength));
+if (sig->created > 0) logmsg = string_fmt_append(logmsg, " t=%lu",
+                                   sig->created);
+if (sig->expires > 0) logmsg = string_fmt_append(logmsg, " x=%lu",
+                                   sig->expires);
+if (sig->bodylength > -1) logmsg = string_fmt_append(logmsg, " l=%lu",
+                                   sig->bodylength);
 
 if (sig->verify_status & PDKIM_VERIFY_POLICY)
   logmsg = string_append(logmsg, 5,
@@ -304,11 +305,11 @@ if (dkim_collect_error)
   log_write(0, LOG_MAIN,
       "DKIM: Error during validation, disabling signature verification: %.100s",
       dkim_collect_error);
-  dkim_disable_verify = TRUE;
+  f.dkim_disable_verify = TRUE;
   goto out;
   }
 
-dkim_collect_input = FALSE;
+dkim_collect_input = 0;
 
 /* Finish DKIM operation and fetch link to signatures chain */
 
@@ -379,7 +380,7 @@ dkim_verify_status = US"none";
 dkim_verify_reason = US"";
 dkim_cur_signer = id;
 
-if (dkim_disable_verify || !id || !dkim_verify_ctx)
+if (f.dkim_disable_verify || !id || !dkim_verify_ctx)
   return OK;
 
 /* Find signatures to run ACL on */
@@ -451,7 +452,7 @@ switch (what)
 uschar *
 dkim_exim_expand_query(int what)
 {
-if (!dkim_verify_ctx || dkim_disable_verify || !dkim_cur_sig)
+if (!dkim_verify_ctx || f.dkim_disable_verify || !dkim_cur_sig)
   return dkim_exim_expand_defaults(what);
 
 switch (what)
@@ -643,6 +644,8 @@ if (dkim_domain)
     uschar * dkim_private_key_expanded;
     uschar * dkim_hash_expanded;
     uschar * dkim_identity_expanded = NULL;
+    uschar * dkim_timestamps_expanded = NULL;
+    unsigned long tval = 0, xval = 0;
 
     /* Get canonicalization to use */
 
@@ -693,6 +696,13 @@ if (dkim_domain)
       else if (!*dkim_identity_expanded)
        dkim_identity_expanded = NULL;
 
+    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);
+
     if (!(sig = pdkim_init_sign(&dkim_sign_ctx, dkim_signing_domain,
                          dkim_signing_selector,
                          dkim_private_key_expanded,
@@ -706,7 +716,7 @@ if (dkim_domain)
                        CS dkim_sign_headers_expanded,
                        CS dkim_identity_expanded,
                        pdkim_canon,
-                       pdkim_canon, -1, 0, 0);
+                       pdkim_canon, -1, tval, xval);
 
     if (!pdkim_set_sig_bodyhash(&dkim_sign_ctx, sig))
       goto bad;
@@ -813,7 +823,7 @@ for (sig = dkim_signatures; sig; sig = sig->next)
           g = string_cat(g, US"permerror (overlong public key record)\n\t\t"); break;
         case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
         case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
-          g = string_cat(g, US"neutral (syntax error in public key record)\n\t\t");
+          g = string_cat(g, US"neutral (public key record import problem)\n\t\t");
           break;
         case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
           g = string_cat(g, US"neutral (signature tag missing or invalid)\n\t\t");