X-Git-Url: https://git.exim.org/users/heiko/exim.git/blobdiff_plain/7cac846baccdb101d9d7c52b50998ca9efb8416e..8a330e5a9133a14ea43b648ae8c5dedcaf7ca3f7:/doc/doc-txt/experimental-spec.txt diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 333307b74..d57cbf903 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -759,90 +759,103 @@ b. Configure, somewhere before the DATA ACL, the control option to -Transport post-delivery actions +Event Actions -------------------------------------------------------------- -An arbitrary per-transport string can be expanded on successful delivery, -and (for SMTP transports) a second string on deferrals caused by a host error. +(Renamed from TPDA, Transport post-delivery actions) + +An arbitrary per-transport string can be expanded upon various transport events. +Additionally a main-section configuration option can be expanded on some +per-message events. This feature may be used, for example, to write exim internal log information (not available otherwise) into a database. -In order to use the feature, you must set +In order to use the feature, you must compile with -EXPERIMENTAL_TPDA=yes +EXPERIMENTAL_EVENT=yes in your Local/Makefile -and define the expandable strings in the runtime config file, to -be executed at end of delivery. +and define one or both of +- the event_action option in the transport +- the event_action main option +to be expanded when the event fires. + +A new variable, $event_name, is set to the event type when the +expansion is done. The current list of events is: + + msg:complete after main per message + msg:delivery after transport per recipient + msg:host:defer after transport per attempt + msg:fail:delivery after main per recipient + msg:fail:internal after main per recipient + tcp:connect before transport per connection + tcp:close after transport per connection + tls:cert before both per certificate in verification chain + smtp:connect after transport per connection -Additionally, there are 6 more variables, available at end of -delivery: +The expansion is called for all event types, and should use the $event_name +value to decide when to act. The variable data is a colon-separated +list, describing an event tree. -tpda_delivery_ip IP of host, which has accepted delivery -tpda_delivery_port Port of remote host which has accepted delivery -tpda_delivery_fqdn FQDN of host, which has accepted delivery -tpda_delivery_local_part local part of address being delivered -tpda_delivery_domain domain part of address being delivered -tpda_delivery_confirmation SMTP confirmation message +There is an auxilary variable, $event_data, for which the +content is event_dependent: -In case of a deferral caused by a host-error: -tpda_defer_errno Error number -tpda_defer_errstr Error string possibly containing more details + msg:delivery smtp confirmation mssage + msg:host:defer error string + tls:cert verification chain depth + smtp:connect smtp banner -The $router_name and $transport_name variables are also usable. +The msg:host:defer event populates one extra variable, $event_defer_errno. +The following variables are likely to be useful depending on the event type: -To take action after successful deliveries, set the following option -on any transport of interest. + router_name, transport_name + local_part, domain + host, host_address, host_port + tls_out_peercert + lookup_dnssec_authenticated, tls_out_dane + sending_ip_address, sending_port + message_exim_id, verify_mode -tpda_delivery_action An example might look like: -tpda_delivery_action = \ -${lookup pgsql {SELECT * FROM record_Delivery( \ +event_action = ${if = {msg:delivery}{$event_name} \ +{${lookup pgsql {SELECT * FROM record_Delivery( \ '${quote_pgsql:$sender_address_domain}',\ '${quote_pgsql:${lc:$sender_address_local_part}}', \ - '${quote_pgsql:$tpda_delivery_domain}', \ - '${quote_pgsql:${lc:$tpda_delivery_local_part}}', \ - '${quote_pgsql:$tpda_delivery_ip}', \ - '${quote_pgsql:${lc:$tpda_delivery_fqdn}}', \ - '${quote_pgsql:$message_exim_id}')}} - -The string is expanded after the delivery completes and any -side-effects will happen. The result is then discarded. + '${quote_pgsql:$domain}', \ + '${quote_pgsql:${lc:$local_part}}', \ + '${quote_pgsql:$host_address}', \ + '${quote_pgsql:${lc:$host}}', \ + '${quote_pgsql:$message_exim_id}')}} \ +} {}} + +The string is expanded when each of the supported events occur +and any side-effects of the expansion will happen. Note that for complex operations an ACL expansion can be used. -In order to log host deferrals, add the following option to an SMTP -transport: +The expansion of the event_action option should normally +return an empty string. Should it return anything else the +following will be forced: -tpda_host_defer_action + msg:delivery (ignored) + msg:host:defer (ignored) + msg:fail:delivery (ignored) + tcp:connect do not connect + tcp:close (ignored) + tls:cert refuse verification + smtp:connect close connection -This is a private option of the SMTP transport. It is intended to -log failures of remote hosts. It is executed only when exim has -attempted to deliver a message to a remote host and failed due to -an error which doesn't seem to be related to the individual -message, sender, or recipient address. -See section 47.2 of the exim documentation for more details on how -this is determined. +No other use is made of the result string. -Example: -tpda_host_defer_action = \ -${lookup mysql {insert into delivlog set \ - msgid = '${quote_mysql:$message_exim_id}', \ - senderlp = '${quote_mysql:${lc:$sender_address_local_part}}', \ - senderdom = '${quote_mysql:$sender_address_domain}', \ - delivlp = '${quote_mysql:${lc:$tpda_delivery_local_part}}', \ - delivdom = '${quote_mysql:$tpda_delivery_domain}', \ - delivip = '${quote_mysql:$tpda_delivery_ip}', \ - delivport = '${quote_mysql:$tpda_delivery_port}', \ - delivfqdn = '${quote_mysql:$tpda_delivery_fqdn}', \ - deliverrno = '${quote_mysql:$tpda_defer_errno}', \ - deliverrstr = '${quote_mysql:$tpda_defer_errstr}' \ - }} +Known issues: +- the tls:cert event is only called for the cert chain elements + received over the wire, with GnuTLS. OpenSSL gives the entire + chain including thse loaded locally. Redis Lookup @@ -1131,6 +1144,8 @@ the next hop does not support DSN. Adding it to a redirect router makes no difference. + + Certificate name checking -------------------------------------------------------------- The X509 certificates used for TLS are supposed be verified @@ -1138,16 +1153,33 @@ that they are owned by the expected host. The coding of TLS support to date has not made these checks. If built with EXPERIMENTAL_CERTNAMES defined, code is -included to do so, and a new smtp transport option -"tls_verify_cert_hostname" supported which takes a list of -names for which the checks must be made. The host must -also be in "tls_verify_hosts". +included to do so for server certificates, and a new smtp transport option +"tls_verify_cert_hostnames" supported which takes a hostlist +which must match the target host for the additional checks must be made. +The option currently defaults to empty, but this may change in +the future. "*" is probably a suitable value. +Whether certificate verification is done at all, and the result of +it failing, is stll under the control of "tls_verify_hosts" nad +"tls_try_verify_hosts". + +The name being checked is that for the host, generally +the result of an MX lookup. Both Subject and Subject-Alternate-Name certificate fields are supported, as are wildcard certificates (limited to a single wildcard being the initial component of a 3-or-more component FQDN). +The equivalent check on the server for client certificates is not +implemented. At least one major email provider is using a client +certificate which fails this check. They do not retry either without +the client certificate or in clear. + +It is possible to duplicate the effect of this checking by +creative use of Events. + + + DANE ------------------------------------------------------------ @@ -1171,6 +1203,10 @@ admins of the target server. The attack surface presented by (a) is thought to be smaller than that of the set of root CAs. +It also allows the server to declare (implicitly) that +connections to it should use TLS. An MITM could simply +fail to pass on a server's STARTTLS. + DANE scales better than having to maintain (and side-channel communicate) copies of server certificates for every possible target server. It also scales @@ -1181,7 +1217,10 @@ means not having to pay a CA for certificates. DANE requires a server operator to do three things: 1) run DNSSEC. This provides assurance to clients that DNS lookups they do for the server have not -been tampered with. +been tampered with. The domain MX record applying +to this server, its A record, its TLSA record and +any associated CNAME records must all be covered by +DNSSEC. 2) add TLSA DNS records. These say what the server certificate for a TLS connection should be. 3) offer a server certificate, or certificate chain, @@ -1192,12 +1231,12 @@ There are no changes to Exim specific to server-side operation of DANE. The TLSA record for the server may have "certificate -usage" of DANE_TA(2) or DANE_EE(3). The latter specifies +usage" of DANE-TA(2) or DANE-EE(3). The latter specifies the End Entity directly, i.e. the certificate involved is that of the server (and should be the sole one transmitted during the TLS handshake); this is appropriate for a single system, using a self-signed certificate. - DANE_TA usage is effectively declaring a specific CA + DANE-TA usage is effectively declaring a specific CA to be used; this might be a private CA or a public, well-known one. A private CA at simplest is just a self-signed certificate which is used to sign @@ -1209,43 +1248,84 @@ the entire certificate chain from CA to server-certificate. If a public CA is used then all clients must be primed with it (losing one advantage of DANE) - but the attack surface is reduced from all public CAs to that single CA. -DANE_TA is commonly used for several services and/or +DANE-TA is commonly used for several services and/or servers, each having a TLSA query-domain CNAME record, all of which point to a single TLSA record. The TLSA record should have a Selector field of SPKI(1) -and a Matching Type fiels of SHA2-512(2). +and a Matching Type field of SHA2-512(2). -For use with the DANE_TA model, server certificates +At the time of writing, https://www.huque.com/bin/gen_tlsa +is useful for quickly generating TLSA records; and commands like + + openssl x509 -in -pubkey -noout /dev/null \ + | openssl sha512 \ + | awk '{print $2}' + +are workable for 4th-field hashes. + +For use with the DANE-TA model, server certificates must have a correct name (SubjectName or SubjectAltName). The use of OCSP-stapling should be considered, allowing for fast revocation of certificates (which would otherwise -be limited by the DNS TTL on the TLSA records). +be limited by the DNS TTL on the TLSA records). However, +this is likely to only be usable with DANE-TA. NOTE: the +default of requesting OCSP for all hosts is modified iff +DANE is in use, to: + + hosts_request_ocsp = ${if or { {= {0}{$tls_out_tlsa_usage}} \ + {= {4}{$tls_out_tlsa_usage}} } \ + {*}{}} + +The (new) variable $tls_out_tlsa_usage is a bitfield with +numbered bits set for TLSA record usage codes. +The zero above means DANE was not in use, +the four means that only DANE-TA usage TLSA records were +found. If the definition of hosts_request_ocsp includes the +string "tls_out_tlsa_usage", they are re-expanded in time to +control the OCSP request. +This modification of hosts_request_ocsp is only done if +it has the default value of "*". Admins who change it, and +those who use hosts_require_ocsp, should consider the interaction +with DANE in their OCSP settings. -For client-side DANE there is a new smtp transport option, -hosts_try_dane. It does the obvious thing. -[ may add a hosts_require_dane, too? ] -[ should it be domain-based rather than host-based? ] + +For client-side DANE there are two new smtp transport options, +hosts_try_dane and hosts_require_dane. They do the obvious thing. +[ should they be domain-based rather than host-based? ] DANE will only be usable if the target host has DNSSEC-secured MX, A and TLSA records. +A TLSA lookup will be done if either of the above options match +and the host-lookup succeded using dnssec. +If the TLSA lookup succeeds, a TLS connection will be required +for the host. + (TODO: specify when fallback happens vs. when the host is not used) If dane is in use the following transport options are ignored: + hosts_require_tls tls_verify_hosts tls_try_verify_hosts tls_verify_certificates tls_crl tls_verify_cert_hostnames - hosts_require_ocsp (might rethink those two) - hosts_request_ocsp Currently dnssec_request_domains must be active (need to think about that) and dnssec_require_domains is ignored. +If verification was successful using DANE then the "CV" item +in the delivery log line will show as "CV=dane". + +There is a new variable $tls_out_dane which will have "yes" if +verification succeeded using DANE and "no" otherwise (only useful +in combination with EXPERIMENTAL_EVENT), and a new variable +$tls_out_tlsa_usage (detailed above). + -------------------------------------------------------------- End of file