From: Tom Kistner Date: Mon, 8 Jun 2009 21:06:31 +0000 (+0000) Subject: Add a bunch of expandables and some DKIM ACL red tape X-Git-Url: https://git.exim.org/users/jgh/exim.git/commitdiff_plain/bb1d997d783b6ffc13bec6d85462366d979a4c70 Add a bunch of expandables and some DKIM ACL red tape --- diff --git a/src/src/dkim.c b/src/src/dkim.c index f0805ac42..a2beafd6c 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.14 2009/05/27 17:29:35 tom Exp $ */ +/* $Cambridge: exim/src/src/dkim.c,v 1.1.2.15 2009/06/08 21:06:31 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -18,6 +18,7 @@ pdkim_ctx *dkim_verify_ctx = NULL; pdkim_signature *dkim_signatures = NULL; +pdkim_signature *dkim_cur_sig = NULL; int dkim_exim_query_dns_txt(char *name, char *answer) { dns_answer dnsa; @@ -79,6 +80,7 @@ void dkim_exim_verify_feed(uschar *data, int len) { void dkim_exim_verify_finish(void) { + pdkim_signature *sig = NULL; int dkim_signing_domains_size = 0; int dkim_signing_domains_ptr = 0; dkim_signing_domains = NULL; @@ -99,49 +101,49 @@ void dkim_exim_verify_finish(void) { /* Finish DKIM operation and fetch link to signatures chain */ if (pdkim_feed_finish(dkim_verify_ctx,&dkim_signatures) != PDKIM_OK) return; - - while (dkim_signatures != NULL) { + sig = dkim_signatures; + while (sig != NULL) { int size = 0; int ptr = 0; /* Log a line for each signature */ uschar *logmsg = string_append(NULL, &size, &ptr, 5, 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", - (dkim_signatures->canon_body == PDKIM_CANON_SIMPLE)?"simple":"relaxed", - (dkim_signatures->algo == PDKIM_ALGO_RSA_SHA256)?"rsa-sha256":"rsa-sha1" + sig->domain, + sig->selector, + (sig->canon_headers == PDKIM_CANON_SIMPLE)?"simple":"relaxed", + (sig->canon_body == PDKIM_CANON_SIMPLE)?"simple":"relaxed", + (sig->algo == PDKIM_ALGO_RSA_SHA256)?"rsa-sha256":"rsa-sha1" ), - ((dkim_signatures->identity != NULL)? - string_sprintf("i=%s ", dkim_signatures->identity) + ((sig->identity != NULL)? + string_sprintf("i=%s ", sig->identity) : US"" ), - ((dkim_signatures->created > 0)? - string_sprintf("t=%lu ", dkim_signatures->created) + ((sig->created > 0)? + string_sprintf("t=%lu ", sig->created) : US"" ), - ((dkim_signatures->expires > 0)? - string_sprintf("x=%lu ", dkim_signatures->expires) + ((sig->expires > 0)? + string_sprintf("x=%lu ", sig->expires) : US"" ), - ((dkim_signatures->bodylength > -1)? - string_sprintf("l=%lu ", dkim_signatures->bodylength) + ((sig->bodylength > -1)? + string_sprintf("l=%lu ", sig->bodylength) : US"" ) ); - switch(dkim_signatures->verify_status) { + switch(sig->verify_status) { case PDKIM_VERIFY_NONE: logmsg = string_append(logmsg, &size, &ptr, 1, "[not verified]"); break; case PDKIM_VERIFY_INVALID: logmsg = string_append(logmsg, &size, &ptr, 1, "[invalid - "); - switch (dkim_signatures->verify_ext_status) { + switch (sig->verify_ext_status) { case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: logmsg = string_append(logmsg, &size, &ptr, 1, "public key record (currently?) unavailable]"); break; @@ -157,7 +159,7 @@ void dkim_exim_verify_finish(void) { break; case PDKIM_VERIFY_FAIL: logmsg = string_append(logmsg, &size, &ptr, 1, "[verification failed - "); - switch (dkim_signatures->verify_ext_status) { + switch (sig->verify_ext_status) { case PDKIM_VERIFY_FAIL_BODY: logmsg = string_append(logmsg, &size, &ptr, 1, "body hash mismatch (body probably modified in transit)]"); break; @@ -181,12 +183,12 @@ void dkim_exim_verify_finish(void) { &dkim_signing_domains_size, &dkim_signing_domains_ptr, 2, - dkim_signatures->domain, + sig->domain, ":" ); /* Process next signature */ - dkim_signatures = dkim_signatures->next; + sig = sig->next; } /* Chop the last colon from the domain list */ @@ -196,9 +198,161 @@ void dkim_exim_verify_finish(void) { } -void dkim_exim_verify_result(uschar *domain, uschar **result, uschar **error) { - if (dkim_verify_ctx) { +void dkim_exim_acl_setup(uschar *id) { + pdkim_signature *sig = dkim_signatures; + dkim_cur_sig = NULL; + if (dkim_disable_verify || + !id || !sig || + !dkim_verify_ctx) return; + /* Find signature to run ACL on */ + while (sig != NULL) { + uschar *cmp_val = NULL; + if (Ustrchr(id,'@') != NULL) cmp_val = (uschar *)sig->identity; + else cmp_val = (uschar *)sig->domain; + if (cmp_val && (strcmpic(cmp_val,id) == 0)) { + dkim_cur_sig = sig; + /* The "dkim_domain" and "dkim_selector" expansion variables have + related globals, since they are used in the signing code too. + Instead of inventing separate names for verification, we set + them here. This is easy since a domain and selector is guaranteed + to be in a signature. The other dkim_* expansion items are + dynamically fetched from dkim_cur_sig at expansion time (see + function below). */ + dkim_signing_domain = (uschar *)sig->domain; + dkim_signing_selector = (uschar *)sig->selector; + return; + } + sig = sig->next; + } +} + + +uschar *dkim_exim_expand_query(int what) { + + if (!dkim_verify_ctx || + dkim_disable_verify || + !dkim_cur_sig) return dkim_exim_expand_defaults(what); + + switch(what) { + case DKIM_ALGO: + return dkim_cur_sig->algo? + (uschar *)(dkim_cur_sig->algo) + :dkim_exim_expand_defaults(what); + case DKIM_BODYLENGTH: + return (dkim_cur_sig->bodylength >= 0)? + (uschar *)string_sprintf(OFF_T_FMT,(LONGLONG_T)dkim_cur_sig->bodylength) + :dkim_exim_expand_defaults(what); + case DKIM_CANON_BODY: + return dkim_cur_sig->canon_body? + (uschar *)(dkim_cur_sig->canon_body) + :dkim_exim_expand_defaults(what); + case DKIM_CANON_HEADERS: + return dkim_cur_sig->canon_headers? + (uschar *)(dkim_cur_sig->canon_headers) + :dkim_exim_expand_defaults(what); + case DKIM_COPIEDHEADERS: + return dkim_cur_sig->copiedheaders? + (uschar *)(dkim_cur_sig->copiedheaders) + :dkim_exim_expand_defaults(what); + case DKIM_CREATED: + return (dkim_cur_sig->created > 0)? + (uschar *)string_sprintf("%llu",dkim_cur_sig->created) + :dkim_exim_expand_defaults(what); + case DKIM_EXPIRES: + return (dkim_cur_sig->expires > 0)? + (uschar *)string_sprintf("%llu",dkim_cur_sig->expires) + :dkim_exim_expand_defaults(what); + case DKIM_HEADERNAMES: + return dkim_cur_sig->headernames? + (uschar *)(dkim_cur_sig->headernames) + :dkim_exim_expand_defaults(what); + case DKIM_IDENTITY: + return dkim_cur_sig->identity? + (uschar *)(dkim_cur_sig->identity) + :dkim_exim_expand_defaults(what); + case DKIM_KEY_GRANULARITY: + return dkim_cur_sig->pubkey? + (dkim_cur_sig->pubkey->granularity? + (uschar *)(dkim_cur_sig->pubkey->granularity) + :dkim_exim_expand_defaults(what) + ) + :dkim_exim_expand_defaults(what); + case DKIM_KEY_SRVTYPE: + return dkim_cur_sig->pubkey? + (dkim_cur_sig->pubkey->srvtype? + (uschar *)(dkim_cur_sig->pubkey->srvtype) + :dkim_exim_expand_defaults(what) + ) + :dkim_exim_expand_defaults(what); + case DKIM_KEY_NOTES: + return dkim_cur_sig->pubkey? + (dkim_cur_sig->pubkey->notes? + (uschar *)(dkim_cur_sig->pubkey->notes) + :dkim_exim_expand_defaults(what) + ) + :dkim_exim_expand_defaults(what); + case DKIM_KEY_TESTING: + return dkim_cur_sig->pubkey? + (dkim_cur_sig->pubkey->testing? + US"1" + :dkim_exim_expand_defaults(what) + ) + :dkim_exim_expand_defaults(what); + case DKIM_NOSUBDOMAINS: + return dkim_cur_sig->pubkey? + (dkim_cur_sig->pubkey->no_subdomaining? + US"1" + :dkim_exim_expand_defaults(what) + ) + :dkim_exim_expand_defaults(what); + case DKIM_VERIFY_STATUS: + switch(dkim_cur_sig->verify_status) { + case PDKIM_VERIFY_INVALID: + return US"invalid"; + case PDKIM_VERIFY_FAIL: + return US"fail"; + case PDKIM_VERIFY_PASS: + return US"pass"; + case PDKIM_VERIFY_NONE: + default: + return US"none"; + } + case DKIM_VERIFY_REASON: + switch (dkim_cur_sig->verify_ext_status) { + case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: + return US"pubkey_unavailable"; + case PDKIM_VERIFY_INVALID_PUBKEY_PARSING: + return US"pubkey_syntax"; + case PDKIM_VERIFY_FAIL_BODY: + return US"bodyhash_mismatch"; + case PDKIM_VERIFY_FAIL_MESSAGE: + return US"signature_incorrect"; + } + default: + return US""; + } +} + +uschar *dkim_exim_expand_defaults(int what) { + switch(what) { + case DKIM_ALGO: return US""; + case DKIM_BODYLENGTH: return US"9999999999999"; + case DKIM_CANON_BODY: return US""; + case DKIM_CANON_HEADERS: return US""; + case DKIM_COPIEDHEADERS: return US""; + case DKIM_CREATED: return US"0"; + case DKIM_EXPIRES: return US"9999999999999"; + case DKIM_HEADERNAMES: return US""; + case DKIM_IDENTITY: return US""; + case DKIM_KEY_GRANULARITY: return US"*"; + case DKIM_KEY_SRVTYPE: return US"*"; + case DKIM_KEY_NOTES: return US""; + case DKIM_KEY_TESTING: return US"0"; + case DKIM_NOSUBDOMAINS: return US"0"; + case DKIM_VERIFY_STATUS: return US"none"; + case DKIM_VERIFY_REASON: return US""; + default: return US""; } } diff --git a/src/src/dkim.h b/src/src/dkim.h index c9c602fa6..f683914d5 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.4 2009/05/20 14:30:14 tom Exp $ */ +/* $Cambridge: exim/src/src/dkim.h,v 1.1.2.5 2009/06/08 21:06:31 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -7,16 +7,27 @@ /* Copyright (c) University of Cambridge 2009 */ /* See the file NOTICE for conditions of use and distribution. */ -uschar *dkim_exim_sign(int, - uschar *, - uschar *, - uschar *, - uschar *, - uschar *); +uschar *dkim_exim_sign(int,uschar *,uschar *,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_acl_setup(uschar *); +uschar *dkim_exim_expand_query(int); +uschar *dkim_exim_expand_defaults(int); -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 **); +#define DKIM_ALGO 1 +#define DKIM_BODYLENGTH 2 +#define DKIM_CANON_BODY 3 +#define DKIM_CANON_HEADERS 4 +#define DKIM_COPIEDHEADERS 5 +#define DKIM_CREATED 6 +#define DKIM_EXPIRES 7 +#define DKIM_HEADERNAMES 8 +#define DKIM_IDENTITY 9 +#define DKIM_KEY_GRANULARITY 10 +#define DKIM_KEY_SRVTYPE 11 +#define DKIM_KEY_NOTES 12 +#define DKIM_KEY_TESTING 13 +#define DKIM_NOSUBDOMAINS 14 +#define DKIM_VERIFY_STATUS 15 +#define DKIM_VERIFY_REASON 16 diff --git a/src/src/expand.c b/src/src/expand.c index f94503c43..7e957b1cd 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/expand.c,v 1.97.2.2 2009/05/27 17:26:54 tom Exp $ */ +/* $Cambridge: exim/src/src/expand.c,v 1.97.2.3 2009/06/08 21:06:31 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -364,6 +364,9 @@ enum { vtype_load_avg, /* value not used; result is int from os_getloadavg */ vtype_pspace, /* partition space; value is T/F for spool/log */ vtype_pinodes /* partition inodes; value is T/F for spool/log */ + #ifndef DISABLE_DKIM + ,vtype_dkim /* Lookup of value in DKIM signature */ + #endif }; /* This table must be kept in alphabetical order. */ @@ -402,9 +405,25 @@ static var_entry var_table[] = { { "demime_reason", vtype_stringptr, &demime_reason }, #endif #ifndef DISABLE_DKIM + { "dkim_algo", vtype_dkim, (void *)DKIM_ALGO }, + { "dkim_bodylength", vtype_dkim, (void *)DKIM_BODYLENGTH }, + { "dkim_canon_body", vtype_dkim, (void *)DKIM_CANON_BODY }, + { "dkim_canon_headers", vtype_dkim, (void *)DKIM_CANON_HEADERS }, + { "dkim_copiedheaders", vtype_dkim, (void *)DKIM_COPIEDHEADERS }, + { "dkim_created", vtype_dkim, (void *)DKIM_CREATED }, { "dkim_domain", vtype_stringptr, &dkim_signing_domain }, + { "dkim_expires", vtype_dkim, (void *)DKIM_EXPIRES }, + { "dkim_headernames", vtype_dkim, (void *)DKIM_HEADERNAMES }, + { "dkim_identity", vtype_dkim, (void *)DKIM_IDENTITY }, + { "dkim_key_granularity",vtype_dkim, (void *)DKIM_KEY_GRANULARITY }, + { "dkim_key_nosubdomains",vtype_dkim, (void *)DKIM_NOSUBDOMAINS }, + { "dkim_key_notes", vtype_dkim, (void *)DKIM_KEY_NOTES }, + { "dkim_key_srvtype", vtype_dkim, (void *)DKIM_KEY_SRVTYPE }, + { "dkim_key_testing", vtype_dkim, (void *)DKIM_KEY_TESTING }, { "dkim_selector", vtype_stringptr, &dkim_signing_selector }, { "dkim_signing_domains",vtype_stringptr, &dkim_signing_domains }, + { "dkim_verify_reason", vtype_dkim, (void *)DKIM_VERIFY_REASON }, + { "dkim_verify_status", vtype_dkim, (void *)DKIM_VERIFY_STATUS}, #endif { "dnslist_domain", vtype_stringptr, &dnslist_domain }, { "dnslist_matched", vtype_stringptr, &dnslist_matched }, @@ -1546,6 +1565,11 @@ while (last > first) } return var_buffer; + #ifndef DKIM_DISABLE + case vtype_dkim: + return dkim_exim_expand_query((int)var_table[middle].value); + #endif + } } diff --git a/src/src/receive.c b/src/src/receive.c index 3ee596ee7..cb29e35da 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.4 2009/05/27 17:26:55 tom Exp $ */ +/* $Cambridge: exim/src/src/receive.c,v 1.45.2.5 2009/06/08 21:06:32 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -2998,20 +2998,35 @@ else itembuf, sizeof(itembuf))) != NULL) { - - + dkim_exim_acl_setup(item); rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, &user_msg, &log_msg); if (rc != OK) break; } - add_acl_headers(US"DKIM"); + if (rc == DISCARD) + { + recipients_count = 0; + blackholed_by = US"DKIM ACL"; + if (log_msg != NULL) + blackhole_log_msg = string_sprintf(": %s", log_msg); + } + else if (rc != OK) + { + Uunlink(spool_name); + if (smtp_handle_acl_fail(ACL_WHERE_DKIM, rc, user_msg, log_msg) != 0) + smtp_yield = FALSE; /* No more messsages after dropped connection */ + smtp_reply = US""; /* Indicate reply already sent */ + message_id[0] = 0; /* Indicate no message accepted */ + goto TIDYUP; /* Skip to end of function */ + } } } } #endif /* DISABLE_DKIM */ #ifdef WITH_CONTENT_SCAN - if (acl_smtp_mime != NULL && + if (recipients_count > 0 && + acl_smtp_mime != NULL && !run_mime_acl(acl_smtp_mime, &smtp_yield, &smtp_reply, &blackholed_by)) goto TIDYUP; #endif /* WITH_CONTENT_SCAN */