DKIM: rework error logging to pass strings back to caller for logging. Bug 966
[exim.git] / src / src / pdkim / pdkim.c
index 6e76b8e9fa2555e0a8e422b618d87a0bf424940d..5fc6045d0b49995a74bfffe62ca1bad58aecdcc4 100644 (file)
@@ -142,19 +142,19 @@ switch(ext_status)
   }
 }
 
-const char *
+const uschar *
 pdkim_errstr(int status)
 {
 switch(status)
   {
-  case PDKIM_OK:               return "OK";
-  case PDKIM_FAIL:             return "FAIL";
-  case PDKIM_ERR_RSA_PRIVKEY:  return "RSA_PRIVKEY";
-  case PDKIM_ERR_RSA_SIGNING:  return "RSA SIGNING";
-  case PDKIM_ERR_LONG_LINE:    return "RSA_LONG_LINE";
-  case PDKIM_ERR_BUFFER_TOO_SMALL:     return "BUFFER_TOO_SMALL";
-  case PDKIM_SIGN_PRIVKEY_WRAP:        return "PRIVKEY_WRAP";
-  case PDKIM_SIGN_PRIVKEY_B64D:        return "PRIVKEY_B64D";
+  case PDKIM_OK:               return US"OK";
+  case PDKIM_FAIL:             return US"FAIL";
+  case PDKIM_ERR_RSA_PRIVKEY:  return US"RSA_PRIVKEY";
+  case PDKIM_ERR_RSA_SIGNING:  return US"RSA SIGNING";
+  case PDKIM_ERR_LONG_LINE:    return US"RSA_LONG_LINE";
+  case PDKIM_ERR_BUFFER_TOO_SMALL:     return US"BUFFER_TOO_SMALL";
+  case PDKIM_SIGN_PRIVKEY_WRAP:        return US"PRIVKEY_WRAP";
+  case PDKIM_SIGN_PRIVKEY_B64D:        return US"PRIVKEY_B64D";
   default: return "(unknown)";
   }
 }
