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);