[exim-cvs] cvs commit: exim/exim-src/src dkim.c

Page principale
Supprimer ce message
Répondre à ce message
Auteur: Michael Haardt
Date:  
À: exim-cvs
Sujet: [exim-cvs] cvs commit: exim/exim-src/src dkim.c
michael 2010/02/18 12:09:15 GMT

  Modified files:
    exim-src/src         dkim.c 
  Log:
  Treat the transport option dkim_domain as a colon separated list, not
  as a single string, and sign the message with each element, omitting
  multiple occurences of the same signer.


The transport option dkim_domain should be renamed to dkim_add_signers.
The values of dkim_selector and dkim_private_key are expanded for
each signer available in $dkim_domain. It is unclear if signatures
for domains that already signed the mail should be omitted and if we
need a new variable for signatures to omit or if it could be hardcoded,
but this question is independent of this patch.

  Revision  Changes    Path
  1.12      +120 -99   exim/exim-src/src/dkim.c


  Index: dkim.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/dkim.c,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- dkim.c    15 Dec 2009 08:23:15 -0000    1.11
  +++ dkim.c    18 Feb 2010 12:09:15 -0000    1.12
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/dkim.c,v 1.11 2009/12/15 08:23:15 tom Exp $ */
  +/* $Cambridge: exim/exim-src/src/dkim.c,v 1.12 2010/02/18 12:09:15 michael Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -387,6 +387,14 @@
                          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;
     pdkim_ctx *ctx = NULL;
     uschar *rc = NULL;
     pdkim_signature *signature;
  @@ -405,127 +413,140 @@
       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) {
  -    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;
  +  /* 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 || (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';


  -  /* Get canonicalization to use */
  -  dkim_canon = expand_string(dkim_canon?dkim_canon:US"relaxed");
  -  if (dkim_canon == 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)
  -    pdkim_canon = PDKIM_CANON_RELAXED;
  -  else if (Ustrcmp(dkim_canon, "simple") == 0)
  -    pdkim_canon = PDKIM_CANON_SIMPLE;
  -  else {
  -    log_write(0, LOG_MAIN, "DKIM: unknown canonicalization method '%s', defaulting to 'relaxed'.\n",dkim_canon);
  -    pdkim_canon = PDKIM_CANON_RELAXED;
  -  }
  +    /* 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;
  +    }


  -  /* Expand signing headers once */
  -  if (dkim_sign_headers != NULL) {
  -    dkim_sign_headers = expand_string(dkim_sign_headers);
  -    if (dkim_sign_headers == NULL) {
  +    /* Get canonicalization to use */
  +    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_sign_headers: %s", expand_string_message);
  +                "dkim_canon: %s", expand_string_message);
         rc = NULL;
         goto CLEANUP;
       }
  -  }
  +    if (Ustrcmp(dkim_canon_expanded, "relaxed") == 0)
  +      pdkim_canon = PDKIM_CANON_RELAXED;
  +    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_expanded);
  +      pdkim_canon = PDKIM_CANON_RELAXED;
  +    }


  -  /* Get private key to use. */
  -  dkim_private_key = expand_string(dkim_private_key);
  -  if (dkim_private_key == 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;
  -  }
  +    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;
  +      goto CLEANUP;
  +    }


  -  if (dkim_private_key[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);
  -    if (privkey_fd < 0) {
  -      log_write(0, LOG_MAIN|LOG_PANIC, "unable to open "
  -        "private key file for reading: %s", dkim_private_key);
  +    /* Get private key to use. */
  +    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;
       }
  -    (void)read(privkey_fd,big_buffer,(big_buffer_size-2));
  -    (void)close(privkey_fd);
  -    dkim_private_key = big_buffer;
  -  }
  +    if ( (Ustrlen(dkim_private_key_expanded) == 0) ||
  +         (Ustrcmp(dkim_private_key_expanded,"0") == 0) ||
  +         (Ustrcmp(dkim_private_key_expanded,"false") == 0) ) {
  +      /* don't sign, but no error */
  +      rc = US"";
  +      goto CLEANUP;
  +    }


  -  ctx = pdkim_init_sign(PDKIM_INPUT_SMTP,
  -                        (char *)dkim_signing_domain,
  -                        (char *)dkim_signing_selector,
  -                        (char *)dkim_private_key
  -                       );
  -
  -  pdkim_set_debug_stream(ctx,debug_file);
  -
  -  pdkim_set_optional(ctx,
  -                     (char *)dkim_sign_headers,
  -                     NULL,
  -                     pdkim_canon,
  -                     pdkim_canon,
  -                     -1,
  -                     PDKIM_ALGO_RSA_SHA256,
  -                     0,
  -                     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_expanded,O_RDONLY);
  +      if (privkey_fd < 0) {
  +        log_write(0, LOG_MAIN|LOG_PANIC, "unable to open "
  +                  "private key file for reading: %s", dkim_private_key_expanded);
  +        rc = NULL;
  +        goto CLEANUP;
  +      }
  +      (void)read(privkey_fd,big_buffer,(big_buffer_size-2));
  +      (void)close(privkey_fd);
  +      dkim_private_key_expanded = big_buffer;
  +    }


  -  while((sread = read(dkim_fd,&buf,4096)) > 0) {
  -    if (pdkim_feed(ctx,buf,sread) != PDKIM_OK) {
  +    ctx = pdkim_init_sign(PDKIM_INPUT_SMTP,
  +                          (char *)dkim_signing_domain,
  +                          (char *)dkim_signing_selector,
  +                          (char *)dkim_private_key_expanded
  +                         );
  +
  +    pdkim_set_debug_stream(ctx,debug_file);
  +
  +    pdkim_set_optional(ctx,
  +                       (char *)dkim_sign_headers_expanded,
  +                       NULL,
  +                       pdkim_canon,
  +                       pdkim_canon,
  +                       -1,
  +                       PDKIM_ALGO_RSA_SHA256,
  +                       0,
  +                       0);
  +
  +    while((sread = read(dkim_fd,&buf,4096)) > 0) {
  +      if (pdkim_feed(ctx,buf,sread) != PDKIM_OK) {
  +        rc = NULL;
  +        goto CLEANUP;
  +      }
  +    }
  +    /* Handle failed read above. */
  +    if (sread == -1) {
  +      debug_printf("DKIM: Error reading -K file.\n");
  +      save_errno = errno;
         rc = NULL;
         goto CLEANUP;
       }
  -  }
  -  /* Handle failed read above. */
  -  if (sread == -1) {
  -    debug_printf("DKIM: Error reading -K file.\n");
  -    save_errno = errno;
  -    rc = NULL;
  -    goto CLEANUP;
  -  }


  -  pdkim_rc = pdkim_feed_finish(ctx,&signature);
  -  if (pdkim_rc != PDKIM_OK) {
  -    log_write(0, LOG_MAIN|LOG_PANIC, "DKIM: signing failed (RC %d)", pdkim_rc);
  -    goto CLEANUP;
  -  }
  +    pdkim_rc = pdkim_feed_finish(ctx,&signature);
  +    if (pdkim_rc != PDKIM_OK) {
  +      log_write(0, LOG_MAIN|LOG_PANIC, "DKIM: signing failed (RC %d)", pdkim_rc);
  +      goto CLEANUP;
  +    }


  -  rc = store_get(strlen(signature->signature_header)+3);
  -  Ustrcpy(rc,US signature->signature_header);
  -  Ustrcat(rc,US"\r\n");
  +    rc = store_get(strlen(signature->signature_header)+3);
  +    Ustrcpy(rc,US signature->signature_header);
  +    Ustrcat(rc,US"\r\n");


  -  CLEANUP:
  -  if (ctx != NULL) {
       pdkim_free_ctx(ctx);
  +    ctx = NULL;
     }
  +
  +  CLEANUP:
  +  if (ctx != NULL)
  +    pdkim_free_ctx(ctx);
     store_pool = old_pool;
     errno = save_errno;
     return rc;