X-Git-Url: https://git.exim.org/users/jgh/exim.git/blobdiff_plain/9621e5878fe73e831478de4c7b7262aa92736337..bb1d997d783b6ffc13bec6d85462366d979a4c70:/src/src/dkim.c 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""; } }