Re: [exim-dev] [exim] Using ADSP?

Top Page
Delete this message
Reply to this message
Author: Michael Haardt
Date:  
To: exim-dev
Subject: Re: [exim-dev] [exim] Using ADSP?
Hello,

I finished the patch and added a few error checks. What remains is to
rename dkim_domain to dkim_add_signers and to decide if a signature should
not be added if the message already contains a signature for the domain.

If you apply this patch, dkim_domain becomes a string list instead of
just a single string, resulting in multiple signatures being added.
Besides signing all From: addresses, you could sign the sender domain
as well.

Michael
----------------------------------------------------------------------
--- ./src/dkim.c.orig    2010-01-27 11:05:45.000000000 +0100
+++ ./src/dkim.c    2010-02-02 12:08:18.000000000 +0100
@@ -387,8 +387,18 @@
                        uschar *dkim_selector,
                        uschar *dkim_canon,
                        uschar *dkim_sign_headers) {
+  int sep = 0;
+  uschar *seen_items = NULL;
+  int seen_items_size = 0;
+  int seen_items_offset = 0;
+  uschar itembuf[256];
+  uschar *dkim_canon_expanded;
+  uschar *dkim_sign_headers_expanded;
+  uschar *dkim_private_key_expanded;
+  off_t dkim_fd_start;
   pdkim_ctx *ctx = NULL;
-  uschar *rc = NULL;
+  int pdkim_fed;
+  uschar *rc = NULL, *tmprc;
   pdkim_signature *signature;
   int pdkim_canon;
   int pdkim_rc;
@@ -405,42 +415,56 @@
     rc = NULL;
     goto CLEANUP;
   }
-  /* Set up $dkim_domain expansion variable. */
-  dkim_signing_domain = dkim_domain;


-  /* Get selector to use. */
-  dkim_selector = expand_string(dkim_selector);
-  if (dkim_selector == NULL) {
+  dkim_fd_start=lseek(dkim_fd,0,SEEK_CUR);
+
+  /* Set $dkim_domain expansion variable to each unique domain in list. */
+  while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep,
+                                                  itembuf,
+                                                  sizeof(itembuf))) != NULL) {
+    if (dkim_signing_domain[0] == '\0') continue;
+    /* Only sign once for each domain, no matter how often it
+       appears in the expanded list. */
+    if (seen_items != NULL) {
+      uschar *seen_items_list = seen_items;
+      if (match_isinlist(dkim_signing_domain,
+                         &seen_items_list,0,NULL,NULL,MCL_STRING,TRUE,NULL) == OK)
+        continue;
+      seen_items = string_append(seen_items,&seen_items_size,&seen_items_offset,1,":");
+    }
+    seen_items = string_append(seen_items,&seen_items_size,&seen_items_offset,1,dkim_signing_domain);
+    seen_items[seen_items_offset] = '\0';
+
+  /* Set up $dkim_selector expansion variable. */
+  dkim_signing_selector = expand_string(dkim_selector);
+  if (dkim_signing_selector == NULL) {
     log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
       "dkim_selector: %s", expand_string_message);
     rc = NULL;
     goto CLEANUP;
   }
-  /* Set up $dkim_selector expansion variable. */
-  dkim_signing_selector = dkim_selector;


   /* Get canonicalization to use */
-  dkim_canon = expand_string(dkim_canon?dkim_canon:US"relaxed");
-  if (dkim_canon == NULL) {
+  dkim_canon_expanded = expand_string(dkim_canon?dkim_canon:US"relaxed");
+  if (dkim_canon_expanded == NULL) {
     /* expansion error, do not send message. */
     log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
           "dkim_canon: %s", expand_string_message);
     rc = NULL;
     goto CLEANUP;
   }
-  if (Ustrcmp(dkim_canon, "relaxed") == 0)
+  if (Ustrcmp(dkim_canon_expanded, "relaxed") == 0)
     pdkim_canon = PDKIM_CANON_RELAXED;
-  else if (Ustrcmp(dkim_canon, "simple") == 0)
+  else if (Ustrcmp(dkim_canon_expanded, "simple") == 0)
     pdkim_canon = PDKIM_CANON_SIMPLE;
   else {
-    log_write(0, LOG_MAIN, "DKIM: unknown canonicalization method '%s', defaulting to 'relaxed'.\n",dkim_canon);
+    log_write(0, LOG_MAIN, "DKIM: unknown canonicalization method '%s', defaulting to 'relaxed'.\n",dkim_canon_expanded);
     pdkim_canon = PDKIM_CANON_RELAXED;
   }


