diff options
author | Tom Kistner <tom@duncanthrax.net> | 2009-05-20 14:30:14 +0000 |
---|---|---|
committer | Tom Kistner <tom@duncanthrax.net> | 2009-05-20 14:30:14 +0000 |
commit | 63b24494e1c7f0c81483b3726b7a0349d2957475 (patch) | |
tree | 247b334a6fbc41199d092869db7b90d8d78a5b46 | |
parent | 1a23c1528c63784b6fa5ff653e60c46f377cc5da (diff) | |
download | exim4-63b24494e1c7f0c81483b3726b7a0349d2957475.tar.gz |
More DKIM wip. I now have a plan, and we are slowly getting there ...
-rw-r--r-- | src/src/acl.c | 10 | ||||
-rw-r--r-- | src/src/dkim.c | 57 | ||||
-rw-r--r-- | src/src/dkim.h | 14 | ||||
-rw-r--r-- | src/src/globals.c | 7 | ||||
-rw-r--r-- | src/src/globals.h | 7 | ||||
-rw-r--r-- | src/src/pdkim/pdkim.c | 90 | ||||
-rw-r--r-- | src/src/pdkim/pdkim.h | 4 | ||||
-rw-r--r-- | src/src/readconf.c | 5 | ||||
-rw-r--r-- | src/src/receive.c | 8 | ||||
-rw-r--r-- | src/src/smtp_in.c | 8 | ||||
-rw-r--r-- | src/src/spool_in.c | 6 | ||||
-rw-r--r-- | src/src/tls-gnu.c | 4 | ||||
-rw-r--r-- | src/src/tls-openssl.c | 4 |
13 files changed, 135 insertions, 89 deletions
diff --git a/src/src/acl.c b/src/src/acl.c index 5eeabe8b8..fece68be7 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/acl.c,v 1.82.2.1 2009/02/24 15:57:55 tom Exp $ */ +/* $Cambridge: exim/src/src/acl.c,v 1.82.2.2 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -197,7 +197,7 @@ static uschar *controls[] = { US"bmi_run", #endif #ifndef DISABLE_DKIM - US"dkim_verify", + US"dkim_disable_verify", #endif US"error", US"caseful_local_part", @@ -493,7 +493,7 @@ static unsigned int control_forbids[] = { #endif #ifndef DISABLE_DKIM - (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)| /* dkim_verify */ + (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)| /* dkim_disable_verify */ (1<<ACL_WHERE_NOTSMTP_START), #endif @@ -574,7 +574,7 @@ static control_def controls_list[] = { { US"bmi_run", CONTROL_BMI_RUN, FALSE }, #endif #ifndef DISABLE_DKIM - { US"dkim_verify", CONTROL_DKIM_VERIFY, FALSE }, + { US"dkim_disable_verify", CONTROL_DKIM_VERIFY, FALSE }, #endif { US"caseful_local_part", CONTROL_CASEFUL_LOCAL_PART, FALSE }, { US"caselower_local_part", CONTROL_CASELOWER_LOCAL_PART, FALSE }, @@ -2556,7 +2556,7 @@ for (; cb != NULL; cb = cb->next) #ifndef DISABLE_DKIM case CONTROL_DKIM_VERIFY: - dkim_do_verify = 1; + dkim_disable_verify = TRUE; break; #endif diff --git a/src/src/dkim.c b/src/src/dkim.c index dd8334b63..86ca50be8 100644 --- a/src/src/dkim.c +++ b/src/src/dkim.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/dkim.c,v 1.1.2.11 2009/05/19 09:49:14 tom Exp $ */ +/* $Cambridge: exim/src/src/dkim.c,v 1.1.2.12 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -24,7 +24,7 @@ int dkim_exim_query_dns_txt(char *name, char *answer) { dns_scan dnss; dns_record *rr; - if (dns_lookup(&dnsa, (uschar *)name, T_TXT, NULL) != DNS_SUCCEED) return 1; + if (dns_lookup(&dnsa, (uschar *)name, T_TXT, NULL) != DNS_SUCCEED) return PDKIM_FAIL; /* Search for TXT record */ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); @@ -45,13 +45,13 @@ int dkim_exim_query_dns_txt(char *name, char *answer) { answer_offset+=len; } } - else return 1; + else return PDKIM_FAIL; return PDKIM_OK; } -int dkim_exim_verify_init(void) { +void dkim_exim_verify_init(void) { /* Free previous context if there is one */ if (dkim_verify_ctx) pdkim_free_ctx(dkim_verify_ctx); @@ -62,37 +62,47 @@ int dkim_exim_verify_init(void) { ); if (dkim_verify_ctx != NULL) { - dkim_collect_input = 1; + dkim_collect_input = TRUE; pdkim_set_debug_stream(dkim_verify_ctx,debug_file); - return 1; - } - else { - dkim_collect_input = 0; - return 0; } + else dkim_collect_input = FALSE; + } -int dkim_exim_verify_feed(uschar *data, int len) { - if (pdkim_feed(dkim_verify_ctx, +void dkim_exim_verify_feed(uschar *data, int len) { + if (dkim_collect_input && + pdkim_feed(dkim_verify_ctx, (char *)data, - len) != PDKIM_OK) return 0; - return 1; + len) != PDKIM_OK) dkim_collect_input = FALSE; } -int dkim_exim_verify_finish(void) { +void dkim_exim_verify_finish(void) { + + /* Delete eventual previous signature chain */ dkim_signatures = NULL; - dkim_collect_input = 0; - if (pdkim_feed_finish(dkim_verify_ctx,&dkim_signatures) != PDKIM_OK) return 0; + /* If we have arrived here with dkim_collect_input == FALSE, it + means there was a processing error somewhere along the way. + Log the incident and disable futher verification. */ + if (!dkim_collect_input) { + log_write(0, LOG_MAIN|LOG_PANIC, "DKIM: Error while running this message through validation, disabling signature verification."); + dkim_disable_verify = TRUE; + return; + } + dkim_collect_input = FALSE; + + /* Finish DKIM operation and fetch link to signatures chain */ + if (pdkim_feed_finish(dkim_verify_ctx,&dkim_signatures) != PDKIM_OK) return; + + /* Log a line for each signature */ while (dkim_signatures != NULL) { int size = 0; int ptr = 0; uschar *logmsg = string_append(NULL, &size, &ptr, 5, - string_sprintf( "DKIM: v=%u d=%s s=%s c=%s/%s a=%s ", - dkim_signatures->version, + string_sprintf( "DKIM: d=%s s=%s c=%s/%s a=%s ", dkim_signatures->domain, dkim_signatures->selector, (dkim_signatures->canon_headers == PDKIM_CANON_SIMPLE)?"simple":"relaxed", @@ -163,21 +173,16 @@ int dkim_exim_verify_finish(void) { logmsg[ptr] = '\0'; log_write(0, LOG_MAIN, (char *)logmsg); - /* Try next signature */ + /* Log next signature */ dkim_signatures = dkim_signatures->next; } - - return dkim_signatures?1:0; } -int dkim_exim_verify_result(uschar *domain, uschar **result, uschar **error) { - +void dkim_exim_verify_result(uschar *domain, uschar **result, uschar **error) { if (dkim_verify_ctx) { } - - return OK; } diff --git a/src/src/dkim.h b/src/src/dkim.h index a6ccd8d0f..c9c602fa6 100644 --- a/src/src/dkim.h +++ b/src/src/dkim.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/dkim.h,v 1.1.2.3 2009/04/09 13:57:21 tom Exp $ */ +/* $Cambridge: exim/src/src/dkim.h,v 1.1.2.4 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -14,9 +14,9 @@ uschar *dkim_exim_sign(int, uschar *, uschar *); -int dkim_exim_verify_init(void); -int dkim_exim_verify_feed(uschar *, int); -int dkim_exim_verify_finish(void); -int dkim_exim_verify_result(uschar *, - uschar **, - uschar **); +void dkim_exim_verify_init(void); +void dkim_exim_verify_feed(uschar *, int); +void dkim_exim_verify_finish(void); +void dkim_exim_verify_result(uschar *, + uschar **, + uschar **); diff --git a/src/src/globals.c b/src/src/globals.c index cfedc22d9..e596afb2b 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.c,v 1.81.2.3 2009/04/09 14:00:51 tom Exp $ */ +/* $Cambridge: exim/src/src/globals.c,v 1.81.2.4 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -529,8 +529,9 @@ BOOL disable_logging = FALSE; #ifndef DISABLE_DKIM uschar *dkim_signing_domain = NULL; uschar *dkim_signing_selector = NULL; -int dkim_do_verify = 0; -int dkim_collect_input = 0; +uschar *dkim_verify_domains = US"@dkim_signed"; +BOOL dkim_collect_input = FALSE; +BOOL dkim_disable_verify = FALSE; #endif uschar *dns_again_means_nonexist = NULL; diff --git a/src/src/globals.h b/src/src/globals.h index c8bad00f8..4c1e0b66e 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.h,v 1.62.2.2 2009/04/09 13:57:21 tom Exp $ */ +/* $Cambridge: exim/src/src/globals.h,v 1.62.2.3 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -298,8 +298,9 @@ extern BOOL disable_logging; /* Disables log writing when TRUE */ #ifndef DISABLE_DKIM extern uschar *dkim_signing_domain; /* Domain used for signing a message. */ extern uschar *dkim_signing_selector; /* Selector used for signing a message. */ -extern int dkim_do_verify; /* DKIM verification switch. Set with ACL control statement. */ -extern int dkim_collect_input; /* Set during message reception, when SMTP input is to be fed to the validator. */ +extern uschar *dkim_verify_domains; /* Colon-separated list of domains for each of which we call the DKIM ACL */ +extern BOOL dkim_collect_input; /* Runtime flag that tracks wether SMTP input is fed to DKIM validation */ +extern BOOL dkim_disable_verify; /* Set via ACL control statement. When set, DKIM verification is disabled for the current message */ #endif extern uschar *dns_again_means_nonexist; /* Domains that are badly set up */ diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index 51e01f7f5..6c6cbf108 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -20,7 +20,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* $Cambridge: exim/src/src/pdkim/pdkim.c,v 1.1.2.15 2009/05/19 09:49:14 tom Exp $ */ +/* $Cambridge: exim/src/src/pdkim/pdkim.c,v 1.1.2.16 2009/05/20 14:30:15 tom Exp $ */ #include <stdlib.h> #include <stdio.h> @@ -1286,7 +1286,6 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu while (sig != NULL) { sha1_context sha1_headers; sha2_context sha2_headers; - pdkim_stringlist *p = sig->headers; char *sig_hdr; char headerhash[32]; @@ -1301,37 +1300,77 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n"); #endif - while (p != NULL) { - char *rh; - - /* SIGNING -------------------------------------------------------------- */ - if (ctx->mode == PDKIM_MODE_SIGN) { + /* SIGNING ---------------------------------------------------------------- */ + /* When signing, walk through our header list and add them to the hash. As we + go, construct a list of the header's names to use for the h= parameter. */ + if (ctx->mode == PDKIM_MODE_SIGN) { + pdkim_stringlist *p = sig->headers; + while (p != NULL) { + char *rh = NULL; /* Collect header names (Note: colon presence is guaranteed here) */ char *q = strchr(p->value,':'); if (pdkim_strncat(headernames, p->value, (q-(p->value))+((p->next==NULL)?0:1)) == NULL) return PDKIM_ERR_OOM; - } - /* ---------------------------------------------------------------------- */ - if (sig->canon_headers == PDKIM_CANON_RELAXED) - rh = pdkim_relax_header(p->value,1); /* cook header for relaxed canon */ - else - rh = strdup(p->value); /* just copy it for simple canon */ + if (sig->canon_headers == PDKIM_CANON_RELAXED) + rh = pdkim_relax_header(p->value,1); /* cook header for relaxed canon */ + else + rh = strdup(p->value); /* just copy it for simple canon */ - if (rh == NULL) return PDKIM_ERR_OOM; + if (rh == NULL) return PDKIM_ERR_OOM; - /* Feed header to the hash algorithm */ - if (sig->algo == PDKIM_ALGO_RSA_SHA1) - sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh)); - else - sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh)); - #ifdef PDKIM_DEBUG - if (ctx->debug_stream) - pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1); - #endif - free(rh); - p = p->next; + /* Feed header to the hash algorithm */ + if (sig->algo == PDKIM_ALGO_RSA_SHA1) + sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh)); + else + sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh)); + #ifdef PDKIM_DEBUG + if (ctx->debug_stream) + pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1); + #endif + free(rh); + p = p->next; + } + } + /* VERIFICATION ----------------------------------------------------------- */ + /* When verifying, walk through the header name list in the h= parameter and + add the headers to the hash in that order. */ + else { + char *b = strdup(sig->headernames); + char *p = b; + char *q = NULL; + if (b == NULL) return PDKIM_ERR_OOM; + + while(1) { + pdkim_stringlist *hdrs = sig->headers; + q = strchr(p,':'); + if (q != NULL) *q = '\0'; + while (hdrs != NULL) { + if (strncasecmp(hdrs->value,p,strlen(p)) == 0) { + char *rh = NULL; + if (sig->canon_headers == PDKIM_CANON_RELAXED) + rh = pdkim_relax_header(hdrs->value,1); /* cook header for relaxed canon */ + else + rh = strdup(hdrs->value); /* just copy it for simple canon */ + if (rh == NULL) return PDKIM_ERR_OOM; + /* Feed header to the hash algorithm */ + if (sig->algo == PDKIM_ALGO_RSA_SHA1) + sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh)); + else + sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh)); + #ifdef PDKIM_DEBUG + if (ctx->debug_stream) + pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1); + #endif + free(rh); + } + hdrs = hdrs->next; + } + if (q == NULL) break; + p = q+1; + } + free(b); } #ifdef PDKIM_DEBUG @@ -1340,7 +1379,6 @@ DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatu "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); #endif - /* SIGNING ---------------------------------------------------------------- */ if (ctx->mode == PDKIM_MODE_SIGN) { /* Copy headernames to signature struct */ diff --git a/src/src/pdkim/pdkim.h b/src/src/pdkim/pdkim.h index 0e884dde2..8e55c246f 100644 --- a/src/src/pdkim/pdkim.h +++ b/src/src/pdkim/pdkim.h @@ -20,7 +20,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* $Cambridge: exim/src/src/pdkim/pdkim.h,v 1.1.2.11 2009/04/30 15:25:39 tom Exp $ */ +/* $Cambridge: exim/src/src/pdkim/pdkim.h,v 1.1.2.12 2009/05/20 14:30:15 tom Exp $ */ /* -------------------------------------------------------------------------- */ /* Debugging. This can also be enabled/disabled at run-time. I recommend to @@ -242,7 +242,7 @@ typedef struct pdkim_signature { /* Verification specific -------------------------------------------- */ char *hnames_check; /* Tick-off header list that we use to keep track of header names that we have already - added to the signature */ + added to the signature candidates. */ char *rawsig_no_b_val; /* Original signature header w/o b= tag value. */ } pdkim_signature; diff --git a/src/src/readconf.c b/src/src/readconf.c index 2e65cd970..672b19763 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/readconf.c,v 1.35 2008/02/12 12:52:51 nm4 Exp $ */ +/* $Cambridge: exim/src/src/readconf.c,v 1.35.2.1 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -205,6 +205,9 @@ static optionlist optionlist_config[] = { { "disable_fsync", opt_bool, &disable_fsync }, #endif { "disable_ipv6", opt_bool, &disable_ipv6 }, +#ifndef DISABLE_DKIM + { "dkim_verify_domains", opt_stringptr, &dkim_verify_domains }, +#endif { "dns_again_means_nonexist", opt_stringptr, &dns_again_means_nonexist }, { "dns_check_names_pattern", opt_stringptr, &check_dns_names_pattern }, { "dns_csa_search_limit", opt_int, &dns_csa_search_limit }, diff --git a/src/src/receive.c b/src/src/receive.c index 82e64a28a..dba469cbc 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/receive.c,v 1.45.2.2 2009/04/09 13:57:21 tom Exp $ */ +/* $Cambridge: exim/src/src/receive.c,v 1.45.2.3 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -1386,11 +1386,9 @@ message_linecount = body_linecount = body_zerocount = #ifndef DISABLE_DKIM /* Call into DKIM to set up the context. */ -if (smtp_input && dkim_do_verify) dkim_do_verify = dkim_exim_verify_init(); -else dkim_do_verify = 0; +if (smtp_input && !smtp_batched_input && !dkim_disable_verify) dkim_exim_verify_init(); #endif - /* Remember the time of reception. Exim uses time+pid for uniqueness of message ids, and fractions of a second are required. See the comments that precede the message id creation below. */ @@ -2971,7 +2969,7 @@ else { #ifndef DISABLE_DKIM - if (dkim_do_verify) dkim_do_verify = dkim_exim_verify_finish(); + if (!dkim_disable_verify) dkim_exim_verify_finish(); #endif #ifdef WITH_CONTENT_SCAN diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index f30daf91c..0a5ae629a 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/smtp_in.c,v 1.63.2.2 2009/04/09 13:57:21 tom Exp $ */ +/* $Cambridge: exim/src/src/smtp_in.c,v 1.63.2.3 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -265,7 +265,7 @@ if (smtp_inptr >= smtp_inend) return EOF; } #ifndef DISABLE_DKIM - if (dkim_collect_input) dkim_collect_input = dkim_exim_verify_feed(smtp_inbuffer, rc); + dkim_exim_verify_feed(smtp_inbuffer, rc); #endif smtp_inend = smtp_inbuffer + rc; smtp_inptr = smtp_inbuffer; @@ -1041,8 +1041,8 @@ bmi_run = 0; bmi_verdicts = NULL; #endif #ifndef DISABLE_DKIM -dkim_do_verify = 0; -dkim_collect_input = 0; +dkim_disable_verify = FALSE; +dkim_collect_input = FALSE; #endif #ifdef EXPERIMENTAL_SPF spf_header_comment = NULL; diff --git a/src/src/spool_in.c b/src/src/spool_in.c index b8c427511..710119543 100644 --- a/src/src/spool_in.c +++ b/src/src/spool_in.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/spool_in.c,v 1.23.2.2 2009/04/09 13:57:21 tom Exp $ */ +/* $Cambridge: exim/src/src/spool_in.c,v 1.23.2.3 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -279,8 +279,8 @@ bmi_verdicts = NULL; #endif #ifndef DISABLE_DKIM -dkim_do_verify = 0; -dkim_collect_input = 0; +dkim_disable_verify = FALSE; +dkim_collect_input = FALSE; #endif #ifdef SUPPORT_TLS diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 566d73922..b76cc5c90 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/tls-gnu.c,v 1.20.2.1 2009/04/09 13:57:21 tom Exp $ */ +/* $Cambridge: exim/src/src/tls-gnu.c,v 1.20.2.2 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -1173,7 +1173,7 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm) return EOF; } #ifndef DISABLE_DKIM - if (dkim_collect_input) dkim_collect_input = dkim_exim_verify_feed(ssl_xfer_buffer, inbytes); + dkim_exim_verify_feed(ssl_xfer_buffer, inbytes); #endif ssl_xfer_buffer_hwm = inbytes; ssl_xfer_buffer_lwm = 0; diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index c07ef10d0..68540ac5f 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/tls-openssl.c,v 1.13.2.1 2009/04/09 13:57:21 tom Exp $ */ +/* $Cambridge: exim/src/src/tls-openssl.c,v 1.13.2.2 2009/05/20 14:30:14 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -888,7 +888,7 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm) return EOF; } #ifndef DISABLE_DKIM - if (dkim_collect_input) dkim_collect_input = dkim_exim_verify_feed(ssl_xfer_buffer, inbytes); + dkim_exim_verify_feed(ssl_xfer_buffer, inbytes); #endif ssl_xfer_buffer_hwm = inbytes; ssl_xfer_buffer_lwm = 0; |