Recommitted change to remove excess newline from debug output
[exim.git] / src / src / pdkim / pdkim.c
index dbc1f4d0cdd3df2b9cb7c89bbf22802480b18723..d2eaecc02908b3cc52730303a270eab9b6332a7b 100644 (file)
@@ -20,7 +20,7 @@
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-/* $Cambridge: exim/src/src/pdkim/pdkim.c,v 1.6 2009/10/29 11:08:01 tom Exp $ */
+/* $Cambridge: exim/src/src/pdkim/pdkim.c,v 1.11 2009/11/23 12:34:51 nm4 Exp $ */
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -105,6 +105,27 @@ pdkim_combined_canon_entry pdkim_combined_canons[] = {
 };
 
 
+char *pdkim_verify_status_str(int status) {
+  switch(status) {
+    case PDKIM_VERIFY_NONE:    return "PDKIM_VERIFY_NONE";
+    case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
+    case PDKIM_VERIFY_FAIL:    return "PDKIM_VERIFY_FAIL";
+    case PDKIM_VERIFY_PASS:    return "PDKIM_VERIFY_PASS";
+    default:                   return "PDKIM_VERIFY_UNKNOWN";
+  }
+}
+char *pdkim_verify_ext_status_str(int ext_status) {
+  switch(ext_status) {
+    case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
+    case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
+    case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
+    case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
+    case PDKIM_VERIFY_INVALID_PUBKEY_PARSING: return "PDKIM_VERIFY_INVALID_PUBKEY_PARSING";
+    default: return "PDKIM_VERIFY_UNKNOWN";
+  }
+}
+
+
 /* -------------------------------------------------------------------------- */
 /* Print debugging functions */
 #ifdef PDKIM_DEBUG
@@ -156,12 +177,12 @@ pdkim_stringlist *pdkim_append_stringlist(pdkim_stringlist *base, char *str) {
   if (new_entry->value == NULL) return NULL;
   if (base != NULL) {
     pdkim_stringlist *last = base;
-    while (last->next != NULL) { last = last->next; };
+    while (last->next != NULL) { last = last->next; }
     last->next = new_entry;
     return base;
   }
   else return new_entry;
-};
+}
 pdkim_stringlist *pdkim_prepend_stringlist(pdkim_stringlist *base, char *str) {
   pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
   if (new_entry == NULL) return NULL;
@@ -172,7 +193,7 @@ pdkim_stringlist *pdkim_prepend_stringlist(pdkim_stringlist *base, char *str) {
     new_entry->next = base;
   }
   return new_entry;
-};
+}
 
 
 /* -------------------------------------------------------------------------- */
@@ -191,7 +212,7 @@ pdkim_str *pdkim_strnew (char *cstr) {
   p->len=len;
   if (cstr) strcpy(p->str,cstr);
   return p;
-};
+}
 char *pdkim_strncat(pdkim_str *str, char *data, int len) {
   if ((str->allocated - str->len) < (len+1)) {
     /* Extend the buffer */
@@ -206,20 +227,20 @@ char *pdkim_strncat(pdkim_str *str, char *data, int len) {
   str->len+=len;
   str->str[str->len] = '\0';
   return str->str;
-};
+}
 char *pdkim_strcat(pdkim_str *str, char *cstr) {
   return pdkim_strncat(str, cstr, strlen(cstr));
-};
+}
 char *pdkim_numcat(pdkim_str *str, unsigned long num) {
   char minibuf[20];
   snprintf(minibuf,20,"%lu",num);
   return pdkim_strcat(str,minibuf);
-};
+}
 char *pdkim_strtrim(pdkim_str *str) {
   char *p = str->str;
   char *q = str->str;
   while ( (*p != '\0') && ((*p == '\t') || (*p == ' ')) ) p++;
-  while (*p != '\0') {*q = *p; q++; p++;};
+  while (*p != '\0') {*q = *p; q++; p++;}
   *q = '\0';
   while ( (q != str->str) && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) ) {
     *q = '\0';
@@ -227,17 +248,17 @@ char *pdkim_strtrim(pdkim_str *str) {
   }
   str->len = strlen(str->str);
   return str->str;
-};
+}
 char *pdkim_strclear(pdkim_str *str) {
   str->str[0] = '\0';
   str->len = 0;
   return str->str;
-};
+}
 void pdkim_strfree(pdkim_str *str) {
   if (str == NULL) return;
   if (str->str != NULL) free(str->str);
   free(str);
-};
+}
 
 
 
@@ -288,7 +309,7 @@ void pdkim_free_sig(pdkim_signature *sig) {
     free(sig);
     if (next != NULL) pdkim_free_sig(next);
   }
-};
+}
 
 
 /* -------------------------------------------------------------------------- */
@@ -298,7 +319,7 @@ DLLEXPORT void pdkim_free_ctx(pdkim_ctx *ctx) {
     pdkim_strfree(ctx->cur_header);
     free(ctx);
   }
-};
+}
 
 
 /* -------------------------------------------------------------------------- */
@@ -401,7 +422,7 @@ char *pdkim_relax_header (char *header, int crlf) {
   *q = '\0';
   if (crlf) strcat(relaxed,"\r\n");
   return relaxed;
-};
+}
 
 
 /* -------------------------------------------------------------------------- */
