Compilation warnings shushing
[exim.git] / src / src / pdkim / pdkim.c
index a77dd5792322a96ccece9b5c326dd6d1c8c64e4e..4c93de70dd1e14124125bcb41626d82d940f121c 100644 (file)
@@ -2,7 +2,7 @@
  *  PDKIM - a RFC4871 (DKIM) implementation
  *
  *  Copyright (C) 2009 - 2016  Tom Kistner <tom@duncanthrax.net>
- *  Copyright (C) 2016  Jeremy Harris <jgh@exim.org>
+ *  Copyright (C) 2016 - 2017  Jeremy Harris <jgh@exim.org>
  *
  *  http://duncanthrax.net/pdkim/
  *
@@ -192,7 +192,8 @@ static void
 pdkim_hexprint(const uschar *data, int len)
 {
 int i;
-for (i = 0 ; i < len; i++) debug_printf("%02x", data[i]);
+if (data) for (i = 0 ; i < len; i++) debug_printf("%02x", data[i]);
+else debug_printf("<NULL>");
 debug_printf("\n");
 }
 
@@ -493,10 +494,8 @@ for (p = raw_hdr; ; p++)
        switch (*cur_tag)
          {
          case 'b':
-           if (cur_tag[1] == 'h')
-             pdkim_decode_base64(cur_val, &sig->bodyhash);
-           else
-             pdkim_decode_base64(cur_val, &sig->sigdata);
+           pdkim_decode_base64(cur_val,
+                           cur_tag[1] == 'h' ? &sig->bodyhash : &sig->sighash);
            break;
          case 'v':
              /* We only support version 1, and that is currently the
@@ -578,12 +577,17 @@ DEBUG(D_acl)
          "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
   pdkim_quoteprint(US sig->rawsig_no_b_val, Ustrlen(sig->rawsig_no_b_val));
   debug_printf(
-         "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sigdata.len*8);
+         "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sighash.len*8);
   debug_printf(
          "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
   }
 
-exim_sha_init(&sig->body_hash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256);
+if (!exim_sha_init(&sig->body_hash_ctx,
+              sig->algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256))
+  {
+  DEBUG(D_acl) debug_printf("PDKIM: hash init internal error\n");
+  return NULL;
+  }
 return sig;
 }
 
@@ -697,15 +701,14 @@ return NULL;
 /* -------------------------------------------------------------------------- */
 
 static int
-pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
+pdkim_update_bodyhash(pdkim_ctx * ctx, const char * data, int len)
 {
-pdkim_signature *sig = ctx->sig;
-/* Cache relaxed version of data */
-uschar *relaxed_data = NULL;
-int     relaxed_len  = 0;
+pdkim_signature * sig;
+uschar * relaxed_data = NULL;  /* Cache relaxed version of data */
+int relaxed_len = 0;
 
 /* Traverse all signatures, updating their hashes. */
-while (sig)
+for (sig = ctx->sig; sig; sig = sig->next)
   {
   /* Defaults to simple canon (no further treatment necessary) */
   const uschar *canon_data = CUS data;
@@ -761,12 +764,10 @@ while (sig)
 
   if (canon_len > 0)
     {
-    exim_sha_update(&sig->body_hash, CUS canon_data, canon_len);
+    exim_sha_update(&sig->body_hash_ctx, CUS canon_data, canon_len);
     sig->signed_body_bytes += canon_len;
     DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len);
     }
-
-  sig = sig->next;
   }
 
 if (relaxed_data) store_free(relaxed_data);
@@ -786,7 +787,7 @@ for (sig = ctx->sig; sig; sig = sig->next)
   {                                    /* Finish hashes */
   blob bh;
 
-  exim_sha_finish(&sig->body_hash, &bh);
+  exim_sha_finish(&sig->body_hash_ctx, &bh);
 
   DEBUG(D_acl)
     {
@@ -807,11 +808,11 @@ for (sig = ctx->sig; sig; sig = sig->next)
       sig->bodylength = -1;
     }
 
-  /* VERIFICATION --------------------------------------------------------- */
   else
-    {
-    /* Compare bodyhash */
-    if (memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
+  /* VERIFICATION --------------------------------------------------------- */
+  /* Be careful that the header sig included a bodyash */
+
+    if (sig->bodyhash.data && memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
       {
       DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
       }
@@ -820,14 +821,12 @@ for (sig = ctx->sig; sig; sig = sig->next)
       DEBUG(D_acl)
         {
        debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain);
-       pdkim_hexprint(sig->bodyhash.data,
-                        exim_sha_hashlen(&sig->body_hash));
+       pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
        debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
        }
       sig->verify_status     = PDKIM_VERIFY_FAIL;
       sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
       }
-    }
   }
 }
 