@@ -416,7 +416,7 @@ return b64encode(b->data, b->len);
 static pdkim_signature *
 pdkim_parse_sig_header(pdkim_ctx *ctx, uschar * raw_hdr)
 {
-pdkim_signature *sig ;
+pdkim_signature * sig;
 uschar *p, *q;
 uschar * cur_tag = NULL; int ts = 0, tl = 0;
 uschar * cur_val = NULL; int vs = 0, vl = 0;
@@ -931,28 +931,25 @@ return PDKIM_OK;
 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
 
 static int
-pdkim_header_complete(pdkim_ctx *ctx)
+pdkim_header_complete(pdkim_ctx * ctx)
 {
+pdkim_signature * sig, * last_sig;
+
 /* Special case: The last header can have an extra \r appended */
 if ( (ctx->cur_header_len > 1) &&
      (ctx->cur_header[(ctx->cur_header_len)-1] == '\r') )
   --ctx->cur_header_len;
 ctx->cur_header[ctx->cur_header_len] = '\0';
 
-ctx->num_headers++;
-if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
+if (++ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
 
 /* SIGNING -------------------------------------------------------------- */
 if (ctx->flags & PDKIM_MODE_SIGN)
-  {
-  pdkim_signature *sig;
-
   for (sig = ctx->sig; sig; sig = sig->next)                   /* Traverse all signatures */
 
     /* Add header to the signed headers list (in reverse order) */
     sig->headers = pdkim_prepend_stringlist(sig->headers,
                                  ctx->cur_header);
-  }
 
 /* VERIFICATION ----------------------------------------------------------- */
 /* DKIM-Signature: headers are added to the verification list */
@@ -962,15 +959,13 @@ else
   DEBUG(D_acl)
     {
     debug_printf("PDKIM >> raw hdr: ");
-    pdkim_quoteprint(CUS ctx->cur_header, Ustrlen(ctx->cur_header));
+    pdkim_quoteprint(CUS ctx->cur_header, ctx->cur_header_len);
     }
 #endif
   if (strncasecmp(CCS ctx->cur_header,
                  DKIM_SIGNATURE_HEADERNAME,
                  Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
     {
-    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. */
@@ -978,14 +973,14 @@ else
     DEBUG(D_acl) debug_printf(
        "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
 
-    new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header);
+    sig = pdkim_parse_sig_header(ctx, ctx->cur_header);
 
     if (!(last_sig = ctx->sig))
-      ctx->sig = new_sig;
+      ctx->sig = sig;
     else
       {
       while (last_sig->next) last_sig = last_sig->next;
-      last_sig->next = new_sig;
+      last_sig->next = sig;
       }
     }
 
@@ -994,8 +989,7 @@ else
   }
 
 BAIL:
-*ctx->cur_header = '\0';
-ctx->cur_header_len = 0;       /* leave buffer for reuse */
+ctx->cur_header[ctx->cur_header_len = 0] = '\0';       /* leave buffer for reuse */
 return PDKIM_OK;
 }
 
@@ -1056,13 +1050,13 @@ else for (p = 0; p<len; p++)
        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");
        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)
       {
@@ -1317,11 +1311,11 @@ return hdr;
 /* -------------------------------------------------------------------------- */
 
 static pdkim_pubkey *
-pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx)
+pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
+  const uschar ** errstr)
 {
 uschar * dns_txt_name, * dns_txt_reply;
 pdkim_pubkey * p;
-const uschar * errstr;
 
 /* Fetch public key for signing domain, from DNS */
 
@@ -1370,9 +1364,9 @@ DEBUG(D_acl) debug_printf(
       "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
 
 /* Import public key */
-if ((errstr = exim_rsa_verify_init(&p->key, vctx)))
+if ((*errstr = exim_rsa_verify_init(&p->key, vctx)))
   {
-  DEBUG(D_acl) debug_printf("verify_init: %s\n", errstr);
+  DEBUG(D_acl) debug_printf("verify_init: %s\n", *errstr);
   sig->verify_status =      PDKIM_VERIFY_INVALID;
   sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
   return NULL;
@@ -1385,7 +1379,8 @@ return p;
 /* -------------------------------------------------------------------------- */
 
 DLLEXPORT int
-pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures)
+pdkim_feed_finish(pdkim_ctx * ctx, pdkim_signature ** return_signatures,
+  const uschar ** err)
 {
 pdkim_signature *sig = ctx->sig;
 
@@ -1566,12 +1561,11 @@ while (sig)
   if (ctx->flags & PDKIM_MODE_SIGN)
     {
     es_ctx sctx;
-    const uschar * errstr;
 
     /* Import private key */
-    if ((errstr = exim_rsa_signing_init(US sig->rsa_privkey, &sctx)))
+    if ((*err = exim_rsa_signing_init(US sig->rsa_privkey, &sctx)))
       {
-      DEBUG(D_acl) debug_printf("signing_init: %s\n", errstr);
+      DEBUG(D_acl) debug_printf("signing_init: %s\n", *err);
       return PDKIM_ERR_RSA_PRIVKEY;
       }
 
@@ -1583,9 +1577,9 @@ while (sig)
     hdata = hhash;
 #endif
 
-    if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sighash)))
+    if ((*err = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sighash)))
       {
-      DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
+      DEBUG(D_acl) debug_printf("signing: %s\n", *err);
       return PDKIM_ERR_RSA_SIGNING;
       }
 
@@ -1602,7 +1596,6 @@ while (sig)
   else
     {
     ev_ctx vctx;
-    const uschar * errstr;
     pdkim_pubkey * p;
 
     /* Make sure we have all required signature tags */
@@ -1636,13 +1629,13 @@ while (sig)
       goto NEXT_VERIFY;
       }
 
-    if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx)))
+    if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err)))
       goto NEXT_VERIFY;
 
     /* Check the signature */
-    if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sighash)))
+    if ((*err = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sighash)))
       {
-      DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
+      DEBUG(D_acl) debug_printf("headers verify: %s\n", *err);
       sig->verify_status =      PDKIM_VERIFY_FAIL;
       sig->verify_ext_status =  PDKIM_VERIFY_FAIL_MESSAGE;
       goto NEXT_VERIFY;
@@ -1700,7 +1693,8 @@ return ctx;
 
 DLLEXPORT pdkim_ctx *
 pdkim_init_sign(char * domain, char * selector, char * rsa_privkey, int algo,
-  BOOL dot_stuffed, int(*dns_txt_callback)(char *, char *))
+  BOOL dot_stuffed, int(*dns_txt_callback)(char *, char *),
+  const uschar ** errstr)
 {
 pdkim_ctx * ctx;
 pdkim_signature * sig;
@@ -1740,7 +1734,7 @@ DEBUG(D_acl)
   ev_ctx vctx;
 
   debug_printf("PDKIM (checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
-  if (!pdkim_key_from_dns(ctx, &s, &vctx))
+  if (!pdkim_key_from_dns(ctx, &s, &vctx, errstr))
     debug_printf("WARNING: bad dkim key in dns\n");
   debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
   }