of SSL-on-connect.
In the event of failure to negotiate TLS, the action taken is controlled
by &%ldap_require_cert%&.
+.new
+This option is ignored for &`ldapi`& connections.
+.wen
.option ldap_version main integer unset
affect Exim's operation, with an unchanged configuration file. For new
options, and new features, see the NewStuff file next to this ChangeLog.
+
Exim version 4.89
-------------------
+
JH/01 Bug 1922: Support IDNA2008. This has slightly different conversion rules
than -2003 did; needs libidn2 in addition to linidn.
JH/02 The path option on a pipe transport is now expanded before use.
+PP/01 GitHub PR 50: Do not call ldap_start_tls_s on ldapi:// connections.
+ Patch provided by "Björn", documentation fix added too.
+
Exim version 4.88
-----------------
+
JH/01 Use SIZE on MAIL FROM in a cutthrough connection, if the destination
supports it and a size is available (ie. the sending peer gave us one).
fallback to "prime256v1".
JH/34 SECURITY: Use proper copy of DATA command in error message.
- Could leak key material. Remotely explaoitable. CVE-2016-9963.
+ Could leak key material. Remotely exploitable. CVE-2016-9963.
Exim version 4.87
-----------------
+
JH/01 Bug 1664: Disable OCSP for GnuTLS library versions at/before 3.3.16
and 3.4.4 - once the server is enabled to respond to an OCSP request
it does even when not requested, resulting in a stapling non-aware
extraction. Accept either.
-
Exim version 4.86
-----------------
+
JH/01 Bug 1545: The smtp transport option "retry_include_ip_address" is now
expanded.
Exim version 4.85
-----------------
+
TL/01 When running the test suite, the README says that variables such as
no_msglog_check are global and can be placed anywhere in a specific
test's script, however it was observed that placement needed to be near
dkim_private_key_expanded = big_buffer;
}
- ctx = pdkim_init_sign( CS dkim_signing_domain,
- CS dkim_signing_selector,
- CS dkim_private_key_expanded,
- PDKIM_ALGO_RSA_SHA256,
- dkim->dot_stuffed);
+ ctx = pdkim_init_sign(CS dkim_signing_domain,
+ CS dkim_signing_selector,
+ CS dkim_private_key_expanded,
+ PDKIM_ALGO_RSA_SHA256,
+ dkim->dot_stuffed,
+ &dkim_exim_query_dns_txt
+ );
dkim_private_key_expanded[0] = '\0';
pdkim_set_optional(ctx,
CS dkim_sign_headers_expanded,
}
+/* -------------------------------------------------------------------------- */
+
+static pdkim_pubkey *
+pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx)
+{
+uschar * dns_txt_name, * dns_txt_reply;
+pdkim_pubkey * p;
+const uschar * errstr;
+
+/* Fetch public key for signing domain, from DNS */
+
+dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
+
+dns_txt_reply = store_get(PDKIM_DNS_TXT_MAX_RECLEN);
+memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
+
+if ( ctx->dns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK
+ || dns_txt_reply[0] == '\0'
+ )
+ {
+ sig->verify_status = PDKIM_VERIFY_INVALID;
+ sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
+ return NULL;
+ }
+
+DEBUG(D_acl)
+ {
+ debug_printf(
+ "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
+ " Raw record: ");
+ pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
+ }
+
+if ( !(p = pdkim_parse_pubkey_record(ctx, CUS dns_txt_reply))
+ || (Ustrcmp(p->srvtype, "*") != 0 && Ustrcmp(p->srvtype, "email") != 0)
+ )
+ {
+ sig->verify_status = PDKIM_VERIFY_INVALID;
+ sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
+
+ DEBUG(D_acl)
+ {
+ if (p)
+ debug_printf(" Invalid public key service type '%s'\n", p->srvtype);
+ else
+ debug_printf(" Error while parsing public key record\n");
+ debug_printf(
+ "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }
+ return NULL;
+ }
+
+DEBUG(D_acl) debug_printf(
+ "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+
+/* Import public key */
+if ((errstr = exim_rsa_verify_init(&p->key, vctx)))
+ {
+ DEBUG(D_acl) debug_printf("verify_init: %s\n", errstr);
+ sig->verify_status = PDKIM_VERIFY_INVALID;
+ sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
+ return NULL;
+ }
+
+return p;
+}
+
+
/* -------------------------------------------------------------------------- */
DLLEXPORT int
const uschar * errstr;
pdkim_pubkey * p;
- uschar *dns_txt_name, *dns_txt_reply;
-
/* Make sure we have all required signature tags */
if (!( sig->domain && *sig->domain
&& sig->selector && *sig->selector
goto NEXT_VERIFY;
}
- /* Fetch public key for signing domain, from DNS */
-
- dns_txt_name = string_sprintf("%s._domainkey.%s.",
- sig->selector, sig->domain);
-
- dns_txt_reply = store_get(PDKIM_DNS_TXT_MAX_RECLEN);
- memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
-
- if ( ctx->dns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK
- || dns_txt_reply[0] == '\0')
- {
- sig->verify_status = PDKIM_VERIFY_INVALID;
- sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
- goto NEXT_VERIFY;
- }
-
- DEBUG(D_acl)
- {
- debug_printf(
- "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
- " Raw record: ");
- pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
- }
-
- if ( !(p = pdkim_parse_pubkey_record(ctx, CUS dns_txt_reply))
- || (Ustrcmp(p->srvtype, "*") != 0 && Ustrcmp(p->srvtype, "email") != 0)
- )
- {
- sig->verify_status = PDKIM_VERIFY_INVALID;
- sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
-
- DEBUG(D_acl)
- {
- if (p)
- debug_printf(" Invalid public key service type '%s'\n", p->srvtype);
- else
- debug_printf(" Error while parsing public key record\n");
- debug_printf(
- "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
- }
+ if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx)))
goto NEXT_VERIFY;
- }
- sig->pubkey = p;
-
- DEBUG(D_acl) debug_printf(
- "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
-
- /* Import public key */
- if ((errstr = exim_rsa_verify_init(&sig->pubkey->key, &vctx)))
- {
- DEBUG(D_acl) debug_printf("verify_init: %s\n", errstr);
- sig->verify_status = PDKIM_VERIFY_INVALID;
- sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
- goto NEXT_VERIFY;
- }
/* Check the signature */
if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sigdata)))
/* -------------------------------------------------------------------------- */
DLLEXPORT pdkim_ctx *
-pdkim_init_sign(char *domain, char *selector, char *rsa_privkey, int algo,
- BOOL dot_stuffed)
+pdkim_init_sign(char * domain, char * selector, char * rsa_privkey, int algo,
+ BOOL dot_stuffed, int(*dns_txt_callback)(char *, char *))
{
-pdkim_ctx *ctx;
-pdkim_signature *sig;
+pdkim_ctx * ctx;
+pdkim_signature * sig;
if (!domain || !selector || !rsa_privkey)
return NULL;
-ctx = store_get(sizeof(pdkim_ctx));
+ctx = store_get(sizeof(pdkim_ctx) + PDKIM_MAX_BODY_LINE_LEN + sizeof(pdkim_signature));
memset(ctx, 0, sizeof(pdkim_ctx));
ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
-ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
+ctx->linebuf = CS (ctx+1);
-sig = store_get(sizeof(pdkim_signature));
+DEBUG(D_acl) ctx->dns_txt_callback = dns_txt_callback;
+
+sig = (pdkim_signature *)(ctx->linebuf + PDKIM_MAX_BODY_LINE_LEN);
memset(sig, 0, sizeof(pdkim_signature));
sig->bodylength = -1;
sig->algo = algo;
exim_sha_init(&sig->body_hash, algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256);
+
+DEBUG(D_acl)
+ {
+ pdkim_signature s = *sig;
+ ev_ctx vctx;
+
+ debug_printf("PDKIM (checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+ if (!pdkim_key_from_dns(ctx, &s, &vctx))
+ debug_printf("WARNING: bad dkim key in dns\n");
+ debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }
+
return ctx;
}
void pdkim_init (void);
DLLEXPORT
-pdkim_ctx *pdkim_init_sign (char *, char *, char *, int, BOOL);
+pdkim_ctx *pdkim_init_sign (char *, char *, char *, int,
+ BOOL, int(*)(char *, char *));
DLLEXPORT
pdkim_ctx *pdkim_init_verify (int(*)(char *, char *), BOOL);
port = PORT_D
dkim_domain = test.ex
+.ifdef SELECTOR
+ dkim_selector = SELECTOR
+.else
dkim_selector = sel
+.endif
dkim_private_key = DIR/aux-fixed/dkim/dkim.private
.ifndef HEADERS_MAXSIZE
dkim_sign_headers = OPT
1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmbB-0005vi-00 => c@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbC-0005vi-00"
1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbD-0005vi-00 => d@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbE-0005vi-00"
+1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
******** SERVER ********
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmbB-0005vi-00@myhost.test.ex
1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <c@test.ex> R=server_dump
1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbE-0005vi-00 DKIM: d=test.ex s=sel_bad c=relaxed/relaxed a=rsa-sha256 b=1024 [invalid - syntax error in public key record]
+1999-03-02 09:44:33 10HmbE-0005vi-00 signer: test.ex bits: 1024 h=Date:Sender:Message-Id:From:Reply-To:Subject:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmbD-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: <d@test.ex> R=server_dump
+1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
# Not all platforms build with DKIM enabled
next if /^PDKIM >> Body data for hash, canonicalized/;
+ # Parts of DKIM-specific debug output depend on the time/date
+ next if /^date:\w+,{SP}/;
+ next if /^PDKIM \[[^[]+\] (Header hash|b) computed:/;
+
# Not all platforms support TCP Fast Open, and the compile omits the check
if (s/\S+ in hosts_try_fastopen\? no \(option unset\)\n$//)
{
-# DKIM simple canonicalisation
+# DKIM verify, simple canonicalisation
#
exim -DSERVER=server -bd -oX PORT_D
****
-# DKIM simple canonicalisation, with spaces
+# DKIM verify, simple canonicalisation, with spaces
#
exim -DSERVER=server -bd -oX PORT_D
****
??? 221
****
#
-# This should fail, but passes - bug 1926 - due to an extra \ in the DNS record.
+# This should fail, due to an extra \ in the DNS record.
# Mail original in aux-fixed/4502.msg1.txt
# Sig generated by: perl aux-fixed/dkim/sign.pl --method=relaxed/relaxed --selector=sel_bad < aux-fixed/4502.msg1.txt
client 127.0.0.1 PORT_D
content
****
+#
+# check that on signing we warn in debug mode about verify problems
+exim -d-all+acl -DHEADERS_MAXSIZE=y -DSELECTOR=sel_bad -odf d@test.ex
+From: nobody@example.com
+
+content
+****
+#
millisleep 500
killdaemon
no_msglog_check
--- /dev/null
+Exim version x.yz ....
+configuration file is TESTSUITE/test-config
+admin user
+LOG: MAIN
+ <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+Exim version x.yz ....
+configuration file is TESTSUITE/test-config
+trusted user
+admin user
+Connecting to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4]:1225 ... connected
+ SMTP<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+ SMTP>> EHLO myhost.test.ex
+cmd buf flush ddd bytes
+ SMTP<< 250-myhost.test.ex Hello the.local.host.name [ip4.ip4.ip4.ip4]
+ 250-SIZE 52428800
+ 250-8BITMIME
+ 250-PIPELINING
+ 250 HELP
+ SMTP>> MAIL FROM:<CALLER@myhost.test.ex> SIZE=ssss
+ SMTP>> RCPT TO:<d@test.ex>
+ SMTP>> DATA
+cmd buf flush ddd bytes
+ SMTP<< 250 OK
+ SMTP<< 250 Accepted
+ SMTP<< 354 Enter message, ending with "." on a line by itself
+PDKIM (checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+ Raw record: v=DKIM1\;{SP}p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXRFf+VhT+lCgFhhSkinZKcFNeRzjYdW8vT29Rbb3NadvTFwAd+cVLPFwZL8H5tUD/7JbUPqNTCPxmpgIL+V5T4tEZMorHatvvUM2qfcpQ45IfsZ+YdhbIiAslHCpy4xNxIR3zylgqRUF4+Dtsaqy3a5LhwMiKCLrnzhXk1F1hxwIDAQAB
+ v=DKIM1\
+ p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXRFf+VhT+lCgFhhSkinZKcFNeRzjYdW8vT29Rbb3NadvTFwAd+cVLPFwZL8H5tUD/7JbUPqNTCPxmpgIL+V5T4tEZMorHatvvUM2qfcpQ45IfsZ+YdhbIiAslHCpy4xNxIR3zylgqRUF4+Dtsaqy3a5LhwMiKCLrnzhXk1F1hxwIDAQAB
+ Error while parsing public key record
+WARNING: bad dkim key in dns
+PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+content{CR}{LF}
+PDKIM [test.ex] Body bytes hashed: 9
+PDKIM [test.ex] Body hash computed: fc06f48221d98ad6106c3845b33a2a41152482ab9e697f736ad26db4853fa657
+PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>>>
+sender:CALLER_NAME{SP}<CALLER@myhost.test.ex>{CR}{LF}
+message-id:<E10HmbD-0005vi-00@myhost.test.ex>{CR}{LF}
+from:nobody@example.com{CR}{LF}
+PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>
+dkim-signature:v=1;{SP}a=rsa-sha256;{SP}q=dns/txt;{SP}c=relaxed/relaxed;{SP}d=test.ex;{SP}s=sel_bad;{SP}h=Date:Sender:Message-Id:From:Reply-To:Subject:To:Cc:MIME-Version:{SP}Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:{SP}Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:{SP}In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:{SP}List-Post:List-Owner:List-Archive;{SP}bh=/Ab0giHZitYQbDhFszoqQRUkgqueaX9zatJttIU/plc=;{SP}b=;
+ SMTP<< 250 OK id=10HmbE-0005vi-00
+ SMTP>> QUIT
+cmd buf flush ddd bytes
+ SMTP(close)>>
+LOG: MAIN
+ => d@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbE-0005vi-00"
+LOG: MAIN
+ Completed
+>>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>>
+
+******** SERVER ********