@@ -959,36 +958,35 @@ if (ctx->flags & PDKIM_MODE_SIGN)
 /* DKIM-Signature: headers are added to the verification list */
 else
   {
+#ifdef notdef
   DEBUG(D_acl)
     {
     debug_printf("PDKIM >> raw hdr: ");
     pdkim_quoteprint(CUS ctx->cur_header, Ustrlen(ctx->cur_header));
     }
+#endif
   if (strncasecmp(CCS ctx->cur_header,
                  DKIM_SIGNATURE_HEADERNAME,
                  Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
     {
-    pdkim_signature *new_sig;
+    pdkim_signature * new_sig, * last_sig;
+
+    /* Create and chain new signature block.  We could error-check for all
+    required tags here, but prefer to create the internal sig and expicitly
+    fail verification of it later. */
 
-    /* Create and chain new signature block */
     DEBUG(D_acl) debug_printf(
        "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
 
-    if ((new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header)))
+    new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header);
+
+    if (!(last_sig = ctx->sig))
+      ctx->sig = new_sig;
+    else
       {
-      pdkim_signature *last_sig = ctx->sig;
-      if (!last_sig)
-       ctx->sig = new_sig;
-      else
-        {
-       while (last_sig->next) last_sig = last_sig->next;
-       last_sig->next = new_sig;
-       }
+      while (last_sig->next) last_sig = last_sig->next;
+      last_sig->next = new_sig;
       }
-    else
-      DEBUG(D_acl) debug_printf(
-         "Error while parsing signature header\n"
-         "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
     }
 
   /* all headers are stored for signature verification */
@@ -1009,7 +1007,7 @@ return PDKIM_OK;
 DLLEXPORT int
 pdkim_feed(pdkim_ctx *ctx, char *data, int len)
 {
-int p;
+int p, rc;
 
 /* Alternate EOD signal, used in non-dotstuffing mode */
 if (!data)
@@ -1034,7 +1032,6 @@ else for (p = 0; p<len; p++)
       ctx->flags |= PDKIM_SEEN_CR;
     else if (c == '\n')
       {
-      int rc;
       ctx->flags &= ~PDKIM_SEEN_CR;
       if ((rc = pdkim_bodyline_complete(ctx)) != PDKIM_OK)
        return rc;
@@ -1054,26 +1051,24 @@ else for (p = 0; p<len; p++)
        ctx->cur_header = string_catn(ctx->cur_header, &ctx->cur_header_size,
                                &ctx->cur_header_len, CUS "\r", 1);
 
-      if (ctx->flags & PDKIM_SEEN_LF)
+      if (ctx->flags & PDKIM_SEEN_LF)          /* Seen last header line */
        {
-       int rc = pdkim_header_complete(ctx); /* Seen last header line */
-       if (rc != PDKIM_OK) return rc;
+       if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
+         return rc;
 
-       ctx->flags = ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR) | PDKIM_PAST_HDRS;
+       ctx->flags = (ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR)) | PDKIM_PAST_HDRS;
        DEBUG(D_acl) debug_printf(
-           "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>\n");
+           "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
        continue;
        }
       else
-       ctx->flags = ctx->flags & ~PDKIM_SEEN_CR | PDKIM_SEEN_LF;
+       ctx->flags = (ctx->flags & ~PDKIM_SEEN_CR) | PDKIM_SEEN_LF;
       }
     else if (ctx->flags & PDKIM_SEEN_LF)
       {
-      if (!(c == '\t' || c == ' '))
-       {
-       int rc = pdkim_header_complete(ctx); /* End of header */
-       if (rc != PDKIM_OK) return rc;
-       }
+      if (!(c == '\t' || c == ' '))                    /* End of header */
+       if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
+         return rc;
       ctx->flags &= ~PDKIM_SEEN_LF;
       }
 
@@ -1308,7 +1303,7 @@ if (sig->bodylength >= 0)
   }
 
 /* Preliminary or final version? */
-base64_b = final ? pdkim_encode_base64(&sig->sigdata) : US"";
+base64_b = final ? pdkim_encode_base64(&sig->sighash) : US"";
 hdr = pdkim_headcat(&col, hdr, &hdr_size, &hdr_len, US";", US"b=", base64_b);
 
 /* add trailing semicolon: I'm not sure if this is actually needed */
@@ -1422,7 +1417,11 @@ while (sig)
   hdata.data = NULL;
   hdata.len = 0;
 
-  exim_sha_init(&hhash_ctx, is_sha1 ? HASH_SHA1 : HASH_SHA256);
+  if (!exim_sha_init(&hhash_ctx, is_sha1 ? HASH_SHA1 : HASH_SHA256))
+    {
+    DEBUG(D_acl) debug_printf("PDKIM: hask setup internal error\n");
+    break;
+    }
 
   DEBUG(D_acl) debug_printf(
       "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>>>\n");
@@ -1584,7 +1583,7 @@ while (sig)
     hdata = hhash;
 #endif
 
-    if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sigdata)))
+    if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sighash)))
       {
       DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
       return PDKIM_ERR_RSA_SIGNING;
@@ -1593,7 +1592,7 @@ while (sig)
     DEBUG(D_acl)
       {
       debug_printf( "PDKIM [%s] b computed: ", sig->domain);
-      pdkim_hexprint(sig->sigdata.data, sig->sigdata.len);
+      pdkim_hexprint(sig->sighash.data, sig->sighash.len);
       }
 
     sig->signature_header = pdkim_create_header(sig, TRUE);
@@ -1611,7 +1610,7 @@ while (sig)
         && sig->selector      && *sig->selector
         && sig->headernames   && *sig->headernames
         && sig->bodyhash.data
-        && sig->sigdata.data
+        && sig->sighash.data
         && sig->algo > -1
         && sig->version
        ) )
@@ -1641,7 +1640,7 @@ while (sig)
       goto NEXT_VERIFY;
 
     /* Check the signature */
-    if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sigdata)))
+    if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sighash)))
       {
       DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
       sig->verify_status =      PDKIM_VERIFY_FAIL;
@@ -1728,7 +1727,12 @@ sig->selector = string_copy(US selector);
 sig->rsa_privkey = string_copy(US rsa_privkey);
 sig->algo = algo;
 
-exim_sha_init(&sig->body_hash, algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256);
+if (!exim_sha_init(&sig->body_hash_ctx,
+              algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256))
+  {
+  DEBUG(D_acl) debug_printf("PDKIM: hash setup internal error\n");
+  return NULL;
+  }
 
 DEBUG(D_acl)
   {
@@ -1740,7 +1744,6 @@ DEBUG(D_acl)
     debug_printf("WARNING: bad dkim key in dns\n");
   debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
   }
-
 return ctx;
 }