@@ -416,12 +437,12 @@ char *pdkim_decode_qp_char(char *qp_p, int *c) {
   if (isxdigit(*qp_p) && isxdigit(qp_p[1])) {
     /* Do hex conversion */
     if (isdigit(*qp_p)) {*c = *qp_p - '0';}
-    else {*c = toupper(*qp_p) - 'A' + 10;};
+    else {*c = toupper(*qp_p) - 'A' + 10;}
     *c <<= 4;
     if (isdigit(qp_p[1])) {*c |= qp_p[1] - '0';}
-    else {*c |= toupper(qp_p[1]) - 'A' + 10;};
+    else {*c |= toupper(qp_p[1]) - 'A' + 10;}
     return qp_p + 2;
-  };
+  }
 
   /* Illegal char here */
   *c = PDKIM_QP_ERROR_DECODE;
@@ -908,7 +929,7 @@ int pdkim_update_bodyhash(pdkim_ctx *ctx, char *data, int len) {
 
   if (relaxed_data != NULL) free(relaxed_data);
   return PDKIM_OK;
-};
+}
 
 
 /* -------------------------------------------------------------------------- */
@@ -976,7 +997,7 @@ int pdkim_finish_bodyhash(pdkim_ctx *ctx) {
   }
 
   return PDKIM_OK;
-};
+}
 
 
 
@@ -1088,7 +1109,7 @@ int pdkim_header_complete(pdkim_ctx *ctx) {
         ctx->sig = new_sig;
       }
       else {
-        while (last_sig->next != NULL) { last_sig = last_sig->next; };
+        while (last_sig->next != NULL) { last_sig = last_sig->next; }
         last_sig->next = new_sig;
       }
     }
@@ -1106,7 +1127,7 @@ int pdkim_header_complete(pdkim_ctx *ctx) {
   BAIL:
   pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
   return PDKIM_OK;
-};
+}
 
 
 
@@ -1164,7 +1185,7 @@ DLLEXPORT int pdkim_feed (pdkim_ctx *ctx,
     }
   }
   return PDKIM_OK;
-};
+}
 
 
 /* -------------------------------------------------------------------------- */
@@ -1267,7 +1288,7 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu
   /* Check if we must still flush a (partial) header. If that is the
      case, the message has no body, and we must compute a body hash
      out of '<CR><LF>' */
-  if (ctx->cur_header->len) {
+  if (ctx->cur_header && ctx->cur_header->len) {
     int rc = pdkim_header_complete(ctx);
     if (rc != PDKIM_OK) return rc;
     pdkim_update_bodyhash(ctx,"\r\n",2);
@@ -1283,7 +1304,7 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu
     #ifdef PDKIM_DEBUG
     if (ctx->debug_stream)
       fprintf(ctx->debug_stream,
-        "\nPDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+        "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
     #endif
   }
 
@@ -1516,7 +1537,7 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu
         sig->verify_status =      PDKIM_VERIFY_INVALID;
         sig->verify_ext_status =  PDKIM_VERIFY_INVALID_BUFFER_SIZE;
         goto NEXT_VERIFY;
-      };
+      }
 
       if ((ctx->dns_txt_callback(dns_txt_name, dns_txt_reply) != PDKIM_OK) ||
           (dns_txt_reply[0] == '\0')) {
@@ -1573,26 +1594,30 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu
                         (unsigned char *)sig->sigdata) != 0) {
         sig->verify_status =      PDKIM_VERIFY_FAIL;
         sig->verify_ext_status =  PDKIM_VERIFY_FAIL_MESSAGE;
-        #ifdef PDKIM_DEBUG
-        if (ctx->debug_stream) {
-          fprintf(ctx->debug_stream, "PDKIM [%s] signature did NOT verify OK\n",
-                  sig->domain);
-        }
-        #endif
         goto NEXT_VERIFY;
       }
 
-      /* We have a winner! */
-      sig->verify_status = PDKIM_VERIFY_PASS;
+      /* We have a winner! (if bodydhash was correct earlier) */
+      if (sig->verify_status == PDKIM_VERIFY_NONE) {
+        sig->verify_status = PDKIM_VERIFY_PASS;
+      }
+
+      NEXT_VERIFY:
 
       #ifdef PDKIM_DEBUG
       if (ctx->debug_stream) {
-        fprintf(ctx->debug_stream, "PDKIM [%s] signature verified OK\n",
-                sig->domain);
+        fprintf(ctx->debug_stream, "PDKIM [%s] signature status: %s",
+                sig->domain, pdkim_verify_status_str(sig->verify_status));
+        if (sig->verify_ext_status > 0) {
+          fprintf(ctx->debug_stream, " (%s)\n",
+                  pdkim_verify_ext_status_str(sig->verify_ext_status));
+        }
+        else {
+          fprintf(ctx->debug_stream, "\n");
+        }
       }
       #endif
 
-      NEXT_VERIFY:
       rsa_free(&rsa);
       free(dns_txt_name);
       free(dns_txt_reply);
@@ -1689,14 +1714,14 @@ DLLEXPORT pdkim_ctx *pdkim_init_sign(int input_mode,
   sha2_starts(ctx->sig->sha2_body,0);
 
   return ctx;
-};
+}
 
 #ifdef PDKIM_DEBUG
 /* -------------------------------------------------------------------------- */
 DLLEXPORT void pdkim_set_debug_stream(pdkim_ctx *ctx,
                             FILE *debug_stream) {
   ctx->debug_stream = debug_stream;
-};
+}
 #endif
 
 /* -------------------------------------------------------------------------- */
@@ -1728,4 +1753,4 @@ DLLEXPORT int pdkim_set_optional(pdkim_ctx *ctx,
   ctx->sig->expires = expires;
 
   return PDKIM_OK;
-};
+}