-  /* Expand signing headers once */
   if (dkim_sign_headers != NULL) {
-    dkim_sign_headers = expand_string(dkim_sign_headers);
-    if (dkim_sign_headers == NULL) {
+    dkim_sign_headers_expanded = expand_string(dkim_sign_headers);
+    if (dkim_sign_headers_expanded == NULL) {
       log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
         "dkim_sign_headers: %s", expand_string_message);
       rc = NULL;
@@ -449,47 +473,51 @@
   }


   /* Get private key to use. */
-  dkim_private_key = expand_string(dkim_private_key);
-  if (dkim_private_key == NULL) {
+  dkim_private_key_expanded = expand_string(dkim_private_key);
+  if (dkim_private_key_expanded == NULL) {
     log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
       "dkim_private_key: %s", expand_string_message);
     rc = NULL;
     goto CLEANUP;
   }
-  if ( (Ustrlen(dkim_private_key) == 0) ||
-       (Ustrcmp(dkim_private_key,"0") == 0) ||
-       (Ustrcmp(dkim_private_key,"false") == 0) ) {
-    /* don't sign, but no error */
-    rc = US"";
-    goto CLEANUP;
-  }
+  if ( Ustrlen(dkim_private_key_expanded) &&
+       (Ustrcmp(dkim_private_key_expanded,"0") != 0) &&
+       (Ustrcmp(dkim_private_key_expanded,"false") != 0) ) {


-  if (dkim_private_key[0] == '/') {
+  if (dkim_private_key_expanded[0] == '/') {
     int privkey_fd = 0;
     /* Looks like a filename, load the private key. */
     memset(big_buffer,0,big_buffer_size);
-    privkey_fd = open(CS dkim_private_key,O_RDONLY);
+    privkey_fd = open(CS dkim_private_key_expanded,O_RDONLY);
     if (privkey_fd < 0) {
+      save_errno = errno;
       log_write(0, LOG_MAIN|LOG_PANIC, "unable to open "
-        "private key file for reading: %s", dkim_private_key);
+        "private key file for reading: %s", dkim_private_key_expanded);
+      rc = NULL;
+      goto CLEANUP;
+    }
+    if (read(privkey_fd,big_buffer,(big_buffer_size-2))==-1) {
+      save_errno = errno;
+      log_write(0, LOG_MAIN|LOG_PANIC, "unable to read "
+        "private key file: %s", dkim_private_key_expanded);
+      (void)close(privkey_fd);
       rc = NULL;
       goto CLEANUP;
     }
-    (void)read(privkey_fd,big_buffer,(big_buffer_size-2));
     (void)close(privkey_fd);
-    dkim_private_key = big_buffer;
+    dkim_private_key_expanded = big_buffer;
   }


   ctx = pdkim_init_sign(PDKIM_INPUT_SMTP,
                         (char *)dkim_signing_domain,
                         (char *)dkim_signing_selector,
-                        (char *)dkim_private_key
+                        (char *)dkim_private_key_expanded
                        );


pdkim_set_debug_stream(ctx,debug_file);

   pdkim_set_optional(ctx,
-                     (char *)dkim_sign_headers,
+                     (char *)dkim_sign_headers_expanded,
                      NULL,
                      pdkim_canon,
                      pdkim_canon,
@@ -498,11 +526,14 @@
                      0,
                      0);


+  lseek(dkim_fd,dkim_fd_start,SEEK_SET);
+  pdkim_fed = 0;
   while((sread = read(dkim_fd,&buf,4096)) > 0) {
     if (pdkim_feed(ctx,buf,sread) != PDKIM_OK) {
       rc = NULL;
       goto CLEANUP;
     }
+    pdkim_fed = 1;
   }
   /* Handle failed read above. */
   if (sread == -1) {
@@ -511,6 +542,11 @@
     rc = NULL;
     goto CLEANUP;
   }
+  /* Somehow nothing was fed to pdkim, should not happen */
+  if (! pdkim_fed) {
+    rc = NULL;
+    goto CLEANUP;
+  }


   pdkim_rc = pdkim_feed_finish(ctx,&signature);
   if (pdkim_rc != PDKIM_OK) {
@@ -518,10 +554,22 @@
     goto CLEANUP;
   }


- rc = store_get(strlen(signature->signature_header)+3);
- Ustrcpy(rc,US signature->signature_header);
+ /* record signature header */
+ tmprc = store_get((rc ? Ustrlen(rc) : 0)+strlen(signature->signature_header)+3);
+ tmprc[0]='\0';
+ if (rc) Ustrcat(tmprc,rc);
+ rc = tmprc;
+ Ustrcat(rc,US signature->signature_header);
Ustrcat(rc,US"\r\n");

+  pdkim_free_ctx(ctx);
+  ctx = NULL;
+  }
+
+  }
+  /* not signed, but no error */
+  if (rc == NULL) rc=US "";
+
   CLEANUP:
   if (ctx != NULL) {
     pdkim_free_ctx(ctx);