. Update the Copyright year (only) when changing content.
. /////////////////////////////////////////////////////////////////////////////
-.set previousversion "4.92"
+.set previousversion "4.93"
.include ./local_params
.set ACL "access control lists (ACLs)"
.set I " "
.macro copyyear
-2018
+2019
.endmacro
. /////////////////////////////////////////////////////////////////////////////
.section "Exim documentation" "SECID1"
. Keep this example change bar when updating the documentation!
+.new
.cindex "documentation"
This edition of the Exim specification applies to version &version() of Exim.
Substantive changes from the &previousversion; edition are marked in some
renditions of this document; this paragraph is so marked if the rendition is
capable of showing a change indicator.
+.wen
This document is very much a reference manual; it is not a tutorial. The reader
is expected to have some familiarity with the SMTP mail transfer protocol and
.section "Including TLS/SSL encryption support" "SECTinctlsssl"
.cindex "TLS" "including support for TLS"
.cindex "encryption" "including support for"
-.cindex "SUPPORT_TLS"
.cindex "OpenSSL" "building Exim with"
.cindex "GnuTLS" "building Exim with"
-Exim can be built to support encrypted SMTP connections, using the STARTTLS
-command as per RFC 2487. It can also support legacy clients that expect to
+Exim is usually built to support encrypted SMTP connections, using the STARTTLS
+command as per RFC 2487. It can also support clients that expect to
start a TLS session immediately on connection to a non-standard port (see the
&%tls_on_connect_ports%& runtime option and the &%-tls-on-connect%& command
line option).
OpenSSL or GnuTLS library. There is no cryptographic code in Exim itself for
implementing SSL.
+If you do not want TLS support you should set
+.code
+DISABLE_TLS=yes
+.endd
+in &_Local/Makefile_&.
+
If OpenSSL is installed, you should set
.code
-SUPPORT_TLS=yes
+USE_OPENSL=yes
TLS_LIBS=-lssl -lcrypto
.endd
in &_Local/Makefile_&. You may also need to specify the locations of the
OpenSSL library and include files. For example:
.code
-SUPPORT_TLS=yes
+USE_OPENSSL=yes
TLS_LIBS=-L/usr/local/openssl/lib -lssl -lcrypto
TLS_INCLUDE=-I/usr/local/openssl/include/
.endd
.cindex "pkg-config" "OpenSSL"
If you have &'pkg-config'& available, then instead you can just use:
.code
-SUPPORT_TLS=yes
+USE_OPENSSL=yes
USE_OPENSSL_PC=openssl
.endd
.cindex "USE_GNUTLS"
If GnuTLS is installed, you should set
.code
-SUPPORT_TLS=yes
USE_GNUTLS=yes
TLS_LIBS=-lgnutls -ltasn1 -lgcrypt
.endd
in &_Local/Makefile_&, and again you may need to specify the locations of the
library and include files. For example:
.code
-SUPPORT_TLS=yes
USE_GNUTLS=yes
TLS_LIBS=-L/usr/gnu/lib -lgnutls -ltasn1 -lgcrypt
TLS_INCLUDE=-I/usr/gnu/include
.cindex "pkg-config" "GnuTLS"
If you have &'pkg-config'& available, then instead you can just use:
.code
-SUPPORT_TLS=yes
USE_GNUTLS=yes
USE_GNUTLS_PC=gnutls
.endd
Bounce messages are just discarded. This option can be used only by an admin
user.
+.vitem &%-MG%&&~<&'queue&~name'&>&~<&'message&~id'&>&~<&'message&~id'&>&~...
+.oindex "&%-MG%&"
+.cindex queue named
+.cindex "named queues"
+.cindex "queue" "moving messages"
+This option requests that each listed message be moved from its current
+queue to the given named queue.
+The destination queue name argument is required, but can be an empty
+string to define the default queue.
+If the messages are not currently located in the default queue,
+a &%-qG<name>%& option will be required to define the source queue.
+
.vitem &%-Mmad%&&~<&'message&~id'&>&~<&'message&~id'&>&~...
.oindex "&%-Mmad%&"
.cindex "delivery" "cancelling all"
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
-.ifdef _HAVE_DNSSEC
- dnssec_request_domains = *
-.endif
no_more
.endd
The &%domains%& option behaves as per smarthost, above.
remote_smtp:
driver = smtp
message_size_limit = ${if > {$max_received_linelength}{998} {1}{0}}
-.ifdef _HAVE_DANE
- hosts_try_dane = *
-.endif
.ifdef _HAVE_PRDR
hosts_try_prdr = *
.endif
This transport is used for delivering messages over SMTP connections.
The list of remote hosts comes from the router.
The &%message_size_limit%& usage is a hack to avoid sending on messages
-with over-long lines. The built-in macro _HAVE_DANE guards configuration
-to use DANE for delivery;
-see section &<<SECDANE>>& for more details.
+with over-long lines.
The &%hosts_try_prdr%& option enables an efficiency SMTP option. It is
negotiated between client and server and not expected to cause problems
tools for building the files can be found in several places:
.display
&url(https://cr.yp.to/cdb.html)
-&url(http://www.corpit.ru/mjt/tinycdb.html)
+&url(https://www.corpit.ru/mjt/tinycdb.html)
&url(https://packages.debian.org/stable/utils/freecdb)
&url(https://github.com/philpennock/cdbtools) (in Go)
.endd
-. --- 2018-09-07: corpit.ru http:-only
A cdb distribution is not needed in order to build Exim with cdb support,
because the code for reading cdb files is included directly in Exim itself.
However, no means of building or testing cdb files is provided with Exim, so
the implicit key is the host's IP address rather than its name (see section
&<<SECThoslispatsikey>>&).
-.new
&*Warning 3*&: Do not use an IPv4-mapped IPv6 address for a key; use the
IPv4, in dotted-quad form. (Exim converts IPv4-mapped IPv6 addresses to this
notation before executing the lookup.)
-.wen
.next
-.new
.cindex lookup json
.cindex json "lookup type"
.cindex JSON expansions
or array; for the latter two a string-representation os the JSON
is returned.
For elements of type string, the returned value is de-quoted.
-.wen
.next
.cindex "linear search"
.cindex "lookup" "lsearch"
With &"strict"& a response from the DNS resolver that
is not labelled as authenticated data
is treated as equivalent to a temporary DNS error.
-The default is &"never"&.
+The default is &"lax"&.
See also the &$lookup_dnssec_authenticated$& variable.
(notated using the quoting facility) so as to distinguish them from IPv4 keys.
For this reason, when the lookup type is &(iplsearch)&, IPv6 addresses are
converted using colons and not dots.
-.new
In all cases except IPv4-mapped IPv6, full, unabbreviated IPv6
addresses are always used.
The latter are converted to IPv4 addresses, in dotted-quad form.
-.wen
Ideally, it would be nice to tidy up this anomalous situation by changing to
colons in all cases, given that quoting is now available for &(lsearch)&.
the data type. ACL rules always expand strings. A couple of expansion
conditions do not expand some of the brace-delimited branches, for security
reasons,
-.new
.cindex "tainted data" expansion
.cindex expansion "tainted data"
and expansion of data deriving from the sender (&"tainted data"&)
is not permitted.
-.wen
object so that it doesn't reload the same object file in the same Exim process
(but of course Exim does start new processes frequently).
-There may be from zero to eight arguments to the function. When compiling
-a local function that is to be called in this way, &_local_scan.h_& should be
-included. The Exim variables and functions that are defined by that API
+There may be from zero to eight arguments to the function.
+
+When compiling
+a local function that is to be called in this way,
+first &_DLFUNC_IMPL_& should be defined,
+and second &_local_scan.h_& should be included.
+The Exim variables and functions that are defined by that API
are also available for dynamically loaded functions. The function itself
must have the following type:
.code
For the &"json"& variant,
if a returned value is a JSON string, it retains its leading and
trailing quotes.
-.new
For the &"jsons"& variant, which is intended for use with JSON strings, the
leading and trailing quotes are removed from the returned value.
-.wen
. XXX should be a UTF-8 compare
The results of matching are handled as above.
For the &"json"& variant,
if a returned value is a JSON string, it retains its leading and
trailing quotes.
-.new
For the &"jsons"& variant, which is intended for use with JSON strings, the
leading and trailing quotes are removed from the returned value.
-.wen
.vitem &*${filter{*&<&'string'&>&*}{*&<&'condition'&>&*}}*&
If the string is a single variable of type certificate,
returns the SHA-256 hash fingerprint of the certificate.
-.new
The operator can also be spelled &%sha2%& and does the same as &%sha256%&
(except for certificates, which are not supported).
Finally, if an underbar
and a number is appended it specifies the output length, selecting a
member of the SHA-2 family of hash functions.
Values of 256, 384 and 512 are accepted, with 256 being the default.
-.wen
.vitem &*${sha3:*&<&'string'&>&*}*& &&&
To scan a named list, expand it with the &*listnamed*& operator.
-.new
.vitem "&*forall_json{*&<&'a JSON array'&>&*}{*&<&'a condition'&>&*}*&" &&&
"&*forany_json{*&<&'a JSON array'&>&*}{*&<&'a condition'&>&*}*&" &&&
"&*forall_jsons{*&<&'a JSON array'&>&*}{*&<&'a condition'&>&*}*&" &&&
The array separator is not changeable.
For the &"jsons"& variants the elements are expected to be JSON strings
and have their quotes removed before the evaluation of the condition.
-.wen
.vindex "&$config_file$&"
The name of the main configuration file Exim is using.
-.new
.vitem &$dmarc_domain_policy$& &&&
&$dmarc_status$& &&&
&$dmarc_status_text$& &&&
&$dmarc_used_domains$&
Results of DMARC verification.
For details see section &<<SECDMARC>>&.
-.wen
.vitem &$dkim_verify_status$&
Results of DKIM verification.
.cindex queues named
The name of the spool queue in use; empty for the default queue.
-.new
.vitem &$r_...$&
.vindex &$r_...$&
.cindex router variables
They can be given any name that starts with &$r_$&.
The values persist for the address being handled through subsequent routers
and the eventual transport.
-.wen
.vitem &$rcpt_count$&
.vindex "&$rcpt_count$&"
&*Note*&: Under versions of OpenSSL preceding 1.1.1,
when a list of more than one
file is used for &%tls_certificate%&, this variable is not reliable.
+The macro "_TLS_BAD_MULTICERT_IN_OURCERT" will be defined for those versions.
.vitem &$tls_in_peercert$&
.vindex "&$tls_in_peercert$&"
but in the context of an outward SMTP delivery taking place via the &(smtp)& transport
becomes the same as &$tls_out_cipher$&.
-.new
.vitem &$tls_in_cipher_std$&
.vindex "&$tls_in_cipher_std$&"
As above, but returning the RFC standard name for the cipher suite.
-.wen
.vitem &$tls_out_cipher$&
.vindex "&$tls_out_cipher$&"
&<<CHAPTLS>>& for details of TLS support and chapter &<<CHAPsmtptrans>>& for
details of the &(smtp)& transport.
-,new
.vitem &$tls_out_cipher_std$&
.vindex "&$tls_out_cipher_std$&"
As above, but returning the RFC standard name for the cipher suite.
-.wen
.vitem &$tls_out_dane$&
.vindex &$tls_out_dane$&
.vindex &$tls_out_tlsa_usage$&
Bitfield of TLSA record types found. See section &<<SECDANE>>&.
-.new
.vitem &$tls_in_ver$&
.vindex "&$tls_in_ver$&"
When a message is received from a remote host over an encrypted SMTP connection
.vindex "&$tls_out_ver$&"
When a message is being delivered to a remote host over an encrypted SMTP connection
this variable is set to the protocol version.
-.wen
.vitem &$tod_bsdinbox$&
.option add_environment main "string list" empty
.cindex "environment" "set values"
-This option allows to set individual environment variables that the
-currently linked libraries and programs in child processes use.
+This option adds individual environment variables that the
+currently linked libraries and programs in child processes may use.
+Each list element should be of the form &"name=value"&.
+
See &<<SECTpipeenv>>& for the environment of &(pipe)& transports.
.option admin_groups main "string list&!!" unset
UTF-8 multicharacters to appear in domain name components, in addition to
letters, digits, and hyphens.
-.new
If Exim is built with internationalization support
and the SMTPUTF8 ESMTP option is in use (see chapter &<<CHAPi18n>>&)
this option can be left as default.
-.wen
Without that,
if you want to look up such domain names in the DNS, you must also
adjust the value of &%dns_check_names_pattern%& to match the extended form. A
.option dkim_verify_hashes main "string list" "sha256 : sha512"
.cindex DKIM "selecting signature algorithms"
This option gives a list of hash types which are acceptable in signatures,
+.wen
and an order of processing.
Signatures with algorithms not in the list will be ignored.
.option dkim_verify_minimal main boolean false
If set to true, verification of signatures will terminate after the
first success.
-.wen
.option dkim_verify_signers main "domain list&!!" $dkim_signers
.cindex DKIM "controlling calls to the ACL"
This is a fudge to help with name servers that give big delays or otherwise do
not work for the AAAA record type. In due course, when the world's name
servers have all been upgraded, there should be no need for this option.
-.new
Note that all lookups, including those done for verification, are affected;
this will result in verify failure for IPv6 connections or ones using names
only valid for IPv6 addresses.
-.wen
.option dns_retrans main time 0s
.cindex "Exim version"
.cindex customizing "version number"
.cindex "version number of Exim" override
-This option allows to override the &$version_number$&/&$exim_version$& Exim reports in
-various places. Use with care, this may fool stupid security scanners.
+This option overrides the &$version_number$&/&$exim_version$& that Exim reports in
+various places. Use with care; this may fool stupid security scanners.
.option extra_local_interfaces main "string list" unset
name. If no specific path is set for the log files at compile or runtime,
or if the option is unset at runtime (i.e. &`log_file_path = `&)
they are written in a sub-directory called &_log_& in Exim's spool directory.
-.new
A path must start with a slash.
To send to syslog, use the word &"syslog"&.
-.wen
Chapter &<<CHAPlog>>& contains further details about Exim's logging, and
section &<<SECTwhelogwri>>& describes how the contents of &%log_file_path%& are
used. If this string is fixed at your installation (contains no expansion
transport driver.
-.option openssl_options main "string list" "+no_sslv2 +no_sslv3 +single_dh_use +no_ticket"
+.option openssl_options main "string list" "+no_sslv2 +no_sslv3 +single_dh_use +no_ticket +no_renegotiation"
.cindex "OpenSSL "compatibility options"
This option allows an administrator to adjust the SSL options applied
by OpenSSL to connections. It is given as a space-separated list of items,
This option is available only when Exim is built with an embedded Perl
interpreter. See chapter &<<CHAPperl>>& for details of its use.
-.option perl_startup main boolean false
+.option perl_taintmode main boolean false
.cindex "Perl"
-This Option enables the taint mode of the embedded Perl interpreter.
+This option enables the taint mode of the embedded Perl interpreter.
.option pgsql_servers main "string list" unset
that clients will use it; &"out of order"& commands that are &"expected"& do
not count as protocol errors (see &%smtp_max_synprot_errors%&).
-.new
.option pipelining_connect_advertise_hosts main "host list&!!" *
.cindex "pipelining" "early connection"
.cindex "pipelining" PIPE_CONNECT
commands are acceptable.
When used, the pipelining saves on roundtrip times.
+See also the &%hosts_pipe_connect%& smtp transport option.
+
Currently the option name &"X_PIPE_CONNECT"& is used.
-.wen
.option prdr_enable main boolean false
added to the message. Otherwise, the string should start with the text
&"Received:"& and conform to the RFC 2822 specification for &'Received:'&
header lines.
-.new
The default setting is:
.code
id $message_exim_id\
${if def:received_for {\n\tfor $received_for}}
.endd
-.wen
The reference to the TLS cipher is omitted when Exim is built without TLS
support. The use of conditional expansions ensures that this works for both
&%sender_unqualified_hosts%&, or if the message was submitted locally (not
using TCP/IP), and the &%-bnq%& option was not set.
-.option add_environment main "string list" empty
-.cindex "environment"
-This option allows to add individual environment variables that the
-currently linked libraries and programs in child processes use. The
-default list is empty.
-
.option slow_lookup_log main integer 0
.cindex "logging" "slow lookups"
&*Note*&: Under versions of OpenSSL preceding 1.1.1,
when a list of more than one
file is used, the &$tls_in_ourcert$& variable is unreliable.
-
-&*Note*&: OCSP stapling is not usable under OpenSSL
-when a list of more than one file is used.
+The macro "_TLS_BAD_MULTICERT_IN_OURCERT" will be defined for those versions.
If the option contains &$tls_out_sni$& and Exim is built against OpenSSL, then
if the OpenSSL build supports TLS extensions and the TLS client sends the
The value of this option is expanded and indicates the source of DH parameters
to be used by Exim.
-.new
This option is ignored for GnuTLS version 3.6.0 and later.
The library manages parameter negotiation internally.
-.wen
&*Note: The Exim Maintainers strongly recommend,
for other TLS library versions,
Certificate Authority.
Usable for GnuTLS 3.4.4 or 3.3.17 or OpenSSL 1.1.0 (or later).
+The macro "_HAVE_TLS_OCSP" will be defined for those versions.
-.new
For OpenSSL 1.1.0 or later, and
-.wen
for GnuTLS 3.5.6 or later the expanded value of this option can be a list
of files, to match a list given for the &%tls_certificate%& option.
The ordering of the two lists must match.
+The macro "_HAVE_TLS_OCSP_LIST" will be defined for those versions.
-.new
The file(s) should be in DER format,
-except for GnuTLS 3.6.3 or later when an optional filetype prefix
-can be used. The prefix must be one of "DER" or "PEM", followed by
+except for GnuTLS 3.6.3 or later
+or for OpenSSL,
+when an optional filetype prefix can be used.
+The prefix must be one of "DER" or "PEM", followed by
a single space. If one is used it sets the format for subsequent
files in the list; the initial format is DER.
-When a PEM format file is used it may contain multiple proofs,
-for multiple certificate chain element proofs under TLS1.3.
-.wen
+If multiple proofs are wanted, for multiple chain elements
+(this only works under TLS1.3)
+they must be coded as a combined OCSP response.
+
+Although GnuTLS will accept PEM files with multiple separate
+PEM blobs (ie. separate OCSP responses), it sends them in the
+TLS Certificate record interleaved with the certificates of the chain;
+although a GnuTLS client is happy with that, an OpenSSL client is not.
.option tls_on_connect_ports main "string list" unset
.cindex SSMTP
This makes the configuration file less messy, and also reduces the number of
lookups (though Exim does cache lookups).
-.new
See also the &%set%& option below.
-.wen
.vindex "&$sender_address_data$&"
.vindex "&$address_data$&"
unless you really, really know what you are doing. See also the generic
transport option of the same name.
-.option dnssec_request_domains routers "domain list&!!" unset
+.option dnssec_request_domains routers "domain list&!!" *
.cindex "MX record" "security"
.cindex "DNSSEC" "MX lookup"
.cindex "security" "MX lookup"
This option controls whether the local part is used to form the key for retry
hints for addresses that suffer temporary errors while being handled by this
-.new
router. The default value is true for any router that has any of
&%check_local_user%&,
&%local_parts%&,
&%local_part_suffix%&,
&%senders%& or
&%require_files%&
-.wen
set, and false otherwise. Note that this option does not apply to hints keys
for transport delays; they are controlled by a generic transport option of the
same name.
matters.
-.new
.option set routers "string list" unset
.cindex router variables
This option may be used multiple times on a router;
The list separator is a semicolon but can be changed in the
usual way.
-Each list-element given must be of the form $"name = value"$
+Each list-element given must be of the form &"name = value"&
and the names used must start with the string &"r_"&.
Values containing a list-separator should have them doubled.
When a router runs, the strings are evaluated in order,
(not including any preconditions)
and by the transport.
Later definitions of a given named variable will override former ones.
-Varible use is via the usual &$r_...$& syntax.
+Variable use is via the usual &$r_...$& syntax.
This is similar to the &%address_data%& option, except that
many independent variables can be used, with choice of naming.
-.wen
.option translate_ip_address routers string&!! unset
Section &<<SECID136>>& contains further information.
-.new
This option should not be used when other message-handling software
may duplicate messages by making hardlinks to the files. When that is done Exim
will count the message size once for each filename, in contrast with the actual
disk usage. When the option is not set, calculating total usage requires
a system-call per file to get the size; the number of links is then available also
as is used to adjust the effective size.
-.wen
.option quota_warn_message appendfile string&!! "see below"
details.
-.option dnssec_request_domains smtp "domain list&!!" unset
+.option dnssec_request_domains smtp "domain list&!!" *
.cindex "MX record" "security"
.cindex "DNSSEC" "MX lookup"
.cindex "security" "MX lookup"
Exim will not use the SMTP PIPELINING extension when delivering to any host
that matches this list, even if the server host advertises PIPELINING support.
-.new
.option hosts_pipe_connect smtp "host list&!!" unset
.cindex "pipelining" "early connection"
.cindex "pipelining" PIPE_CONNECT
It also turns SMTP into a client-first protocol
so combines well with TCP Fast Open.
+See also the &%pipelining_connect_advertise_hosts%& main option.
+
Note:
When the facility is used, the transport &%helo_data%& option
will be expanded before the &$sending_ip_address$& variable
presence of a &"def:"& test on it, but suitably complex coding
can avoid the check and produce unexpected results.
You have been warned.
-.wen
.option hosts_avoid_tls smtp "host list&!!" unset
message on the same connection. See section &<<SECTmulmessam>>& for an
explanation of when this might be needed.
-.new
.option hosts_noproxy_tls smtp "host list&!!" unset
.cindex "TLS" "passing connection"
.cindex "multiple SMTP deliveries"
For any host that matches this list, a TLS session which has
been started will not be passed to a new delivery process for sending another
message on the same session.
-.wen
The traditional implementation closes down TLS and re-starts it in the new
process, on the same open TCP connection, for each successive message
the Cyrus SASL authentication library.
The third is an interface to Dovecot's authentication system, delegating the
work via a socket interface.
-.new
The fourth provides for negotiation of authentication done via non-SMTP means,
as defined by RFC 4422 Appendix A.
-.wen
The fifth provides an interface to the GNU SASL authentication library, which
provides mechanisms but typically not data sources.
The sixth provides direct access to Heimdal GSSAPI, geared for Kerberos, but
use unencrypted plain text, you should not use the same passwords for SMTP
connections as you do for login accounts.
-.section "Plaintext options" "SECID171"
+.section "Avoiding cleartext use" "SECTplain_TLS"
+The following generic option settings will disable &(plaintext)& authenticators when
+TLS is not being used:
+.code
+ server_advertise_condition = ${if def:tls_in_cipher }
+ client_condition = ${if def:tls_out_cipher}
+.endd
+
+&*Note*&: a plaintext SMTP AUTH done inside TLS is not vulnerable to casual snooping,
+but is still vulnerable to a Man In The Middle attack unless certificates
+(including their names) have been properly verified.
+
+.section "Plaintext server options" "SECID171"
.cindex "options" "&(plaintext)& authenticator (server)"
When configured as a server, &(plaintext)& uses the following options:
This is actually a global authentication option, but it must be set in order to
configure the &(plaintext)& driver as a server. Its use is described below.
-.option server_prompts plaintext string&!! unset
+.option server_prompts plaintext "string list&!!" unset
The contents of this option, after expansion, must be a colon-separated list of
prompt strings. If expansion fails, a temporary authentication rejection is
given.
(which usually means the full set of public CAs)
and which has a mail-SAN matching the claimed identity sent by the client.
-Note that, up to TLS1.2, the client cert is on the wire in-clear, including the SAN,
+&*Note*&: up to TLS1.2, the client cert is on the wire in-clear, including the SAN.
The account name is therefore guessable by an opponent.
TLS 1.3 protects both server and client certificates, and is not vulnerable
in this way.
-Likewise, a traditional plaintext SMTP AUTH done inside TLS is not.
.section "Using external in a client" "SECTexternclient"
.section "OpenSSL vs GnuTLS" "SECTopenvsgnu"
.cindex "TLS" "OpenSSL &'vs'& GnuTLS"
-The first TLS support in Exim was implemented using OpenSSL. Support for GnuTLS
-followed later, when the first versions of GnuTLS were released. To build Exim
-to use GnuTLS, you need to set
+TLS is supported in Exim using either the OpenSSL or GnuTLS library.
+To build Exim to use OpenSSL you need to set
.code
-USE_GNUTLS=yes
+USE_OPENSSL=yes
.endd
-in Local/Makefile, in addition to
+in Local/Makefile.
+
+To build Exim to use GnuTLS, you need to set
.code
-SUPPORT_TLS=yes
+USE_GNUTLS=yes
.endd
+in Local/Makefile.
+
You must also set TLS_LIBS and TLS_INCLUDE appropriately, so that the
include files and libraries for GnuTLS can be found.
if it requests it. If the server is Exim, it will request a certificate only if
&%tls_verify_hosts%& or &%tls_try_verify_hosts%& matches the client.
-.new
-Do not use a certificate which has the OCSP-must-staple extension,
+&*Note*&: Do not use a certificate which has the OCSP-must-staple extension,
for client use (they are usable for server use).
-As TLS has no means for the client to staple before TLS 1.3 it will result
+As the TLS protocol has no means for the client to staple before TLS 1.3 it will result
in failed connections.
-.wen
If the &%tls_verify_certificates%& option is set on the &(smtp)& transport, it
specifies a collection of expected server certificates.
For client-side DANE there are three new smtp transport options, &%hosts_try_dane%&, &%hosts_require_dane%&
and &%dane_require_tls_ciphers%&.
-The require variant will result in failure if the target host is not
+The &"require"& variant will result in failure if the target host is not
DNSSEC-secured. To get DNSSEC-secured hostname resolution, use
the &%dnssec_request_domains%& router or transport option.
If DANE is not usable, whether requested or not, and CA-anchored
verification evaluation is wanted, the above variables should be set appropriately.
-Currently the (router or transport options) &%dnssec_request_domains%& must be active and &%dnssec_require_domains%& is ignored.
+The router and transport option &%dnssec_request_domains%& must not be
+set to &"never"&, 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".
&'Resent-Cc:'& header lines exist, they are also checked. This condition can be
used only in a DATA or non-SMTP ACL.
-.new
There is one possible option, &`case_insensitive`&. If this is present then
local parts are checked case-insensitively.
-.wen
There are, of course, many legitimate messages that make use of blind (bcc)
recipients. This check should not be used on its own for blocking messages.
specialized interfaces for &"daemon"& type virus scanners, which are resident
in memory and thus are much faster.
-.new
Since message data needs to have arrived,
the condition may be only called in ACL defined by
&%acl_smtp_data%&,
&%acl_smtp_data_prdr%&,
&%acl_smtp_mime%& or
&%acl_smtp_dkim%&
-.wen
A timeout of 2 minutes is applied to a scanner call (by default);
if it expires then a defer action is taken.
This function is used in conjunction with &'smtp_printf()'&, as described
below.
-.vitem &*void&~smtp_printf(char&~*,&~...)*&
-The arguments of this function are like &[printf()]&; it writes to the SMTP
+.vitem &*void&~smtp_printf(char&~*,BOOL,&~...)*&
+The arguments of this function are almost like &[printf()]&; it writes to the SMTP
output stream. You should use this function only when there is an SMTP output
stream, that is, when the incoming message is being received via interactive
SMTP. This is the case when &%smtp_input%& is TRUE and &%smtp_batched_input%&
If an SMTP TLS connection is established, &'smtp_printf()'& uses the TLS
output function, so it can be used for all forms of SMTP connection.
+The second argument is used to request that the data be buffered
+(when TRUE) or flushed (along with any previously buffered, when FALSE).
+This is advisory only, but likely to save on system-calls and packets
+sent when a sequence of calls to the function are made.
+
+The argument was added in Exim version 4.90 - changing the API/ABI.
+Nobody noticed until 4.93 was imminent, at which point the
+ABI version number was incremented.
+
Strings that are written by &'smtp_printf()'& from within &[local_scan()]&
must start with an appropriate response code: 550 if you are going to return
LOCAL_SCAN_REJECT, 451 if you are going to return
multiple output lines.
The &'smtp_printf()'& function does not return any error indication, because it
-does not automatically flush pending output, and therefore does not test
+does not
+guarantee a flush of
+pending output, and therefore does not test
the state of the stream. (In the main code of Exim, flushing and error
detection is done when Exim is ready for the next SMTP input command.) If
you want to flush the output and check for an error (for example, the
&%millisec%&: Timestamps have a period and three decimal places of finer granularity
appended to the seconds value.
.next
-.new
.cindex "log" "message id"
&%msg_id%&: The value of the Message-ID: header.
.next
This will be either because the message is a bounce, or was submitted locally
(submission mode) without one.
The field identifier will have an asterix appended: &"id*="&.
-.wen
.next
.cindex "log" "outgoing interface"
.cindex "log" "local interface"
On accept lines, where PIPELINING was offered but not used by the client,
the field has a minus appended.
-.new
.cindex "pipelining" "early connection"
If Exim is built with the SUPPORT_PIPE_CONNECT build option
accept "L" fields have a period appended if the feature was
offered but not used, or an asterisk appended if used.
Delivery "L" fields have an asterisk appended if used.
-.wen
.next
.cindex "log" "queue run"
.vitem &*-x*&
Match only non-frozen messages.
-.new
.vitem &*-G*&&~<&'queuename'&>
Match only messages in the given queue. Without this, the default queue is searched.
-.wen
.endlist
The following options control the format of the output:
certificate.
.endlist
-.new
Any of the above may have an extra hyphen prepended, to indicate the the
corresponding data is untrusted.
-.wen
Following the options there is a list of those addresses to which the message
is not to be delivered. This set of addresses is initialized from the command
The domain(s) you want to sign with.
After expansion, this can be a list.
Each element in turn,
-.new
lowercased,
-.wen
is put into the &%$dkim_domain%& expansion variable
while expanding the remaining signing options.
If it is empty after expansion, DKIM signing is not done,
Signers SHOULD use RSA keys of at least 2048 bits.
.endd
-.new
EC keys for DKIM are defined by RFC 8463.
-.wen
They are considerably smaller than RSA keys for equivalent protection.
As they are a recent development, users should consider dual-signing
(by setting a list of selectors, and an expansion for this option)
certtool --load_privkey=dkim_ed25519.private --pubkey_info --outder | tail -c +13 | base64
.endd
-.new
Exim also supports an alternate format
of Ed25519 keys in DNS which was a candidate during development
of the standard, but not adopted.
A future release will probably drop that support.
-.wen
.option dkim_hash smtp string&!! sha256
Can be set to any one of the supported hash methods, which are:
Verification of DKIM signatures in SMTP incoming email is done for all
messages for which an ACL control &%dkim_disable_verify%& has not been set.
-.new
.cindex DKIM "selecting signature algorithms"
Individual classes of signature algorithm can be ignored by changing
the main options &%dkim_verify_hashes%& or &%dkim_verify_keytypes%&.
The &%dkim_verify_minimal%& option can be set to cease verification
processing for a message once the first passing signature is found.
-.wen
.cindex authentication "expansion item"
Performing verification sets up information used by the
&%authresults%& expansion item.
-.new
For most purposes the default option settings suffice and the remainder
of this section can be ignored.
-.wen
The results of verification are made available to the
&%acl_smtp_dkim%& ACL, which can examine and modify them.
If a domain or identity is listed several times in the (expanded) value of
&%dkim_verify_signers%&, the ACL is only called once for that domain or identity.
-.new
Note that if the option is set using untrustworthy data
(such as the From: header)
care should be taken to force lowercase for domains
and for the domain part if identities.
The default setting can be regarded as trustworthy in this respect.
-.wen
If multiple signatures match a domain (or identity), the ACL is called once
for each matching signature.
To enforce this you must either have a DKIM ACL which checks this variable
and overwrites the &$dkim_verify_status$& variable as discussed above,
-.new
or have set the main option &%dkim_verify_hashes%& to exclude
processing of such signatures.
-.wen
.vitem &%$dkim_canon_body%&
The body canonicalization method. One of 'relaxed' or 'simple'.
SPF is a mechanism whereby a domain may assert which IP addresses may transmit
messages with its domain in the envelope from, documented by RFC 7208.
-For more information on SPF see &url(http://www.openspf.org).
-. --- 2018-09-07: still not https
+For more information on SPF see &url(http://www.open-spf.org), a static copy of
+the &url(http://openspf.org).
+. --- 2019-10-28: still not https, open-spf.org is told to be a
+. --- web-archive copy of the now dead openspf.org site
+. --- See https://www.mail-archive.com/mailop@mailop.org/msg08019.html for a
+. --- discussion.
Messages sent by a system not authorised will fail checking of such assertions.
This includes retransmissions done by traditional forwarders.
message = $sender_host_address is not allowed to send mail from \
${if def:sender_address_domain \
{$sender_address_domain}{$sender_helo_name}}. \
- Please see http://www.openspf.org/Why?scope=\
+ Please see http://www.open-spf.org/Why?scope=\
${if def:sender_address_domain {mfrom}{helo}};\
identity=${if def:sender_address_domain \
{$sender_address}{$sender_helo_name}};\
"Best-guess". Strictly speaking, "Best-guess" is not standard
SPF, but it is supported by the same framework that enables SPF
capability.
-Refer to &url(http://www.openspf.org/FAQ/Best_guess_record)
+Refer to &url(http://www.open-spf.org/FAQ/Best_guess_record)
for a description of what it means.
-. --- 2018-09-07: still not https:
+. --- 2019-10-28: still not https:
To access this feature, simply use the spf_guess condition in place
of the spf one. For example:
.cindex lookup spf
A lookup expansion is also available. It takes an email
address as the key and an IP address
-.new
(v4 or v6)
-.wen
as the database:
.code
-.new
.section DMARC SECDMARC
.cindex DMARC verification
For building Exim yourself, obtain the library from
&url(http://sourceforge.net/projects/opendmarc/)
-to obtain a copy, or find it in your favorite rpm package
+to obtain a copy, or find it in your favorite package
repository. You will need to attend to the local/Makefile feature
SUPPORT_DMARC and the associated LDFLAGS addition.
This description assumes
status of messages coming from remote, untrusted sources. You can
use standard conditions such as hosts, senders, etc, to decide that
DMARC verification should *not* be performed for them and disable
-DMARC with a control setting:
+DMARC with an ACL control modifier:
.code
control = dmarc_disable_verify
.endd
be subscribed to, etc). You must configure exim to submit forensic
reports to the owner of the domain. If the DMARC record contains a
forensic address and you specify the control statement below, then
-exim will send these forensic emails. It's also advised that you
-configure a dmarc_forensic_sender because the default sender address
+exim will send these forensic emails. It is also advised that you
+configure a &%dmarc_forensic_sender%& because the default sender address
construction might be inadequate.
.code
control = dmarc_enable_forensic
.endd
(AGAIN: You can choose not to send these forensic reports by simply
not putting the dmarc_enable_forensic control line at any point in
-your exim config. If you don't tell it to send them, it will not
+your exim config. If you don't tell exim to send them, it will not
send them.)
There are no options to either control. Both must appear before
. subsection
DMARC checks cam be run on incoming SMTP messages by using the
-"dmarc_status" ACL condition in the DATA ACL. You are required to
-call the "spf" condition first in the ACLs, then the "dmarc_status"
+&"dmarc_status"& ACL condition in the DATA ACL. You are required to
+call the &"spf"& condition first in the ACLs, then the &"dmarc_status"&
condition. Putting this condition in the ACLs is required in order
for a DMARC check to actually occur. All of the variables are set
up before the DATA ACL, but there is no actual DMARC check that
-occurs until a "dmarc_status" condition is encountered in the ACLs.
+occurs until a &"dmarc_status"& condition is encountered in the ACLs.
-The dmarc_status condition takes a list of strings on its
+The &"dmarc_status"& condition takes a list of strings on its
right-hand side. These strings describe recommended action based
on the DMARC check. To understand what the policy recommendations
mean, refer to the DMARC website above. Valid strings are:
processed, and you can use them in this ACL. The following
expansion variables are available:
-&$dmarc_status$&
+.vlist
+.vitem &$dmarc_status$&
.vindex &$dmarc_status$&
.cindex DMARC result
-is a one word status indicating what the DMARC library
+A one word status indicating what the DMARC library
thinks of the email. It is a combination of the results of
DMARC record lookup and the SPF/DKIM/DMARC processing results
(if a DMARC record was found). The actual policy declared
in the DMARC record is in a separate expansion variable.
-&$dmarc_status_text$&
+.vitem &$dmarc_status_text$&
.vindex &$dmarc_status_text$&
-is a slightly longer, human readable status.
+Slightly longer, human readable status.
-&$dmarc_used_domain$&
+.vitem &$dmarc_used_domain$&
.vindex &$dmarc_used_domain$&
-is the domain which DMARC used to look up the DMARC policy record.
+The domain which DMARC used to look up the DMARC policy record.
-&$dmarc_domain_policy$&
+.vitem &$dmarc_domain_policy$&
.vindex &$dmarc_domain_policy$&
-is the policy declared in the DMARC record. Valid values
+The policy declared in the DMARC record. Valid values
are "none", "reject" and "quarantine". It is blank when there
is any error, including no DMARC record.
+.endlist
. subsection
In order to log statistics suitable to be imported by the opendmarc
tools, you need to:
.ilist
-Configure the global setting dmarc_history_file
+Configure the global option &%dmarc_history_file%&
.next
Configure cron jobs to call the appropriate opendmarc history
import scripts and truncating the dmarc_history_file
In order to send forensic reports, you need to:
.ilist
-Configure the global setting dmarc_forensic_sender
+Configure the global option &%dmarc_forensic_sender%&
.next
Configure, somewhere before the DATA ACL, the control option to
enable sending DMARC forensic reports
warn add_header = :at_start:${authresults {$primary_hostname}}
.endd
-.wen
The name is placed in the variable &$event_name$& and the event action
expansion must check this, as it will be called for every possible event type.
-.new
The current list of events is:
-.wen
.display
&`dane:fail after transport `& per connection
&`msg:complete after main `& per message
-Change log file for Exim from version 4.21
-------------------------------------------
This document describes *changes* to previous versions, that might
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.next
--------------------
+Exim version 4.94
+-----------------
JH/01 Avoid costly startup code when not strictly needed. This reduces time
for some exim process initialisations. It does mean that the logging
function is unnecessary and discouraged on GnuTLS 3.6.0 or later. Since
3.6.0, DH parameters are negotiated following RFC7919."
+HS/06 Change the default of dnssec_request_domains to "*"
+
+JH/42 Bug 2545: Fix CHUNKING for all RCPT commands rejected. Previously we
+ carried on and emitted a BDAT command, even when PIPELINING was not
+ active.
+
JH/43 Bug 2465: Fix taint-handling in dsearch lookup. Previously a nontainted
buffer was used for the filename, resulting in a trap when tainted
arguments (eg. $domain) were used.
+JH/44 With OpenSSL 1.1.1 (onwards) disable renegotiation for TLS1.2 and below;
+ recommended to avoid a possible server-load attack. The feature can be
+ re-enabled via the openssl_options main cofiguration option.
+
+JH/45 local_scan API: documented the current smtp_printf() call. This changed
+ for version 4.90 - adding a "more data" boolean to the arguments.
+ Bumped the ABI version number also, this having been missed previously;
+ release versions 4.90 to 4.92.3 inclusive were effectively broken in
+ respect of usage of smtp_printf() by either local_scan code or libraries
+ accessed via the ${dlfunc } expansion item. Both will need coding
+ adjustment for any calls to smtp_printf() to match the new function
+ signature; a FALSE value for the new argument is always safe.
+
JH/46 FreeBSD: fix use of the sendfile() syscall. The shim was not updating
the file-offset (which the Linux syscall does, and exim expects); this
resulted in an indefinite loop.
+JH/47 ARC: fix crash in signing, triggered when a configuration error failed
+ to do ARC verification. The Authentication-Results: header line added
+ by the configuration then had no ARC item.
+
Exim version 4.92
-----------------
test from the snapshots or the Git before the documentation is updated. Once
the documentation is updated, this file is reduced to a short list.
-Version 4.next
---------------
+Version 4.94
+------------
1. EXPERIMENTAL_SRS_NATIVE optional build feature. See the experimental.spec
file.
- 2. Variables $tls_in_ver, $tls_out_ver.
-
- 3. Channel-binding for authenticators is now supported under OpenSSL.
+ 2. Channel-binding for authenticators is now supported under OpenSSL.
Previously it was GnuTLS-only.
11. Main options for DKIM verify to filter hash and key types.
-12. Under GnuTLS, with TLS1.3, support for full-chain OCSP stapling.
+12. With TLS1.3, support for full-chain OCSP stapling.
13. Dual-certificate stacks on servers now support OCSP stapling, under OpenSSL.
14: An smtp:ehlo transport event, for observability of the remote offered features.
+15: Support under OpenSSL for writing NSS-style key files for packet-capture
+ decode. The environment variable SSLKEYLOGFILE is used; if an absolute path
+ it must indicate a file under the spool directory; if relative the the spool
+ directory is prepended. Works on the server side only. Support under
+ GnuTLS was already there, being done purely by the library (server side
+ only, and exim must be run as root).
+
+16: Command-line option to move messages from one named queue to another.
+
+17. Variables $tls_in_ver, $tls_out_ver.
+
Version 4.92
--------------
Specification: https://tools.ietf.org/html/draft-ietf-dmarc-arc-protocol-11
Note that this is not an RFC yet, so may change.
+[RFC 8617 was published 2019/06. Draft 11 was 2018/01. A review of the
+changes has not yet been done]
+
ARC is intended to support the utility of SPF and DKIM in the presence of
intermediaries in the transmission path - forwarders and mailinglists -
by establishing a cryptographically-signed chain in headers.
an intermediary. One might do verify for local destinations.
ARC uses the notion of a "ADministrative Management Domain" (ADMD).
-Described in RFC 5598 (section 2.3), this is essentially the set of
-mail-handling systems that the mail transits. A label should be chosen to
-identify the ADMD. Messages should be ARC-verified on entry to the ADMD,
-and ARC-signed on exit from it.
+Described in RFC 5598 (section 2.3), this is essentially a set of
+mail-handling systems that mail transits that are all under the control
+of one organisation. A label should be chosen to identify the ADMD.
+Messages should be ARC-verified on entry to the ADMD, and ARC-signed on exit
+from it.
+
+
+Building with ARC Support
+--
+Enable using EXPERIMENTAL_ARC=yes in your Local/Makefile.
+You must also have DKIM present (not disabled), and you very likely
+want to have SPF enabled.
Verification
#my $stamp = $context->{minor} ? '_'.$context->{minor} : '';
#$stamp .= $context->{rc} if $context->{rc};
- my $release = $context->{v}{rc} ? $context->{v}{target_release}
- : $context->{v}{last_tag};
+ my $release = $context->{quick} ? $context->{v}{last_tag}
+ : $context->{v}{target_release};
my $variant =
$context->{v}{rc} ? $context->{v}{rc}
# See also environment variables set in main, tuning compression levels
- my (%size, %sha256);
+ my (%size, %sha256, %sha512);
foreach my $dir ( glob( catdir( $pkg_trees, ( 'exim*-' . $context->{v}{release} ) ) ) ) {
my $dirname = ( splitdir($dir) )[-1];
# calculate size and md5sum
$size{$basename} = -s $outfile;
- $sha256{$basename} = do {
- my $sha = Digest::SHA->new(256);
- $sha->addfile($outfile);
- $sha->hexdigest;
- };
+ $sha256{$basename} = Digest::SHA->new(256)->addfile($outfile)->hexdigest;
+ $sha512{$basename} = Digest::SHA->new(512)->addfile($outfile)->hexdigest;
}
}
# write the sizes file
if ($context->{sizes}) {
- open my $sizes, '>', $_ = catfile $pkg_tars, 'sizes.txt'
- or die "$ME: Can't open `$_': $!\n";
+ for ([ sizes => 'SIZE' => \%size ],
+ [ sha256sums => 'SHA256' => \%sha256 ],
+ [ sha512sums => 'SHA512' => \%sha512 ]) {
- print $sizes join "\n",
- (map { "SIZE($_) = $size{$_}" } sort keys %size),
- (map { "SHA256($_) = $sha256{$_}" } sort keys %sha256);
+ my $outfile = catfile $pkg_tars, "00-$_->[0].txt";
+ my $tag = $_->[1];
+ my $sizes = $_->[2];
- close($sizes) or die "$ME: Can't close $_: $!\n";
+ open my $out, '>', $outfile
+ or die "$ME: Can't open `$outfile': $!\n";
+
+ print $out join "\n",
+ (map { "$tag ($_) = $sizes->{$_}" } sort keys %$sizes),
+ '';
+
+ close($out) or die "$ME: Can't close $outfile: $!\n";
+ }
}
}
# Exim: OS-specific make file for FreeBSD
-# There's no setting of CFLAGS here, to allow the system default
-# for "make" to be the default.
CHOWN_COMMAND=/usr/sbin/chown
STRIP_COMMAND=/usr/bin/strip
The rest of this document contains information about changes in 4.xx releases
that might affect a running system.
+Exim version 4.93
+-----------------
+
+For a detailed list of changes that might affect Exim's operation with
+an unchanged configuration, please see the doc/ChangeLog file.
+
+Build:
+
+ * SUPPORT_DMARC replaces EXPERIMENTAL_DMARC
+
+ * DISABLE_TLS replaces SUPPORT_TLS
+
+ * Bump the version for the local_scan API.
+
+Runtime:
+
+ * smtp transport option hosts_try_fastopen defaults to "*".
+
+ * DNSSec is requested (not required) for all queries. (This seemes to
+ ask for trouble if your resolver is a systemd-resolved.)
+
+ * Generic router option retry_use_local_part defaults to "true" under specific
+ pre-conditions.
+
+ * Introduce a tainting mechanism for values read from untrusted sources.
+
+ * Use longer file names for temporary spool files (this avoids
+ name conflicts with spool on a shared file system).
+
+ * Use dsn_from main config option (was ignored previously).
+
Exim version 4.92
-----------------
#------------------------------------------------------------------------------
# Compiling the Exim monitor: If you want to compile the Exim monitor, a
# program that requires an X11 display, then EXIM_MONITOR should be set to the
-# value "eximon.bin". Comment out this setting to disable compilation of the
+# value "eximon.bin". De-comment this setting to enable compilation of the
# monitor. The locations of various X11 directories for libraries and include
# files are defaulted in the OS/Makefile-Default file, but can be overridden in
# local OS-specific make files.
-EXIM_MONITOR=eximon.bin
+# EXIM_MONITOR=eximon.bin
#------------------------------------------------------------------------------
if (string_is_ip_address(domain, NULL) != 0)
{
if (!dns_csa_use_reverse) return CSA_UNKNOWN;
- dns_build_reverse(domain, target);
- domain = target;
+ domain = dns_build_reverse(domain);
}
/* Find out if we've already done the CSA check for this domain. If we have,
*/
#include "exim.h"
-#ifdef EXPERIMENTAL_ARC
-# if !defined SUPPORT_SPF
-# error SPF must also be enabled for ARC
-# elif defined DISABLE_DKIM
+#if defined EXPERIMENTAL_ARC
+# if defined DISABLE_DKIM
# error DKIM must also be enabled for ARC
# else
const uschar * s;
int len;
-if (!exim_sha_init(&hhash_ctx, pdkim_hashes[hashtype].exim_hashmethod))
+if ( hashtype == -1
+ || !exim_sha_init(&hhash_ctx, pdkim_hashes[hashtype].exim_hashmethod))
{
DEBUG(D_acl)
debug_printf("ARC: hash setup error, possibly nonhandled hashtype\n");
static pdkim_bodyhash *
arc_ams_setup_vfy_bodyhash(arc_line * ams)
{
-int canon_head, canon_body;
+int canon_head = -1, canon_body = -1;
long bodylen;
if (!ams->c.data) ams->c.data = US"simple"; /* RFC 6376 (DKIM) default */
}
hashtype = pdkim_hashname_to_hashtype(ams->a_hash.data, ams->a_hash.len);
+if (hashtype == -1)
+ {
+ DEBUG(D_acl) debug_printf("ARC i=%d AMS verify bad a_hash\n", as->instance);
+ return as->ams_verify_done = arc_state_reason = US"AMS sig nonverify";
+ }
if ((errstr = exim_dkim_verify(&vctx,
pdkim_hashes[hashtype].exim_hashmethod, &hhash, &sighash)))
hashtype = pdkim_hashname_to_hashtype(hdr_as->a_hash.data, hdr_as->a_hash.len);
-if (!exim_sha_init(&hhash_ctx, pdkim_hashes[hashtype].exim_hashmethod))
+if ( hashtype == -1
+ || !exim_sha_init(&hhash_ctx, pdkim_hashes[hashtype].exim_hashmethod))
{
DEBUG(D_acl)
debug_printf("ARC: hash setup error, possibly nonhandled hashtype\n");
return US"fail";
}
-hashtype = pdkim_hashname_to_hashtype(hdr_as->a_hash.data, hdr_as->a_hash.len);
-
if ((errstr = exim_dkim_verify(&vctx,
pdkim_hashes[hashtype].exim_hashmethod,
&hhash_computed, &sighash)))
const uschar * privkey, unsigned options)
{
gstring * arcset;
-arc_set * as;
uschar * status = arc_ar_cv_status(ar);
arc_line * al = store_get(sizeof(header_line) + sizeof(arc_line), FALSE);
header_line * h = (header_line *)(al+1);
+uschar * badline_str;
gstring * hdata = NULL;
int hashtype = pdkim_hashname_to_hashtype(US"sha256", 6); /*XXX hardwired */
- all ARC set headers, set-number order, aar then ams then as,
including self (but with an empty b= in self)
*/
+DEBUG(D_transport) debug_printf("ARC: building AS for status '%s'\n", status);
/* Construct the AS except for the signature */
/* For any but "fail" chain-verify status, walk the entire chain in order by
instance. For fail, only the new arc-set. Accumulate the elements walked. */
-for (as = Ustrcmp(status, US"fail") == 0
+for (arc_set * as = Ustrcmp(status, US"fail") == 0
? ctx->arcset_chain_last : ctx->arcset_chain;
as; as = as->next)
{
+ arc_line * l;
/* Accumulate AAR then AMS then AS. Relaxed canonicalisation
is required per standard. */
- h = as->hdr_aar->complete;
+ badline_str = US"aar";
+ if (!(l = as->hdr_aar)) goto badline;
+ h = l->complete;
hdata = string_cat(hdata, pdkim_relax_header_n(h->text, h->slen, TRUE));
- h = as->hdr_ams->complete;
+ badline_str = US"ams";
+ if (!(l = as->hdr_ams)) goto badline;
+ h = l->complete;
hdata = string_cat(hdata, pdkim_relax_header_n(h->text, h->slen, TRUE));
- h = as->hdr_as->complete;
+ badline_str = US"as";
+ if (!(l = as->hdr_as)) goto badline;
+ h = l->complete;
hdata = string_cat(hdata, pdkim_relax_header_n(h->text, h->slen, !!as->next));
}
/* Finally, append the AMS and AAR to the new AS */
return string_catn(arcset, arcset_interim->s, arcset_interim->ptr);
+
+badline:
+ DEBUG(D_transport)
+ debug_printf("ARC: while building AS, missing %s in chain\n", badline_str);
+ return NULL;
}
if ((errstr = arc_parse_line(&al, &h, ARC_HDRLEN_AMS, FALSE)))
{
DEBUG(D_acl) if (errstr) debug_printf("ARC: %s\n", errstr);
- return US"line parsing error";
+ goto badline;
+ }
+
+if (!al.a_hash.data)
+ {
+ DEBUG(D_acl) debug_printf("ARC: no a_hash from '%.*s'\n", h.slen, h.text);
+ goto badline;
}
/* defaults */
should have been created here. */
return NULL;
+
+badline:
+ return US"line parsing error";
}
}
-# endif /* SUPPORT_SPF */
+# endif /* DISABLE_DKIM */
#endif /* EXPERIMENTAL_ARC */
/* vi: aw ai sw=2
*/
.ifdef _HAVE_PRDR
acl_check_prdr:
warn set acl_m_did_prdr = y
-.endif
#############################################################################
# do lookup on filtering, with $local_part@$domain, deny on filter match
#############################################################################
accept
+.endif
# This ACL is used after the contents of a message have been received. This
# is the ACL in which you can test a message's headers or body, and in
transport = smarthost_smtp
route_data = ROUTER_SMARTHOST
ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
-.ifdef _HAVE_DNSSEC
- dnssec_request_domains = *
-.endif
no_more
.else
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
# if ipv6-enabled then instead use:
# ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
-.ifdef _HAVE_DNSSEC
- dnssec_request_domains = *
-.endif
no_more
# This closes the ROUTER_SMARTHOST ifdef around the choice of routing for
remote_smtp:
driver = smtp
message_size_limit = ${if > {$max_received_linelength}{998} {1}{0}}
-.ifdef _HAVE_DANE
- hosts_try_dane = *
-.endif
.ifdef _HAVE_PRDR
hosts_try_prdr = *
.endif
}
}
- if (dane->selectors[DANESSL_USAGE_DANE_TA])
+if (dane->selectors[DANESSL_USAGE_DANE_TA])
+ {
+ if ((matched = set_trust_anchor(ctx, dane, cert)) < 0)
{
- if ((matched = set_trust_anchor(ctx, dane, cert)) < 0)
- {
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_OUT_OF_MEM);
- return -1;
- }
- if (matched)
- {
- /*
- * Check that setting the untrusted chain updates the expected
- * structure member at the expected offset.
- */
- X509_STORE_CTX_trusted_stack(ctx, dane->roots);
- X509_STORE_CTX_set_chain(ctx, dane->chain);
- OPENSSL_assert(dane->chain == X509_STORE_CTX_get0_untrusted(ctx));
- }
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_OUT_OF_MEM);
+ return -1;
}
+ if (matched)
+ {
+ /*
+ * Check that setting the untrusted chain updates the expected
+ * structure member at the expected offset.
+ */
+ X509_STORE_CTX_trusted_stack(ctx, dane->roots);
+ X509_STORE_CTX_set_chain(ctx, dane->chain);
+ OPENSSL_assert(dane->chain == X509_STORE_CTX_get0_untrusted(ctx));
+ }
+ }
- /*
- * Name checks and usage 0/1 constraint enforcement are delayed until
- * X509_verify_cert() builds the full chain and calls our verify_chain()
- * wrapper.
- */
- dane->verify = X509_STORE_CTX_get_verify(ctx);
- X509_STORE_CTX_set_verify(ctx, verify_chain);
+/*
+ * Name checks and usage 0/1 constraint enforcement are delayed until
+ * X509_verify_cert() builds the full chain and calls our verify_chain()
+ * wrapper.
+ */
+dane->verify = X509_STORE_CTX_get_verify(ctx);
+X509_STORE_CTX_set_verify(ctx, verify_chain);
- if (X509_verify_cert(ctx))
- return 1;
+if (X509_verify_cert(ctx))
+ return 1;
- /*
- * If the chain is invalid, clear any matching cert or hostname, to
- * protect callers that might erroneously rely on these alone without
- * checking the validation status.
- */
- if (dane->match)
- {
- X509_free(dane->match);
- dane->match = 0;
- }
- if (dane->mhost)
- {
- OPENSSL_free(dane->mhost);
- dane->mhost = 0;
- }
- return 0;
+/*
+ * If the chain is invalid, clear any matching cert or hostname, to
+ * protect callers that might erroneously rely on these alone without
+ * checking the validation status.
+ */
+if (dane->match)
+ {
+ X509_free(dane->match);
+ dane->match = 0;
+ }
+if (dane->mhost)
+ {
+ OPENSSL_free(dane->mhost);
+ dane->mhost = 0;
+ }
+ return 0;
}
static dane_list
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) Wolfgang Breyha 2005 - 2015
+/* Copyright (c) Wolfgang Breyha 2005 - 2019
* Vienna University Computer Center
* wbreyha@gmx.net
* See the file NOTICE for conditions of use and distribution.
*
- * Copyright (c) The Exim Maintainers 2015 - 2018
+ * Copyright (c) The Exim Maintainers 2015 - 2019
*/
-/* This patch is based on code from Tom Kistners exiscan (ACL integration) and
- * the DCC local_scan patch from Christopher Bodenstein */
-
/* Code for calling dccifd. Called from acl.c. */
#include "exim.h"
#include "dcc.h"
#include "unistd.h"
-uschar dcc_header_str[256];
+#define DCC_HEADER_LIMIT 120
+
int dcc_ok = 0;
int dcc_rc = 0;
/* This function takes a file descriptor and a buffer as input and
* returns either 0 for success or errno in case of error. */
-int flushbuffer (int socket, uschar *buffer)
- {
+int flushbuffer (int socket, gstring *buffer)
+{
int retval, rsp;
- rsp = write(socket, buffer, Ustrlen(buffer));
+ rsp = write(socket, buffer->s, buffer->ptr);
DEBUG(D_acl)
- debug_printf("DCC: Result of the write() = %d\n", rsp);
- if(rsp < 0)
- {
+ debug_printf("DCC: flushbuffer(): Result of the write() = %d\n", rsp);
+ if(rsp < 0) {
DEBUG(D_acl)
- debug_printf("DCC: Error writing buffer to socket: %s\n", strerror(errno));
+ debug_printf("DCC: flushbuffer(): Error writing buffer to socket: %s\n", strerror(errno));
retval = errno;
}
else {
DEBUG(D_acl)
- debug_printf("DCC: Wrote buffer to socket:\n%s\n", buffer);
+ debug_printf("DCC: flushbuffer(): Wrote buffer to socket:\n%.*s\n", buffer->ptr, buffer->s);
retval = 0;
}
return retval;
FILE *data_file;
uschar *dcc_default_ip_option = US"127.0.0.1";
uschar *dcc_helo_option = US"localhost";
- uschar *dcc_reject_message = US"Rejected by DCC";
uschar *xtra_hdrs = NULL;
uschar *override_client_ip = NULL;
/* from local_scan */
- int j, k, c, retval, sockfd, resp, line;
+ int dcc_resplen, retval, sockfd, resp;
unsigned int portnr;
struct sockaddr_un serv_addr;
struct sockaddr_in serv_addr_in;
struct hostent *ipaddress;
uschar sockpath[128];
uschar sockip[40], client_ip[40];
- uschar opts[128];
- uschar rcpt[128], from[128];
- uschar sendbuf[4096];
- uschar recvbuf[4096];
- uschar dcc_return_text[1024];
- struct header_line *dcchdr;
+ gstring *dcc_headers;
+ gstring *sendbuf;
+ uschar *dcc_return_text;
+ struct header_line *mail_headers;
uschar *dcc_acl_options;
- uschar dcc_acl_options_buffer[10];
- uschar dcc_xtra_hdrs[1024];
+ gstring *dcc_xtra_hdrs;
+ gstring *dcc_header_str;
/* grep 1st option */
- if ((dcc_acl_options = string_nextinlist(&list, &sep,
- dcc_acl_options_buffer, sizeof(dcc_acl_options_buffer))))
- {
+ if ((dcc_acl_options = string_nextinlist(&list, &sep, NULL, 0))) {
/* parse 1st option */
if ( strcmpic(dcc_acl_options, US"false") == 0
- || Ustrcmp(dcc_acl_options, "0") == 0
- )
+ || Ustrcmp(dcc_acl_options, "0") == 0)
return FAIL; /* explicitly no matching */
- }
+ }
else
return FAIL; /* empty means "don't match anything" */
return dcc_rc;
/* open the spooled body */
- for (int i = 0; i < 2; i++)
- {
+ for (int i = 0; i < 2; i++) {
uschar message_subdir[2];
set_subdir_str(message_subdir, message_id, i);
if ((data_file = Ufopen(
- spool_fname(US"input", message_subdir, message_id, US"-D"),
- "rb")))
+ spool_fname(US"input", message_subdir, message_id, US"-D"), "rb")))
break;
- }
+ }
- if (!data_file)
- {
+ if (!data_file) {
/* error while spooling */
log_write(0, LOG_MAIN|LOG_PANIC,
- "dcc acl condition: error while opening spool file");
+ "DCC: error while opening spool file");
return DEFER;
- }
+ }
/* Initialize the variables */
else
if( sscanf(CS dccifd_address, "%s %u", sockip, &portnr) != 2) {
log_write(0, LOG_MAIN,
- "dcc acl condition: warning - invalid dccifd address: '%s'", dccifd_address);
+ "DCC: warning - invalid dccifd address: '%s'", dccifd_address);
(void)fclose(data_file);
return DEFER;
}
}
- /* opts is what we send as dccifd options - see man dccifd */
+ /* dcc_headers is what we send as dccifd options - see man dccifd */
/* We don't support any other option than 'header' so just copy that */
- bzero(opts,sizeof(opts));
- Ustrncpy(opts, dccifd_options, sizeof(opts)-1);
+ dcc_headers = string_cat(NULL, dccifd_options);
/* if $acl_m_dcc_override_client_ip is set use it */
if (((override_client_ip = expand_string(US"$acl_m_dcc_override_client_ip")) != NULL) &&
(override_client_ip[0] != '\0')) {
DEBUG(D_acl)
debug_printf("DCC: Client IP (default): %s\n", client_ip);
}
- /* strncat(opts, my_request, strlen(my_request)); */
- Ustrcat(opts, US"\n");
- Ustrncat(opts, client_ip, sizeof(opts)-Ustrlen(opts)-1);
- Ustrncat(opts, US"\nHELO ", sizeof(opts)-Ustrlen(opts)-1);
- Ustrncat(opts, dcc_helo_option, sizeof(opts)-Ustrlen(opts)-2);
- Ustrcat(opts, US"\n");
+ /* build options block */
+ dcc_headers = string_append(dcc_headers, 5, US"\n", client_ip, US"\nHELO ", dcc_helo_option, US"\n");
/* initialize the other variables */
- dcchdr = header_list;
+ mail_headers = header_list;
/* we set the default return value to DEFER */
retval = DEFER;
- bzero(sendbuf,sizeof(sendbuf));
- bzero(dcc_header_str,sizeof(dcc_header_str));
- bzero(rcpt,sizeof(rcpt));
- bzero(from,sizeof(from));
-
/* send a null return path as "<>". */
- if (Ustrlen(sender_address) > 0)
- Ustrncpy(from, sender_address, sizeof(from));
- else
- Ustrncpy(from, US"<>", sizeof(from));
- Ustrncat(from, US"\n", sizeof(from)-Ustrlen(from)-1);
+ dcc_headers = string_cat (dcc_headers, *sender_address ? sender_address : US"<>");
+ dcc_headers = string_catn(dcc_headers, US"\n", 1);
/**************************************
* Now creating the socket connection *
**************************************/
/* If sockip contains an ip, we use a tcp socket, otherwise a UNIX socket */
- if(Ustrcmp(sockip, "")){
+ if(Ustrcmp(sockip, "")) {
ipaddress = gethostbyname(CS sockip);
bzero(CS &serv_addr_in, sizeof(serv_addr_in));
serv_addr_in.sin_family = AF_INET;
bcopy(CS ipaddress->h_addr, CS &serv_addr_in.sin_addr.s_addr, ipaddress->h_length);
serv_addr_in.sin_port = htons(portnr);
- if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) < 0){
+ if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) < 0) {
DEBUG(D_acl)
debug_printf("DCC: Creating TCP socket connection failed: %s\n", strerror(errno));
log_write(0,LOG_PANIC,"DCC: Creating TCP socket connection failed: %s\n", strerror(errno));
return retval;
}
/* Now connecting the socket (INET) */
- if (connect(sockfd, (struct sockaddr *)&serv_addr_in, sizeof(serv_addr_in)) < 0){
+ if (connect(sockfd, (struct sockaddr *)&serv_addr_in, sizeof(serv_addr_in)) < 0) {
DEBUG(D_acl)
debug_printf("DCC: Connecting to TCP socket failed: %s\n", strerror(errno));
log_write(0,LOG_PANIC,"DCC: Connecting to TCP socket failed: %s\n", strerror(errno));
(void)fclose(data_file);
return retval;
}
- } else {
+ }
+ else {
/* connecting to the dccifd UNIX socket */
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sun_family = AF_UNIX;
Ustrncpy(US serv_addr.sun_path, sockpath, sizeof(serv_addr.sun_path));
- if ((sockfd = socket(AF_UNIX, SOCK_STREAM,0)) < 0){
+ if ((sockfd = socket(AF_UNIX, SOCK_STREAM,0)) < 0) {
DEBUG(D_acl)
debug_printf("DCC: Creating UNIX socket connection failed: %s\n", strerror(errno));
log_write(0,LOG_PANIC,"DCC: Creating UNIX socket connection failed: %s\n", strerror(errno));
return retval;
}
/* Now connecting the socket (UNIX) */
- if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
+ if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
DEBUG(D_acl)
- debug_printf("DCC: Connecting to UNIX socket failed: %s\n", strerror(errno));
+ debug_printf("DCC: Connecting to UNIX socket failed: %s\n", strerror(errno));
log_write(0,LOG_PANIC,"DCC: Connecting to UNIX socket failed: %s\n", strerror(errno));
/* if we cannot contact the socket, defer the mail */
(void)fclose(data_file);
}
/* the socket is open, now send the options to dccifd*/
DEBUG(D_acl)
- debug_printf("\nDCC: ---------------------------\nDCC: Socket opened; now sending input\nDCC: -----------------\n");
- /* First, fill in the input buffer */
- Ustrncpy(sendbuf, opts, sizeof(sendbuf));
- Ustrncat(sendbuf, from, sizeof(sendbuf)-Ustrlen(sendbuf)-1);
-
- DEBUG(D_acl)
- {
- debug_printf("DCC: opts = %s\nDCC: sender = %s\nDCC: rcpt count = %d\n", opts, from, recipients_count);
- debug_printf("DCC: Sending options:\nDCC: ****************************\n");
- }
+ debug_printf("DCC: -----------------------------------\nDCC: Socket opened; now sending input\n"
+ "DCC: -----------------------------------\n");
/* let's send each of the recipients to dccifd */
- for (int i = 0; i < recipients_count; i++){
+ for (int i = 0; i < recipients_count; i++) {
DEBUG(D_acl)
debug_printf("DCC: recipient = %s\n",recipients_list[i].address);
- if(Ustrlen(sendbuf) + Ustrlen(recipients_list[i].address) > sizeof(sendbuf))
- {
- DEBUG(D_acl)
- debug_printf("DCC: Writing buffer: %s\n", sendbuf);
- flushbuffer(sockfd, sendbuf);
- bzero(sendbuf, sizeof(sendbuf));
- }
- Ustrncat(sendbuf, recipients_list[i].address, sizeof(sendbuf)-Ustrlen(sendbuf)-1);
- Ustrncat(sendbuf, US"\r\n", sizeof(sendbuf)-Ustrlen(sendbuf)-1);
+ dcc_headers = string_append(dcc_headers, 2, recipients_list[i].address, "\n");
}
/* send a blank line between options and message */
- Ustrncat(sendbuf, US"\n", sizeof(sendbuf)-Ustrlen(sendbuf)-1);
+ dcc_headers = string_catn(dcc_headers, US"\n", 1);
/* Now we send the input buffer */
+ (void) string_from_gstring(dcc_headers);
DEBUG(D_acl)
- debug_printf("DCC: %s\nDCC: ****************************\n", sendbuf);
- flushbuffer(sockfd, sendbuf);
+ debug_printf("DCC: ***********************************\nDCC: Sending options:\n%s"
+ "DCC: ***********************************\n", dcc_headers->s);
+ if (flushbuffer(sockfd, dcc_headers) != 0) {
+ (void)fclose(data_file);
+ return retval;
+ }
/* now send the message */
- /* Clear the input buffer */
- bzero(sendbuf, sizeof(sendbuf));
/* First send the headers */
- /* Now send the headers */
DEBUG(D_acl)
- debug_printf("DCC: Sending headers:\nDCC: ****************************\n");
- Ustrncpy(sendbuf, dcchdr->text, sizeof(sendbuf)-2);
- while((dcchdr=dcchdr->next)) {
- if(dcchdr->slen > sizeof(sendbuf)-2) {
- /* The size of the header is bigger than the size of
- * the input buffer, so split it up in smaller parts. */
- flushbuffer(sockfd, sendbuf);
- bzero(sendbuf, sizeof(sendbuf));
- j = 0;
- while(j < dcchdr->slen)
- {
- for(int i = 0; i < sizeof(sendbuf)-2; i++) {
- sendbuf[i] = dcchdr->text[j];
- j++;
- }
- flushbuffer(sockfd, sendbuf);
- bzero(sendbuf, sizeof(sendbuf));
- }
- } else if(Ustrlen(sendbuf) + dcchdr->slen > sizeof(sendbuf)-2) {
- flushbuffer(sockfd, sendbuf);
- bzero(sendbuf, sizeof(sendbuf));
- Ustrncpy(sendbuf, dcchdr->text, sizeof(sendbuf)-2);
- } else {
- Ustrncat(sendbuf, dcchdr->text, sizeof(sendbuf)-Ustrlen(sendbuf)-2);
- }
+ debug_printf("DCC: ***********************************\nDCC: Sending headers:\n");
+ sendbuf = string_get(8192);
+ sendbuf = string_catn(sendbuf, mail_headers->text, mail_headers->slen);
+ while((mail_headers=mail_headers->next)) {
+ sendbuf = string_catn(sendbuf, mail_headers->text, mail_headers->slen);
}
/* a blank line separates header from body */
- Ustrncat(sendbuf, US"\n", sizeof(sendbuf)-Ustrlen(sendbuf)-1);
- flushbuffer(sockfd, sendbuf);
+ sendbuf = string_catn(sendbuf, US"\r\n", 2);
+ (void) string_from_gstring(sendbuf);
+ gstring_release_unused(sendbuf);
DEBUG(D_acl)
- debug_printf("\nDCC: ****************************\n%s", sendbuf);
-
- /* Clear the input buffer */
- bzero(sendbuf, sizeof(sendbuf));
+ debug_printf("%sDCC: ***********************************\n", sendbuf->s);
+ if (flushbuffer(sockfd, sendbuf) != 0) {
+ (void)fclose(data_file);
+ return retval;
+ }
/* now send the body */
DEBUG(D_acl)
- debug_printf("DCC: Writing body:\nDCC: ****************************\n");
+ debug_printf("DCC: ***********************************\nDCC: Writing body:\n");
(void)fseek(data_file, SPOOL_DATA_START_OFFSET, SEEK_SET);
- while((fread(sendbuf, 1, sizeof(sendbuf)-1, data_file)) > 0) {
- flushbuffer(sockfd, sendbuf);
- bzero(sendbuf, sizeof(sendbuf));
+
+ gstring filebuf = { .size = big_buffer_size, .ptr = 0, .s = big_buffer };
+
+ while((filebuf.ptr = fread(filebuf.s, 1, filebuf.size, data_file)) > 0) {
+ if (flushbuffer(sockfd, &filebuf) != 0) {
+ (void)fclose(data_file);
+ return retval;
+ }
}
DEBUG(D_acl)
- debug_printf("\nDCC: ****************************\n");
+ debug_printf("DCC: ***********************************\n");
/* shutdown() the socket */
- if(shutdown(sockfd, 1) < 0){
+ if(shutdown(sockfd, SHUT_WR) < 0) {
DEBUG(D_acl)
debug_printf("DCC: Couldn't shutdown socket: %s\n", strerror(errno));
log_write(0,LOG_MAIN,"DCC: Couldn't shutdown socket: %s\n", strerror(errno));
return retval;
}
DEBUG(D_acl)
- debug_printf("\nDCC: -------------------------\nDCC: Input sent.\nDCC: -------------------------\n");
+ debug_printf("DCC: Input sent.\n"
+ "DCC: +++++++++++++++++++++++++++++++++++\n"
+ "DCC: Now receiving output from server\n"
+ "DCC: -----------------------------------\n");
- /********************************
+ /********************************
* receiving output from dccifd *
********************************/
- DEBUG(D_acl)
- debug_printf("\nDCC: -------------------------------------\nDCC: Now receiving output from server\nDCC: -----------------------------------\n");
/******************************************************************
* We should get 3 lines: *
* 3/ Third line contains the X-DCC header. *
******************************************************************/
- line = 1; /* we start at the first line of the output */
- j = 0; /* will be used as index for the recipients list */
- k = 0; /* initializing the index of the X-DCC header: dcc_header_str[k] */
+ int line = 1; /* we start at the first line of the output */
+ int bufoffset;
+ dcc_header_str = string_get(DCC_HEADER_LIMIT + 2);
/* Let's read from the socket until there's nothing left to read */
- bzero(recvbuf, sizeof(recvbuf));
- while((resp = read(sockfd, recvbuf, sizeof(recvbuf)-1)) > 0) {
- /* How much did we get from the socket */
- c = Ustrlen(recvbuf) + 1;
+ while((dcc_resplen = read(sockfd, big_buffer, big_buffer_size-1)) > 0) {
+ /* fail on read error */
+ if(dcc_resplen < 0) {
+ DEBUG(D_acl)
+ debug_printf("DCC: Error reading from socket: %s\n", strerror(errno));
+ (void)fclose(data_file);
+ return retval;
+ }
+ /* make the answer 0-terminated. only needed for debug_printf */
DEBUG(D_acl)
- debug_printf("DCC: Length of the output buffer is: %d\nDCC: Output buffer is:\nDCC: ------------\nDCC: %s\nDCC: -----------\n", c, recvbuf);
+ debug_printf("DCC: Length of the output buffer is: %d\nDCC: Output buffer is:\n"
+ "DCC: -----------------------------------\n%.*s\n"
+ "DCC: -----------------------------------\n", dcc_resplen, dcc_resplen, big_buffer);
/* Now let's read each character and see what we've got */
- for(int i = 0; i < c; i++) {
+ for(bufoffset = 0; bufoffset < dcc_resplen, line <= 2; bufoffset++) {
/* First check if we reached the end of the line and
* then increment the line counter */
- if(recvbuf[i] == '\n')
+ if(big_buffer[bufoffset] == '\n')
line++;
else {
/* The first character of the first line is the
* overall response. If there's another character
* on that line it is not correct. */
if(line == 1) {
- if(i == 0) {
+ if(bufoffset == 0) {
/* Now get the value and set the
* return value accordingly */
- if(recvbuf[i] == 'A') {
- DEBUG(D_acl)
- debug_printf("DCC: Overall result = A\treturning OK\n");
- Ustrcpy(dcc_return_text, US"Mail accepted by DCC");
- dcc_result = US"A";
- retval = OK;
- }
- else if(recvbuf[i] == 'R') {
- DEBUG(D_acl)
- debug_printf("DCC: Overall result = R\treturning FAIL\n");
- dcc_result = US"R";
- retval = FAIL;
- if(sender_host_name) {
- log_write(0, LOG_MAIN, "H=%s [%s] F=<%s>: rejected by DCC", sender_host_name, sender_host_address, sender_address);
- }
- else {
- log_write(0, LOG_MAIN, "H=[%s] F=<%s>: rejected by DCC", sender_host_address, sender_address);
- }
- Ustrncpy(dcc_return_text, dcc_reject_message, Ustrlen(dcc_reject_message) + 1);
- }
- else if(recvbuf[i] == 'S') {
- DEBUG(D_acl)
- debug_printf("DCC: Overall result = S\treturning OK\n");
- Ustrcpy(dcc_return_text, US"Not all recipients accepted by DCC");
- /* Since we're in an ACL we want a global result
- * so we accept for all */
- dcc_result = US"A";
- retval = OK;
- }
- else if(recvbuf[i] == 'G') {
- DEBUG(D_acl)
- debug_printf("DCC: Overall result = G\treturning FAIL\n");
- Ustrcpy(dcc_return_text, US"Greylisted by DCC");
- dcc_result = US"G";
- retval = FAIL;
- }
- else if(recvbuf[i] == 'T') {
- DEBUG(D_acl)
- debug_printf("DCC: Overall result = T\treturning DEFER\n");
- retval = DEFER;
- log_write(0,LOG_MAIN,"Temporary error with DCC: %s\n", recvbuf);
- Ustrcpy(dcc_return_text, US"Temporary error with DCC");
- dcc_result = US"T";
- }
- else {
- DEBUG(D_acl)
- debug_printf("DCC: Overall result = something else\treturning DEFER\n");
- retval = DEFER;
- log_write(0,LOG_MAIN,"Unknown DCC response: %s\n", recvbuf);
- Ustrcpy(dcc_return_text, US"Unknown DCC response");
- dcc_result = US"T";
+ switch(big_buffer[bufoffset]) {
+ case 'A':
+ DEBUG(D_acl)
+ debug_printf("DCC: Overall result = A\treturning OK\n");
+ dcc_return_text = US"Mail accepted by DCC";
+ dcc_result = US"A";
+ retval = OK;
+ break;
+ case 'R':
+ DEBUG(D_acl)
+ debug_printf("DCC: Overall result = R\treturning FAIL\n");
+ dcc_return_text = US"Rejected by DCC";
+ dcc_result = US"R";
+ retval = FAIL;
+ if(sender_host_name)
+ log_write(0, LOG_MAIN, "H=%s [%s] F=<%s>: rejected by DCC",
+ sender_host_name, sender_host_address, sender_address);
+ else
+ log_write(0, LOG_MAIN, "H=[%s] F=<%s>: rejected by DCC",
+ sender_host_address, sender_address);
+ break;
+ case 'S':
+ DEBUG(D_acl)
+ debug_printf("DCC: Overall result = S\treturning OK\n");
+ dcc_return_text = US"Not all recipients accepted by DCC";
+ /* Since we're in an ACL we want a global result
+ * so we accept for all */
+ dcc_result = US"A";
+ retval = OK;
+ break;
+ case 'G':
+ DEBUG(D_acl)
+ debug_printf("DCC: Overall result = G\treturning FAIL\n");
+ dcc_return_text = US"Greylisted by DCC";
+ dcc_result = US"G";
+ retval = FAIL;
+ break;
+ case 'T':
+ DEBUG(D_acl)
+ debug_printf("DCC: Overall result = T\treturning DEFER\n");
+ dcc_return_text = US"Temporary error with DCC";
+ dcc_result = US"T";
+ retval = DEFER;
+ log_write(0,LOG_MAIN,"Temporary error with DCC: %s\n", big_buffer);
+ break;
+ default:
+ DEBUG(D_acl)
+ debug_printf("DCC: Overall result = something else\treturning DEFER\n");
+ dcc_return_text = US"Unknown DCC response";
+ dcc_result = US"T";
+ retval = DEFER;
+ log_write(0,LOG_MAIN,"Unknown DCC response: %s\n", big_buffer);
+ break;
}
}
else {
/* We're on the first line but not on the first character,
* there must be something wrong. */
- DEBUG(D_acl) debug_printf("DCC: Line = %d but i = %d != 0"
- " character is %c - This is wrong!\n", line, i, recvbuf[i]);
- log_write(0,LOG_MAIN,"Wrong header from DCC, output is %s\n", recvbuf);
+ DEBUG(D_acl) debug_printf("DCC: Line = %d but bufoffset = %d != 0"
+ " character is %c - This is wrong!\n", line, bufoffset, big_buffer[bufoffset]);
+ log_write(0,LOG_MAIN,"Wrong header from DCC, output is %s\n", big_buffer);
}
}
else if(line == 2) {
* it because we're in an acl and take the
* global result. */
}
- else if(line > 2) {
- /* The third and following lines are the X-DCC header,
- * so we store it in dcc_header_str. */
- /* check if we don't get more than we can handle */
- if(k < sizeof(dcc_header_str)) {
- dcc_header_str[k] = recvbuf[i];
- k++;
- }
- else {
- DEBUG(D_acl) debug_printf("DCC: We got more output than we can store"
- " in the X-DCC header. Truncating at 120 characters.\n");
- }
- }
- else {
- /* Wrong line number. There must be a problem with the output. */
- DEBUG(D_acl)
- debug_printf("DCC: Wrong line number in output. Line number is %d\n", line);
- }
}
}
- /* we reinitialize the output buffer before we read again */
- bzero(recvbuf,sizeof(recvbuf));
+ if(line > 2) {
+ /* The third and following lines are the X-DCC header,
+ * so we store it in dcc_header_str up to our limit. */
+ /* check if buffer contains the end of the header .."\n\n" and truncate it */
+ if ((big_buffer[dcc_resplen-1] == '\n') &&
+ (big_buffer[dcc_resplen-2] == '\n'))
+ dcc_resplen -= 2;
+ dcc_resplen -= bufoffset;
+ if (dcc_header_str->ptr + dcc_resplen > DCC_HEADER_LIMIT) {
+ dcc_resplen = DCC_HEADER_LIMIT - dcc_header_str->ptr;
+ DEBUG(D_acl) debug_printf("DCC: We got more output than we can store"
+ "in the X-DCC header. Truncating at 120 characters.\n");
+ }
+ dcc_header_str = string_catn(dcc_header_str, &big_buffer[bufoffset], dcc_resplen);
+ }
}
- /* We have read everything from the socket */
-
- /* We need to terminate the X-DCC header with a '\n' character. This needs to be k-1
- * since dcc_header_str[k] contains '\0'. */
- dcc_header_str[k-1] = '\n';
+ /* We have read everything from the socket. make sure the header ends with "\n" */
+ dcc_header_str = string_catn(dcc_header_str, US"\n", 1);
+ (void) string_from_gstring(dcc_header_str);
/* Now let's sum up what we've got. */
DEBUG(D_acl)
- debug_printf("\nDCC: --------------------------\nDCC: Overall result = %d\nDCC: X-DCC header: %sReturn message: %s\nDCC: dcc_result: %s\n", retval, dcc_header_str, dcc_return_text, dcc_result);
+ debug_printf("\nDCC: --------------------------\nDCC: Overall result = %d\n"
+ "DCC: X-DCC header: %sReturn message: %s\nDCC: dcc_result: %s\n",
+ retval, dcc_header_str->s, dcc_return_text, dcc_result);
/* We only add the X-DCC header if it starts with X-DCC */
- if(!(Ustrncmp(dcc_header_str, "X-DCC", 5))){
- dcc_header = dcc_header_str;
+ if(!(Ustrncmp(dcc_header_str->s, "X-DCC", 5))) {
+ dcc_header = dcc_header_str->s;
if(dcc_direct_add_header) {
- header_add(' ' , "%s", dcc_header_str);
+ header_add(' ' , "%s", dcc_header_str->s);
/* since the MIME ACL already writes the .eml file to disk without DCC Header we've to erase it */
unspool_mbox();
}
}
else {
DEBUG(D_acl)
- debug_printf("DCC: Wrong format of the X-DCC header: %s\n", dcc_header_str);
+ debug_printf("DCC: Wrong format of the X-DCC header: %.*s\n", dcc_header_str->ptr, dcc_header_str->s);
}
/* check if we should add additional headers passed in acl_m_dcc_add_header */
if(dcc_direct_add_header) {
if (((xtra_hdrs = expand_string(US"$acl_m_dcc_add_header")) != NULL) && (xtra_hdrs[0] != '\0')) {
- Ustrncpy(dcc_xtra_hdrs, xtra_hdrs, sizeof(dcc_xtra_hdrs) - 2);
- if (dcc_xtra_hdrs[Ustrlen(dcc_xtra_hdrs)-1] != '\n')
- Ustrcat(dcc_xtra_hdrs, US"\n");
- header_add(' ', "%s", dcc_xtra_hdrs);
+ dcc_xtra_hdrs = string_cat(NULL, xtra_hdrs);
+ if (dcc_xtra_hdrs->s[dcc_xtra_hdrs->ptr - 1] != '\n')
+ dcc_xtra_hdrs = string_catn(dcc_xtra_hdrs, US"\n", 1);
+ header_add(' ', "%s", string_from_gstring(dcc_xtra_hdrs));
DEBUG(D_acl)
- debug_printf("DCC: adding additional headers in $acl_m_dcc_add_header: %s", dcc_xtra_hdrs);
+ debug_printf("DCC: adding additional headers in $acl_m_dcc_add_header: %.*s", dcc_xtra_hdrs->ptr, dcc_xtra_hdrs->s);
}
}
dcc_ok = 1;
/* Now return to exim main process */
DEBUG(D_acl)
- debug_printf("DCC: Before returning to exim main process:\nDCC: return_text = %s - retval = %d\nDCC: dcc_result = %s\n", dcc_return_text, retval, dcc_result);
+ debug_printf("DCC: Before returning to exim main process:\nDCC: return_text = %s - retval = %d\n"
+ "DCC: dcc_result = %s\n", dcc_return_text, retval, dcc_result);
(void)fclose(data_file);
dcc_rc = retval;
/* Otherwise, if we are running in the test harness, wait a bit, to let the
newly created process get going before we create another process. This should
- ensure repeatability in the tests. We only need to wait a tad. */
+ ensure repeatability in the tests. Wait long enough for most cases to complete
+ the transport. */
- else testharness_pause_ms(500);
+ else testharness_pause_ms(600);
continue;
}
+
+/* When running in the test harness, there's an option that allows us to
+fudge this time so as to get repeatability of the tests. Take the first
+time off the list. In queue runs, the list pointer gets updated in the
+calling process. */
+
+int
+test_harness_fudged_queue_time(int actual_time)
+{
+int qt;
+if ( f.running_in_test_harness && *fudged_queue_times
+ && (qt = readconf_readtime(fudged_queue_times, '/', FALSE)) >= 0)
+ {
+ DEBUG(D_deliver) debug_printf("fudged queue_times = %s\n",
+ fudged_queue_times);
+ return qt;
+ }
+return actual_time;
+}
+
/*************************************************
* Deliver one message *
*************************************************/
new->onetime_parent = recipients_list[r->pno].address;
/* If DSN support is enabled, set the dsn flags and the original receipt
- to be passed on to other DSN enabled MTAs */
+ to be passed on to other DSN enabled MTAs */
+
new->dsn_flags = r->dsn_flags & rf_dsnflags;
new->dsn_orcpt = r->orcpt;
DEBUG(D_deliver) debug_printf("DSN: set orcpt: %s flags: 0x%x\n",
);
/* send report if next hop not DSN aware or a router flagged "last DSN hop"
- and a report was requested */
- if ( ( a->dsn_aware != dsn_support_yes
- || a->dsn_flags & rf_dsnlasthop
- )
+ and a report was requested */
+
+ if ( (a->dsn_aware != dsn_support_yes || a->dsn_flags & rf_dsnlasthop)
&& a->dsn_flags & rf_notify_success
)
{
int show_time;
int queue_time = time(NULL) - received_time.tv_sec;
- /* When running in the test harness, there's an option that allows us to
- fudge this time so as to get repeatability of the tests. Take the first
- time off the list. In queue runs, the list pointer gets updated in the
- calling process. */
-
- if (f.running_in_test_harness && fudged_queue_times[0] != 0)
- {
- int qt = readconf_readtime(fudged_queue_times, '/', FALSE);
- if (qt >= 0)
- {
- DEBUG(D_deliver) debug_printf("fudged queue_times = %s\n",
- fudged_queue_times);
- queue_time = qt;
- }
- }
+ queue_time = test_harness_fudged_queue_time(queue_time);
/* See how many warnings we should have sent by now */
Arguments:
string the IP address as a string
- buffer a suitable buffer, long enough to hold the result
-Returns: nothing
+Returns: an allocated string
*/
-void
-dns_build_reverse(const uschar *string, uschar *buffer)
+uschar *
+dns_build_reverse(const uschar * string)
{
-const uschar *p = string + Ustrlen(string);
-uschar *pp = buffer;
+const uschar * p = string + Ustrlen(string);
+gstring * g = NULL;
/* Handle IPv4 address */
{
for (int i = 0; i < 4; i++)
{
- const uschar *ppp = p;
+ const uschar * ppp = p;
while (ppp > string && ppp[-1] != '.') ppp--;
- Ustrncpy(pp, ppp, p - ppp);
- pp += p - ppp;
- *pp++ = '.';
+ g = string_catn(g, ppp, p - ppp);
+ g = string_catn(g, US".", 1);
p = ppp - 1;
}
- Ustrcpy(pp, US"in-addr.arpa");
+ g = string_catn(g, US"in-addr.arpa", 12);
}
/* Handle IPv6 address; convert to binary so as to fill out any
else
{
int v6[4];
+
+ g = string_get_tainted(32, is_tainted(string));
(void)host_aton(string, v6);
/* The original specification for IPv6 reverse lookup was to invert each
for (int i = 3; i >= 0; i--)
for (int j = 0; j < 32; j += 4)
- pp += sprintf(CS pp, "%x.", (v6[i] >> j) & 15);
- Ustrcpy(pp, US"ip6.arpa.");
+ g = string_fmt_append(g, "%x.", (v6[i] >> j) & 15);
+ g = string_catn(g, US"ip6.arpa.", 9);
/* Another way of doing IPv6 reverse lookups was proposed in conjunction
with A6 records. However, it fell out of favour when they did. The
}
#endif
+return string_from_gstring(g);
}
const uschar * auth_name;
const uschar * trusted;
+if (dnsa->answerlen < 0) return FALSE;
if (h->ad) return TRUE;
-/* If the resolver we ask is authoritative for the domain in question, it
-* may not set the AD but the AA bit. If we explicitly trust
-* the resolver for that domain (via a domainlist in dns_trust_aa),
-* we return TRUE to indicate a secure answer.
-*/
+/* If the resolver we ask is authoritative for the domain in question, it may
+not set the AD but the AA bit. If we explicitly trust the resolver for that
+domain (via a domainlist in dns_trust_aa), we return TRUE to indicate a secure
+answer. */
if ( !h->aa
|| !dns_trust_aa
************************************************/
BOOL
-dns_is_aa(const dns_answer *dnsa)
+dns_is_aa(const dns_answer * dnsa)
{
#ifdef DISABLE_DNSSEC
return FALSE;
#else
-return ((const HEADER*)dnsa->answer)->aa;
+return dnsa->answerlen >= 0 && ((const HEADER *)dnsa->answer)->aa;
#endif
}
-/* Return the TTL suitable for an NXDOMAIN result, which is given
-in the SOA. We hope that one was returned in the lookup, and do not
-bother doing a separate lookup; if not found return a forever TTL.
-*/
-
-time_t
-dns_expire_from_soa(dns_answer * dnsa)
-{
-const HEADER * h = (const HEADER *)dnsa->answer;
-dns_scan dnss;
-
/* This is really gross. The successful return value from res_search() is
the packet length, which is stored in dnsa->answerlen. If we get a
negative DNS reply then res_search() returns -1, which causes the bounds
success and packet length return values.) For added safety we only reset
the packet length if the packet header looks plausible. */
-if ( h->qr == 1 && h->opcode == QUERY && h->tc == 0
+static void
+fake_dnsa_len_for_fail(dns_answer * dnsa, int type)
+{
+const HEADER * h = (const HEADER *)dnsa->answer;
+
+if ( h->qr == 1 /* a response */
+ && h->opcode == QUERY
+ && h->tc == 0 /* nmessage not truncated */
&& (h->rcode == NOERROR || h->rcode == NXDOMAIN)
- && (ntohs(h->qdcount) == 1 || f.running_in_test_harness)
- && ntohs(h->ancount) == 0
- && ntohs(h->nscount) >= 1)
- dnsa->answerlen = sizeof(dnsa->answer);
+ && ( ntohs(h->qdcount) == 1 /* one question record */
+ || f.running_in_test_harness)
+ && ntohs(h->ancount) == 0 /* no answer records */
+ && ntohs(h->nscount) >= 1) /* authority records */
+ {
+ DEBUG(D_dns) debug_printf("faking res_search(%s) response length as %d\n",
+ dns_text_type(type), (int)sizeof(dnsa->answer));
+ dnsa->answerlen = sizeof(dnsa->answer);
+ }
+}
+
+
+/* Return the TTL suitable for an NXDOMAIN result, which is given
+in the SOA. We hope that one was returned in the lookup, and do not
+bother doing a separate lookup; if not found return a forever TTL.
+*/
+
+time_t
+dns_expire_from_soa(dns_answer * dnsa, int type)
+{
+dns_scan dnss;
+
+fake_dnsa_len_for_fail(dnsa, type);
for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_AUTHORITY);
rr; rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
*/
if ((rc = dns_fail_cache_hit(name, type)) > 0)
+ {
+ dnsa->answerlen = -1;
return rc;
+ }
#ifdef SUPPORT_I18N
/* Convert all names to a-label form before doing lookup */
(res_search), we call fakens_search(), which recognizes certain special
domains, and interfaces to a fake nameserver for certain special zones. */
+h_errno = 0;
dnsa->answerlen = f.running_in_test_harness
? fakens_search(name, type, dnsa->answer, sizeof(dnsa->answer))
: res_search(CCS name, C_IN, type, dnsa->answer, sizeof(dnsa->answer));
case HOST_NOT_FOUND:
DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave HOST_NOT_FOUND\n"
"returning DNS_NOMATCH\n", name, dns_text_type(type));
- return dns_fail_return(name, type, dns_expire_from_soa(dnsa), DNS_NOMATCH);
+ return dns_fail_return(name, type, dns_expire_from_soa(dnsa, type), DNS_NOMATCH);
case TRY_AGAIN:
DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave TRY_AGAIN\n",
}
DEBUG(D_dns) debug_printf("%s is in dns_again_means_nonexist: returning "
"DNS_NOMATCH\n", name);
- return dns_fail_return(name, type, dns_expire_from_soa(dnsa), DNS_NOMATCH);
+ return dns_fail_return(name, type, dns_expire_from_soa(dnsa, type), DNS_NOMATCH);
#else /* For stand-alone tests */
return dns_fail_return(name, type, 0, DNS_AGAIN);
case NO_DATA:
DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave NO_DATA\n"
"returning DNS_NODATA\n", name, dns_text_type(type));
- return dns_fail_return(name, type, dns_expire_from_soa(dnsa), DNS_NODATA);
+ return dns_fail_return(name, type, dns_expire_from_soa(dnsa, type), DNS_NODATA);
default:
DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave unknown DNS error %d\n"
if (rc == DNS_NOMATCH)
{
- /* This is really gross. The successful return value from res_search() is
- the packet length, which is stored in dnsa->answerlen. If we get a
- negative DNS reply then res_search() returns -1, which causes the bounds
- checks for name decompression to fail when it is treated as a packet
- length, which in turn causes the authority search to fail. The correct
- packet length has been lost inside libresolv, so we have to guess a
- replacement value. (The only way to fix this properly would be to
- re-implement res_search() and res_query() so that they don't muddle their
- success and packet length return values.) For added safety we only reset
- the packet length if the packet header looks plausible. */
-
- const HEADER * h = (const HEADER *)dnsa->answer;
- if (h->qr == 1 && h->opcode == QUERY && h->tc == 0
- && (h->rcode == NOERROR || h->rcode == NXDOMAIN)
- && ntohs(h->qdcount) == 1 && ntohs(h->ancount) == 0
- && ntohs(h->nscount) >= 1)
- dnsa->answerlen = sizeof(dnsa->answer);
+ fake_dnsa_len_for_fail(dnsa, T_CSA);
for (rr = dns_next_rr(dnsa, &dnss, RESET_AUTHORITY);
rr; rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
BOOL
cleanup_environment()
{
+int old_pool = store_pool;
+store_pool = POOL_PERM; /* Need perm memory for any created env vars */
+
if (!keep_environment || *keep_environment == '\0')
{
/* From: https://github.com/dovecot/core/blob/master/src/lib/env-util.c#L55
int sep = 0;
const uschar * envlist = add_environment;
- while ((p = string_nextinlist(&envlist, &sep, NULL, 0))) putenv(CS p);
+ while ((p = string_nextinlist(&envlist, &sep, NULL, 0)))
+ {
+ DEBUG(D_expand) debug_printf("adding %s\n", p);
+ putenv(CS p);
+ }
}
+#ifndef DISABLE_TLS
+tls_clean_env();
+#endif
+store_pool = old_pool;
return TRUE;
}
msg_action = MSG_DELIVER;
deliver_give_up = TRUE;
}
+ else if (Ustrcmp(argrest, "G") == 0)
+ {
+ msg_action = MSG_SETQUEUE;
+ queue_name_dest = argv[++i];
+ }
else if (Ustrcmp(argrest, "mad") == 0)
{
msg_action = MSG_MARK_ALL_DELIVERED;
if (!f.admin_user)
{
BOOL debugset = (debug_selector & ~D_v) != 0;
- if (deliver_give_up || f.daemon_listen || malware_test_file ||
- (count_queue && queue_list_requires_admin) ||
- (list_queue && queue_list_requires_admin) ||
- (queue_interval >= 0 && prod_requires_admin) ||
- (debugset && !f.running_in_test_harness))
+ if ( deliver_give_up || f.daemon_listen || malware_test_file
+ || count_queue && queue_list_requires_admin
+ || list_queue && queue_list_requires_admin
+ || queue_interval >= 0 && prod_requires_admin
+ || queue_name_dest && prod_requires_admin
+ || debugset && !f.running_in_test_harness
+ )
exim_fail("exim:%s permission denied\n", debugset? " debugging" : "");
}
root. There will be further calls later for each message received. */
#ifdef LOAD_AVG_NEEDS_ROOT
-if (receiving_message &&
- (queue_only_load >= 0 ||
- (f.is_inetd && smtp_load_reserve >= 0)
- ))
- {
+if ( receiving_message
+ && (queue_only_load >= 0 || (f.is_inetd && smtp_load_reserve >= 0)))
load_average = OS_GETLOADAVG();
- }
#endif
/* The queue_only configuration option can be overridden by -odx on the command
for (i = msg_action_arg; i < argc; i++)
if (!queue_action(argv[i], msg_action, NULL, 0, 0))
yield = EXIT_FAILURE;
+ switch (msg_action)
+ {
+ case MSG_REMOVE: MSG_DELETE: case MSG_FREEZE: case MSG_THAW: break;
+ default: printf("\n"); break;
+ }
}
else if (!queue_action(argv[msg_action_arg], msg_action, argv, argc,
BEGIN { pop @INC if $INC[-1] eq '.' };
use Getopt::Long;
use File::Basename;
+use Pod::Usage;
-my($p_name) = $0 =~ m|/?([^/]+)$|;
+my $p_name = basename $0;
my $p_version = "20100323.0";
-my $p_usage = "Usage: $p_name [--help|--version] (see --help for details)";
+my $p_usage = "Usage: $p_name [--help|--man|--version] (see --help for details)";
my $p_cp = <<EOM;
Copyright (c) 2003-2010 John Jetmore <jj33\@pobox.com>
+ Copyright (c) 2019 The Exim Maintainers
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
EOM
-ext_usage(); # before we do anything else, check for --help
$| = 1; # unbuffer STDOUT
'spool=s' => \$G::spool, # exim spool dir
'C|Config=s' => \$G::config, # use alternative Exim configuration file
'input-dir=s' => \$G::input_dir, # name of the "input" dir
+ 'queue=s' => \$G::queue, # name of the queue
'finput' => \$G::finput, # same as "--input-dir Finput"
'bp' => \$G::mailq_bp, # List the queue (noop - default)
'bpa' => \$G::mailq_bpa, # ... with generated address as well
'just-vars' => \$G::just_vars, # only display vars, no other info
'show-rules' => \$G::show_rules, # display compiled match rules
'show-tests' => \$G::show_tests, # display tests as applied to each message
+ 'man' => sub { pod2usage(-verbose => 2, -exit => 0, -noperldoc => system('perldoc -V >/dev/null 2>&1')) },
+ 'help' => sub { pod2usage(-verbose => 1, -exit => 0) },
'version' => sub {
- print basename($0) . ": $0\n",
+ print "$p_name: $0\n",
"build: EXIM_RELEASE_VERSIONEXIM_VARIANT_VERSION\n",
"perl(runtime): $]\n";
exit 0;
},
-) || exit(1);
+) or pod2usage;
# if both freeze and thaw specified, only thaw as it is less destructive
$G::freeze = undef if ($G::freeze && $G::thaw);
$spool = defined $G::spool ? $G::spool
: do { chomp($_ = `$exim @{[defined $G::config ? "-C $G::config" : '']} -n -bP spool_directory`)
and $_ or $spool };
-my $input_dir = $G::input_dir || ($G::finput ? "Finput" : "input");
+my $input_dir = (defined $G::queue ? "$G::queue/" : '')
+ . (defined $G::input_dir || ($G::finput ? "Finput" : "input"));
my $count_only = 1 if ($G::mailq_bpc || $G::qgrep_c);
my $unsorted = 1 if ($G::mailq_bpr || $G::mailq_bpra ||
$G::mailq_bpru || $G::unsorted);
$self->{_vars}{warning_count} = $2;
$self->{_vars}{message_age} = time() - $self->{_vars}{received_time};
- while (<I>) {
- chomp();
- if (/^(-\S+)\s*(.*$)/) {
- my $tag = $1;
- my $arg = $2;
- if ($tag eq '-acl') {
- my $t;
- return(0) if ($arg !~ /^(\d+)\s(\d+)$/);
- if ($1 < $Exim::SpoolFile::ACL_C_MAX_LEGACY) {
- $t = "acl_c$1";
- } else {
- $t = "acl_m" . ($1 - $Exim::SpoolFile::ACL_C_MAX_LEGACY);
- }
- read(I, $self->{_vars}{$t}, $2+1) || return(0);
- chomp($self->{_vars}{$t});
- } elsif ($tag eq '-aclc') {
- #return(0) if ($arg !~ /^(\d+)\s(\d+)$/);
- return(0) if ($arg !~ /^(\S+)\s(\d+)$/);
- my $t = "acl_c$1";
- read(I, $self->{_vars}{$t}, $2+1) || return(0);
- chomp($self->{_vars}{$t});
- } elsif ($tag eq '-aclm') {
- #return(0) if ($arg !~ /^(\d+)\s(\d+)$/);
- return(0) if ($arg !~ /^(\S+)\s(\d+)$/);
- my $t = "acl_m$1";
- read(I, $self->{_vars}{$t}, $2+1) || return(0);
- chomp($self->{_vars}{$t});
- } elsif ($tag eq '-local') {
- $self->{_vars}{sender_local} = 1;
- } elsif ($tag eq '-localerror') {
- $self->{_vars}{local_error_message} = 1;
- } elsif ($tag eq '-local_scan') {
- $self->{_vars}{local_scan_data} = $arg;
- } elsif ($tag eq '-spam_score_int') {
- $self->{_vars}{spam_score_int} = $arg;
- $self->{_vars}{spam_score} = $arg / 10;
- } elsif ($tag eq '-bmi_verdicts') {
- $self->{_vars}{bmi_verdicts} = $arg;
- } elsif ($tag eq '-host_lookup_deferred') {
- $self->{_vars}{host_lookup_deferred} = 1;
- } elsif ($tag eq '-host_lookup_failed') {
- $self->{_vars}{host_lookup_failed} = 1;
- } elsif ($tag eq '-body_linecount') {
- $self->{_vars}{body_linecount} = $arg;
- } elsif ($tag eq '-max_received_linelength') {
- $self->{_vars}{max_received_linelength} = $arg;
- } elsif ($tag eq '-body_zerocount') {
- $self->{_vars}{body_zerocount} = $arg;
- } elsif ($tag eq '-frozen') {
- $self->{_vars}{deliver_freeze} = 1;
- $self->{_vars}{deliver_frozen_at} = $arg;
- } elsif ($tag eq '-allow_unqualified_recipient') {
- $self->{_vars}{allow_unqualified_recipient} = 1;
- } elsif ($tag eq '-allow_unqualified_sender') {
- $self->{_vars}{allow_unqualified_sender} = 1;
- } elsif ($tag eq '-deliver_firsttime') {
- $self->{_vars}{deliver_firsttime} = 1;
- $self->{_vars}{first_delivery} = 1;
- } elsif ($tag eq '-manual_thaw') {
- $self->{_vars}{deliver_manual_thaw} = 1;
- $self->{_vars}{manually_thawed} = 1;
- } elsif ($tag eq '-auth_id') {
- $self->{_vars}{authenticated_id} = $arg;
- } elsif ($tag eq '-auth_sender') {
- $self->{_vars}{authenticated_sender} = $arg;
- } elsif ($tag eq '-sender_set_untrusted') {
- $self->{_vars}{sender_set_untrusted} = 1;
- } elsif ($tag eq '-tls_certificate_verified') {
- $self->{_vars}{tls_certificate_verified} = 1;
- } elsif ($tag eq '-tls_cipher') {
- $self->{_vars}{tls_cipher} = $arg;
- } elsif ($tag eq '-tls_peerdn') {
- $self->{_vars}{tls_peerdn} = $arg;
- } elsif ($tag eq '-tls_sni') {
- $self->{_vars}{tls_sni} = $arg;
- } elsif ($tag eq '-host_address') {
- $self->{_vars}{sender_host_port} = $self->_get_host_and_port(\$arg);
- $self->{_vars}{sender_host_address} = $arg;
- } elsif ($tag eq '-interface_address') {
- $self->{_vars}{received_port} =
- $self->{_vars}{interface_port} = $self->_get_host_and_port(\$arg);
- $self->{_vars}{received_ip_address} =
- $self->{_vars}{interface_address} = $arg;
- } elsif ($tag eq '-active_hostname') {
- $self->{_vars}{smtp_active_hostname} = $arg;
- } elsif ($tag eq '-host_auth') {
- $self->{_vars}{sender_host_authenticated} = $arg;
- } elsif ($tag eq '-host_name') {
- $self->{_vars}{sender_host_name} = $arg;
- } elsif ($tag eq '-helo_name') {
- $self->{_vars}{sender_helo_name} = $arg;
- } elsif ($tag eq '-ident') {
- $self->{_vars}{sender_ident} = $arg;
- } elsif ($tag eq '-received_protocol') {
- $self->{_vars}{received_protocol} = $arg;
- } elsif ($tag eq '-N') {
- $self->{_vars}{dont_deliver} = 1;
+ TAGGED: while (<I>) {
+ my ($tag, $arg) = /^-?(-\S+)(?:\s+(.*))?$/ or last TAGGED;
+ chomp;
+
+ if ($tag eq '-acl') {
+ my $t;
+ return(0) if ($arg !~ /^(\d+)\s(\d+)$/);
+ if ($1 < $Exim::SpoolFile::ACL_C_MAX_LEGACY) {
+ $t = "acl_c$1";
} else {
- # unrecognized tag, save it for reference
- $self->{$tag} = $arg;
+ $t = "acl_m" . ($1 - $Exim::SpoolFile::ACL_C_MAX_LEGACY);
}
+ read(I, $self->{_vars}{$t}, $2+1) || return(0);
+ chomp($self->{_vars}{$t});
+ } elsif ($tag eq '-aclc') {
+ #return(0) if ($arg !~ /^(\d+)\s(\d+)$/);
+ return(0) if ($arg !~ /^(\S+)\s(\d+)$/);
+ my $t = "acl_c$1";
+ read(I, $self->{_vars}{$t}, $2+1) || return(0);
+ chomp($self->{_vars}{$t});
+ } elsif ($tag eq '-aclm') {
+ #return(0) if ($arg !~ /^(\d+)\s(\d+)$/);
+ return(0) if ($arg !~ /^(\S+)\s(\d+)$/);
+ my $t = "acl_m$1";
+ read(I, $self->{_vars}{$t}, $2+1) || return(0);
+ chomp($self->{_vars}{$t});
+ } elsif ($tag eq '-local') {
+ $self->{_vars}{sender_local} = 1;
+ } elsif ($tag eq '-localerror') {
+ $self->{_vars}{local_error_message} = 1;
+ } elsif ($tag eq '-local_scan') {
+ $self->{_vars}{local_scan_data} = $arg;
+ } elsif ($tag eq '-spam_score_int') {
+ $self->{_vars}{spam_score_int} = $arg;
+ $self->{_vars}{spam_score} = $arg / 10;
+ } elsif ($tag eq '-bmi_verdicts') {
+ $self->{_vars}{bmi_verdicts} = $arg;
+ } elsif ($tag eq '-host_lookup_deferred') {
+ $self->{_vars}{host_lookup_deferred} = 1;
+ } elsif ($tag eq '-host_lookup_failed') {
+ $self->{_vars}{host_lookup_failed} = 1;
+ } elsif ($tag eq '-body_linecount') {
+ $self->{_vars}{body_linecount} = $arg;
+ } elsif ($tag eq '-max_received_linelength') {
+ $self->{_vars}{max_received_linelength} = $arg;
+ } elsif ($tag eq '-body_zerocount') {
+ $self->{_vars}{body_zerocount} = $arg;
+ } elsif ($tag eq '-frozen') {
+ $self->{_vars}{deliver_freeze} = 1;
+ $self->{_vars}{deliver_frozen_at} = $arg;
+ } elsif ($tag eq '-allow_unqualified_recipient') {
+ $self->{_vars}{allow_unqualified_recipient} = 1;
+ } elsif ($tag eq '-allow_unqualified_sender') {
+ $self->{_vars}{allow_unqualified_sender} = 1;
+ } elsif ($tag eq '-deliver_firsttime') {
+ $self->{_vars}{deliver_firsttime} = 1;
+ $self->{_vars}{first_delivery} = 1;
+ } elsif ($tag eq '-manual_thaw') {
+ $self->{_vars}{deliver_manual_thaw} = 1;
+ $self->{_vars}{manually_thawed} = 1;
+ } elsif ($tag eq '-auth_id') {
+ $self->{_vars}{authenticated_id} = $arg;
+ } elsif ($tag eq '-auth_sender') {
+ $self->{_vars}{authenticated_sender} = $arg;
+ } elsif ($tag eq '-sender_set_untrusted') {
+ $self->{_vars}{sender_set_untrusted} = 1;
+ } elsif ($tag eq '-tls_certificate_verified') {
+ $self->{_vars}{tls_certificate_verified} = 1;
+ } elsif ($tag eq '-tls_cipher') {
+ $self->{_vars}{tls_cipher} = $arg;
+ } elsif ($tag eq '-tls_peerdn') {
+ $self->{_vars}{tls_peerdn} = $arg;
+ } elsif ($tag eq '-tls_sni') {
+ $self->{_vars}{tls_sni} = $arg;
+ } elsif ($tag eq '-host_address') {
+ $self->{_vars}{sender_host_port} = $self->_get_host_and_port(\$arg);
+ $self->{_vars}{sender_host_address} = $arg;
+ } elsif ($tag eq '-interface_address') {
+ $self->{_vars}{received_port} =
+ $self->{_vars}{interface_port} = $self->_get_host_and_port(\$arg);
+ $self->{_vars}{received_ip_address} =
+ $self->{_vars}{interface_address} = $arg;
+ } elsif ($tag eq '-active_hostname') {
+ $self->{_vars}{smtp_active_hostname} = $arg;
+ } elsif ($tag eq '-host_auth') {
+ $self->{_vars}{sender_host_authenticated} = $arg;
+ } elsif ($tag eq '-host_name') {
+ $self->{_vars}{sender_host_name} = $arg;
+ } elsif ($tag eq '-helo_name') {
+ $self->{_vars}{sender_helo_name} = $arg;
+ } elsif ($tag eq '-ident') {
+ $self->{_vars}{sender_ident} = $arg;
+ } elsif ($tag eq '-received_protocol') {
+ $self->{_vars}{received_protocol} = $arg;
+ } elsif ($tag eq '-N') {
+ $self->{_vars}{dont_deliver} = 1;
} else {
- last;
+ # unrecognized tag, save it for reference
+ $self->{$tag} = $arg;
}
}
# when we drop out of the while loop, we have the first line of the
# delivered tree in $_
do {
+ chomp;
if ($_ eq 'XX') {
; # noop
} elsif ($_ =~ s/^[YN][YN]\s+//) {
} else {
return(0);
}
- chomp($_ = <I>);
+ $_ = <I>;
} while ($_ !~ /^\d+$/);
$self->{_numrecips} = $_;
} # BEGIN
-sub ext_usage {
- if ($ARGV[0] =~ /^--help$/i) {
- require Config;
- $ENV{PATH} .= ":" unless $ENV{PATH} eq "";
- $ENV{PATH} = "$ENV{PATH}$Config::Config{'installscript'}";
- #exec("perldoc", "-F", "-U", $0) || exit 1;
- $< = $> = 1 if ($> == 0 || $< == 0);
- exec("perldoc", $0) || exit 1;
- # make parser happy
- %Config::Config = ();
- } elsif ($ARGV[0] =~ /^--version$/i) {
- print "$p_name version $p_version\n\n$p_cp\n";
- } else {
- return;
- }
-
- exit(0);
-}
-
__END__
=head1 NAME
-exipick - selectively display messages from an Exim queue
+ exipick - selectively display messages from an Exim queue
=head1 SYNOPSIS
-exipick [<options>] [<criterion> [<criterion> ...]]
+ exipick [<options>] [<criterion> [<criterion> ...]]
+ exipick --help|--man
=head1 DESCRIPTION
-exipick is a tool to display messages in an Exim queue. It is very similar to exiqgrep and is, in fact, a drop in replacement for exiqgrep. exipick allows you to select messages to be displayed using any piece of data stored in an Exim spool file. Matching messages can be displayed in a variety of formats.
+B<exipick> is a tool to display messages in an Exim queue. It is very similar to exiqgrep and is, in fact, a drop in replacement for exiqgrep. B<exipick> allows you to select messages to be displayed using any piece of data stored in an Exim spool file. Matching messages can be displayed in a variety of formats.
=head1 QUICK START
Delete every frozen message from queue:
+
exipick -zi | xargs exim -Mrm
Show only messages which have not yet been virus scanned:
+
exipick '$received_protocol ne virus-scanned'
Run the queue in a semi-random order:
+
exipick -i --random | xargs exim -M
Show the count and total size of all messages which either originated from localhost or have a received protocol of 'local':
+
exipick --or --size --bpc \
'$sender_host_address eq 127.0.0.1' \
'$received_protocol eq local'
Display all messages received on the MSA port, ordered first by the sender's email domain and then by the size of the emails:
+
exipick --sort sender_address_domain,message_size \
'$received_port == 587'
Display only messages whose every recipient is in the example.com domain, also listing the IP address of the sending host:
+
exipick --show-vars sender_host_address \
'$each_recipients = example.com'
Same as above, but show values for all defined variables starting with sender_ and the number of recipients:
+
exipick --show-vars ^sender_,recipients_count \
'$each_recipients = example.com'
=over 4
-=item --and
+=item B<--and>
Display messages matching all criteria (default)
-=item -b
+=item B<-b>
Display messages in brief format (exiqgrep)
-=item -bp
+=item B<-bp> | B<-l>
-Display messages in standard mailq format (default)
+Display messages in standard mailq format (default).
+(exiqgrep: C<-l>)
-=item -bpa
+=item B<-bpa>
-Same as -bp, show generated addresses also (exim)
+Same as C<-bp>, show generated addresses also (exim)
-=item -bpc
+=item B<-bpc>
Show a count of matching messages (exim)
-=item -bpr
+=item B<-bpr>
-Same as '-bp --unsorted' (exim)
+Same as C<-bp --unsorted> (exim)
-=item -bpra
+=item B<-bpra>
-Same as '-bpa --unsorted' (exim)
+Same as C<-bpa --unsorted> (exim)
-=item -bpru
+=item B<-bpru>
-Same as '-bpu --unsorted' (exim)
+Same as C<-bpu --unsorted> (exim)
-=item -bpu
+=item B<-bpu>
-Same as -bp, but only show undelivered messages (exim)
+Same as C<-bp>, but only show undelivered messages (exim)
-=item -C | --config <config>
+=item B<-C> | B<--config> I<config>
-Use <config> to determine the proper spool directory. (See C<--spool>
+Use I<config> to determine the proper spool directory. (See C<--spool>
or C<--input> for alternative ways to specify the directories to operate on.)
-=item -c
+=item B<-c>
Show a count of matching messages (exiqgrep)
-=item --caseful
+=item B<--caseful>
-Make operators involving '=' honor case
+Make operators involving C<=> honor case
-=item --charset
+=item B<--charset>
-Override the default local character set for $header_ decoding
+Override the default local character set for C<$header_> decoding
-=item -f <regexp>
+=item B<-f> I<regexp>
-Same as '$sender_address =~ /<regexp>/' (exiqgrep). Note that this preserves the default case sensitivity of exiqgrep's interface.
+Same as C<< $sender_address =~ /<regexp>/ >> (exiqgrep). Note that this preserves the default case sensitivity of exiqgrep's interface.
-=item --finput
+=item B<--finput>
-Same as '--input-dir Finput'. 'Finput' is where exim copies frozen messages when compiled with SUPPORT_MOVE_FROZEN_MESSAGES.
+Same as C<--input-dir Finput>. F<Finput> is where exim copies frozen messages when compiled with SUPPORT_MOVE_FROZEN_MESSAGES.
-=item --flatq
+=item B<--flatq>
Use a single-line output format
-=item --freeze <cache file>
+=item B<--freeze> I<cache file>
Save queue information in an quickly retrievable format
-=item --help
+=item B<--help>
Display this output
-=item -i
+=item B<-i>
Display only the message IDs (exiqgrep)
-=item --input-dir <inputname>
-
-Set the name of the directory under the spool directory. By default this is "input". If this starts with '/', the value of --spool is ignored. See also --finput.
-
-=item -l
+=item B<--input-dir> I<inputname>
-Same as -bp (exiqgrep)
+Set the name of the directory under the spool directory. By default this is F<input>. If this starts with F</>,
+the value of C<--spool> is ignored. See also C<--finput>.
-=item --not
+=item B<--not>
Negate all tests.
-=item -o <seconds>
+=item B<-o> I<seconds>
-Same as '$message_age > <seconds>' (exiqgrep)
+Same as C<< $message_age > <seconds> >> (exiqgrep)
-=item --or
+=item B<--or>
Display messages matching any criteria
-=item -R
+=item B<--queue> I<name>
-Same as --reverse (exiqgrep)
+Name of the queue (default: ''). See "named queues" in the spec.
-=item -r <regexp>
+=item B<-r> I<regexp>
-Same as '$recipients =~ /<regexp>/' (exiqgrep). Note that this preserves the default case sensitivity of exiqgrep's interface.
+Same as C<< $recipients =~ /<regexp>/ >> (exiqgrep). Note that this preserves the default case sensitivity of exiqgrep's interface.
-=item --random
+=item B<--random>
Display messages in random order
-=item --reverse
+=item B<--reverse> | B<-R>
-Display messages in reverse order
+Display messages in reverse order (exiqgrep: C<-R>)
-=item -s <string>
+=item B<-s> I<string>
-Same as '$shown_message_size eq <string>' (exiqgrep)
+Same as C<< $shown_message_size eq <string> >> (exiqgrep)
-=item --spool <path>
+=item B<--spool> I<path>
-Set the path to the exim spool to use. This value will have the argument to --input or 'input' appended, or be ignored if --input is a full path. If not specified, exipick uses the value from C<exim [-C config] -n -bP spool_directory>, and if this call fails, the F</opt/exim/spool> from build time (F<Local/Makefile>) is used. See also --config.
+Set the path to the exim spool to use. This value will have the arguments to C<--queue>, and C<--input> or F<input> appended, or be ignored if C<--input> is a full path. If not specified, B<exipick> uses the value from C<exim [-C config] -n -bP spool_directory>, and if this call fails, the F</opt/exim/spool> from build time (F<Local/Makefile>) is used. See also C<--config>.
-=item --show-rules
+=item B<--show-rules>
Show the internal representation of each criterion specified
-=item --show-tests
+=item B<--show-tests>
Show the result of each criterion on each message
-=item --show-vars <variable>[,<variable>...]
+=item B<--show-vars> I<variable>[,I<variable>...]
-Show the value for <variable> for each displayed message. <variable> will be a regular expression if it begins with a circumflex.
+Show the value for I<variable> for each displayed message. I<variable> will be a regular expression if it begins with a circumflex.
-=item --size
+=item B<--size>
Show the total bytes used by each displayed message
-=item --thaw <cache file>
+=item B<--thaw> I<cache file>
-Read queue information cached from a previous --freeze run
+Read queue information cached from a previous C<--freeze> run
-=item --sort <variable>[,<variable>...]
+=item B<--sort> I<variable>[,I<variable>...]
-Display matching messages sorted according to <variable>
+Display matching messages sorted according to I<variable>
-=item --unsorted
+=item B<--unsorted>
Do not apply any sorting to output
-=item --version
+=item B<--version>
Display the version of this command
-=item -x
+=item B<-x>
-Same as '!$deliver_freeze' (exiqgrep)
+Same as C<!$deliver_freeze> (exiqgrep)
-=item -y
+=item B<-y>
-Same as '$message_age < <seconds>' (exiqgrep)
+Same as C<< $message_age < <seconds> >> (exiqgrep)
-=item -z
+=item B<-z>
-Same as '$deliver_freeze' (exiqgrep)
+Same as C<$deliver_freeze> (exiqgrep)
=back
=head1 CRITERIA
-Exipick decides which messages to display by applying a test against each message. The rules take the general form of 'VARIABLE OPERATOR VALUE'. For example, '$message_age > 60'. When exipick is deciding which messages to display, it checks the $message_age variable for each message. If a message's age is greater than 60, the message will be displayed. If the message's age is 60 or less seconds, it will not be displayed.
+B<Exipick> decides which messages to display by applying a test against each message. The rules take the general form of "I<VARIABLE> I<OPERATOR> I<VALUE>". For example, C<< $message_age > 60 >>. When B<exipick> is deciding which messages to display, it checks the C<$message_age> variable for each message. If a message's age is greater than 60, the message will be displayed. If the message's age is 60 or less seconds, it will not be displayed.
-Multiple criteria can be used. The order they are specified does not matter. By default all criteria must evaluate to true for a message to be displayed. If the --or option is used, a message is displayed as long as any of the criteria evaluate to true.
+Multiple criteria can be used. The order they are specified does not matter. By default all criteria must evaluate to true for a message to be displayed. If the C<--or> option is used, a message is displayed as long as any of the criteria evaluate to true.
See the VARIABLES and OPERATORS sections below for more details
=item BOOLEAN
Boolean variables are checked simply by being true or false. There is no real operator except negation. Examples of valid boolean tests:
- '$deliver_freeze'
- '!$deliver_freeze'
+
+ $deliver_freeze
+ !$deliver_freeze
=item NUMERIC
Valid comparisons are <, <=, >, >=, ==, and !=. Numbers can be integers or floats. Any number in a test suffixed with d, h, m, s, M, K, or B will be multiplied by 86400, 3600, 60, 1, 1048576, 1024, or 1 respectively. Examples of valid numeric tests:
- '$message_age >= 3d'
- '$local_interface == 587'
- '$message_size < 30K'
+
+ $message_age >= 3d
+ $local_interface == 587
+ $message_size < 30K
=item STRING
-The string operators are =, eq, ne, =~, and !~. With the exception of '=', the operators all match the functionality of the like-named perl operators. eq and ne match a string exactly. !~, =~, and = apply a perl regular expression to a string. The '=' operator behaves just like =~ but you are not required to place // around the regular expression. Examples of valid string tests:
- '$received_protocol eq esmtp'
- '$sender_address = example.com'
- '$each_recipients =~ /^a[a-z]{2,3}@example.com$/'
+The string operators are =, eq, ne, =~, and !~. With the exception of C<< = >>, the operators all match the functionality of the like-named perl operators. eq and ne match a string exactly. !~, =~, and = apply a perl regular expression to a string. The C<< = >> operator behaves just like =~ but you are not required to place // around the regular expression. Examples of valid string tests:
+
+ $received_protocol eq esmtp
+ $sender_address = example.com
+ $each_recipients =~ /^a[a-z]{2,3}@example.com$/
=item NEGATION
-There are many ways to negate tests, each having a reason for existing. Many tests can be negated using native operators. For instance, >1 is the opposite of <=1 and eq and ne are opposites. In addition, each individual test can be negated by adding a ! at the beginning of the test. For instance, '!$acl_m1 =~ /^DENY$/' is the same as '$acl_m1 !~ /^DENY$/'. Finally, every test can be specified by using the command line argument --not. This is functionally equivalent to adding a ! to the beginning of every test.
+There are many ways to negate tests, each having a reason for existing. Many tests can be negated using native operators. For instance, >1 is the opposite of <=1 and eq and ne are opposites. In addition, each individual test can be negated by adding a ! at the beginning of the test. For instance, C<< !$acl_m1 =~ /^DENY$/ >> is the same as C<< $acl_m1 !~ /^DENY$/ >>. Finally, every test can be specified by using the command line argument C<--not>. This is functionally equivalent to adding a ! to the beginning of every test.
=back
With a few exceptions the available variables match Exim's internal expansion variables in both name and exact contents. There are a few notable additions and format deviations which are noted below. Although a brief explanation is offered below, Exim's spec.txt should be consulted for full details. It is important to remember that not every variable will be defined for every message. For example, $sender_host_port is not defined for messages not received from a remote host.
-Internally, all variables are represented as strings, meaning any operator will work on any variable. This means that '$sender_host_name > 4' is a legal criterion, even if it does not produce meaningful results. Variables in the list below are marked with a 'type' to help in choosing which types of operators make sense to use.
+Internally, all variables are represented as strings, meaning any operator will work on any variable. This means that C<< $sender_host_name > 4 >> is a legal criterion, even if it does not produce meaningful results. Variables in the list below are marked with a 'type' to help in choosing which types of operators make sense to use.
Identifiers
B - Boolean variables
=over 4
-=item S . $acl_c0-$acl_c9, $acl_m0-$acl_m9
+=item S . B<$acl_c0>-B<$acl_c9>, B<$acl_m0>-B<$acl_m9>
User definable variables.
-=item B + $allow_unqualified_recipient
+=item B + B<$allow_unqualified_recipient>
TRUE if unqualified recipient addresses are permitted in header lines.
-=item B + $allow_unqualified_sender
+=item B + B<$allow_unqualified_sender>
TRUE if unqualified sender addresses are permitted in header lines.
-=item S . $authenticated_id
+=item S . B<$authenticated_id>
Optional saved information from authenticators, or the login name of the calling process for locally submitted messages.
-=item S . $authenticated_sender
+=item S . B<$authenticated_sender>
The value of AUTH= param for smtp messages, or a generated value from the calling processes login and qualify domain for locally submitted messages.
-=item S . $bheader_*, $bh_*
+=item S . B<$bheader_*>, B<$bh_*>
Value of the header(s) with the same name with any RFC2047 words decoded if present. See section 11.5 of Exim's spec.txt for full details.
-=item S + $bmi_verdicts
+=item S + B<$bmi_verdicts>
The verdict string provided by a Brightmail content scan
-=item N . $body_linecount
+=item N . B<$body_linecount>
The number of lines in the message's body.
-=item N . $body_zerocount
+=item N . B<$body_zerocount>
The number of binary zero bytes in the message's body.
-=item S + $data_path
+=item S + B<$data_path>
The path to the body file's location in the filesystem.
-=item B + $deliver_freeze
+=item B + B<$deliver_freeze>
TRUE if the message is currently frozen.
-=item N + $deliver_frozen_at
+=item N + B<$deliver_frozen_at>
The epoch time at which message was frozen.
-=item B + $dont_deliver
+=item B + B<$dont_deliver>
TRUE if, under normal circumstances, Exim will not try to deliver the message.
-=item S + $each_recipients
+=item S + B<$each_recipients>
-This is a pseudo variable which allows you to apply a test against each address in $recipients individually. Whereas '$recipients =~ /@aol.com/' will match if any recipient address contains aol.com, '$each_recipients =~ /@aol.com$/' will only be true if every recipient matches that pattern. Note that this obeys --and or --or being set. Using it with --or is very similar to just matching against $recipients, but with the added benefit of being able to use anchors at the beginning and end of each recipient address.
+This is a pseudo variable which allows you to apply a test against each address in $recipients individually. Whereas C<< $recipients =~ /@aol.com/ >> will match if any recipient address contains aol.com, C<< $each_recipients =~ /@aol.com$/ >> will only be true if every recipient matches that pattern. Note that this obeys C<--and> or C<--or> being set. Using it with C<--or> is very similar to just matching against $recipients, but with the added benefit of being able to use anchors at the beginning and end of each recipient address.
-=item S + $each_recipients_del
+=item S + B<$each_recipients_del>
Like $each_recipients, but for $recipients_del
-=item S + $each_recipients_undel
+=item S + B<$each_recipients_undel>
Like $each_recipients, but for $recipients_undel
-=item B . $first_delivery
+=item B . B<$first_delivery>
TRUE if the message has never been deferred.
-=item S . $header_*, $h_*
+=item S . B<$header_*>, B<$h_*>
This will always match the contents of the corresponding $bheader_* variable currently (the same behaviour Exim displays when iconv is not installed).
-=item S + $header_path
+=item S + B<$header_path>
The path to the header file's location in the filesystem.
-=item B . $host_lookup_deferred
+=item B . B<$host_lookup_deferred>
TRUE if there was an attempt to look up the host's name from its IP address, but an error occurred that during the attempt.
-=item B . $host_lookup_failed
+=item B . B<$host_lookup_failed>
TRUE if there was an attempt to look up the host's name from its IP address, but the attempt returned a negative result.
-=item B + $local_error_message
+=item B + B<$local_error_message>
TRUE if the message is a locally-generated error message.
-=item S . $local_scan_data
+=item S . B<$local_scan_data>
The text returned by the local_scan() function when a message is received.
-=item B . $manually_thawed
+=item B . B<$manually_thawed>
TRUE when the message has been manually thawed.
-=item N . $max_received_linelength
+=item N . B<$max_received_linelength>
The number of bytes in the longest line that was received as part of the message, not counting line termination characters.
-=item N . $message_age
+=item N . B<$message_age>
The number of seconds since the message was received.
-=item S # $message_body
+=item S # B<$message_body>
The message's body. Unlike Exim's variable of the same name, this variable contains the entire message body. Newlines and nulls are replaced by spaces.
-=item B + $message_body_missing
+=item B + B<$message_body_missing>
TRUE is a message's spool data file (-D file) is missing or unreadable.
-=item N . $message_body_size
+=item N . B<$message_body_size>
The size of the body in bytes.
-=item S . $message_exim_id, $message_id
+=item S . B<$message_exim_id>, B<$message_id>
The unique message id that is used by Exim to identify the message. $message_id is deprecated as of Exim 4.53.
-=item S . $message_headers
+=item S . B<$message_headers>
A concatenation of all the header lines except for lines added by routers or transports. RFC2047 decoding is performed
-=item S . $message_headers_raw
+=item S . B<$message_headers_raw>
A concatenation of all the header lines except for lines added by routers or transports. No decoding or translation is performed.
-=item N . $message_linecount
+=item N . B<$message_linecount>
The number of lines in the entire message (body and headers).
-=item N . $message_size
+=item N . B<$message_size>
The size of the message in bytes.
-=item N . $originator_gid
+=item N . B<$originator_gid>
The group id under which the process that called Exim was running as when the message was received.
-=item S + $originator_login
+=item S + B<$originator_login>
The login of the process which called Exim.
-=item N . $originator_uid
+=item N . B<$originator_uid>
The user id under which the process that called Exim was running as when the message was received.
-=item S . $received_ip_address, $interface_address
+=item S . B<$received_ip_address>, B<$interface_address>
The address of the local IP interface for network-originated messages. $interface_address is deprecated as of Exim 4.64
-=item N . $received_port, $interface_port
+=item N . B<$received_port>, B<$interface_port>
The local port number if network-originated messages. $interface_port is deprecated as of Exim 4.64
-=item N . $received_count
+=item N . B<$received_count>
The number of Received: header lines in the message.
-=item S . $received_protocol
+=item S . B<$received_protocol>
The name of the protocol by which the message was received.
-=item N . $received_time
+=item N . B<$received_time>
The epoch time at which the message was received.
-=item S # $recipients
+=item S # B<$recipients>
The list of envelope recipients for a message. Unlike Exim's version, this variable always contains every recipient of the message. The recipients are separated by a comma and a space. See also $each_recipients.
-=item N . $recipients_count
+=item N . B<$recipients_count>
The number of envelope recipients for the message.
-=item S + $recipients_del
+=item S + B<$recipients_del>
The list of delivered envelope recipients for a message. This non-standard variable is in the same format as $recipients and contains the list of already-delivered recipients including any generated addresses. See also $each_recipients_del.
-=item N + $recipients_del_count
+=item N + B<$recipients_del_count>
The number of envelope recipients for the message which have already been delivered. Note that this is the count of original recipients to which the message has been delivered. It does not include generated addresses so it is possible that this number will be less than the number of addresses in the $recipients_del string.
-=item S + $recipients_undel
+=item S + B<$recipients_undel>
The list of undelivered envelope recipients for a message. This non-standard variable is in the same format as $recipients and contains the list of undelivered recipients. See also $each_recipients_undel.
-=item N + $recipients_undel_count
+=item N + B<$recipients_undel_count>
The number of envelope recipients for the message which have not yet been delivered.
-=item S . $reply_address
+=item S . B<$reply_address>
The contents of the Reply-To: header line if one exists and it is not empty, or otherwise the contents of the From: header line.
-=item S . $rheader_*, $rh_*
+=item S . B<$rheader_*>, B<$rh_*>
The value of the message's header(s) with the same name. See section 11.5 of Exim's spec.txt for full description.
-=item S . $sender_address
+=item S . B<$sender_address>
The sender's address that was received in the message's envelope. For bounce messages, the value of this variable is the empty string.
-=item S . $sender_address_domain
+=item S . B<$sender_address_domain>
The domain part of $sender_address.
-=item S . $sender_address_local_part
+=item S . B<$sender_address_local_part>
The local part of $sender_address.
-=item S . $sender_helo_name
+=item S . B<$sender_helo_name>
The HELO or EHLO value supplied for smtp or bsmtp messages.
-=item S . $sender_host_address
+=item S . B<$sender_host_address>
The remote host's IP address.
-=item S . $sender_host_authenticated
+=item S . B<$sender_host_authenticated>
The name of the authenticator driver which successfully authenticated the client from which the message was received.
-=item S . $sender_host_name
+=item S . B<$sender_host_name>
The remote host's name as obtained by looking up its IP address.
-=item N . $sender_host_port
+=item N . B<$sender_host_port>
The port number that was used on the remote host for network-originated messages.
-=item S . $sender_ident
+=item S . B<$sender_ident>
The identification received in response to an RFC 1413 request for remote messages, the login name of the user that called Exim for locally generated messages.
-=item B + $sender_local
+=item B + B<$sender_local>
TRUE if the message was locally generated.
-=item B + $sender_set_untrusted
+=item B + B<$sender_set_untrusted>
TRUE if the envelope sender of this message was set by an untrusted local caller.
-=item S + $shown_message_size
+=item S + B<$shown_message_size>
This non-standard variable contains the formatted size string. That is, for a message whose $message_size is 66566 bytes, $shown_message_size is 65K.
-=item S . $smtp_active_hostname
+=item S . B<$smtp_active_hostname>
The value of the active host name when the message was received, as specified by the "smtp_active_hostname" option.
-=item S . $spam_score
+=item S . B<$spam_score>
The spam score of the message, for example '3.4' or '30.5'. (Requires exiscan or WITH_CONTENT_SCAN)
-=item S . $spam_score_int
+=item S . B<$spam_score_int>
The spam score of the message, multiplied by ten, as an integer value. For instance '34' or '305'. (Requires exiscan or WITH_CONTENT_SCAN)
-=item B . $tls_certificate_verified
+=item B . B<$tls_certificate_verified>
TRUE if a TLS certificate was verified when the message was received.
-=item S . $tls_cipher
+=item S . B<$tls_cipher>
The cipher suite that was negotiated for encrypted SMTP connections.
-=item S . $tls_peerdn
+=item S . B<$tls_peerdn>
The value of the Distinguished Name of the certificate if Exim is configured to request one
-=item S . $tls_sni
+=item S . B<$tls_sni>
The value of the Server Name Indication TLS extension sent by a client, if one was sent.
-=item N + $warning_count
+=item N + B<$warning_count>
The number of delay warnings which have been sent for this message.
=item EMAIL: proj-exipick@jetmore.net
-=item HOME: jetmore.org/john/code/#exipick
+=item HOME: L<https://jetmore.org/john/code/#exipick>
+
+This script was incorporated into the main Exim distribution some years ago.
=back
=cut
+
+# vim:ft=perl
extern uschar * tls_cert_fprt_sha1(void *);
extern uschar * tls_cert_fprt_sha256(void *);
+extern void tls_clean_env(void);
extern BOOL tls_client_start(client_conn_ctx *, smtp_connect_args *,
void *, tls_support *, uschar **);
#endif
extern dns_address *dns_address_from_rr(dns_answer *, dns_record *);
extern int dns_basic_lookup(dns_answer *, const uschar *, int);
-extern void dns_build_reverse(const uschar *, uschar *);
-extern time_t dns_expire_from_soa(dns_answer *);
+extern uschar *dns_build_reverse(const uschar *);
+extern time_t dns_expire_from_soa(dns_answer *, int);
extern void dns_init(BOOL, BOOL, BOOL);
extern BOOL dns_is_aa(const dns_answer *);
extern BOOL dns_is_secure(const dns_answer *);
extern int strncmpic(const uschar *, const uschar *, int);
extern uschar *strstric(uschar *, uschar *, BOOL);
+extern int test_harness_fudged_queue_time(int);
extern void tcp_init(void);
#ifdef EXIM_TFO_PROBE
extern void tfo_probe(void);
# endif
static inline uschar *
-spool_sname(const uschar * purpose, uschar * subdir)
+spool_q_sname(const uschar * purpose, const uschar * q, uschar * subdir)
{
return string_sprintf("%s%s%s%s%s",
- queue_name, *queue_name ? "/" : "",
+ q, *q ? "/" : "",
purpose,
*subdir ? "/" : "", subdir);
}
+static inline uschar *
+spool_sname(const uschar * purpose, uschar * subdir)
+{
+return spool_q_sname(purpose, queue_name, subdir);
+}
+
+static inline uschar *
+spool_q_fname(const uschar * purpose, const uschar * q,
+ const uschar * subdir, const uschar * fname, const uschar * suffix)
+{
+return string_sprintf("%s/%s/%s/%s/%s%s",
+ spool_directory, q, purpose, subdir, fname, suffix);
+}
+
static inline uschar *
spool_fname(const uschar * purpose, const uschar * subdir, const uschar * fname,
const uschar * suffix)
{
-return string_sprintf("%s/%s/%s/%s/%s%s",
- spool_directory, queue_name, purpose, subdir, fname, suffix);
+return spool_q_fname(purpose, queue_name, subdir, fname, suffix);
}
static inline void
if (diff->tv_sec >= 5 || !LOGGING(millisec))
return readconf_printtime((int)diff->tv_sec);
-sprintf(CS buf, "%u.%03us", (uint)diff->tv_sec, (uint)diff->tv_usec/1000);
+snprintf(CS buf, sizeof(buf), "%u.%03us", (uint)diff->tv_sec, (uint)diff->tv_usec/1000);
return buf;
}
uschar *queue_domains = NULL;
int queue_interval = -1;
uschar *queue_name = US"";
+uschar *queue_name_dest = NULL;
uschar *queue_only_file = NULL;
int queue_only_load = -1;
uschar *queue_run_max = US"5";
.pass_router = NULL,
.redirect_router = NULL,
- .dnssec = { NULL, NULL }, /* dnssec_domains {require,request} */
+ .dnssec = { .request= US"*", .require=NULL },
};
uschar *router_name = NULL;
extern int queue_run_pipe; /* Pipe for synchronizing */
extern int queue_interval; /* Queue running interval */
extern uschar *queue_name; /* Name of queue, if nondefault spooling */
+extern uschar *queue_name_dest; /* Destination queue, for moving messages */
extern BOOL queue_only; /* TRUE to disable immediate delivery */
extern int queue_only_load; /* Max load before auto-queue */
extern BOOL queue_only_load_latch; /* Latch queue_only_load TRUE */
time_msec = get_time_in_ms();
retval = dns_lookup(dnsa, name, type, fully_qualified_name);
if ((time_msec = get_time_in_ms() - time_msec) > slow_lookup_log)
- log_long_lookup(US"name", name, time_msec);
+ log_long_lookup(dns_text_type(type), name, time_msec);
return retval;
}
if ( slow_lookup_log
&& (time_msec = get_time_in_ms() - time_msec) > slow_lookup_log
)
- log_long_lookup(US"name", sender_host_address, time_msec);
+ log_long_lookup(US"gethostbyaddr", sender_host_address, time_msec);
/* Failed to look up the host. */
int sep = 0;
uschar *save_hostname;
uschar **aliases;
-uschar buffer[256];
uschar *ordername;
const uschar *list = host_lookup_order;
dns_answer * dnsa = store_get_dns_answer();
/* Do lookups directly in the DNS or via gethostbyaddr() (or equivalent), in
the order specified by the host_lookup_order option. */
-while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
+while ((ordername = string_nextinlist(&list, &sep, NULL, 0)))
{
if (strcmpic(ordername, US"bydns") == 0)
{
+ uschar * name = dns_build_reverse(sender_host_address);
+
dns_init(FALSE, FALSE, FALSE); /* dnssec ctrl by dns_dnssec_ok glbl */
- dns_build_reverse(sender_host_address, buffer);
- rc = dns_lookup_timerwrap(dnsa, buffer, T_PTR, NULL);
+ rc = dns_lookup_timerwrap(dnsa, name, T_PTR, NULL);
/* The first record we come across is used for the name; others are
considered to be aliases. We have to scan twice, in order to find out the
if ( slow_lookup_log
&& (time_msec = get_time_in_ms() - time_msec) > slow_lookup_log)
- log_long_lookup(US"name", host->name, time_msec);
+ log_long_lookup(US"gethostbyname", host->name, time_msec);
if (hostdata == NULL)
{
if (dnssec_request)
if (dns_is_secure(dnsa))
{
- DEBUG(D_host_lookup) debug_printf("%s MX DNSSEC\n", host->name);
+ DEBUG(D_host_lookup) debug_printf("%s (MX resp) DNSSEC\n", host->name);
dnssec = DS_YES; lookup_dnssec_authenticated = US"yes";
}
else
return yield;
}
+
+
+
+#ifdef SUPPORT_DANE
+/* Lookup TLSA record for host/port.
+Return: OK success with dnssec; DANE mode
+ DEFER Do not use this host now, may retry later
+ FAIL_FORCED No TLSA record; DANE not usable
+ FAIL Do not use this connection
+*/
+
+int
+tlsa_lookup(const host_item * host, dns_answer * dnsa, BOOL dane_required)
+{
+uschar buffer[300];
+const uschar * fullname = buffer;
+int rc;
+BOOL sec;
+
+/* TLSA lookup string */
+(void)sprintf(CS buffer, "_%d._tcp.%.256s", host->port, host->name);
+
+rc = dns_lookup_timerwrap(dnsa, buffer, T_TLSA, &fullname);
+sec = dns_is_secure(dnsa);
+DEBUG(D_transport)
+ debug_printf("TLSA lookup ret %d %sDNSSEC\n", rc, sec ? "" : "not ");
+
+switch (rc)
+ {
+ case DNS_AGAIN:
+ return DEFER; /* just defer this TLS'd conn */
+
+ case DNS_SUCCEED:
+ if (sec)
+ {
+ DEBUG(D_transport)
+ {
+ dns_scan dnss;
+ for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
+ rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
+ if (rr->type == T_TLSA && rr->size > 3)
+ {
+ uint16_t payload_length = rr->size - 3;
+ uschar s[MAX_TLSA_EXPANDED_SIZE], * sp = s, * p = US rr->data;
+
+ sp += sprintf(CS sp, "%d ", *p++); /* usage */
+ sp += sprintf(CS sp, "%d ", *p++); /* selector */
+ sp += sprintf(CS sp, "%d ", *p++); /* matchtype */
+ while (payload_length-- > 0 && sp-s < (MAX_TLSA_EXPANDED_SIZE - 4))
+ sp += sprintf(CS sp, "%02x", *p++);
+
+ debug_printf(" %s\n", s);
+ }
+ }
+ return OK;
+ }
+ log_write(0, LOG_MAIN,
+ "DANE error: TLSA lookup for %s not DNSSEC", host->name);
+ /*FALLTRHOUGH*/
+
+ case DNS_NODATA: /* no TLSA RR for this lookup */
+ case DNS_NOMATCH: /* no records at all for this lookup */
+ return dane_required ? FAIL : FAIL_FORCED;
+
+ default:
+ case DNS_FAIL:
+ return dane_required ? FAIL : DEFER;
+ }
+}
+#endif /*SUPPORT_DANE*/
+
+
+
/*************************************************
**************************************************
* Stand-alone test program *
each time a new feature is added (in a way that doesn't break backward
compatibility). */
-#define LOCAL_SCAN_ABI_VERSION_MAJOR 2
-#define LOCAL_SCAN_ABI_VERSION_MINOR 0
+#define LOCAL_SCAN_ABI_VERSION_MAJOR 3
+#define LOCAL_SCAN_ABI_VERSION_MINOR 1
#define LOCAL_SCAN_ABI_VERSION \
LOCAL_SCAN_ABI_VERSION_MAJOR.LOCAL_SCAN_ABI_VERSION_MINOR
string_sprintf_trc(fmt, US __FUNCTION__, __LINE__, __VA_ARGS__)
extern uschar *string_sprintf_trc(const char *, const uschar *, unsigned, ...) ALMOST_PRINTF(1,4);
-#ifdef LOCAL_SCAN
+#if defined(LOCAL_SCAN) || defined(DLFUNC_IMPL)
/* When compiling a local_scan() file we want to rename a published API, so that
we can use an inlined implementation in the compiles of the main Exim files,
with the original name. */
# define string_copy_taint(s, t) string_copy_taint_function((s), (t))
extern uschar * string_copy_function(const uschar *);
-extern uschar * string_copyn_function(const uschar *);
-extern uschar * string_copy_taint_function(const uschar *);
+extern uschar * string_copyn_function(const uschar *, int n);
+extern uschar * string_copy_taint_function(const uschar *, BOOL tainted);
#endif
/* End of local_scan.h */
causes the whole lookup to defer only if none of the DNS queries succeeds; and
'never', where all defers are as if the lookup failed. The default is 'lax'.
-- 'dnssec_FOO', with 'strict', 'lax' and 'never' (default). The meanings are
+- 'dnssec_FOO', with 'strict', 'lax' (default), and 'never'. The meanings are
require, try and don't-try dnssec respectively.
- 'retrans_VAL', set the timeout value. VAL is an Exim time specification
int rc;
int sep = 0;
int defer_mode = PASS;
-int dnssec_mode = OK;
+int dnssec_mode = PASS;
int save_retrans = dns_retrans;
int save_retry = dns_retry;
int type;
while ((domain = string_nextinlist(&keystring, &sep, NULL, 0)))
{
- uschar rbuffer[256];
int searchtype = type == T_CSA ? T_SRV : /* record type we want */
type == T_MXH ? T_MX :
type == T_ZNS ? T_NS : type;
if ((type == T_PTR || type == T_CSA) &&
string_is_ip_address(domain, NULL) != 0)
- {
- dns_build_reverse(domain, rbuffer);
- domain = rbuffer;
- }
+ domain = dns_build_reverse(domain);
do
{
enum { MSG_DELIVER, MSG_FREEZE, MSG_REMOVE, MSG_THAW, MSG_ADD_RECIPIENT,
MSG_MARK_ALL_DELIVERED, MSG_MARK_DELIVERED, MSG_EDIT_SENDER,
- MSG_SHOW_COPY, MSG_LOAD,
+ MSG_SHOW_COPY, MSG_LOAD, MSG_SETQUEUE,
/* These ones must be last: a test for >= MSG_SHOW_BODY is used
to test for actions that list individual spool files. */
MSG_SHOW_BODY, MSG_SHOW_HEADER, MSG_SHOW_LOG };
{
pdkim_bodyhash * b;
+if (hashtype == -1 || canon_method == -1) return NULL;
+
for (b = ctx->bodyhash; b; b = b->next)
if ( hashtype == b->hashtype
&& canon_method == b->canon_method
if (f.running_in_test_harness && !f.queue_2stage)
{
- uschar *fqtnext = Ustrchr(fudged_queue_times, '/');
- if (fqtnext != NULL) fudged_queue_times = fqtnext + 1;
+ uschar * fqtnext = Ustrchr(fudged_queue_times, '/');
+ if (fqtnext) fudged_queue_times = fqtnext + 1;
}
} /* End loop for list of messages */
}
+ case MSG_SETQUEUE:
+ /* The global "queue_name_dest" is used as destination, "queue_name"
+ as source */
+
+ spool_move_message(id, message_subdir, US"", US"");
+ break;
+
+
case MSG_MARK_ALL_DELIVERED:
for (int i = 0; i < recipients_count; i++)
tree_add_nonrecipient(recipients_list[i].address);
}
}
-/* Do a dummy store-allocation of a size related to the (toplevel) file size.
-This assumes we will need this much storage to handle all the allocations
-during startup; it won't help when .include is being used. When it does, it
-will cut down on the number of store blocks (and malloc calls, and sbrk
-syscalls). It also assume we're on the relevant pool. */
-
-if (statbuf.st_size > 8192)
- {
- rmark r = store_mark();
- void * dummy = store_get((int)statbuf.st_size, FALSE);
- store_reset(r);
- }
-
/* Process the main configuration settings. They all begin with a lower case
letter. If we see something starting with an upper case letter, it is taken as
a macro definition. */
checking that: for convenience, TLS output errors are remembered here so that
they are also picked up later by smtp_fflush().
+This function is exposed to the local_scan API; do not change the signature.
+
Arguments:
format format string
more further data expected
/* This is split off so that verify.c:respond_printf() can, in effect, call
smtp_printf(), bearing in mind that in C a vararg function can't directly
-call another vararg function, only a function which accepts a va_list. */
+call another vararg function, only a function which accepts a va_list.
+
+This function is exposed to the local_scan API; do not change the signature.
+*/
/*XXX consider passing caller-info in, for string_vformat-onward */
void
DEBUG(D_receive) debug_printf("spf: SPF_server_new() failed.\n");
return FALSE;
}
+ /* Quick hack to override the outdated explanation URL.
+ See https://www.mail-archive.com/mailop@mailop.org/msg08019.html */
+ SPF_server_set_explanation(spf_server, "Please%_see%_http://www.open-spf.org/Why?id=%{S}&ip=%{C}&receiver=%{R}", &spf_response);
+ if (SPF_response_errcode(spf_response) != SPF_E_SUCCESS)
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", SPF_strerror(SPF_response_errcode(spf_response)));
+
return TRUE;
}
received_time.tv_usec = 0;
message_age = time(NULL) - received_time.tv_sec;
+#ifndef COMPILE_UTILITY
+if (f.running_in_test_harness)
+ message_age = test_harness_fudged_queue_time(message_age);
+#endif
#ifndef COMPILE_UTILITY
DEBUG(D_deliver) debug_printf("user=%s uid=%ld gid=%ld sender=%s\n",
originator_login, (long int)originator_uid, (long int)originator_gid,
sender_address);
-#endif /* COMPILE_UTILITY */
+#endif
/* Now there may be a number of optional lines, each starting with "-". If you
add a new setting here, make sure you set the default above.
}
-#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
-
/************************************************
* Make a hard link *
************************************************/
Arguments:
dir base directory name
+ dq destiinationqueue name
subdir subdirectory name
id message id
suffix suffix to add to id
*/
static BOOL
-make_link(uschar *dir, uschar *subdir, uschar *id, uschar *suffix, uschar *from,
- uschar *to, BOOL noentok)
+make_link(uschar *dir, uschar * dq, uschar *subdir, uschar *id, uschar *suffix,
+ uschar *from, uschar *to, BOOL noentok)
{
uschar * fname = spool_fname(string_sprintf("%s%s", from, dir), subdir, id, suffix);
-uschar * tname = spool_fname(string_sprintf("%s%s", to, dir), subdir, id, suffix);
+uschar * tname = spool_q_fname(string_sprintf("%s%s", to, dir), dq, subdir, id, suffix);
if (Ulink(fname, tname) < 0 && (!noentok || errno != ENOENT))
{
log_write(0, LOG_MAIN|LOG_PANIC, "link(\"%s\", \"%s\") failed while moving "
/* Move the files for a message (-H, -D, and msglog) from one directory (or
hierarchy) to another. It is assume that there is no -J file in existence when
-this is done. At present, this is used only when move_frozen_messages is set,
-so compile it only when that support is configured.
+this is done.
Arguments:
id the id of the message to be delivered
BOOL
spool_move_message(uschar *id, uschar *subdir, uschar *from, uschar *to)
{
+uschar * dest_qname = queue_name_dest ? queue_name_dest : queue_name;
+
/* Create any output directories that do not exist. */
(void) directory_make(spool_directory,
- spool_sname(string_sprintf("%sinput", to), subdir),
+ spool_q_sname(string_sprintf("%sinput", to), dest_qname, subdir),
INPUT_DIRECTORY_MODE, TRUE);
(void) directory_make(spool_directory,
- spool_sname(string_sprintf("%smsglog", to), subdir),
+ spool_q_sname(string_sprintf("%smsglog", to), dest_qname, subdir),
INPUT_DIRECTORY_MODE, TRUE);
/* Move the message by first creating new hard links for all the files, and
the mail spool, the -D file should be open and locked at the time, thus keeping
Exim's hands off. */
-if (!make_link(US"msglog", subdir, id, US"", from, to, TRUE) ||
- !make_link(US"input", subdir, id, US"-D", from, to, FALSE) ||
- !make_link(US"input", subdir, id, US"-H", from, to, FALSE))
+if (!make_link(US"msglog", dest_qname, subdir, id, US"", from, to, TRUE) ||
+ !make_link(US"input", dest_qname, subdir, id, US"-D", from, to, FALSE) ||
+ !make_link(US"input", dest_qname, subdir, id, US"-H", from, to, FALSE))
return FALSE;
if (!break_link(US"input", subdir, id, US"-H", from, FALSE) ||
!break_link(US"msglog", subdir, id, US"", from, TRUE))
return FALSE;
-log_write(0, LOG_MAIN, "moved from %sinput, %smsglog to %sinput, %smsglog",
- from, from, to, to);
+log_write(0, LOG_MAIN, "moved from %s%s%s%sinput, %smsglog to %s%s%s%sinput, %smsglog",
+ *queue_name?"(":"", *queue_name?queue_name:US"", *queue_name?") ":"",
+ from, from,
+ *dest_qname?"(":"", *dest_qname?dest_qname:US"", *dest_qname?") ":"",
+ to, to);
return TRUE;
}
-#endif
/* End of spool_out.c */
/* vi: aw ai sw=2
-#if defined(HAVE_LOCAL_SCAN) && !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
+#if (defined(HAVE_LOCAL_SCAN) || defined(EXPAND_DLFUNC)) \
+ && !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
/*************************************************
* Copy and save string *
*************************************************/
# define GNUTLS_AUTO_GLOBAL_INIT
# define GNUTLS_AUTO_PKCS11_MANUAL
#endif
+#if (GNUTLS_VERSION_NUMBER >= 0x030404) \
+ || (GNUTLS_VERSION_NUMBER >= 0x030311) && (GNUTLS_VERSION_NUMBER & 0xffff00 == 0x030300)
+# ifndef DISABLE_OCSP
+# define EXIM_HAVE_OCSP
+# endif
+#endif
#if GNUTLS_VERSION_NUMBER >= 0x030500
# define SUPPORT_GNUTLS_KEYLOG
#endif
# ifdef EXIM_HAVE_TLS1_3
builtin_macro_create(US"_HAVE_TLS1_3");
# endif
+# ifdef EXIM_HAVE_OCSP
+builtin_macro_create(US"_HAVE_TLS_OCSP");
+# endif
+# ifdef SUPPORT_SRV_OCSP_STACK
+builtin_macro_create(US"_HAVE_TLS_OCSP_LIST");
+# endif
}
#else
#ifdef SUPPORT_GNUTLS_SESS_DESC
debug_printf("%s\n", gnutls_session_get_desc(state->session));
#endif
-#ifdef SUPPORT_GNUTLS_KEYLOG
+#ifdef SUPPORT_GNUTLS_KEYLOG
# ifdef EXIM_HAVE_TLS1_3
if (gnutls_protocol_get_version(state->session) < GNUTLS_TLS1_3)
-#else
+# else
if (TRUE)
-#endif
+# endif
{
gnutls_datum_t c, s;
gstring * gc, * gs;
- /* we only want the client random and the master secret */
+ /* For TLS1.2 we only want the client random and the master secret */
gnutls_session_get_random(state->session, &c, &s);
gnutls_session_get_master_secret(state->session, &s);
gc = ddump(&c);
" add SSLKEYLOGFILE to keep_environment in the exim config\n"
" run exim as root\n"
" if using sudo, add SSLKEYLOGFILE to env_keep in /etc/sudoers\n"
- " (works for TLS1.2 also, and saves cut-paste into file)\n");
+ " (works for TLS1.2 also, and saves cut-paste into file)"
+ " Trying to use add_environment for this will not work\n");
#endif
}
# define EXIM_HAVE_SESSION_TICKET
# define EXIM_HAVE_OPESSL_TRACE
# define EXIM_HAVE_OPESSL_GET0_SERIAL
+# ifndef DISABLE_OCSP
+# define EXIM_HAVE_OCSP
+# endif
# else
# define EXIM_NEED_OPENSSL_INIT
# endif
# define OPENSSL_HAVE_KEYLOG_CB
# define OPENSSL_HAVE_NUM_TICKETS
# define EXIM_HAVE_OPENSSL_CIPHER_STD_NAME
+# else
+# define OPENSSL_BAD_SRVR_OURCERT
# endif
#endif
==> 1.0.1b <==
Plus SSL_OP_SAFARI_ECDHE_ECDSA_BUG from 2013-June patch/discussion on openssl-dev
Plus SSL_OP_NO_TLSv1_3 for 1.1.2-dev
+Plus SSL_OP_NO_RENEGOTIATION for 1.1.1
+
+XXX could we autobuild this list, as with predefined-macros?
+Seems just parsing ssl.h for SSL_OP_.* would be enough.
+Also allow a numeric literal?
*/
static exim_openssl_option exim_openssl_options[] = {
/* KEEP SORTED ALPHABETICALLY! */
#ifdef SSL_OP_NO_COMPRESSION
{ US"no_compression", SSL_OP_NO_COMPRESSION },
#endif
+#ifdef SSL_OP_NO_RENEGOTIATION
+ { US"no_renegotiation", SSL_OP_NO_RENEGOTIATION },
+#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
{ US"no_session_resumption_on_renegotiation", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION },
#endif
# ifdef SSL_OP_NO_TLSv1_3
builtin_macro_create(US"_HAVE_TLS1_3");
# endif
+# ifdef OPENSSL_BAD_SRVR_OURCERT
+builtin_macro_create(US"_TLS_BAD_MULTICERT_IN_OURCERT");
+# endif
+# ifdef EXIM_HAVE_OCSP
+builtin_macro_create(US"_HAVE_TLS_OCSP");
+builtin_macro_create(US"_HAVE_TLS_OCSP_LIST");
+# endif
}
#else
static void
keylog_callback(const SSL *ssl, const char *line)
{
+char * filename;
+FILE * fp;
DEBUG(D_tls) debug_printf("%.200s\n", line);
+if (!(filename = getenv("SSLKEYLOGFILE"))) return;
+if (!(fp = fopen(filename, "a"))) return;
+fprintf(fp, "%s\n", line);
+fclose(fp);
}
#endif
sctx the SSL_CTX* to update
cbinfo various parts of session state
filename the filename putatively holding an OCSP response
+ is_pem file is PEM format; otherwise is DER
*/
static void
ocsp_load_response(SSL_CTX * sctx, tls_ext_ctx_cb * cbinfo,
- const uschar * filename)
+ const uschar * filename, BOOL is_pem)
{
BIO * bio;
OCSP_RESPONSE * resp;
unsigned long verify_flags;
int status, reason, i;
-DEBUG(D_tls) debug_printf("tls_ocsp_file '%s'\n", filename);
+DEBUG(D_tls)
+ debug_printf("tls_ocsp_file (%s) '%s'\n", is_pem ? "PEM" : "DER", filename);
if (!(bio = BIO_new_file(CS filename, "rb")))
{
return;
}
-resp = d2i_OCSP_RESPONSE_bio(bio, NULL);
+if (is_pem)
+ {
+ uschar * data, * freep;
+ char * dummy;
+ long len;
+ if (!PEM_read_bio(bio, &dummy, &dummy, &data, &len))
+ {
+ DEBUG(D_tls) debug_printf("Failed to read PEM file \"%s\"\n",
+ filename);
+ return;
+ }
+debug_printf("read pem file\n");
+ freep = data;
+ resp = d2i_OCSP_RESPONSE(NULL, CUSS &data, len);
+ OPENSSL_free(freep);
+ }
+else
+ resp = d2i_OCSP_RESPONSE_bio(bio, NULL);
BIO_free(bio);
+
if (!resp)
{
DEBUG(D_tls) debug_printf("Error reading OCSP response.\n");
const uschar * olist = cbinfo->u_ocsp.server.file;
int osep = 0;
uschar * ofile;
+ BOOL fmt_pem = FALSE;
if (olist)
if (!expand_check(olist, US"tls_ocsp_file", USS &olist, errstr))
#ifndef DISABLE_OCSP
if (olist)
if ((ofile = string_nextinlist(&olist, &osep, NULL, 0)))
- ocsp_load_response(sctx, cbinfo, ofile);
+ {
+ if (Ustrncmp(ofile, US"PEM ", 4) == 0)
+ {
+ fmt_pem = TRUE;
+ ofile += 4;
+ }
+ else if (Ustrncmp(ofile, US"DER ", 4) == 0)
+ {
+ fmt_pem = FALSE;
+ ofile += 4;
+ }
+ ocsp_load_response(sctx, cbinfo, ofile, fmt_pem);
+ }
else
DEBUG(D_tls) debug_printf("ran out of ocsp file list\n");
#endif
OCSP_BASICRESP * bs;
int i;
-DEBUG(D_tls) debug_printf("Received TLS status response (OCSP stapling):");
+DEBUG(D_tls) debug_printf("Received TLS status callback (OCSP stapling):\n");
len = SSL_get_tlsext_status_ocsp_resp(s, &p);
if(!p)
{
/* Expect this when we requested ocsp but got none */
if (cbinfo->u_ocsp.client.verify_required && LOGGING(tls_cipher))
- log_write(0, LOG_MAIN, "Received TLS status callback, null content");
+ log_write(0, LOG_MAIN, "Required TLS certificate status not received");
else
DEBUG(D_tls) debug_printf(" null\n");
return cbinfo->u_ocsp.client.verify_required ? 0 : 1;
*/
{
BIO * bp = NULL;
- int status, reason;
- ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+#ifndef EXIM_HAVE_OCSP_RESP_COUNT
+ STACK_OF(OCSP_SINGLERESP) * sresp = bs->tbsResponseData->responses;
+#endif
DEBUG(D_tls) bp = BIO_new_fp(debug_file, BIO_NOCLOSE);
/* DEBUG(D_tls) x509_store_dump_cert_s_names(cbinfo->u_ocsp.client.verify_store); */
if ((i = OCSP_basic_verify(bs, cbinfo->verify_stack,
- cbinfo->u_ocsp.client.verify_store, 0)) <= 0)
- {
- tls_out.ocsp = OCSP_FAILED;
- if (LOGGING(tls_cipher)) log_write(0, LOG_MAIN,
- "Received TLS cert status response, itself unverifiable: %s",
- ERR_reason_error_string(ERR_peek_error()));
- BIO_printf(bp, "OCSP response verify failure\n");
- ERR_print_errors(bp);
- OCSP_RESPONSE_print(bp, rsp, 0);
- goto failed;
- }
+ cbinfo->u_ocsp.client.verify_store, OCSP_NOEXPLICIT)) <= 0)
+ if (ERR_peek_error())
+ {
+ tls_out.ocsp = OCSP_FAILED;
+ if (LOGGING(tls_cipher)) log_write(0, LOG_MAIN,
+ "Received TLS cert status response, itself unverifiable: %s",
+ ERR_reason_error_string(ERR_peek_error()));
+ BIO_printf(bp, "OCSP response verify failure\n");
+ ERR_print_errors(bp);
+ OCSP_RESPONSE_print(bp, rsp, 0);
+ goto failed;
+ }
+ else
+ DEBUG(D_tls) debug_printf("no explicit trust for OCSP signing"
+ " in the root CA certificate; ignoring\n");
- BIO_printf(bp, "OCSP response well-formed and signed OK\n");
+ DEBUG(D_tls) debug_printf("OCSP response well-formed and signed OK\n");
/*XXX So we have a good stapled OCSP status. How do we know
it is for the cert of interest? OpenSSL 1.1.0 has a routine
For now, carry on blindly accepting the resp. */
- {
- OCSP_SINGLERESP * single;
-
+ for (int idx =
#ifdef EXIM_HAVE_OCSP_RESP_COUNT
- if (OCSP_resp_count(bs) != 1)
+ OCSP_resp_count(bs) - 1;
#else
- STACK_OF(OCSP_SINGLERESP) * sresp = bs->tbsResponseData->responses;
- if (sk_OCSP_SINGLERESP_num(sresp) != 1)
+ sk_OCSP_SINGLERESP_num(sresp) - 1;
#endif
- {
- tls_out.ocsp = OCSP_FAILED;
- log_write(0, LOG_MAIN, "OCSP stapling "
- "with multiple responses not handled");
- goto failed;
- }
- single = OCSP_resp_get0(bs, 0);
+ idx >= 0; idx--)
+ {
+ OCSP_SINGLERESP * single = OCSP_resp_get0(bs, idx);
+ int status, reason;
+ ASN1_GENERALIZEDTIME * rev, * thisupd, * nextupd;
+
+ /*XXX so I can see putting a loop in here to handle a rsp with >1 singleresp
+ - but what happens with a GnuTLS-style input?
+
+ we could do with a debug label for each singleresp
+ - it has a certID with a serialNumber, but I see no API to get that
+ */
status = OCSP_single_get0_status(single, &reason, &rev,
&thisupd, &nextupd);
- }
- DEBUG(D_tls) time_print(bp, "This OCSP Update", thisupd);
- DEBUG(D_tls) if(nextupd) time_print(bp, "Next OCSP Update", nextupd);
- if (!OCSP_check_validity(thisupd, nextupd,
- EXIM_OCSP_SKEW_SECONDS, EXIM_OCSP_MAX_AGE))
- {
- tls_out.ocsp = OCSP_FAILED;
- DEBUG(D_tls) ERR_print_errors(bp);
- log_write(0, LOG_MAIN, "Server OSCP dates invalid");
- }
- else
- {
+ DEBUG(D_tls) time_print(bp, "This OCSP Update", thisupd);
+ DEBUG(D_tls) if(nextupd) time_print(bp, "Next OCSP Update", nextupd);
+ if (!OCSP_check_validity(thisupd, nextupd,
+ EXIM_OCSP_SKEW_SECONDS, EXIM_OCSP_MAX_AGE))
+ {
+ tls_out.ocsp = OCSP_FAILED;
+ DEBUG(D_tls) ERR_print_errors(bp);
+ log_write(0, LOG_MAIN, "Server OSCP dates invalid");
+ goto failed;
+ }
+
DEBUG(D_tls) BIO_printf(bp, "Certificate status: %s\n",
OCSP_cert_status_str(status));
switch(status)
{
case V_OCSP_CERTSTATUS_GOOD:
- tls_out.ocsp = OCSP_VFIED;
- i = 1;
- goto good;
+ continue; /* the idx loop */
case V_OCSP_CERTSTATUS_REVOKED:
- tls_out.ocsp = OCSP_FAILED;
log_write(0, LOG_MAIN, "Server certificate revoked%s%s",
reason != -1 ? "; reason: " : "",
reason != -1 ? OCSP_crl_reason_str(reason) : "");
DEBUG(D_tls) time_print(bp, "Revocation Time", rev);
break;
default:
- tls_out.ocsp = OCSP_FAILED;
log_write(0, LOG_MAIN,
"Server certificate status unknown, in OCSP stapling");
break;
}
+
+ goto failed;
}
+
+ i = 1;
+ tls_out.ocsp = OCSP_VFIED;
+ goto good;
+
failed:
+ tls_out.ocsp = OCSP_FAILED;
i = cbinfo->u_ocsp.client.verify_required ? 0 : 1;
good:
BIO_free(bp);
for resumption next to the TLS session, and used here. */
if (!tlsp->verify_override)
- tlsp->certificate_verified = SSL_get_verify_result(ssl) == X509_V_OK;
+ tlsp->certificate_verified =
+#ifdef SUPPORT_DANE
+ tlsp->dane_verified ||
+#endif
+ SSL_get_verify_result(ssl) == X509_V_OK;
}
}
/* Handle genuine errors */
case SSL_ERROR_SSL:
- (void) tls_error(US"SSL_accept", NULL, sigalrm_seen ? US"timed out" : NULL, errstr);
+ {
+ uschar * s = US"SSL_accept";
+ unsigned long e = ERR_peek_error();
+ if (ERR_GET_REASON(e) == SSL_R_WRONG_VERSION_NUMBER)
+ s = string_sprintf("%s (%s)", s, SSL_get_version(server_ssl));
+ (void) tls_error(s, NULL, sigalrm_seen ? US"timed out" : NULL, errstr);
return FAIL;
+ }
default:
DEBUG(D_tls) debug_printf("Got SSL error %d\n", error);
tls_openssl_options_parse(uschar *option_spec, long *results)
{
long result, item;
-uschar *end;
+uschar * exp, * end;
uschar keep_c;
BOOL adding, item_parsed;
result = SSL_OP_NO_TICKET;
/* Prior to 4.80 we or'd in SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; removed
- * from default because it increases BEAST susceptibility. */
+from default because it increases BEAST susceptibility. */
#ifdef SSL_OP_NO_SSLv2
result |= SSL_OP_NO_SSLv2;
#endif
#ifdef SSL_OP_SINGLE_DH_USE
result |= SSL_OP_SINGLE_DH_USE;
#endif
+#ifdef SSL_OP_NO_RENEGOTIATION
+result |= SSL_OP_NO_RENEGOTIATION;
+#endif
if (!option_spec)
{
return TRUE;
}
-for (uschar * s = option_spec; *s; /**/)
+if (!expand_check(option_spec, US"openssl_options", &exp, &end))
+ return FALSE;
+
+for (uschar * s = exp; *s; /**/)
{
while (isspace(*s)) ++s;
if (*s == '\0')
DEBUG(D_tls) debug_printf("openssl option setting unrecognised: \"%s\"\n", s);
return FALSE;
}
- DEBUG(D_tls) debug_printf("openssl option, %s %8lx: %lx (%s)\n",
+ DEBUG(D_tls) debug_printf("openssl option, %s %08lx: %08lx (%s)\n",
adding ? "adding to " : "removing from", result, item, s);
if (adding)
result |= item;
}
+/* Environment cleanup: The GnuTLS library uses SSLKEYLOGFILE in the environment
+and writes a file by that name. Our OpenSSL code does the same, using keying
+info from the library API.
+The GnuTLS support only works if exim is run by root, not taking advantage of
+the setuid bit.
+You can use either the external environment (modulo the keep_environment config)
+or the add_environment config option for SSLKEYLOGFILE; the latter takes
+precedence.
+
+If the path is absolute, require it starts with the spooldir; otherwise delete
+the env variable. If relative, prefix the spooldir.
+*/
+void
+tls_clean_env(void)
+{
+uschar * path = US getenv("SSLKEYLOGFILE");
+if (path)
+ if (!*path)
+ unsetenv("SSLKEYLOGFILE");
+ else if (*path != '/')
+ {
+ DEBUG(D_tls)
+ debug_printf("prepending spooldir to env SSLKEYLOGFILE\n");
+ setenv("SSLKEYLOGFILE", CCS string_sprintf("%s/%s", spool_directory, path), 1);
+ }
+ else if (Ustrncmp(path, spool_directory, Ustrlen(spool_directory)) != 0)
+ {
+ DEBUG(D_tls)
+ debug_printf("removing env SSLKEYLOGFILE=%s: not under spooldir\n", path);
+ unsetenv("SSLKEYLOGFILE");
+ }
+}
/*************************************************
* Drop privs for checking TLS config *
switch(type)
{
case tod_epoch:
- (void) sprintf(CS timebuf, TIME_T_FMT, now.tv_sec); /* Unix epoch format */
+ (void) snprintf(CS timebuf, sizeof(timebuf), TIME_T_FMT, now.tv_sec); /* Unix epoch format */
return timebuf; /* NB the above will be wrong if time_t is FP */
case tod_epoch_l:
/* Unix epoch/usec format */
- (void) sprintf(CS timebuf, TIME_T_FMT "%06ld", now.tv_sec, (long) now.tv_usec );
+ (void) snprintf(CS timebuf, sizeof(timebuf), TIME_T_FMT "%06ld", now.tv_sec, (long) now.tv_usec );
return timebuf;
case tod_zulu:
t = gmtime(&now.tv_sec);
- (void) sprintf(CS timebuf, "%04u%02u%02u%02u%02u%02uZ",
+ (void) snprintf(CS timebuf, sizeof(timebuf), "%04u%02u%02u%02u%02u%02uZ",
1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday, (uint)t->tm_hour, (uint)t->tm_min,
(uint)t->tm_sec);
return timebuf;
case tod_log_bare: /* Format used in logging without timezone */
#ifndef COMPILE_UTILITY
if (LOGGING(millisec))
- sprintf(CS timebuf, "%04u-%02u-%02u %02u:%02u:%02u.%03u",
+ snprintf(CS timebuf, sizeof(timebuf), "%04u-%02u-%02u %02u:%02u:%02u.%03u",
1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday,
(uint)t->tm_hour, (uint)t->tm_min, (uint)t->tm_sec,
(uint)(now.tv_usec/1000));
else
#endif
- sprintf(CS timebuf, "%04u-%02u-%02u %02u:%02u:%02u",
+ snprintf(CS timebuf, sizeof(timebuf), "%04u-%02u-%02u %02u:%02u:%02u",
1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday,
(uint)t->tm_hour, (uint)t->tm_min, (uint)t->tm_sec);
#ifdef TESTING_LOG_DATESTAMP
case tod_log_datestamp_daily:
case tod_log_datestamp_monthly:
- sprintf(CS timebuf, "%04u%02u%02u%02u%02u",
+ snprintf(CS timebuf, sizeof(timebuf), "%04u%02u%02u%02u%02u",
1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday,
(uint)t->tm_hour, (uint)t->tm_min);
break;
#else
case tod_log_datestamp_daily:
- sprintf(CS timebuf, "%04u%02u%02u",
+ snprintf(CS timebuf, sizeof(timebuf), "%04u%02u%02u",
1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday);
break;
case tod_log_datestamp_monthly:
#ifndef COMPILE_UTILITY
- sprintf(CS timebuf, "%04u%02u",
+ snprintf(CS timebuf, sizeof(timebuf), "%04u%02u",
1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon);
#endif
break;
case tod_log_zone: /* Format used in logging with timezone */
#ifndef COMPILE_UTILITY
if (LOGGING(millisec))
- (void) sprintf(CS timebuf,
+ (void) snprintf(CS timebuf, sizeof(timebuf),
"%04u-%02u-%02u %02u:%02u:%02u.%03u %+03d%02d",
1900 + (uint)local.tm_year, 1 + (uint)local.tm_mon, (uint)local.tm_mday,
(uint)local.tm_hour, (uint)local.tm_min, (uint)local.tm_sec, (uint)(now.tv_usec/1000),
diff_hour, diff_min);
else
#endif
- (void) sprintf(CS timebuf,
+ (void) snprintf(CS timebuf, sizeof(timebuf),
"%04u-%02u-%02u %02u:%02u:%02u %+03d%02d",
1900 + (uint)local.tm_year, 1 + (uint)local.tm_mon, (uint)local.tm_mday,
(uint)local.tm_hour, (uint)local.tm_min, (uint)local.tm_sec,
break;
case tod_zone: /* Just the timezone offset */
- (void) sprintf(CS timebuf, "%+03d%02d", diff_hour, diff_min);
+ (void) snprintf(CS timebuf, sizeof(timebuf), "%+03d%02d", diff_hour, diff_min);
break;
/* tod_mbx: format used in MBX mailboxes - subtly different to tod_full */
case tod_mbx:
{
int len;
- (void) sprintf(CS timebuf, "%02u-", (uint)local.tm_mday);
+ (void) snprintf(CS timebuf, sizeof(timebuf), "%02u-", (uint)local.tm_mday);
len = Ustrlen(timebuf);
len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b-%Y %H:%M:%S",
&local);
- (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
+ (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, " %+03d%02d", diff_hour, diff_min);
}
break;
#endif
default:
{
int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", &local);
- (void) sprintf(CS timebuf + len, "%02u ", (uint)local.tm_mday);
+ (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, "%02u ", (uint)local.tm_mday);
len += Ustrlen(timebuf + len);
len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b %Y %H:%M:%S",
&local);
- (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
+ (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, " %+03d%02d", diff_hour, diff_min);
}
break;
}
.gethostbyname = FALSE,
.dns_qualify_single = TRUE,
.dns_search_parents = FALSE,
- .dnssec = { .request=NULL, .require=NULL },
+ .dnssec = { .request= US"*", .require=NULL },
.delay_after_cutoff = TRUE,
.hosts_override = FALSE,
.hosts_randomize = FALSE,
-#ifdef SUPPORT_DANE
-/* Lookup TLSA record for host/port.
-Return: OK success with dnssec; DANE mode
- DEFER Do not use this host now, may retry later
- FAIL_FORCED No TLSA record; DANE not usable
- FAIL Do not use this connection
-*/
-
-int
-tlsa_lookup(const host_item * host, dns_answer * dnsa, BOOL dane_required)
-{
-/* move this out to host.c given the similarity to dns_lookup() ? */
-uschar buffer[300];
-const uschar * fullname = buffer;
-int rc;
-BOOL sec;
-
-/* TLSA lookup string */
-(void)sprintf(CS buffer, "_%d._tcp.%.256s", host->port, host->name);
-
-rc = dns_lookup(dnsa, buffer, T_TLSA, &fullname);
-sec = dns_is_secure(dnsa);
-DEBUG(D_transport)
- debug_printf("TLSA lookup ret %d %sDNSSEC\n", rc, sec ? "" : "not ");
-
-switch (rc)
- {
- case DNS_AGAIN:
- return DEFER; /* just defer this TLS'd conn */
-
- case DNS_SUCCEED:
- if (sec)
- {
- DEBUG(D_transport)
- {
- dns_scan dnss;
- for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
- rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
- if (rr->type == T_TLSA && rr->size > 3)
- {
- uint16_t payload_length = rr->size - 3;
- uschar s[MAX_TLSA_EXPANDED_SIZE], * sp = s, * p = US rr->data;
-
- sp += sprintf(CS sp, "%d ", *p++); /* usage */
- sp += sprintf(CS sp, "%d ", *p++); /* selector */
- sp += sprintf(CS sp, "%d ", *p++); /* matchtype */
- while (payload_length-- > 0 && sp-s < (MAX_TLSA_EXPANDED_SIZE - 4))
- sp += sprintf(CS sp, "%02x", *p++);
-
- debug_printf(" %s\n", s);
- }
- }
- return OK;
- }
- log_write(0, LOG_MAIN,
- "DANE error: TLSA lookup for %s not DNSSEC", host->name);
- /*FALLTRHOUGH*/
-
- case DNS_NODATA: /* no TLSA RR for this lookup */
- case DNS_NOMATCH: /* no records at all for this lookup */
- return dane_required ? FAIL : FAIL_FORCED;
-
- default:
- case DNS_FAIL:
- return dane_required ? FAIL : DEFER;
- }
-}
-#endif
-
-
-
typedef struct smtp_compare_s
{
uschar *current_sender_address;
well as body. Set the appropriate timeout value to be used for each chunk.
(Haven't been able to make it work using select() for writing yet.) */
-if (!(sx.peer_offered & OPTION_CHUNKING) && !sx.ok)
+if ( !sx.ok
+ && (!(sx.peer_offered & OPTION_CHUNKING) || !pipelining_active))
{
/* Save the first address of the next batch. */
sx.first_addr = sx.next_addr;
dns_basic_lookup(), we have a dnslist cache entry allocated and
tree-inserted. So we may as well use it. */
- time_t soa_negttl = dns_expire_from_soa(dnsa);
+ time_t soa_negttl = dns_expire_from_soa(dnsa, T_A);
cb->expiry = soa_negttl ? soa_negttl : time(NULL) + ttl;
break;
}
--- /dev/null
+OCSP Response Information:
+ Response Status: Successful
+ Response Type: Basic OCSP Response
+ Version: 1
+ Responder ID: CN=clica CA rsa,O=example.com
+ Produced At: Thu Oct 10 20:08:22 UTC 2019
+ Responses:
+ Certificate ID:
+ Hash Algorithm: SHA256
+ Issuer Name Hash: 5af082e51d62fe01fd706baebeb878db64e68f76e74a36f36d914297ddee24b8
+ Issuer Key Hash: 333db14364b98e78a33dd8a4fae8d8378ea9b0f5fbca97b25685aa0d32116091
+ Serial Number: 65
+ Certificate Status: good
+ This Update: Thu Oct 10 20:08:22 UTC 2019
+ Next Update: Tue Oct 09 20:08:22 UTC 2029
+ Certificate ID:
+ Hash Algorithm: SHA256
+ Issuer Name Hash: bfa7275a566efd4be2df82dbd9d1290d470186f6ff2acd8c16659f342ab56109
+ Issuer Key Hash: 208f9d28c7c0bc914144dfa8c0be3d5b3bfcebb622c8a8dc27e865fc06ca0e12
+ Serial Number: 42
+ Certificate Status: good
+ This Update: Thu Oct 10 20:08:22 UTC 2019
+ Next Update: Tue Oct 09 20:08:22 UTC 2029
+ Certificate ID:
+ Hash Algorithm: SHA256
+ Issuer Name Hash: bfa7275a566efd4be2df82dbd9d1290d470186f6ff2acd8c16659f342ab56109
+ Issuer Key Hash: 208f9d28c7c0bc914144dfa8c0be3d5b3bfcebb622c8a8dc27e865fc06ca0e12
+ Serial Number: 41
+ Certificate Status: good
+ This Update: Thu Oct 10 20:08:22 UTC 2019
+ Next Update: Tue Oct 09 20:08:22 UTC 2029
+ Extensions:
+ Signature Algorithm: RSA-SHA256
+
+-----BEGIN OCSP RESPONSE-----
+MIIC/AoBAKCCAvUwggLxBgkrBgEFBQcwAQEEggLiMIIC3jCCAcahLzAtMRQwEgYD
+VQQKEwtleGFtcGxlLmNvbTEVMBMGA1UEAxMMY2xpY2EgQ0EgcnNhGA8yMDE5MTAx
+MDIwMDgyMlowggGAMH4wVjANBglghkgBZQMEAgEFAAQgWvCC5R1i/gH9cGuuvrh4
+22Tmj3bnSjbzbZFCl93uJLgEIDM9sUNkuY54oz3YpPro2DeOqbD1+8qXslaFqg0y
+EWCRAgFlgAAYDzIwMTkxMDEwMjAwODIyWqARGA8yMDI5MTAwOTIwMDgyMlowfjBW
+MA0GCWCGSAFlAwQCAQUABCC/pydaVm79S+LfgtvZ0SkNRwGG9v8qzYwWZZ80KrVh
+CQQgII+dKMfAvJFBRN+owL49Wzv867YiyKjcJ+hl/AbKDhICAUKAABgPMjAxOTEw
+MTAyMDA4MjJaoBEYDzIwMjkxMDA5MjAwODIyWjB+MFYwDQYJYIZIAWUDBAIBBQAE
+IL+nJ1pWbv1L4t+C29nRKQ1HAYb2/yrNjBZlnzQqtWEJBCAgj50ox8C8kUFE36jA
+vj1bO/zrtiLIqNwn6GX8BsoOEgIBQYAAGA8yMDE5MTAxMDIwMDgyMlqgERgPMjAy
+OTEwMDkyMDA4MjJaMA0GCSqGSIb3DQEBCwUAA4IBAQBm8uLIawRny88oLSzr7sxj
+IgGjhC+S2OXWjAlTxErHoEsJ0JPKkQAt/s5YLy4IKiPbCg6CIm9KotgE4vnpMFjg
+297pSrdYKdtb2iBPKq5afB2Iv6ET78L/j2HhBFyJaxlt6lhI0Ly6JE75IbUrdP24
+c5uIh+KpJaC60bTZehgcRnrw9fR7HJ5W9ln9mbOZDggNQeM9hmFLUmQYPQWxav2x
+IjCYAZOfIp8ficETnLhuDuILsohFRnQnFAaf1YTgvW2zoKLMeLUWzMm8a6IoBpXQ
+0ecpPJs2FFiaYL78EcRNN47YbClcfDQRAjTvlSZupk59YuxedlwiH6uc7Cwa3RnN
+-----END OCSP RESPONSE-----
####
- # so, for full-chain OCSP we sill want an OCSP resp for the Signer cert and also (?) one for the
- # CA cert itself. The existing bits below only create for the leaf certs, next layer down.
- #
- # First test will be just adding OCSP for the Signer cert. Presumably we could use the CA cert
- # to sign that.
-
# create OCSP reqs & resps
CADIR=$idir/CA
done
# convert one good leaf-resp to PEM
- $server=server1
+ server=server1
RESP=$idir/$server.$iname/$server.$iname.ocsp.signernocert.good.resp
ocsptool -S $RESP -j > $RESP.pem
- # Then, ocsp request and responses for the signer cert
+ # Then, ocsp request and (valid, revoked) responses for the signer cert
REQ=$CADIR/Signer.ocsp.req
RESP=$CADIR/Signer.ocsp.signernocert.good.resp
openssl ocsp -issuer $CADIR/CA.pem -sha256 -cert $CADIR/Signer.pem -no_nonce -reqout $REQ
-ndays 3652 -reqin $REQ -respout $RESP
ocsptool -S $RESP -j > $RESP.pem
- # Then, ocsp request and response for the CA cert
- REQ=$CADIR/CA.ocsp.req
- RESP=$CADIR/CA.ocsp.signernocert.good.resp
- openssl ocsp -issuer $CADIR/CA.pem -sha256 -cert $CADIR/CA.pem -no_nonce -reqout $REQ
- openssl ocsp $IVALID -rsigner $CADIR/CA.pem -rkey $CADIR/CA.key -CA $CADIR/CA.pem -resp_no_certs -noverify \
+ # Finally, a full-chain all-good request and response
+ REQ=$idir/$server.$iname/fullchain.ocsp.req
+ leafcert=$idir/$server.$iname/$server.$iname.pem
+ signercert=$CADIR/Signer.pem
+ cacert=$CADIR/CA.pem
+ openssl ocsp -sha256 -no_nonce -reqout $REQ \
+ -issuer $signercert -cert $leafcert \
+ -issuer $cacert -cert $CADIR/Signer.pem -cert $CADIR/CA.pem
+
+ RESP=$idir/$server.$iname/fullchain.ocsp.resp
+ authorities=$idir/$server.$iname/ca_chain.pem
+ openssl ocsp $IVALID -rsigner $CADIR/CA.pem -rkey $CADIR/CA.key -CA $authorities -resp_no_certs -noverify \
-ndays 3652 -reqin $REQ -respout $RESP
ocsptool -S $RESP -j > $RESP.pem
-keep_environment = PATH:SSLKEYLOGFILE:EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK
+keep_environment = PATH:EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK
+add_environment = SSLKEYLOGFILE=DIR/spool/sslkeys
exim_path = EXIM_PATH
host_lookup_order = bydns
spool_directory = DIR/spool
# ----- Main settings -----
-ignore_bounce_errors_after = 2s
-timeout_frozen_after = 5s
+ignore_bounce_errors_after = 4s
+timeout_frozen_after = 10s
queue_run_in_order
.ifdef OPT
dsn_advertise_hosts = *
.endif
-delay_warning = 3s : 24h
+delay_warning = 6s : 24h
accept_8bitmime = false
pipelining_advertise_hosts = :
begin retry
-* * F,1m,3s
+* * F,2m,10s
# End
--- /dev/null
+1003
\ No newline at end of file
+++ /dev/null
-5652
\ No newline at end of file
--- /dev/null
+5665
\ No newline at end of file
--- /dev/null
+5670
\ No newline at end of file
+++ /dev/null
-# Exim test configuration 5652
-# OCSP stapling, server, multiple leaf-certs
-
-.include DIR/aux-var/tls_conf_prefix
-
-primary_hostname = server1.example.com
-
-# ----- Main settings -----
-
-acl_smtp_mail = check_mail
-acl_smtp_rcpt = check_recipient
-
-log_selector = +tls_peerdn
-
-queue_only
-queue_run_in_order
-
-tls_advertise_hosts = *
-
-CADIR = DIR/aux-fixed/exim-ca
-DRSA = CADIR/example.com
-DECDSA = CADIR/example_ec.com
-
-tls_certificate = DRSA/server1.example.com/server1.example.com.pem \
- : DECDSA/server1.example_ec.com/server1.example_ec.com.pem
-tls_privatekey = DRSA/server1.example.com/server1.example.com.unlocked.key \
- : DECDSA/server1.example_ec.com/server1.example_ec.com.unlocked.key
-tls_ocsp_file = DRSA/server1.example.com/server1.example.com.ocsp.good.resp \
- : DECDSA/server1.example_ec.com/server1.example_ec.com.ocsp.good.resp
-
-
-.ifdef _HAVE_GNUTLS
-tls_require_ciphers = NORMAL:!VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.0
-.endif
-.ifdef _OPT_OPENSSL_NO_TLSV1_3_X
-openssl_options = +no_tlsv1_3
-.endif
-
-# ------ ACL ------
-
-begin acl
-
-check_mail:
- accept logwrite = acl_mail: ocsp in status: $tls_in_ocsp \
- (${listextract {${eval:$tls_in_ocsp+1}} \
- {notreq:notresp:vfynotdone:failed:verified}})
-
-check_recipient:
- accept
-
-
-# ----- Routers -----
-
-begin routers
-
-client:
- driver = manualroute
- condition = ${if !eq {SERVER}{server}}
- route_list = * 127.0.0.1
- self = send
- transport = remote_delivery
- errors_to = ""
-
-srvr:
- driver = accept
- retry_use_local_part
- transport = local_delivery
-
-
-# ----- Transports -----
-
-begin transports
-
-remote_delivery:
- driver = smtp
- port = PORT_D
- hosts_try_fastopen = :
- hosts_require_tls = *
-.ifdef _HAVE_GNUTLS
- tls_require_ciphers = NONE:\
- ${if eq {SELECTOR}{auth_ecdsa} \
- {+SIGN-ECDSA-SHA512:+VERS-TLS-ALL:+KX-ALL:} \
- {+SIGN-RSA-SHA256:+VERS-TLS-ALL:+ECDHE-RSA:+DHE-RSA:+RSA:}}\
- +CIPHER-ALL:+MAC-ALL:+COMP-NULL:+CURVE-ALL:+CTYPE-X509
-.endif
-.ifdef _HAVE_OPENSSL
- tls_require_ciphers = ${if eq {SELECTOR}{auth_ecdsa} {ECDSA:RSA:!COMPLEMENTOFDEFAULT} {RSA}}
-.endif
- hosts_require_ocsp = *
- tls_verify_certificates = CADIR/\
- ${if eq {SELECTOR}{auth_ecdsa} \
- {example_ec.com/server1.example_ec.com/ca_chain.pem}\
- {example.com/server1.example.com/ca_chain.pem}}
- tls_verify_cert_hostnames = :
-
-local_delivery:
- driver = appendfile
- file = DIR/test-mail/$local_part
- headers_add = TLS: cipher=$tls_cipher peerdn=$tls_peerdn
- user = CALLER
-
-# End
+++ /dev/null
-# Exim test configuration 5655
-# OCSP stapling, server, multiple chain-element OCSP
-
-.include DIR/aux-var/tls_conf_prefix
-
-primary_hostname = server1.example.com
-
-# ----- Main settings -----
-
-acl_smtp_connect = accept logwrite = ${env {SSLKEYLOGFILE}}
-acl_smtp_mail = check_mail
-acl_smtp_rcpt = check_recipient
-
-log_selector = +tls_peerdn
-
-queue_only
-queue_run_in_order
-
-tls_advertise_hosts = *
-
-CADIR = DIR/aux-fixed/exim-ca
-DRSA = CADIR/example.com
-DECDSA = CADIR/example_ec.com
-
-tls_certificate = DRSA/server1.example.com/fullchain.pem \
- : DECDSA/server1.example_ec.com/server1.example_ec.com.pem
-tls_privatekey = DRSA/server1.example.com/server1.example.com.unlocked.key \
- : DECDSA/server1.example_ec.com/server1.example_ec.com.unlocked.key
-
-.ifndef CONTROL
-tls_ocsp_file = PEM DIR/tmp/ocsp/triple.ocsp.pem \
- : DER DECDSA/server1.example_ec.com/server1.example_ec.com.ocsp.good.resp
-.else
-tls_ocsp_file = PEM DIR/tmp/ocsp/double_r.ocsp.pem \
- : DER DECDSA/server1.example_ec.com/server1.example_ec.com.ocsp.good.resp
-.endif
-
-
-.ifdef _HAVE_GNUTLS
-tls_require_ciphers = ${if eq {LIMIT}{TLS1.2} {NORMAL:!VERS-ALL:+VERS-TLS1.2} {}}
-.endif
-
-# ------ ACL ------
-
-begin acl
-
-check_mail:
- accept logwrite = acl_mail: ocsp in status: $tls_in_ocsp \
- (${listextract {${eval:$tls_in_ocsp+1}} \
- {notreq:notresp:vfynotdone:failed:verified}})
-
-check_recipient:
- accept
-
-
-# ----- Routers -----
-
-begin routers
-
-client:
- driver = manualroute
- condition = ${if !eq {SERVER}{server}}
- route_list = * 127.0.0.1
- self = send
- transport = remote_delivery
- errors_to = ""
-
-srvr:
- driver = accept
- retry_use_local_part
- transport = local_delivery
-
-
-# ----- Transports -----
-
-begin transports
-
-remote_delivery:
- driver = smtp
- port = PORT_D
- hosts_require_tls = *
-.ifdef _HAVE_GNUTLS
-
- tls_require_ciphers = ${if eq {LIMIT}{TLS1.2} \
- {NONE:\
- ${if eq {OPT}{rsa} \
- {+SIGN-RSA-SHA256:+VERS-TLS-ALL:+ECDHE-RSA:+DHE-RSA:+RSA} \
- {+SIGN-ECDSA-SHA512:+VERS-TLS-ALL:+KX-ALL}}\
- :+CIPHER-ALL:+MAC-ALL:+COMP-NULL:+CURVE-ALL:+CTYPE-X509} \
- {}}
- tls_verify_certificates = CADIR/\
- ${if eq {OPT}{rsa} \
- {example.com/server1.example.com} \
- {example_ec.com/server1.example_ec.com}}\
- /ca_chain.pem
-.endif
- hosts_require_ocsp = *
- tls_verify_cert_hostnames = :
-
-local_delivery:
- driver = appendfile
- file = DIR/test-mail/$local_part
- headers_add = TLS: cipher=$tls_cipher peerdn=$tls_peerdn
- user = CALLER
-
-# End
--- /dev/null
+# Exim test configuration 5652
+# OCSP stapling, server, multiple leaf-certs
+
+.include DIR/aux-var/tls_conf_prefix
+
+primary_hostname = server1.example.com
+
+# ----- Main settings -----
+
+acl_smtp_mail = check_mail
+acl_smtp_rcpt = check_recipient
+
+log_selector = +tls_peerdn
+
+queue_only
+queue_run_in_order
+
+tls_advertise_hosts = *
+
+CADIR = DIR/aux-fixed/exim-ca
+DRSA = CADIR/example.com
+DECDSA = CADIR/example_ec.com
+
+tls_certificate = DRSA/server1.example.com/server1.example.com.pem \
+ : DECDSA/server1.example_ec.com/server1.example_ec.com.pem
+tls_privatekey = DRSA/server1.example.com/server1.example.com.unlocked.key \
+ : DECDSA/server1.example_ec.com/server1.example_ec.com.unlocked.key
+tls_ocsp_file = DRSA/server1.example.com/server1.example.com.ocsp.good.resp \
+ : DECDSA/server1.example_ec.com/server1.example_ec.com.ocsp.good.resp
+
+
+.ifdef _HAVE_GNUTLS
+tls_require_ciphers = NORMAL:!VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.0
+.endif
+.ifdef _OPT_OPENSSL_NO_TLSV1_3_X
+openssl_options = +no_tlsv1_3
+.endif
+
+# ------ ACL ------
+
+begin acl
+
+check_mail:
+ accept logwrite = acl_mail: ocsp in status: $tls_in_ocsp \
+ (${listextract {${eval:$tls_in_ocsp+1}} \
+ {notreq:notresp:vfynotdone:failed:verified}})
+
+check_recipient:
+ accept
+
+
+# ----- Routers -----
+
+begin routers
+
+client:
+ driver = manualroute
+ condition = ${if !eq {SERVER}{server}}
+ route_list = * 127.0.0.1
+ self = send
+ transport = remote_delivery
+ errors_to = ""
+
+srvr:
+ driver = accept
+ retry_use_local_part
+ transport = local_delivery
+
+
+# ----- Transports -----
+
+begin transports
+
+remote_delivery:
+ driver = smtp
+ port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = *
+.ifdef _HAVE_GNUTLS
+ tls_require_ciphers = NONE:\
+ ${if eq {SELECTOR}{auth_ecdsa} \
+ {+SIGN-ECDSA-SHA512:+VERS-TLS-ALL:+KX-ALL:} \
+ {+SIGN-RSA-SHA256:+VERS-TLS-ALL:+ECDHE-RSA:+DHE-RSA:+RSA:}}\
+ +CIPHER-ALL:+MAC-ALL:+COMP-NULL:+CURVE-ALL:+CTYPE-X509
+.endif
+.ifdef _HAVE_OPENSSL
+ tls_require_ciphers = ${if eq {SELECTOR}{auth_ecdsa} {ECDSA:RSA:!COMPLEMENTOFDEFAULT} {RSA}}
+.endif
+ hosts_require_ocsp = *
+ tls_verify_certificates = CADIR/\
+ ${if eq {SELECTOR}{auth_ecdsa} \
+ {example_ec.com/server1.example_ec.com/ca_chain.pem}\
+ {example.com/server1.example.com/ca_chain.pem}}
+ tls_verify_cert_hostnames = :
+
+local_delivery:
+ driver = appendfile
+ file = DIR/test-mail/$local_part
+ headers_add = TLS: cipher=$tls_cipher peerdn=$tls_peerdn
+ user = CALLER
+
+# End
--- /dev/null
+# Exim test configuration 5655
+# OCSP stapling, server, multiple chain-element OCSP. Both GnuTLS and OpenSSL.
+
+.include DIR/aux-var/tls_conf_prefix
+
+primary_hostname = server1.example.com
+
+# ----- Main settings -----
+
+acl_smtp_mail = check_mail
+acl_smtp_rcpt = check_recipient
+
+log_selector = +tls_peerdn
+
+queue_only
+queue_run_in_order
+
+tls_advertise_hosts = *
+
+CADIR = DIR/aux-fixed/exim-ca
+DRSA = CADIR/example.com
+DECDSA = CADIR/example_ec.com
+
+tls_certificate = DRSA/server1.example.com/fullchain.pem
+tls_privatekey = DRSA/server1.example.com/server1.example.com.unlocked.key
+
+.ifndef CONTROL
+tls_ocsp_file = PEM DRSA/server1.example.com/fullchain.ocsp.resp.pem
+.else
+tls_ocsp_file = PEM DIR/tmp/ocsp/double_r.ocsp.pem
+.endif
+
+
+.ifdef _HAVE_GNUTLS
+tls_require_ciphers = ${if eq {LIMIT}{TLS1.2} {NORMAL:!VERS-ALL:+VERS-TLS1.2} {}}
+.endif
+.ifdef _HAVE_OPENSSL
+.ifdef LIMIT
+openssl_options = ${if eq {LIMIT}{TLS1.2} {+no_tlsv1_3} {}}
+.endif
+.endif
+
+# ------ ACL ------
+
+begin acl
+
+check_mail:
+ accept logwrite = acl_mail: ocsp in status: $tls_in_ocsp \
+ (${listextract {${eval:$tls_in_ocsp+1}} \
+ {notreq:notresp:vfynotdone:failed:verified}})
+
+check_recipient:
+ accept
+
+
+# ----- Routers -----
+
+begin routers
+
+client:
+ driver = manualroute
+ condition = ${if !eq {SERVER}{server}}
+ route_list = * 127.0.0.1
+ self = send
+ transport = remote_delivery
+ errors_to = ""
+
+srvr:
+ driver = accept
+ retry_use_local_part
+ transport = local_delivery
+
+
+# ----- Transports -----
+
+begin transports
+
+remote_delivery:
+ driver = smtp
+ port = PORT_D
+ hosts_require_tls = *
+
+.ifdef _HAVE_GNUTLS
+ tls_require_ciphers = ${if eq {LIMIT}{TLS1.2} \
+ {NONE:\
+ +SIGN-RSA-SHA256:+VERS-TLS-ALL:+ECDHE-RSA:+DHE-RSA:+RSA\
+ :+CIPHER-ALL:+MAC-ALL:+COMP-NULL:+CURVE-ALL:+CTYPE-X509} \
+ {}}
+.endif
+.ifdef _HAVE_OPENSSL
+ tls_require_ciphers = RSA
+.endif
+ tls_verify_certificates = CADIR/example.com/server1.example.com/ca_chain.pem
+ hosts_require_ocsp = *
+ tls_verify_cert_hostnames = :
+
+local_delivery:
+ driver = appendfile
+ file = DIR/test-mail/$local_part
+ headers_add = TLS: cipher=$tls_cipher peerdn=$tls_peerdn
+ user = CALLER
+
+# End
--- /dev/null
+; This is a testing zone file for use when testing DNS handling in Exim. This
+; is a fake zone of no real use. The zone name is
+; test.ex. This file is passed through the substitution mechanism before being
+; used by the fakens auxiliary program. This inserts the actual IP addresses
+; of the local host into the zone.
+
+; NOTE (1): apart from ::1, IPv6 addresses must always have 8 components. Do
+; not abbreviate them by using the :: feature. Leading zeros in components may,
+; however, be omitted.
+
+; NOTE (2): the fakens program is very simple and assumes that the buffer into
+; which is puts the response is always going to be big enough. In other words,
+; the expectation is for just a few RRs for each query.
+
+; NOTE (3): the top-level networks for testing addresses are parameterized by
+; the use of V4NET and V6NET. These networks should be such that no real
+; host ever uses them.
+;
+; Several prefixes may be used, see the source in src/fakens.c for a complete list
+; and description.
+
+kitterman.org. NS exim.kitterman.org.
+kitterman.org. SOA exim.kitterman.org. hostmaster.exim.kitterman.org 1430683638 1200 120 604800 3000
+
+; Record copied 2019/10/22
+
+ed25519._domainkey TXT "v=DKIM1; k=ed25519; p=yi50DjK5O9pqbFpNHklsv9lqaS0ArSYu02qp1S0DW1Y="
+
+
+; End
1999-03-02 09:44:33 10HmbA-0005vi-00 => alternate <alternate@test.ex> F=<CALLER@the.local.host.name> R=all T=dump
1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 using queue ''
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local-smtp S=sss for normal@test.ex
+1999-03-02 09:44:33 using queue 'alternate'
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local-smtp S=sss Q=alternate for alternate@test.ex
+1999-03-02 09:44:33 10HmbB-0005vi-00 moved from input, msglog to (third) input, msglog
+1999-03-02 09:44:33 10HmbC-0005vi-00 moved from (alternate) input, msglog to (third) input, msglog
+1999-03-02 09:44:33 10HmbB-0005vi-00 moved from (third) input, msglog to input, msglog
+1999-03-02 09:44:33 10HmbC-0005vi-00 moved from (third) input, msglog to input, msglog
******** SERVER ********
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, -qGlowpri/3s, not listening for SMTP
1999-03-02 09:44:33 End queue run: pid=pppp
1999-03-02 09:44:33 playout
1999-03-02 09:44:33 Start queue run: pid=pppp
-1999-03-02 09:44:33 10HmbB-0005vi-00 event tcp:connect
-1999-03-02 09:44:33 10HmbB-0005vi-00 event smtp:connect
-1999-03-02 09:44:33 10HmbB-0005vi-00 event smtp:ehlo
-1999-03-02 09:44:33 10HmbB-0005vi-00 event msg:rcpt:host:defer
-1999-03-02 09:44:33 10HmbB-0005vi-00 event msg:rcpt:defer
-1999-03-02 09:44:33 10HmbB-0005vi-00 event tcp:close
-1999-03-02 09:44:33 10HmbB-0005vi-00 == rmt_defer@test.ex R=r2 T=smtp defer (-44) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<rmt_defer@test.ex>: 451 Temporary local problem - please try later
+1999-03-02 09:44:33 10HmbB-0005vi-00 == rmt_defer@test.ex routing defer (-51): retry time not reached
1999-03-02 09:44:33 10HmbD-0005vi-00 <= <> R=10HmbB-0005vi-00 U=EXIMUSER P=local S=sss for c@dump.ex
-1999-03-02 09:44:33 10HmbC-0005vi-00 event tcp:connect
-1999-03-02 09:44:33 10HmbC-0005vi-00 event smtp:connect
-1999-03-02 09:44:33 10HmbC-0005vi-00 event smtp:ehlo
-1999-03-02 09:44:33 10HmbC-0005vi-00 event msg:rcpt:host:defer
-1999-03-02 09:44:33 10HmbC-0005vi-00 event msg:rcpt:defer
-1999-03-02 09:44:33 10HmbC-0005vi-00 event tcp:close
-1999-03-02 09:44:33 10HmbC-0005vi-00 == rmt_defer@test.ex R=r2 T=smtp defer (-44) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<rmt_defer@test.ex>: 451 Temporary local problem - please try later
+1999-03-02 09:44:33 10HmbC-0005vi-00 == rmt_defer@test.ex routing defer (-51): retry time not reached
1999-03-02 09:44:33 End queue run: pid=pppp
1999-03-02 09:44:33 10HmbB-0005vi-00 event msg:fail:internal
1999-03-02 09:44:33 10HmbB-0005vi-00 event msg:complete
1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<c@dump.ex> temporarily rejected RCPT <rmt_defer@test.ex>
1999-03-02 09:44:33 10HmbC-0005vi-00 <= d@dump.ex H=(testclient) [ip4.ip4.ip4.ip4] P=esmtp S=sss for rmt_defer@test.ex
1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<d@dump.ex> temporarily rejected RCPT <rmt_defer@test.ex>
-1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<c@dump.ex> temporarily rejected RCPT <rmt_defer@test.ex>
-1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<d@dump.ex> temporarily rejected RCPT <rmt_defer@test.ex>
1999-03-02 09:44:33 10HmbE-0005vi-00 <= e@dump.ex H=(testclient) [ip4.ip4.ip4.ip4] P=esmtp S=sss for rmt_reject@test.ex
1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<e@dump.ex> rejected RCPT <rmt_reject@test.ex>
1999-03-02 09:44:33 10HmbB-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for e@test.ex
1999-03-02 09:44:33 10HmbB-0005vi-00 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after end of data: 400 not right now
1999-03-02 09:44:33 10HmbB-0005vi-00 == e@test.ex R=to_server T=remote_smtp defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after end of data: 400 not right now
-1999-03-02 09:44:33 10HmbC-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for p@test.ex
-1999-03-02 09:44:33 10HmbC-0005vi-00 => p@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK bdat"
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for ebad@test.ex
+1999-03-02 09:44:33 10HmbC-0005vi-00 ** ebad@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<ebad@test.ex>: 550 sorry, no
+1999-03-02 09:44:33 10HmbC-0005vi-00 ebad@test.ex: error ignored
1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbD-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for q@test.ex
-1999-03-02 09:44:33 10HmbD-0005vi-00 H=127.0.0.1 [127.0.0.1]: SMTP timeout after pipelined end of data (ddd bytes written): Connection timed out
-1999-03-02 09:44:33 10HmbD-0005vi-00 == q@test.ex R=to_server T=remote_smtp defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after pipelined end of data (ddd bytes written)
-1999-03-02 09:44:33 10HmbE-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for r@test.ex
-1999-03-02 09:44:33 10HmbE-0005vi-00 => r@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK bdat"
-1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbF-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for s@test.ex
-1999-03-02 09:44:33 10HmbF-0005vi-00 ** s@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 550 unacceptable mail-from
-1999-03-02 09:44:33 10HmbF-0005vi-00 s@test.ex: error ignored
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for p@test.ex
+1999-03-02 09:44:33 10HmbD-0005vi-00 => p@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK bdat"
+1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for q@test.ex
+1999-03-02 09:44:33 10HmbE-0005vi-00 H=127.0.0.1 [127.0.0.1]: SMTP timeout after pipelined end of data (ddd bytes written): Connection timed out
+1999-03-02 09:44:33 10HmbE-0005vi-00 == q@test.ex R=to_server T=remote_smtp defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after pipelined end of data (ddd bytes written)
+1999-03-02 09:44:33 10HmbF-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for r@test.ex
+1999-03-02 09:44:33 10HmbF-0005vi-00 => r@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1] K C="250 OK bdat"
1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbG-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for s1@test.ex
-1999-03-02 09:44:33 10HmbG-0005vi-00 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 450 greylisted mail-from
-1999-03-02 09:44:33 10HmbG-0005vi-00 == s1@test.ex R=to_server T=remote_smtp defer (-45) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 450 greylisted mail-from
-1999-03-02 09:44:33 10HmbH-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for t@test.ex
-1999-03-02 09:44:33 10HmbH-0005vi-00 ** t@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<t@test.ex>: 550 no such recipient
-1999-03-02 09:44:33 10HmbH-0005vi-00 t@test.ex: error ignored
-1999-03-02 09:44:33 10HmbH-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbI-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for u@test.ex
-1999-03-02 09:44:33 10HmbI-0005vi-00 ** u@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 500 oops bdat
-1999-03-02 09:44:33 10HmbI-0005vi-00 u@test.ex: error ignored
+1999-03-02 09:44:33 10HmbG-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for s@test.ex
+1999-03-02 09:44:33 10HmbG-0005vi-00 ** s@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 550 unacceptable mail-from
+1999-03-02 09:44:33 10HmbG-0005vi-00 s@test.ex: error ignored
+1999-03-02 09:44:33 10HmbG-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbH-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for s1@test.ex
+1999-03-02 09:44:33 10HmbH-0005vi-00 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 450 greylisted mail-from
+1999-03-02 09:44:33 10HmbH-0005vi-00 == s1@test.ex R=to_server T=remote_smtp defer (-45) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 450 greylisted mail-from
+1999-03-02 09:44:33 10HmbI-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for t@test.ex
+1999-03-02 09:44:33 10HmbI-0005vi-00 ** t@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<t@test.ex>: 550 no such recipient
+1999-03-02 09:44:33 10HmbI-0005vi-00 t@test.ex: error ignored
1999-03-02 09:44:33 10HmbI-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbJ-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for v@test.ex
-1999-03-02 09:44:33 10HmbJ-0005vi-00 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 400 not right now bdat
-1999-03-02 09:44:33 10HmbJ-0005vi-00 == v@test.ex R=to_server T=remote_smtp defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 400 not right now bdat
+1999-03-02 09:44:33 10HmbJ-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for u@test.ex
+1999-03-02 09:44:33 10HmbJ-0005vi-00 ** u@test.ex R=to_server T=remote_smtp H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 500 oops bdat
+1999-03-02 09:44:33 10HmbJ-0005vi-00 u@test.ex: error ignored
+1999-03-02 09:44:33 10HmbJ-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbK-0005vi-00 <= sender@source.dom U=root P=local-bsmtp S=sss for v@test.ex
+1999-03-02 09:44:33 10HmbK-0005vi-00 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 400 not right now bdat
+1999-03-02 09:44:33 10HmbK-0005vi-00 == v@test.ex R=to_server T=remote_smtp defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined end of data: 400 not right now bdat
1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-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 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
-1999-03-02 09:44:33 10HmaY-0005vi-00 => user4@h1.test.ex R=client T=send_to_server1 H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbC-0005vi-00"
+1999-03-02 09:44:33 10HmaY-0005vi-00 => user4@h1.test.ex R=client T=send_to_server1 H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbB-0005vi-00"
1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
-1999-03-02 09:44:33 10HmaZ-0005vi-00 => user6@h2.test.ex R=client T=send_to_server2 H=::1 [::1] C="250 OK id=10HmbD-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => user6@h3.test.ex R=client T=send_to_server3 H=::1 [::1] C="250 OK id=10HmbC-0005vi-00"
1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbA-0005vi-00 => user6@h3.test.ex R=client T=send_to_server3 H=::1 [::1] C="250 OK id=10HmbE-0005vi-00"
+1999-03-02 09:44:33 10HmbA-0005vi-00 => user6@h4.test.ex R=client T=send_to_server4 H=::1 [::1] C="250 OK id=10HmbD-0005vi-00"
1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbB-0005vi-00 => user6@h4.test.ex R=client T=send_to_server4 H=::1 [::1] C="250 OK id=10HmbF-0005vi-00"
-1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
1999-03-02 09:44:33 10HmaX-0005vi-00 == user6@h5.test.ex R=client T=send_to_server5 defer (-1): failed to expand "interface" option for send_to_server5 transport: condition name expected, but found ""
1999-03-02 09:44:33 End queue run: pid=pppp -qf
******** SERVER ********
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D (IPv6 and IPv4)
-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=E10HmaY-0005vi-00@myhost.test.ex
-1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6] P=esmtp S=sss id=E10HmaZ-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaY-0005vi-00@myhost.test.ex
1999-03-02 09:44:33 no host name found for IP address ::1
-1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@myhost.test.ex H=(myhost.test.ex) [::1] P=esmtp S=sss id=E10HmbA-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex H=(myhost.test.ex) [::1] P=esmtp S=sss id=E10HmaZ-0005vi-00@myhost.test.ex
1999-03-02 09:44:33 no host name found for IP address ::1
-1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@myhost.test.ex H=(myhost.test.ex) [::1] P=esmtp S=sss id=E10HmbB-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex H=(myhost.test.ex) [::1] P=esmtp S=sss id=E10HmbA-0005vi-00@myhost.test.ex
--- /dev/null
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaX-0005vi-00 => user6@h2.test.ex R=client T=send_to_server2 H=::1 [::1] C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D (IPv6 and IPv4)
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex
1999-03-02 09:44:33 der_b64 MIIDuDCCAqCgAwIBAgICAMkwDQYJKoZIhvcNAQELBQAwNzEUMBIGA1UEChMLZXhhbXBsZS5jb20xHzAdBgNVBAMTFmNsaWNhIFNpZ25pbmcgQ2VydCByc2EwHhcNMTIxMTAxMTI0MDA0WhcNMzcxMjAxMTI0MDA0WjAeMRwwGgYDVQQDExNzZXJ2ZXIyLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA52Rfiv2Igy0NiaKN5gc0VPLbEoHngkdJWv3wEORp+iFl6skQRbsCylT8djJ2pvHstFpnzSodF3Wwjj2/EDuj3iKBzN9HeXJOvJz8j9Si1xkgCxJeUjPGgYcvKdxybaZAOpi9l3xwPCCEXN4JBq/WaQQ9+eP1PczeMNfvFtXma+VcHXG743ttPOv7eSMr0JxQl3zjQvYGOhFP/KAw6jh/N6YPqii9kV0cC/ubeVzpqJ5/+hndx5YrmAu39N5qzwWujhDPkFNSgCJUhfkEiMaQiPxFxDTbUzWnQ5jpAQ5El4WJVkGWkqxose1bOjSSNzFPJt59YtxxJC3IWN3UtGODTwIDAQABo4HmMIHjMA4GA1UdDwEB/wQEAwIE8DAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTgYDVR0jBEcwRYANQUFidHdDeGNYZ2IwUaExpC8wLTEUMBIGA1UEChMLZXhhbXBsZS5jb20xFTATBgNVBAMTDGNsaWNhIENBIHJzYYIBQjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vc2NwLmV4YW1wbGUuY29tLzApBgNVHREEIjAgghNzZXJ2ZXIyLmV4YW1wbGUuY29tggkqLnRlc3QuZXgwDQYJKoZIhvcNAQELBQADggEBALHOkZkvHLpNm0QSof09vmmdNFE6/+0TCIoPExeqqSOsy4NsF+Ha46WttjJRSVtbhRxF8jxEU7btPiFgQUaOcJZTwQPDhmQSOPNO8GS46oJ57aQ7U7O+X3M1sVS5Pa2IzE6vrJSh349/CNbTA8WPQdWLlxVJhJXAcZNtaEu6lCsZuDSMTpAsW5I4+snyrm3yvP5t0eD28K5LgCKePX962drkAOP6XGQ51VnbMQ7b1TSdQedtYKIpR3VKUvG5Ky/+0c+Rmwfi2aQ8oXXwekzJyS5jvovdVVsdhO68It+Rz/zursN5Pn+Gj1YuQNUs2nDrGHN+VIIFpgWUjLZO4bcJctY=
1999-03-02 09:44:33 cipher: TLS1.x:ke-RSA-AES256-SHAnnn:xxx
1999-03-02 09:44:33 cipher_ TLS1.x:ke_RSA_WITH_ci_mac
+<<<<<<< HEAD
+1999-03-02 09:44:33 ver: TLS1.x
+=======
1999-03-02 09:44:33 ver: TLSv1.x
+>>>>>>> 4.next
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex H=[ip4.ip4.ip4.ip4] P=smtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server2.example.com" S=sss
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
1999-03-02 09:44:33 Our cert SN: <CN=server1.example_ec.com>
1999-03-02 09:44:33 Authentication-Results: myhost.test.ex;\n spf=pass smtp.mailfrom=example.com
1999-03-02 09:44:33 spf_result neutral (guess <yes>)
1999-03-02 09:44:33 spf_header_comment myhost.test.ex: ip4.ip4.ip4.ip4 is neither permitted nor denied by domain of test.example.com
-1999-03-02 09:44:33 spf_smtp_comment Please see http://www.openspf.org/Why?id=b%40test.example.com&ip=ip4.ip4.ip4.ip4&receiver=myhost.test.ex : Reason: mechanism
+1999-03-02 09:44:33 spf_smtp_comment Please see http://www.open-spf.org/Why?id=b%40test.example.com&ip=ip4.ip4.ip4.ip4&receiver=myhost.test.ex : Reason: mechanism
1999-03-02 09:44:33 spf_received Received-SPF: neutral (myhost.test.ex: ip4.ip4.ip4.ip4 is neither permitted nor denied by domain of test.example.com) client-ip=ip4.ip4.ip4.ip4; envelope-from=b@test.example.com; helo=testclient;
1999-03-02 09:44:33 Authentication-Results: myhost.test.ex;\n spf=neutral (best guess record for domain) smtp.mailfrom=test.example.com
1999-03-02 09:44:33 H=(testclient) [ip4.ip4.ip4.ip4] F=<b@test.example.com> rejected RCPT <fred@test.ex>
1999-03-02 09:44:33 10HmbB-0005vi-00 => CALLER@test.ex R=client T=send_to_server3 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" 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@server1.example.com U=CALLER P=local S=sss for CALLER@test.ex
-1999-03-02 09:44:33 10HmbD-0005vi-00 Received TLS status callback, null content
+1999-03-02 09:44:33 10HmbD-0005vi-00 Required TLS certificate status not received
1999-03-02 09:44:33 10HmbD-0005vi-00 == CALLER@test.ex R=client T=send_to_server3 defer (-37) H=127.0.0.1 [127.0.0.1]: TLS session: (SSL_connect): error: <<detail omitted>>
1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss for CALLER@test.ex
1999-03-02 09:44:33 10HmbE-0005vi-00 Server certificate revoked; reason: superseded
+++ /dev/null
-1999-03-02 09:44:33 1: Server sends good staple on request, to client requiring RSA auth
-1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaX-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
-1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
-1999-03-02 09:44:33 2: Server sends good staple on request, to client preferring ECDSA auth
-1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaZ-0005vi-00 => ecdsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-ECDSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example_ec.com" C="250 OK id=10HmbA-0005vi-00"
-1999-03-02 09:44:33 10HmaZ-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 PORT_D
-1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
-1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@server1.example.com
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
-1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
-1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-ECDSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
1999-03-02 09:44:33 10HmaX-0005vi-00 => norequire@test.ex R=client T=send_to_server2 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaZ-0005vi-00 => nostaple@test.ex R=client T=send_to_server1 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => nostaple@test.ex R=client T=send_to_server1 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbB-0005vi-00"
1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbB-0005vi-00 => CALLER@test.ex R=client T=send_to_server3 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbC-0005vi-00"
-1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbA-0005vi-00 => CALLER@test.ex R=client T=send_to_server3 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbC-0005vi-00"
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbD-0005vi-00 Received TLS status callback, null content
+1999-03-02 09:44:33 10HmbD-0005vi-00 Required TLS certificate status not received
1999-03-02 09:44:33 10HmbD-0005vi-00 == CALLER@test.ex R=client T=send_to_server3 defer (-37) H=127.0.0.1 [127.0.0.1]: TLS session: (SSL_connect): error: <<detail omitted>>
1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmbE-0005vi-00 Server certificate revoked; reason: superseded
1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <norequire@test.ex> R=server
1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
-1999-03-02 09:44:33 10HmbA-0005vi-00 client claims: ocsp status 0 (notreq)
-1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@server1.example.com H=the.local.host.name (server1.example.com) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
-1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: <nostaple@test.ex> R=server
-1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbB-0005vi-00 client claims: ocsp status 0 (notreq)
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@server1.example.com H=the.local.host.name (server1.example.com) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
+1999-03-02 09:44:33 10HmbB-0005vi-00 => :blackhole: <nostaple@test.ex> R=server
+1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
1999-03-02 09:44:33 10HmbC-0005vi-00 client claims: ocsp status 4 (verified)
-1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@server1.example.com H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbB-0005vi-00@server1.example.com
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@server1.example.com H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbA-0005vi-00@server1.example.com
1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <CALLER@test.ex> R=server
1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
--- /dev/null
+1999-03-02 09:44:33 1: Server sends good staple on request, to client requiring RSA auth
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 2: Server sends good staple on request, to client preferring ECDSA auth
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => ecdsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-ECDSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example_ec.com" C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-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 PORT_D
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@server1.example.com
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-ECDSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
--- /dev/null
+1999-03-02 09:44:33 1: TLS1.2 Server sends good leaf-staple on request, to client requiring RSA auth
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 2: TLS1.3 Server sends good 3-element staple on request, to client requiring RSA auth
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-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 PORT_D
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@server1.example.com
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
1999-03-02 09:44:33 10HmaX-0005vi-00 => norequire@test.ex R=client T=send_to_server2 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaZ-0005vi-00 => nostaple@test.ex R=client T=send_to_server1 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => nostaple@test.ex R=client T=send_to_server1 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbB-0005vi-00"
1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbB-0005vi-00 => CALLER@test.ex R=client T=send_to_server3 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbC-0005vi-00"
-1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbA-0005vi-00 => CALLER@test.ex R=client T=send_to_server3 H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbC-0005vi-00"
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmbD-0005vi-00 == CALLER@test.ex R=client T=send_to_server3 defer (-37) H=127.0.0.1 [127.0.0.1]: TLS session: (certificate status check failed)
1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <norequire@test.ex> R=server
1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
-1999-03-02 09:44:33 10HmbA-0005vi-00 client claims: OCSP status 0 (notreq)
-1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@server1.example.com H=the.local.host.name (server1.example.com) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
-1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: <nostaple@test.ex> R=server
-1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbB-0005vi-00 client claims: OCSP status 0 (notreq)
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@server1.example.com H=the.local.host.name (server1.example.com) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
+1999-03-02 09:44:33 10HmbB-0005vi-00 => :blackhole: <nostaple@test.ex> R=server
+1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
1999-03-02 09:44:33 10HmbC-0005vi-00 client claims: OCSP status 4 (verified)
-1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@server1.example.com H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbB-0005vi-00@server1.example.com
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@server1.example.com H=(helo.data.changed) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmbA-0005vi-00@server1.example.com
1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <CALLER@test.ex> R=server
1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
+++ /dev/null
-1999-03-02 09:44:33 1: Server sends good staple on request, to client requiring RSA auth
-1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaX-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
-1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
-1999-03-02 09:44:33 2: Server sends good staple on request, to client preferring ECDSA auth
-1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaZ-0005vi-00 => ecdsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-ECDSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example_ec.com" C="250 OK id=10HmbA-0005vi-00"
-1999-03-02 09:44:33 10HmaZ-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 PORT_D
-1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
-1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@server1.example.com
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
-1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
-1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-ECDSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
+++ /dev/null
-1999-03-02 09:44:33 1: TLS1.2 Server sends good leaf-staple on request, to client requiring RSA auth
-1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaX-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
-1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
-1999-03-02 09:44:33 2: TLS1.3 Server sends good 3-element staple on request, to client requiring RSA auth
-1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaZ-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbA-0005vi-00"
-1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
-1999-03-02 09:44:33 3: TLS1.3 Server sends bad nonleaf staple, client detects it
-1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbB-0005vi-00 == rsa.auth@test.ex R=client T=remote_delivery defer (-37) H=127.0.0.1 [127.0.0.1]: TLS session: (certificate status check failed)
-1999-03-02 09:44:33 10HmbB-0005vi-00 ** rsa.auth@test.ex: retry timeout exceeded
-1999-03-02 09:44:33 10HmbB-0005vi-00 rsa.auth@test.ex: error ignored
-1999-03-02 09:44:33 10HmbB-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 PORT_D
-1999-03-02 09:44:33
-1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
-1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@server1.example.com
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
-1999-03-02 09:44:33
-1999-03-02 09:44:33 acl_mail: ocsp in status: 1 (notresp)
-1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
-1999-03-02 09:44:33
-1999-03-02 09:44:33 TLS error on connection from localhost [127.0.0.1] (recv): The TLS connection was non-properly terminated.
--- /dev/null
+1999-03-02 09:44:33 1: Server sends good staple on request, to client requiring RSA auth
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 2: Server sends good staple on request, to client preferring ECDSA auth
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => ecdsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-ECDSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example_ec.com" C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-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 PORT_D
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@server1.example.com
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-ECDSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
--- /dev/null
+1999-03-02 09:44:33 1: TLS1.2 Server sends good leaf-staple on request, to client requiring RSA auth
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 2: TLS1.3 Server sends good 3-element staple on request, to client requiring RSA auth
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => rsa.auth@test.ex R=client T=remote_delivery H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 3: TLS1.3 Server sends bad nonleaf staple, client detects it
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmbB-0005vi-00 == rsa.auth@test.ex R=client T=remote_delivery defer (-37) H=127.0.0.1 [127.0.0.1]: TLS session: (certificate status check failed)
+1999-03-02 09:44:33 10HmbB-0005vi-00 ** rsa.auth@test.ex: retry timeout exceeded
+1999-03-02 09:44:33 10HmbB-0005vi-00 rsa.auth@test.ex: error ignored
+1999-03-02 09:44:33 10HmbB-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 PORT_D
+1999-03-02 09:44:33 acl_mail: ocsp in status: 4 (verified)
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@server1.example.com
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 acl_mail: ocsp in status: 1 (notresp)
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> H=localhost (server1.example.com) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaZ-0005vi-00@server1.example.com
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 TLS error on connection from localhost [127.0.0.1] (recv): The TLS connection was non-properly terminated.
1999-03-02 09:44:33 10HmbD-0005vi-00 client ocsp status: 4 (verified)
1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss for failrequire@test.ex
-1999-03-02 09:44:33 10HmbF-0005vi-00 Received TLS status callback, null content
+1999-03-02 09:44:33 10HmbF-0005vi-00 Required TLS certificate status not received
1999-03-02 09:44:33 10HmbF-0005vi-00 client ocsp status: 1 (notresp)
1999-03-02 09:44:33 10HmbF-0005vi-00 == failrequire@test.ex R=client T=send_to_server3 defer (-37) H=127.0.0.1 [127.0.0.1]: TLS session: (SSL_connect): error: <<detail omitted>>
1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@server1.example.com U=CALLER P=local S=sss for failrevoked@test.ex
1999-03-02 09:44:33 10HmbB-0005vi-00 => CALLER@localhost.test.ex R=client T=send_to_server H=localhost.test.ex [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" 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 for CALLER@dane256ee.test.ex
-1999-03-02 09:44:33 10HmbD-0005vi-00 => CALLER@dane256ee.test.ex R=client T=send_to_server H=dane256ee.test.ex [ip4.ip4.ip4.ip4] X=TLS1.2:RSA_CAMELLIA_256_GCM-SHAnnn:256 CV=dane DN="CN=server1.example.com" C="250 OK id=10HmbE-0005vi-00"
+1999-03-02 09:44:33 10HmbD-0005vi-00 => CALLER@dane256ee.test.ex R=client T=send_to_server H=dane256ee.test.ex [ip4.ip4.ip4.ip4] X=TLS1.x:RSA__CAMELLIA_256_GCM:256 CV=dane DN="CN=server1.example.com" C="250 OK id=10HmbE-0005vi-00"
1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
******** SERVER ********
1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <CALLER@localhost.test.ex> R=server
1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
1999-03-02 09:44:33 "rcpt ACL"
-1999-03-02 09:44:33 10HmbE-0005vi-00 <= <> H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.2:RSA_CAMELLIA_256_GCM-SHAnnn:256 CV=no S=sss id=E10HmbD-0005vi-00@myhost.test.ex for CALLER@dane256ee.test.ex
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= <> H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:RSA__CAMELLIA_256_GCM:256 CV=no S=sss id=E10HmbD-0005vi-00@myhost.test.ex for CALLER@dane256ee.test.ex
1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: <CALLER@dane256ee.test.ex> R=server
1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<a@dump.ex> rejected RCPT <rmt_reject@test.ex>
1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<c@dump.ex> temporarily rejected RCPT <rmt_defer@test.ex>
1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<d@dump.ex> temporarily rejected RCPT <rmt_defer@test.ex>
-1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<c@dump.ex> temporarily rejected RCPT <rmt_defer@test.ex>
-1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<d@dump.ex> temporarily rejected RCPT <rmt_defer@test.ex>
1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<e@dump.ex> rejected RCPT <rmt_reject@test.ex>
my $force_update = 0;
my $log_failed_filename = 'failed-summary.log';
my $log_summary_filename = 'run-summary.log';
-my $more = 'less -XF';
+my @more = qw'less -XF';
my $optargs = '';
my $save_output = 0;
my $server_opts = '';
# Also, the length of space at the end of the host line is dependent
# on the length of the longest line, so strip it also on otherwise
# un-rewritten lines like localhost
+ #
+ # host 127.0.0.1 [127.0.0.1]
+ # host 10.0.0.1 [10.0.0.1]-
+ #
+ # host 127.0.0.1 [127.0.0.1]--
+ # host 169.16.16.16 [169.16.16.10]
s/^\s+host\s(\S+)\s+(\S+)/ host $1 $2/;
s/^\s+(host\s\S+\s\S+)\s+(port=.*)/ host $1 $2/;
s/(^|\W)\K\Q$parm_ipv6_stripped\E/ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6/g;
s/\b\Q$parm_ipv4r\E\b/ip4-reverse/g;
s/(^|\W)\K\Q$parm_ipv6r\E/ip6-reverse/g;
- s/^(\s+host\s\S+\s+\[\S+\]) +$/$1 /;
+ s/^\s+host\s\S+\s+\[\S+\]\K +$//; # strip, not collapse the trailing whitespace
# ======== Test network IP addresses ========
next if /DNS lookup of \S+ \(AAAA\) using fakens/;
next if / in dns_ipv4_lookup?/;
next if / writing neg-cache entry for .*AAAA/;
+ next if /^faking res_search\(AAAA\) response length as 65535/;
if (/DNS lookup of \S+ \(AAAA\) gave NO_DATA/)
{
next;
}
+ # Non-TLS bulds have a different Recieved: header expansion
+ s/^((.*)\t}}}}by \$primary_hostname \$\{if def:received_protocol \{with \$received_protocol }})\(Exim \$version_number\)$/$1\${if def:tls_in_cipher_std { tls \$tls_in_cipher_std\n$2\t}}(Exim \$version_number)/;
+ s/^((\s*).*considering: with \$received_protocol }})\(Exim \$version_number\)$/$1\${if def:tls_in_cipher_std { tls \$tls_in_cipher_std\n$2\t}}(Exim \$version_number)/;
+ if (/condition: def:tls_in_cipher_std$/)
+ {
+ $_= <IN>; $_= <IN>; $_= <IN>; $_= <IN>;
+ $_= <IN>; $_= <IN>; $_= <IN>; $_= <IN>;
+ $_= <IN>; $_= <IN>; $_= <IN>; next;
+ }
+
+
# Skip tls_advertise_hosts and hosts_require_tls checks when the options
# are unset, because tls ain't always there.
# openssl version variances
s/(TLS error on connection [^:]*: error:)[0-9A-F]{8}(:system library):(?:fopen|func\(4095\)):(No such file or directory)$/$1xxxxxxxx$2:fopen:$3/;
- s/(DANE attempt failed.*error:)[0-9A-F]{8}(:SSL routines:)(ssl3_get_server_certificate|tls_process_server_certificate|CONNECT_CR_CERT)(?=:certificate verify failed$)/$1xxxxxxxx$2ssl3_get_server_certificate/;
+ s/(DANE attempt failed.*error:)[0-9A-F]{8}(:SSL routines:)(?:(?i)ssl3_get_server_certificate|tls_process_server_certificate|CONNECT_CR_CERT)(?=:certificate verify failed$)/$1xxxxxxxx$2ssl3_get_server_certificate/;
s/(DKIM: validation error: )error:[0-9A-F]{8}:rsa routines:(?:(?i)int_rsa_verify|CRYPTO_internal):(?:bad signature|algorithm mismatch)$/$1Public key signature verification has failed./;
s/ARC: AMS signing: privkey PEM-block import: error:\K[0-9A-F]{8}:(PEM routines):get_name:(no start line)/0906D06C:$1:PEM_read_bio:$2/;
print "\n";
print "------------ $f -----------\n"
if (defined $rf && -s $rf && defined $rsf && -s $rsf);
- system("$more '$f'");
+ system @more => $f;
}
}
}
}
- open(MUNGED, '>', $mf) || tests_exit(-1, "Failed to open $mf: $!");
- for ($i = 0; $i < @munged; $i++)
- { print MUNGED $munged[$i]; }
- close(MUNGED);
+ open(my $fh, '>', $mf) or tests_exit(-1, "Failed to open $mf: $!");
+ print $fh @munged;
}
# Deal with log sorting
if ($sortfile)
{
- my(@munged, $i, $j);
- open(MUNGED, $mf) || tests_exit(-1, "Failed to open $mf: $!");
- @munged = <MUNGED>;
- close(MUNGED);
+ my @munged = do {
+ open(my $fh, '<', $mf) or tests_exit(-1, "Failed to open $mf: $!");
+ <$fh>;
+ };
- for ($i = 0; $i < @munged; $i++)
+ for (my $i = 0; $i < @munged; $i++)
{
if ($munged[$i] =~ /^[-\d]{10}\s[:\d]{8}\s[-A-Za-z\d]{16}\s[-=*]>/)
{
+ my $j;
for ($j = $i + 1; $j < @munged; $j++)
{
last if $munged[$j] !~
}
}
- open(MUNGED, ">$mf") || tests_exit(-1, "Failed to open $mf: $!");
- print MUNGED "**NOTE: The delivery lines in this file have been sorted.\n";
- for ($i = 0; $i < @munged; $i++)
- { print MUNGED $munged[$i]; }
- close(MUNGED);
+ open(my $fh, '>', $mf) or tests_exit(-1, "Failed to open $mf: $!");
+ print $fh "**NOTE: The delivery lines in this file have been sorted.\n";
+ print $fh @munged;
}
# Do the comparison
# Handle comparison failure
print "** Comparison of $mf with $sf_current failed";
- system("$more test-cf");
+ system @more => 'test-cf';
print "\n";
for (;;)
# if we deal with a flavour file, we can't delete it, because next time the generic
# file would be used again
if ($sf_current eq $sf_flavour) {
- open(FOO, ">$sf_current");
- close(FOO);
+ open(my $fh, '>', $sf_current);
}
else {
tests_exit(-1, "Failed to unlink $sf_current") if !unlink($sf_current);
},
'debug_pid' =>
- { 'stderr' => 's/(^\s{0,4}|(?<=Process )|(?<=child ))\d{1,5}/ppppp/g' },
+ { 'stderr' => 's/(^\s{0,4}|(?<=Process )|(?<=child ))\d+/ppppp/g' },
'optional_dsn_info' =>
{ 'mail' => '/^(X-(Remote-MTA-(smtp-greeting|helo-response)|Exim-Diagnostic|(body|message)-linecount):|Remote-MTA: X-ip;)/'
if (/^dump\s+(\S+)/)
{
- my($which) = $1;
- my(@temp);
+ my $which = $1;
print ">> ./eximdir/exim_dumpdb $parm_cwd/spool $which\n" if $debug;
- open(IN, "./eximdir/exim_dumpdb $parm_cwd/spool $which |");
- open(OUT, ">>test-stdout");
- print OUT "+++++++++++++++++++++++++++\n";
+ open(my $in, "-|", './eximdir/exim_dumpdb', "$parm_cwd/spool", $which) or die "Can't run exim_dumpdb: $!";
+ open(my $out, ">>test-stdout");
+ print $out "+++++++++++++++++++++++++++\n";
if ($which eq "retry")
{
- $/ = "\n ";
- @temp = <IN>;
- $/ = "\n";
-
- @temp = sort {
- my($aa) = split(' ', $a);
- my($bb) = split(' ', $b);
- return $aa cmp $bb;
- } @temp;
-
+ # the sort key is the first part of the retry db dump line, but for
+ # sorting we (temporarly) replace the own hosts ipv4 with a munged
+ # version, which matches the munging that is done later
+ # Why? We must ensure sure, that 127.0.0.1 always sorts first
+ # map-sort-map: Schwartz's transformation
+ # test 0099
+ my @temp = map { $_->[1] }
+ sort { $a->[0] cmp $b->[0] }
+ #map { [ (split)[0] =~ s/\Q$parm_ipv4/ip4.ip4.ip4.ip4/gr, $_ ] } # this is too modern for 5.10.1
+ map {
+ (my $k = (split)[0]) =~ s/\Q$parm_ipv4/ip4.ip4.ip4.ip4/g;
+ [ $k, $_ ]
+ }
+ do { local $/ = "\n "; <$in> };
foreach $item (@temp)
{
$item =~ s/^\s*(.*)\n(.*)\n?\s*$/$1\n$2/m;
- print OUT " $item\n";
+ print $out " $item\n";
}
}
else
{
- @temp = <IN>;
+ my @temp = <$in>;
if ($which eq "callout")
{
@temp = sort {
return $aa cmp $bb;
} @temp;
}
- print OUT @temp;
+ print $out @temp;
}
-
- close(IN);
- close(OUT);
+ close($in); # close it explicitly, otherwise $? does not get set
return 1;
}
if ($args =~ /\$msg/)
{
- my @listcmd = ("$parm_cwd/eximdir/exim", '-bp',
+ my($queuespec);
+ if ($args =~ /-qG\w+/) { $queuespec = $&; }
+
+ my @listcmd;
+
+ if (defined $queuespec)
+ {
+ @listcmd = ("$parm_cwd/eximdir/exim", '-bp',
+ $queuespec,
+ "-DEXIM_PATH=$parm_cwd/eximdir/exim",
+ -C => "$parm_cwd/test-config");
+ }
+ else
+ {
+ @listcmd = ("$parm_cwd/eximdir/exim", '-bp',
"-DEXIM_PATH=$parm_cwd/eximdir/exim",
-C => "$parm_cwd/test-config");
+ }
print ">> Getting queue list from:\n>> @listcmd\n" if $debug;
# We need the message ids sorted in ascending order.
# Message id is: <timestamp>-<pid>-<fractional-time>. On some systems (*BSD) the
# Check for the "less" command #
##################################################
-$more = 'more' if system('which less >/dev/null 2>&1') != 0;
+@more = 'more' if system('which less >/dev/null 2>&1') != 0;
GetOptions(
'debug' => sub { $debug = 1; $cr = "\n" },
'diff' => sub { $cf = 'diff -u' },
- 'continue' => sub { $force_continue = 1; $more = 'cat' },
+ 'continue' => sub { $force_continue = 1; @more = 'cat' },
'update' => \$force_update,
'ipv4!' => \$have_ipv4,
'ipv6!' => \$have_ipv6,
if (not $parm_ipv4 and /^\s*inet(?:\saddr(?:ess))?:?\s*(\d+\.\d+\.\d+\.\d+)(?:\/\d+)?\s/i)
{
- # It would ne nice to be able to vary the /16 used for manyhome; we could take
+ # It would be nice to be able to vary the /16 used for manyhome; we could take
# an option to runtest used here - but we'd also have to pass it on to fakens.
# Possibly an environment variable?
next if $1 eq '0.0.0.0' or $1 =~ /^(?:127|10\.250)\./;
$parm_ipv4 = $1;
}
- if (not $parm_ipv6 and /^\s*inet6(?:\saddr(?:ess))?:?\s*([abcdef\d:]+)(?:%[^ \/]+)?(?:\/\d+)?/i)
+ if ( (not $parm_ipv6 or $parm_ipv6 =~ /%/)
+ and /^\s*inet6(?:\saddr(?:ess))?:?\s*([abcdef\d:]+)(?:%[^ \/]+)?(?:\/\d+)?/i)
{
next if $1 eq '::' or $1 eq '::1' or $1 =~ /^ff00/i or $1 =~ /^fe80::1/i;
$parm_ipv6 = $1;
}
unlink("$parm_cwd/test-config");
}
+ elsif (/^ipv6-non-linklocal/)
+ {
+ if ($parm_ipv6 =~ /%/) { $wantthis = 0; last; }
+ }
else
{
tests_exit(-1, "Unknown line in \"scripts/$testdir/REQUIRES\": \"$_\"");
tests_exit(-1, "Failed to open $parm_cwd/dnszones/db.ip4.$components[0]: $!");
print OUT "$components[3].$components[2].$components[1] PTR $parm_hostname.\n\n";
close(OUT);
- }
+ }
else
{
open(OUT, ">$parm_cwd/dnszones/db.ip4.$components[0]") ||
last if /^[rc]$/i;
if (/^e$/i)
{
- system("$more test-stderr");
+ system @more => 'test-stderr';
}
elsif (/^o$/i)
{
- system("$more test-stdout");
+ system @more => 'test-stdout';
}
}
****
# now 2 frozen, one of which is a bounce
# check that ignore_bounce_errors_after finishes off the frozen bounce (only)
-millisleep 2500
-exim -qf
+#sleep 5
+exim -Tqt 5s/5s/ -qf
****
-sleep 3
+#sleep 6
# check that timeout_frozen_after finishes off the (remaining) frozen
-exim -q
+exim -Tqt 11s/11s -q
****
no_msglog_check
exim -q
****
#
+#
+# Native queue transfer
+### load messages
+exim -bs
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO: <normal@test.ex>
+DATA
+Subject: test
+
+foo
+.
+RSET
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO: <alternate@test.ex>
+DATA
+Subject: test
+
+foo
+.
+QUIT
+****
+### default q
+exim -bp
+****
+### alternate q
+exim -bp -qGalternate
+****
+#
+exim -MG third $msg1
+****
+exim -qGalternate -MG third $msg1
+****
+### third q
+exim -bp -qGthird
+****
+exim -qGthird -MG '' $msg1 $msg2
+****
+### default q
+exim -bp
+****
+### alternate q
+exim -bp -qGalternate
+****
+### third q
+exim -bp -qGthird
+****
+#
no_stderr_check
#
# Client requests notification of deferral. First time of trying, we get
# a defer but queue-time probably has not hit the 1st retry time yet, so no DSN
-# will be sent and the message remains queued. Later, after a sleep, we will
-# try again.
+# will be sent and the message remains queued. Then, claiming time has elapsed,
+# we will look again (expecting a delay-DSN to be produced). We won't see a
+# retry since the actual retry time has not passed.
exim -z defer/delay
****
client HOSTIPV4 PORT_D
****
exim -q
****
-sleep 3
#
#
#
# We should see the notify for c@dump.ex but not d@dump.ex
exim -z playout
****
-exim -q
+exim -Tqt 10s/ -q
****
sleep 1
exim -Mrm $msg1 $msg2
DATA
Subject: foo
+data
+.
+QUIT
+****
+#
+#
+# Server rejects RCPT. Client should not proceed to BDAT.
+server PORT_S
+220 Greetings
+EHLO
+250-Hello there
+250 CHUNKING
+MAIL FROM
+250 OK
+RCPT TO
+550 sorry, no
+QUIT
+****
+sudo exim -odf -bS
+EHLO test
+MAIL FROM:<sender@source.dom>
+RCPT TO:<ebad@test.ex>
+DATA
+Subject: foo
+
data
.
QUIT
1
interface: <; ::1 ; HOSTIPV4
****
-exim user6@h2.test.ex
-
-2
-interface: <; HOSTIPV6 ; HOSTIPV4
-****
exim user6@h3.test.ex
3
--- /dev/null
+# interface selection (v4 vs v6) in outgoing SMTP, non-linklocal
+need_ipv4
+need_ipv6
+#
+exim -DSERVER=server -bd -oX PORT_D
+****
+#
+# This tries to send to ::1 from HOSTIPV6 - which is ok until HOSTIPV6
+# is a link-local addr (with a scope-id specifying the link). Then,
+# it seems, ::1 is not on that link (for Linux & FreeBSD, at least). The connect
+# times out and the testcase fails.
+exim user6@h2.test.ex
+
+2
+interface: <; HOSTIPV6 ; HOSTIPV4
+****
+exim -qf
+****
+killdaemon
+no_msglog_check
--- /dev/null
+support IPv6
+ipv6-non-linklocal
#
# This should pass, an independently-generated sample from Scott Kitterman.
-# I don't want to retain this longterm as it hits an external DNS record,
-# not under the testsuite.
+# We use a copied version of his DNS record.
client 127.0.0.1 PORT_D
??? 220
HELO xxx
+++ /dev/null
-# OCSP stapling, server, multiple leaf-certs
-# This will fail on OpenSSL versions before 1.1.0
-#
-#
-#
-exim -z '1: Server sends good staple on request, to client requiring RSA auth'
-****
-#
-exim -bd -oX PORT_D -DSERVER=server
-****
-exim -odf -DSELECTOR=auth_rsa rsa.auth@test.ex
-Subject: test
-
-.
-****
-killdaemon
-#
-#
-#
-#
-exim -z '2: Server sends good staple on request, to client preferring ECDSA auth'
-****
-#
-exim -bd -oX PORT_D -DSERVER=server
-****
-exim -odf -DSELECTOR=auth_ecdsa ecdsa.auth@test.ex
-Subject: test
-
-.
-****
-killdaemon
-no_msglog_check
--- /dev/null
+# OCSP stapling, server, multiple leaf-certs
+# This will fail on OpenSSL versions before 1.1.0
+#
+#
+#
+exim -z '1: Server sends good staple on request, to client requiring RSA auth'
+****
+#
+exim -bd -oX PORT_D -DSERVER=server
+****
+exim -odf -DSELECTOR=auth_rsa rsa.auth@test.ex
+Subject: test
+
+.
+****
+killdaemon
+#
+#
+#
+#
+exim -z '2: Server sends good staple on request, to client preferring ECDSA auth'
+****
+#
+exim -bd -oX PORT_D -DSERVER=server
+****
+exim -odf -DSELECTOR=auth_ecdsa ecdsa.auth@test.ex
+Subject: test
+
+.
+****
+killdaemon
+no_msglog_check
--- /dev/null
+support OpenSSL
+support OCSP
+running IPv4
+feature _HAVE_TLS_OCSP_LIST
--- /dev/null
+# OCSP stapling, server, multiple chain-element OCSP
+#
+#
+#
+#
+exim -z '1: TLS1.2 Server sends good leaf-staple on request, to client requiring RSA auth'
+****
+#
+exim -bd -oX PORT_D -DSERVER=server -DLIMIT=TLS1.2
+****
+#
+exim -odf -DOPT=rsa -DLIMIT=TLS1.2 rsa.auth@test.ex
+Subject: test
+
+.
+****
+killdaemon
+#
+#
+exim -z '2: TLS1.3 Server sends good 3-element staple on request, to client requiring RSA auth'
+****
+#
+# Works when the (single) proof file has an ocsp-response with 3 statusses.
+# Contrast with with GnuTLS which can do either that or have 3 proof files
+# each with one status.
+#
+exim -bd -oX PORT_D -DSERVER=server -DLIMIT=TLS1.3
+****
+exim -odf -DOPT=rsa rsa.auth@test.ex
+Subject: test
+
+.
+****
+killdaemon
+#
+##
+##
+#exim -z '3: TLS1.3 Server sends bad nonleaf staple, client detects it'
+#****
+##
+#EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK=y exim -bd -oX PORT_D -DSERVER=server -DLIMIT=TLS1.3 -DCONTROL=bad
+#****
+#exim -odf -DOPT=rsa rsa.auth@test.ex
+#Subject: test
+#
+#.
+#****
+#killdaemon
+##
+##
+#
+#
+sudo rm -fr tmp/
+no_msglog_check
--- /dev/null
+support OpenSSL
+support OCSP
+running IPv4
+feature _HAVE_TLS1_3
+++ /dev/null
-# OCSP stapling, server, multiple leaf-certs
-#
-#
-#
-exim -z '1: Server sends good staple on request, to client requiring RSA auth'
-****
-#
-exim -bd -oX PORT_D -DSERVER=server
-****
-exim -odf -DSELECTOR=auth_rsa rsa.auth@test.ex
-Subject: test
-
-.
-****
-killdaemon
-#
-#
-#
-#
-exim -z '2: Server sends good staple on request, to client preferring ECDSA auth'
-****
-#
-exim -bd -oX PORT_D -DSERVER=server
-****
-exim -odf -DSELECTOR=auth_ecdsa ecdsa.auth@test.ex
-Subject: test
-
-.
-****
-killdaemon
-no_msglog_check
+++ /dev/null
-# OCSP stapling, server, multiple chain-element OCSP
-#
-#
-#
-mkdir -p DIR/tmp/ocsp
-sudo chown -R EXIMUSER:EXIMGROUP tmp
-sudo chmod -R a+rwx DIR/tmp/ocsp
-perl
-chdir 'aux-fixed/exim-ca/example.com';
-system 'cat server1.example.com/server1.example.com.ocsp.signernocert.good.resp.pem CA/Signer.ocsp.signernocert.good.resp.pem CA/CA.ocsp.signernocert.good.resp.pem > DIR/tmp/ocsp/triple.ocsp.pem';
-system 'cat server1.example.com/server1.example.com.ocsp.signernocert.good.resp.pem CA/Signer.ocsp.signernocert.revoked.resp.pem > DIR/tmp/ocsp/double_r.ocsp.pem';
-****
-#
-#
-exim -z '1: TLS1.2 Server sends good leaf-staple on request, to client requiring RSA auth'
-****
-#
-exim -bd -oX PORT_D -DSERVER=server -DLIMIT=TLS1.2
-****
-#
-exim -odf -DOPT=rsa -DLIMIT=TLS1.2 rsa.auth@test.ex
-Subject: test
-
-.
-****
-killdaemon
-#
-#
-exim -z '2: TLS1.3 Server sends good 3-element staple on request, to client requiring RSA auth'
-****
-#
-exim -bd -oX PORT_D -DSERVER=server -DLIMIT=TLS1.3
-****
-exim -odf -DOPT=rsa rsa.auth@test.ex
-Subject: test
-
-.
-****
-killdaemon
-#
-#
-#
-exim -z '3: TLS1.3 Server sends bad nonleaf staple, client detects it'
-****
-#
-EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK=y exim -bd -oX PORT_D -DSERVER=server -DLIMIT=TLS1.3 -DCONTROL=bad
-****
-exim -odf -DOPT=rsa rsa.auth@test.ex
-Subject: test
-
-.
-****
-killdaemon
-#
-#
-#
-#
-sudo rm -fr tmp/
-no_msglog_check
+++ /dev/null
-support GnuTLS
-support OCSP
-running IPv4
-feature _HAVE_TLS1_3
--- /dev/null
+# OCSP stapling, server, multiple leaf-certs
+#
+#
+#
+exim -z '1: Server sends good staple on request, to client requiring RSA auth'
+****
+#
+exim -bd -oX PORT_D -DSERVER=server
+****
+exim -odf -DSELECTOR=auth_rsa rsa.auth@test.ex
+Subject: test
+
+.
+****
+killdaemon
+#
+#
+#
+#
+exim -z '2: Server sends good staple on request, to client preferring ECDSA auth'
+****
+#
+exim -bd -oX PORT_D -DSERVER=server
+****
+exim -odf -DSELECTOR=auth_ecdsa ecdsa.auth@test.ex
+Subject: test
+
+.
+****
+killdaemon
+no_msglog_check
--- /dev/null
+support GnuTLS
+support OCSP
+running IPv4
+feature _HAVE_TLS_OCSP_LIST
--- /dev/null
+# OCSP stapling, server, multiple chain-element OCSP
+#
+#
+#
+mkdir -p DIR/tmp/ocsp
+sudo chown -R EXIMUSER:EXIMGROUP tmp
+sudo chmod -R a+rwx DIR/tmp/ocsp
+perl
+chdir 'aux-fixed/exim-ca/example.com';
+system 'cat server1.example.com/server1.example.com.ocsp.signernocert.good.resp.pem CA/Signer.ocsp.signernocert.revoked.resp.pem > DIR/tmp/ocsp/double_r.ocsp.pem';
+****
+#
+#
+exim -z '1: TLS1.2 Server sends good leaf-staple on request, to client requiring RSA auth'
+****
+#
+sudo exim -bd -oX PORT_D -DSERVER=server -DLIMIT=TLS1.2
+****
+#
+exim -odf -DOPT=rsa -DLIMIT=TLS1.2 rsa.auth@test.ex
+Subject: test
+
+.
+****
+killdaemon
+#
+#
+exim -z '2: TLS1.3 Server sends good 3-element staple on request, to client requiring RSA auth'
+****
+#
+# Prefix with sudo to get SSLKEYLOGFILE to work. Only works on the server.
+exim -bd -oX PORT_D -DSERVER=server -DLIMIT=TLS1.3
+****
+exim -odf -DOPT=rsa rsa.auth@test.ex
+Subject: test
+
+.
+****
+killdaemon
+#
+#
+#
+exim -z '3: TLS1.3 Server sends bad nonleaf staple, client detects it'
+****
+#
+EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK=y exim -bd -oX PORT_D -DSERVER=server -DLIMIT=TLS1.3 -DCONTROL=bad
+****
+exim -odf -DOPT=rsa rsa.auth@test.ex
+Subject: test
+
+.
+****
+killdaemon
+#
+#
+#
+#
+sudo rm -fr tmp/
+no_msglog_check
--- /dev/null
+support GnuTLS
+support OCSP
+running IPv4
+feature _HAVE_TLS1_3
qtypelen the length of qtype
pkptr points to the output buffer pointer; this is updated
countptr points to the record count; this is updated
- dnssec points to the AD flag indicator; this is updated
- aa points to the AA flag indicator; this is updated
+ dnssec_p points to the AD flag indicator; this is updated
+ aa_p points to the AA flag indicator; this is updated
Returns: 0 on success, else HOST_NOT_FOUND or NO_DATA or NO_RECOVERY or
PASS_ON - the latter if a "PASS ON NOT FOUND" line is seen
static int
find_records(FILE *f, uschar *zone, uschar *domain, uschar *qtype,
- int qtypelen, uschar **pkptr, int *countptr, BOOL * dnssec, BOOL * aa)
+ int qtypelen, uschar **pkptr, int *countptr, BOOL * dnssec_p, BOOL * aa_p)
{
int yield = HOST_NOT_FOUND;
int domainlen = Ustrlen(domain);
if (yield == HOST_NOT_FOUND)
{
yield = NO_DATA;
- if (dnssec) *dnssec = TRUE; /* cancelled by first nonsecure rec found */
- if (aa) *aa = TRUE; /* cancelled by first non-aa rec found */
+ if (dnssec_p) *dnssec_p = TRUE; /* cancelled by first nonsecure rec found */
+ if (aa_p) *aa_p = TRUE; /* cancelled by first non-aa rec found */
}
/* Compare RR types; a CNAME record is always returned */
if (delay)
millisleep(delay);
- if (dnssec && !rr_sec)
- *dnssec = FALSE; /* cancel AD return */
+ if (dnssec_p && !rr_sec)
+ *dnssec_p = FALSE; /* cancel AD return */
- if (aa && !rr_aa)
- *aa = FALSE; /* cancel AA return */
+ if (aa_p && !rr_aa)
+ *aa_p = FALSE; /* cancel AA return */
if (rr_ignore) continue;
uschar packet[2048 * 32 + 32];
HEADER *header = (HEADER *)packet;
uschar *pk = packet;
-BOOL dnssec;
-BOOL aa;
+BOOL dnssec = FALSE;
+BOOL aa = FALSE;
signal(SIGALRM, alarmfn);
(void)sprintf(CS buffer, "%s/dnszones", argv[1]);
-d = opendir(CCS buffer);
-if (d == NULL)
+if (!(d = opendir(CCS buffer)))
{
fprintf(stderr, "fakens: failed to opendir %s: %s\n", buffer,
strerror(errno));
return NO_RECOVERY;
}
-while ((de = readdir(d)) != NULL)
+while ((de = readdir(d)))
{
uschar *name = US de->d_name;
if (Ustrncmp(name, "qualify.", 8) == 0)
header->qr = 1; /* query */
header->opcode = QUERY; /* standard query */
-header->tc = 0; /* no trucation */
+header->tc = 0; /* no truncation */
/* Find the records we want, and add them to the result. */
#define udn 2 /* Unix domain socket number */
#define skn 2 /* Potential number of sockets */
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
{
int i;
int port = 0;
DNS lookup of 99.99.99.V4NET.rbl.test.ex (A) using fakens
DNS lookup of 99.99.99.V4NET.rbl.test.ex (A) gave HOST_NOT_FOUND
returning DNS_NOMATCH
+faking res_search(A) response length as 65535
writing neg-cache entry for 99.99.99.V4NET.rbl.test.ex-A-xxxx, ttl 3000
+faking res_search(A) response length as 65535
dnslists: wrote cache entry, ttl=3000
DNS lookup for 99.99.99.V4NET.rbl.test.ex failed
=> that means V4NET.99.99.99 is not listed at rbl.test.ex
routed by lookuphost router
envelope to: xx@mxt6.test.ex
transport: remote_smtp
- host ten-1.test.ex [V4NET.0.0.1] MX=5
+ host ten-1.test.ex [V4NET.0.0.1] MX=5 dnssec=no
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
configuration file is TESTSUITE/test-config
Exim version x.yz ....
changed uid/gid: forcing real = effective
uid=uuuu gid=CALLER_GID pid=pppp
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
changed uid/gid: privilege not needed
routed by lookuphost router
envelope to: xxx@mxt9.test.ex
transport: <none>
- host ten-1.test.ex [V4NET.0.0.1] MX=5
- host ten-2.test.ex [V4NET.0.0.2] MX=6
- host ten-3.test.ex [V4NET.0.0.3] MX=7
+ host ten-1.test.ex [V4NET.0.0.1] MX=5 dnssec=no
+ host ten-2.test.ex [V4NET.0.0.2] MX=6 dnssec=no
+ host ten-3.test.ex [V4NET.0.0.3] MX=7 dnssec=no
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
configuration file is TESTSUITE/test-config
routed by lookuphost router
envelope to: xxx@mxt9a.test.ex
transport: <none>
- host ten-1.test.ex [V4NET.0.0.1] MX=5
- host ten-2.test.ex [V4NET.0.0.2] MX=6
- host ten-3.test.ex [V4NET.0.0.3] MX=7
+ host ten-1.test.ex [V4NET.0.0.1] MX=5 dnssec=no
+ host ten-2.test.ex [V4NET.0.0.2] MX=6 dnssec=no
+ host ten-3.test.ex [V4NET.0.0.3] MX=7 dnssec=no
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
configuration file is TESTSUITE/test-config
routed by lookuphost router
envelope to: xxx@mxt9b.test.ex
transport: <none>
- host ten-1.test.ex [V4NET.0.0.1] MX=5
- host ten-2.test.ex [V4NET.0.0.2] MX=6
- host ten-3.test.ex [V4NET.0.0.3] MX=7
+ host ten-1.test.ex [V4NET.0.0.1] MX=5 dnssec=no
+ host ten-2.test.ex [V4NET.0.0.2] MX=6 dnssec=no
+ host ten-3.test.ex [V4NET.0.0.3] MX=7 dnssec=no
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing x@mxt10.test.ex
>>> calling domainlist router
+>>> mxt10.test.ex in "*"? yes (matched "*")
>>> domainlist router declined for x@mxt10.test.ex
>>> "more" is false: skipping remaining routers
>>> no more routers
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing x@ten-1.test.ex
>>> calling domainlist router
+>>> ten-1.test.ex in "*"? yes (matched "*")
>>> routed by domainlist router
>>> ----------- end verify ------------
>>> require: condition test succeeded in ACL "check_recipient"
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing x@mxt10.test.ex
>>> calling domainlist router
+>>> mxt10.test.ex in "*"? yes (matched "*")
>>> domainlist router declined for x@mxt10.test.ex
>>> "more" is false: skipping remaining routers
>>> no more routers
routed by lookuphost router
envelope to: xx@mxt6.test.ex
transport: remote_smtp
- host ten-1.test.ex [V4NET.0.0.1] MX=5
+ host ten-1.test.ex [V4NET.0.0.1] MX=5 dnssec=no
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
configuration file is TESTSUITE/test-config
>>> fail_sender2 router declined for user@ten-1.test.ex
>>> ten-1.test.ex in "! +local_domains"? yes (end of list)
>>> calling lookuphost router
+>>> ten-1.test.ex in "*"? yes (matched "*")
>>> routed by lookuphost router
>>> ----------- end verify ------------
>>> require: condition test succeeded in ACL "check_recipient"
calling lookuphost router
lookuphost router called for userx@test.again.dns
domain = test.again.dns
+test.again.dns in "*"? yes (matched "*")
DNS lookup of test.again.dns (MX) using fakens
DNS lookup of test.again.dns (MX) gave TRY_AGAIN
test.again.dns in dns_again_means_nonexist? no (option unset)
calling lookuphost router
lookuphost router called for abcd@test.again.dns
domain = test.again.dns
+test.again.dns in "*"? yes (matched "*")
DNS lookup of test.again.dns-MX: using cached value DNS_AGAIN
lookuphost router: defer for abcd@test.again.dns
message: host lookup did not complete
calling lookuphost router
lookuphost router called for abcd@ten-1.test.ex
domain = ten-1.test.ex
+ten-1.test.ex in "*"? yes (matched "*")
DNS lookup of ten-1.test.ex (MX) using fakens
DNS lookup of ten-1.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for ten-1.test.ex-MX-xxxx, ttl 3000
+ten-1.test.ex (MX resp) DNSSEC
DNS lookup of ten-1.test.ex (A) using fakens
DNS lookup of ten-1.test.ex (A) succeeded
fully qualified name = ten-1.test.ex
set transport smtp
finding IP address for test.again.dns
doing DNS lookup
+test.again.dns in "*"? yes (matched "*")
DNS lookup of test.again.dns (A) using fakens
DNS lookup of test.again.dns (A) gave TRY_AGAIN
test.again.dns in dns_again_means_nonexist? no (option unset)
expanded list of hosts = 'test.again.dns' options = 'bydns'
finding IP address for test.again.dns
doing DNS lookup
+test.again.dns in "*"? yes (matched "*")
DNS lookup of test.again.dns-A: using cached value DNS_AGAIN
useryz router: defer for userz@test.again.dns
message: host lookup for test.again.dns did not complete (DNS timeout?)
calling lookuphost router
lookuphost router called for xyz@ten-1.test.ex
domain = ten-1.test.ex
+ten-1.test.ex in "*"? yes (matched "*")
DNS lookup of ten-1.test.ex-MX: using cached value DNS_NODATA
DNS lookup of ten-1.test.ex (A) using fakens
DNS lookup of ten-1.test.ex (A) succeeded
calling lookuphost router
lookuphost router called for userx@test.fail.dns
domain = test.fail.dns
+test.fail.dns in "*"? yes (matched "*")
DNS lookup of test.fail.dns (MX) using fakens
DNS lookup of test.fail.dns (MX) gave NO_RECOVERY
returning DNS_FAIL
calling lookuphost router
lookuphost router called for abcd@test.fail.dns
domain = test.fail.dns
+test.fail.dns in "*"? yes (matched "*")
DNS lookup of test.fail.dns-MX: using cached value DNS_FAIL
lookuphost router: defer for abcd@test.fail.dns
message: host lookup did not complete
calling lookuphost router
lookuphost router called for abcd@ten-1.test.ex
domain = ten-1.test.ex
+ten-1.test.ex in "*"? yes (matched "*")
DNS lookup of ten-1.test.ex (MX) using fakens
DNS lookup of ten-1.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for ten-1.test.ex-MX-xxxx, ttl 3000
+ten-1.test.ex (MX resp) DNSSEC
DNS lookup of ten-1.test.ex (A) using fakens
DNS lookup of ten-1.test.ex (A) succeeded
fully qualified name = ten-1.test.ex
set transport smtp
finding IP address for test.fail.dns
doing DNS lookup
+test.fail.dns in "*"? yes (matched "*")
DNS lookup of test.fail.dns (A) using fakens
DNS lookup of test.fail.dns (A) gave NO_RECOVERY
returning DNS_FAIL
expanded list of hosts = 'test.fail.dns' options = 'bydns'
finding IP address for test.fail.dns
doing DNS lookup
+test.fail.dns in "*"? yes (matched "*")
DNS lookup of test.fail.dns-A: using cached value DNS_FAIL
useryz router: defer for userz@test.fail.dns
message: host lookup for test.fail.dns did not complete (DNS timeout?)
calling lookuphost router
lookuphost router called for xyz@ten-1.test.ex
domain = ten-1.test.ex
+ten-1.test.ex in "*"? yes (matched "*")
DNS lookup of ten-1.test.ex-MX: using cached value DNS_NODATA
DNS lookup of ten-1.test.ex (A) using fakens
DNS lookup of ten-1.test.ex (A) succeeded
calling lookuphost router
lookuphost router called for userx@nonexist.test.ex
domain = nonexist.test.ex
+nonexist.test.ex in "*"? yes (matched "*")
DNS lookup of nonexist.test.ex (MX) using fakens
DNS lookup of nonexist.test.ex (MX) gave HOST_NOT_FOUND
returning DNS_NOMATCH
+faking res_search(MX) response length as 65535
writing neg-cache entry for nonexist.test.ex-MX-xxxx, ttl 3000
lookuphost router declined for userx@nonexist.test.ex
"more" is false: skipping remaining routers
calling lookuphost router
lookuphost router called for abcd@nonexist.test.ex
domain = nonexist.test.ex
+nonexist.test.ex in "*"? yes (matched "*")
DNS lookup of nonexist.test.ex-MX: using cached value DNS_NOMATCH
lookuphost router declined for abcd@nonexist.test.ex
"more" is false: skipping remaining routers
calling lookuphost router
lookuphost router called for abcd@ten-1.test.ex
domain = ten-1.test.ex
+ten-1.test.ex in "*"? yes (matched "*")
DNS lookup of ten-1.test.ex (MX) using fakens
DNS lookup of ten-1.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for ten-1.test.ex-MX-xxxx, ttl 3000
+ten-1.test.ex (MX resp) DNSSEC
DNS lookup of ten-1.test.ex (A) using fakens
DNS lookup of ten-1.test.ex (A) succeeded
fully qualified name = ten-1.test.ex
set transport smtp
finding IP address for nonexist.test.ex
doing DNS lookup
+nonexist.test.ex in "*"? yes (matched "*")
DNS lookup of nonexist.test.ex (A) using fakens
DNS lookup of nonexist.test.ex (A) gave HOST_NOT_FOUND
returning DNS_NOMATCH
+faking res_search(A) response length as 65535
writing neg-cache entry for nonexist.test.ex-A-xxxx, ttl 3000
useryz router: defer for usery@nonexist.test.ex
message: lookup of host "nonexist.test.ex" failed in useryz router
expanded list of hosts = 'nonexist.test.ex' options = 'bydns'
finding IP address for nonexist.test.ex
doing DNS lookup
+nonexist.test.ex in "*"? yes (matched "*")
DNS lookup of nonexist.test.ex-A: using cached value DNS_NOMATCH
useryz router: defer for userz@nonexist.test.ex
message: lookup of host "nonexist.test.ex" failed in useryz router
calling lookuphost router
lookuphost router called for xyz@ten-1.test.ex
domain = ten-1.test.ex
+ten-1.test.ex in "*"? yes (matched "*")
DNS lookup of ten-1.test.ex-MX: using cached value DNS_NODATA
DNS lookup of ten-1.test.ex (A) using fakens
DNS lookup of ten-1.test.ex (A) succeeded
calling srv router
srv router called for srv@test.again.dns
domain = test.again.dns
+test.again.dns in "*"? yes (matched "*")
DNS lookup of _smtp._tcp.test.again.dns (SRV) using fakens
DNS lookup of _smtp._tcp.test.again.dns (SRV) gave TRY_AGAIN
_smtp._tcp.test.again.dns in dns_again_means_nonexist? no (option unset)
calling srv router
srv router called for srv@test.fail.dns
domain = test.fail.dns
+test.fail.dns in "*"? yes (matched "*")
DNS lookup of _smtp._tcp.test.fail.dns (SRV) using fakens
DNS lookup of _smtp._tcp.test.fail.dns (SRV) gave NO_RECOVERY
returning DNS_FAIL
calling lookuphost router
lookuphost router called for userx@nonexist.example.com
domain = nonexist.example.com
+nonexist.example.com in "*"? yes (matched "*")
DNS lookup of nonexist.example.com (MX) using fakens
DNS lookup of nonexist.example.com (MX) gave HOST_NOT_FOUND
returning DNS_NOMATCH
+faking res_search(MX) response length as 65535
writing neg-cache entry for nonexist.example.com-MX-xxxx, ttl 2
lookuphost router declined for userx@nonexist.example.com
"more" is false: skipping remaining routers
calling delay router
delay router called for userd@nonexist.example.com
domain = nonexist.example.com
+nonexist.example.com in "*"? yes (matched "*")
DNS lookup of nonexist.example.com-MX: cached value DNS_NOMATCH past valid time
DNS lookup of nonexist.example.com (MX) using fakens
DNS lookup of nonexist.example.com (MX) gave HOST_NOT_FOUND
returning DNS_NOMATCH
+faking res_search(MX) response length as 65535
update neg-cache entry for nonexist.example.com-MX-xxxx, ttl 2
delay router declined for userd@nonexist.example.com
"more" is false: skipping remaining routers
calling r2 router
r2 router called for unknown@test.ex
domain = test.ex
+test.ex in "*"? yes (matched "*")
DNS lookup of test.ex (MX) using fakens
DNS lookup of test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for test.ex-MX-xxxx, ttl 3000
+test.ex (MX resp) DNSSEC
DNS lookup of test.ex (A) using fakens
DNS lookup of test.ex (A) gave NO_DATA
returning DNS_NODATA
+faking res_search(A) response length as 65535
writing neg-cache entry for test.ex-A-xxxx, ttl 3000
r2 router declined for unknown@test.ex
--------> r3 router <--------
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing x@ten-1
>>> calling dnslookup router
+>>> ten-1 in "*"? yes (matched "*")
>>> re-routed to x@ten-1.test.ex
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing x@ten-1.test.ex
>>> calling dnslookup router
+>>> ten-1.test.ex in "*"? yes (matched "*")
>>> routed by dnslookup router
>>> ----------- end verify ------------
>>> deny: condition test failed in ACL "check_rcpt"
calling r1 router
r1 router called for kilos@recurse.test.ex
domain = recurse.test.ex
+recurse.test.ex in "*"? yes (matched "*")
DNS lookup of recurse.test.ex (MX) using fakens
DNS lookup of recurse.test.ex (MX) gave HOST_NOT_FOUND
returning DNS_NOMATCH
+faking res_search(MX) response length as 65535
writing neg-cache entry for recurse.test.ex-MX-xxxx, ttl 3000
r1 router widened recurse.test.ex to recurse.test.ex.test.ex
+recurse.test.ex.test.ex in "*"? yes (matched "*")
DNS lookup of recurse.test.ex.test.ex (MX) using fakens
DNS lookup of recurse.test.ex.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for recurse.test.ex.test.ex-MX-xxxx, ttl 3000
+recurse.test.ex.test.ex (MX resp) DNSSEC
DNS lookup of recurse.test.ex.test.ex (A) using fakens
DNS lookup of recurse.test.ex.test.ex (A) succeeded
fully qualified name = recurse.test.ex.test.ex
Exim version x.yz ....
changed uid/gid: forcing real = effective
uid=uuuu gid=CALLER_GID pid=pppp
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
changed uid/gid: privilege not needed
for $received_for}}
├──expanding: ($tls_in_ver)
├─────result: ()
- ╰───skipping: result is not used
- ├──condition: def:tls_in_cipher_std
- ├─────result: false
- ╭───scanning: tls $tls_in_cipher_std
- }}(Exim $version_number)
- ${if def:sender_address {(envelope-from <$sender_address>)
- }}id $message_exim_id${if def:received_for {
- for $received_for}}
- ├──expanding: tls $tls_in_cipher_std
-
- ├─────result: tls
-
╰───skipping: result is not used
├──condition: def:sender_address
├─────result: true
Exim version x.yz ....
changed uid/gid: forcing real = effective
uid=uuuu gid=EXIM_GID pid=pppp
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
trusted user
admin user
calling dnslookup router
dnslookup router called for k@mxt13.test.ex
domain = mxt13.test.ex
+mxt13.test.ex in "*"? yes (matched "*")
DNS lookup of mxt13.test.ex (MX) using fakens
DNS lookup of mxt13.test.ex (MX) succeeded
DNS lookup of other1.test.ex (A) using fakens
routed by dnslookup router
envelope to: k@mxt13.test.ex
transport: smtp
- host other1.test.ex [V4NET.12.4.5] MX=4
+ host other1.test.ex [V4NET.12.4.5] MX=4 dnssec=no
search_tidyup called
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
calling r1 router
r1 router called for x@uppercase.test.ex
domain = uppercase.test.ex
+uppercase.test.ex (MX resp) DNSSEC
local host found for non-MX address
fully qualified name = UpperCase.test.ex
uppercase.test.ex 127.0.0.1 mx=-1 sort=xx
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing x@ten-1.test.ex
>>> calling r1 router
+>>> ten-1.test.ex in "*"? yes (matched "*")
>>> routed by r1 router
>>> Attempting full verification using callout
>>> callout cache: no domain record found for ten-1.test.ex
DNS lookup of ten-1 (MX) using fakens
DNS lookup of ten-1 (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for ten-1-MX-xxxx, ttl 3000
Address records are not being sought
ten-1 in "!@mx_any"? yes (end of list)
calling all router
all router called for x@ten-1
domain = ten-1
+ten-1 in "*"? yes (matched "*")
DNS lookup of ten-1 (MX) using fakens
DNS lookup of ten-1 (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for ten-1-MX-xxxx, ttl 3000
+ten-1 (MX resp) DNSSEC
DNS lookup of ten-1 (A) using fakens
DNS lookup of ten-1 (A) succeeded
fully qualified name = ten-1.test.ex
DNS lookup of ten-1.test.ex (MX) using fakens
DNS lookup of ten-1.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for ten-1.test.ex-MX-xxxx, ttl 3000
Address records are not being sought
ten-1.test.ex in "!@mx_any"? yes (end of list)
calling all router
all router called for x@ten-1.test.ex
domain = ten-1.test.ex
+ten-1.test.ex in "*"? yes (matched "*")
DNS lookup of ten-1.test.ex (MX) using fakens
DNS lookup of ten-1.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for ten-1.test.ex-MX-xxxx, ttl 3000
+ten-1.test.ex (MX resp) DNSSEC
DNS lookup of ten-1.test.ex (A) using fakens
DNS lookup of ten-1.test.ex (A) succeeded
fully qualified name = ten-1.test.ex
calling r1 router
r1 router called for x@mxt1c.test.ex
domain = mxt1c.test.ex
+mxt1c.test.ex in "*"? yes (matched "*")
DNS lookup of mxt1c.test.ex (MX) using fakens
DNS lookup of mxt1c.test.ex (MX) succeeded
DNS lookup of dontqualify (A) using fakens
H=127.0.0.1 [127.0.0.1] Connection refused
set_process_info: pppp delivering 10HmaZ-0005vi-00: just tried 127.0.0.1 [127.0.0.1]:PORT_S for CALLER@the.local.host.name: result DEFER
added retry item for T:127.0.0.1:127.0.0.1:1224: errno=dd more_errno=dd,A flags=2
-set_process_info: pppp delivering 10HmaZ-0005vi-00: waiting for a remote delivery subprocess to finish
all IP addresses skipped or deferred at least one address
updating wait-t1 database
added to list for 127.0.0.1
Leaving t1 transport
set_process_info: pppp delivering 10HmaZ-0005vi-00 (just run t1 for CALLER@the.local.host.name in subprocess)
+set_process_info: pppp delivering 10HmaZ-0005vi-00: waiting for a remote delivery subprocess to finish
set_process_info: pppp delivering 10HmaZ-0005vi-00
LOG: MAIN
== CALLER@the.local.host.name R=r1 T=t1 defer (dd): Connection refused
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing x@mxt2.test.ex
>>> calling r1 router
+>>> mxt2.test.ex in "*"? yes (matched "*")
>>> r1 router declined for x@mxt2.test.ex
>>> no more routers
>>> ----------- end verify ------------
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
╭considering: ${tod_full}
for $received_for}}
├──expanding: ($tls_in_ver)
├─────result: ()
- ╰───skipping: result is not used
- ├──condition: def:tls_in_cipher_std
- ├─────result: false
- ╭───scanning: tls $tls_in_cipher_std
- }}(Exim $version_number)
- ${if def:sender_address {(envelope-from <$sender_address>)
- }}id $message_exim_id${if def:received_for {
- for $received_for}}
- ├──expanding: tls $tls_in_cipher_std
-
- ├─────result: tls
-
╰───skipping: result is not used
├──condition: def:sender_address
├─────result: true
<= CALLER@test.ex U=CALLER P=local S=sss
created log directory TESTSUITE/spool/log
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
trusted user
admin user
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
LOG: smtp_connection MAIN
calling dns router
dns router called for userx@alias-eximtesthost
domain = alias-eximtesthost
+alias-eximtesthost in "*"? yes (matched "*")
DNS lookup of alias-eximtesthost (MX) using fakens
DNS lookup of alias-eximtesthost (MX) succeeded
CNAME found: change to eximtesthost.test.ex
DNS lookup of eximtesthost.test.ex (MX) using fakens
DNS lookup of eximtesthost.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for eximtesthost.test.ex-MX-xxxx, ttl 3000
+alias-eximtesthost (MX resp) DNSSEC
DNS lookup of alias-eximtesthost (A) using fakens
DNS lookup of alias-eximtesthost (A) succeeded
CNAME found: change to eximtesthost.test.ex
calling dns router
dns router called for userx@alias-eximtesthost.test.ex
domain = alias-eximtesthost.test.ex
+alias-eximtesthost.test.ex in "*"? yes (matched "*")
DNS lookup of alias-eximtesthost.test.ex (MX) using fakens
DNS lookup of alias-eximtesthost.test.ex (MX) succeeded
CNAME found: change to eximtesthost.test.ex
calling dns router
dns router called for userx@alias-eximtesthost.test.ex
domain = alias-eximtesthost.test.ex
+alias-eximtesthost.test.ex in "*"? yes (matched "*")
DNS lookup of alias-eximtesthost.test.ex (MX) using fakens
DNS lookup of alias-eximtesthost.test.ex (MX) succeeded
CNAME found: change to eximtesthost.test.ex
DNS lookup of eximtesthost.test.ex (MX) using fakens
DNS lookup of eximtesthost.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for eximtesthost.test.ex-MX-xxxx, ttl 3000
+alias-eximtesthost.test.ex (MX resp) DNSSEC
DNS lookup of alias-eximtesthost.test.ex (A) using fakens
DNS lookup of alias-eximtesthost.test.ex (A) succeeded
CNAME found: change to eximtesthost.test.ex
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing should_log@delay1500.test.ex
>>> calling all router
-LOG: Long name lookup for 'delay1500.test.ex': ssss msec
+>>> delay1500.test.ex in "*"? yes (matched "*")
+LOG: Long A lookup for 'delay1500.test.ex': ssss msec
>>> local host found for non-MX address
>>> routed by all router
>>> ----------- end verify ------------
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing should_not_log@delay500.test.ex
>>> calling all router
+>>> delay500.test.ex in "*"? yes (matched "*")
>>> local host found for non-MX address
>>> routed by all router
>>> ----------- end verify ------------
DNS lookup of v6.test.ex (MX) using fakens
DNS lookup of v6.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for v6.test.ex-MX-xxxx, ttl 3000
DNS lookup of v6.test.ex (AAAA) succeeded
DNS lookup of v6.test.ex (A) using fakens
DNS lookup of v6.test.ex (A) gave NO_DATA
returning DNS_NODATA
+faking res_search(A) response length as 65535
writing neg-cache entry for v6.test.ex-A-xxxx, ttl 3000
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
DNS lookup of v6.test.ex (MX) using fakens
DNS lookup of v6.test.ex (MX) gave NO_DATA
returning DNS_NODATA
+faking res_search(MX) response length as 65535
writing neg-cache entry for v6.test.ex-MX-xxxx, ttl 3000
DNS lookup of v6.test.ex (A) using fakens
DNS lookup of v6.test.ex (A) gave NO_DATA
returning DNS_NODATA
+faking res_search(A) response length as 65535
writing neg-cache entry for v6.test.ex-A-xxxx, ttl 3000
>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=2 >>>>>>>>>>>>>>>>
DNS lookup of unknown (TXT) using fakens
DNS lookup of unknown (TXT) gave HOST_NOT_FOUND
returning DNS_NOMATCH
+faking res_search(TXT) response length as 65535
writing neg-cache entry for unknown-TXT-xxxx, ttl 3000
lookup failed
unknown in "dnsdb;unknown"? no (end of list)
1999-03-02 09:44:33 this is a warning at TESTSUITE/aux-fixed/3000.pl line 25.
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
dropping to exim gid; retaining priv uid
>>> calling skipped router
>>> skipped router declined for userx@test.again.dns
>>> calling temp router
+>>> test.again.dns in "*"? yes (matched "*")
>>> test.again.dns in dns_again_means_nonexist? no (option unset)
>>> temp router: defer for userx@test.again.dns
>>> message: host lookup did not complete
>>> routing r1-userx@test.again.dns
>>> test.again.dns in "!testdb;fail"? yes (end of list)
>>> calling r1 router
+>>> test.again.dns in "*"? yes (matched "*")
>>> test.again.dns in dns_again_means_nonexist? no (option unset)
>>> r1 router: defer for r1-userx@test.again.dns
>>> message: host lookup did not complete
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
in hosts_connection_nolog? no (option unset)
for $received_for}}
├──expanding: ($tls_in_ver)
├─────result: ()
- ╰───skipping: result is not used
- ├──condition: def:tls_in_cipher_std
- ├─────result: false
- ╭───scanning: tls $tls_in_cipher_std
- }}(Exim $version_number)
- ${if def:sender_address {(envelope-from <$sender_address>)
- }}id $message_exim_id${if def:received_for {
- for $received_for}}
- ├──expanding: tls $tls_in_cipher_std
-
- ├─────result: tls
-
╰───skipping: result is not used
├──condition: def:sender_address
├─────result: true
SMTP connection from CALLER closed by QUIT
>>>>>>>>>>>>>>>> Exim pid=pppp (msg setup toplevel) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
in hosts_connection_nolog? no (option unset)
for $received_for}}
├──expanding: ($tls_in_ver)
├─────result: ()
- ╰───skipping: result is not used
- ├──condition: def:tls_in_cipher_std
- ├─────result: false
- ╭───scanning: tls $tls_in_cipher_std
- }}(Exim $version_number)
- ${if def:sender_address {(envelope-from <$sender_address>)
- }}id $message_exim_id${if def:received_for {
- for $received_for}}
- ├──expanding: tls $tls_in_cipher_std
-
- ├─────result: tls
-
╰───skipping: result is not used
├──condition: def:sender_address
├─────result: true
SMTP connection from CALLER closed by QUIT
>>>>>>>>>>>>>>>> Exim pid=pppp (msg setup toplevel) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
in hosts_connection_nolog? no (option unset)
for $received_for}}
├──expanding: ($tls_in_ver)
├─────result: ()
- ╰───skipping: result is not used
- ├──condition: def:tls_in_cipher_std
- ├─────result: false
- ╭───scanning: tls $tls_in_cipher_std
- }}(Exim $version_number)
- ${if def:sender_address {(envelope-from <$sender_address>)
- }}id $message_exim_id${if def:received_for {
- for $received_for}}
- ├──expanding: tls $tls_in_cipher_std
-
- ├─────result: tls
-
╰───skipping: result is not used
├──condition: def:sender_address
├─────result: true
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
in hosts_connection_nolog? no (option unset)
for $received_for}}
├──expanding: ($tls_in_ver)
├─────result: ()
- ╰───skipping: result is not used
- ├──condition: def:tls_in_cipher_std
- ├─────result: false
- ╭───scanning: tls $tls_in_cipher_std
- }}(Exim $version_number)
- ${if def:sender_address {(envelope-from <$sender_address>)
- }}id $message_exim_id${if def:received_for {
- for $received_for}}
- ├──expanding: tls $tls_in_cipher_std
-
- ├─────result: tls
-
╰───skipping: result is not used
├──condition: def:sender_address
├─────result: true
SMTP connection from CALLER closed by QUIT
>>>>>>>>>>>>>>>> Exim pid=pppp (msg setup toplevel) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
in hosts_connection_nolog? no (option unset)
for $received_for}}
├──expanding: ($tls_in_ver)
├─────result: ()
- ╰───skipping: result is not used
- ├──condition: def:tls_in_cipher_std
- ├─────result: false
- ╭───scanning: tls $tls_in_cipher_std
- }}(Exim $version_number)
- ${if def:sender_address {(envelope-from <$sender_address>)
- }}id $message_exim_id${if def:received_for {
- for $received_for}}
- ├──expanding: tls $tls_in_cipher_std
-
- ├─────result: tls
-
╰───skipping: result is not used
├──condition: def:sender_address
├─────result: true
SMTP connection from CALLER closed by QUIT
>>>>>>>>>>>>>>>> Exim pid=pppp (msg setup toplevel) terminating with rc=0 >>>>>>>>>>>>>>>>
Exim version x.yz ....
+adding SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
configuration file is TESTSUITE/test-config
admin user
in hosts_connection_nolog? no (option unset)
for $received_for}}
├──expanding: ($tls_in_ver)
├─────result: ()
- ╰───skipping: result is not used
- ├──condition: def:tls_in_cipher_std
- ├─────result: false
- ╭───scanning: tls $tls_in_cipher_std
- }}(Exim $version_number)
- ${if def:sender_address {(envelope-from <$sender_address>)
- }}id $message_exim_id${if def:received_for {
- for $received_for}}
- ├──expanding: tls $tls_in_cipher_std
-
- ├─────result: tls
-
╰───skipping: result is not used
├──condition: def:sender_address
├─────result: true
condition =
debug_print =
no_disable_logging
-dnssec_request_domains =
+dnssec_request_domains = *
dnssec_require_domains =
domains =
driver = accept
userx@bdomain1
router = r3, transport = smtp2
host ipv4.ipv4.ipv4.ipv4 [ipv4.ipv4.ipv4.ipv4]
- host 127.0.0.1 [127.0.0.1]
+ host 127.0.0.1 [127.0.0.1]
host the.local.host.name [ip4.ip4.ip4.ip4]
userx@bdomain2
router = r3, transport = smtp2
host the.local.host.name [ip4.ip4.ip4.ip4]
- host 127.0.0.1 [127.0.0.1]
+ host 127.0.0.1 [127.0.0.1]
host ipv4.ipv4.ipv4.ipv4 [ipv4.ipv4.ipv4.ipv4]
userx@bdomain3
router = r3, transport = smtp2
host ipv4.ipv4.ipv4.ipv4 [ipv4.ipv4.ipv4.ipv4]
- host 127.0.0.1 [127.0.0.1]
+ host 127.0.0.1 [127.0.0.1]
host the.local.host.name [ip4.ip4.ip4.ip4]
******** SERVER ********
xx@yy
router = r1, transport = t1
- host 1.2.3.4 [1.2.3.4]
+ host 1.2.3.4 [1.2.3.4]
host other2.test.ex [V4NET.12.3.2]
router = r1, transport = t1
host ten-1.test.ex [V4NET.0.0.1] MX=5
host eximtesthost.test.ex [ip4.ip4.ip4.ip4] MX=5
- host ten-6.test.ex [V4NET.0.0.6]
+ host ten-6.test.ex [V4NET.0.0.6]
x@manual.route is undeliverable: lowest numbered MX record points to local host
x@random.manual.route cannot be resolved at this time: lookup of host "localhost.test.ex" failed in r2 router
x@random.manual.route
condition =
debug_print =
no_disable_logging
-dnssec_request_domains =
+dnssec_request_domains = *
dnssec_require_domains =
domains =
driver = accept
delay_after_cutoff
dns_qualify_single
no_dns_search_parents
-dnssec_request_domains =
+dnssec_request_domains = *
dnssec_require_domains =
dscp =
fallback_hosts =
# 1 "TESTSUITE/aux-var/std_conf_prefix"
# 1 "TESTSUITE/aux-var/std_conf_prefix"
# 1 "TESTSUITE/aux-var/tls_conf_prefix"
-keep_environment = PATH:SSLKEYLOGFILE:EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK
+keep_environment = PATH:EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK
+add_environment = SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
exim_path = TESTSUITE/eximdir/exim
host_lookup_order = bydns
spool_directory = TESTSUITE/spool
# 1 "TESTSUITE/aux-var/std_conf_prefix"
# 1 "TESTSUITE/aux-var/std_conf_prefix"
# 1 "TESTSUITE/aux-var/tls_conf_prefix"
-keep_environment = PATH:SSLKEYLOGFILE:EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK
+keep_environment = PATH:EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK
+add_environment = SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
exim_path = TESTSUITE/eximdir/exim
host_lookup_order = bydns
spool_directory = TESTSUITE/spool
354 Enter message, ending with "." on a line by itself\r
250 OK id=10HmbA-0005vi-00\r
221 the.local.host.name closing connection\r
+### load messages
+220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250 OK\r
+250 Accepted\r
+354 Enter message, ending with "." on a line by itself\r
+250 OK id=10HmbB-0005vi-00\r
+250 Reset OK\r
+250 OK\r
+250 Accepted\r
+354 Enter message, ending with "." on a line by itself\r
+250 OK id=10HmbC-0005vi-00\r
+221 the.local.host.name closing connection\r
+### default q
+ 0m sss 10HmbB-0005vi-00 <CALLER@the.local.host.name>
+ normal@test.ex
+
+### alternate q
+ 0m sss 10HmbC-0005vi-00 <CALLER@the.local.host.name>
+ alternate@test.ex
+
+Message 10HmbB-0005vi-00
+Message 10HmbC-0005vi-00
+### third q
+ 0m sss 10HmbB-0005vi-00 <CALLER@the.local.host.name>
+ normal@test.ex
+
+ 0m sss 10HmbC-0005vi-00 <CALLER@the.local.host.name>
+ alternate@test.ex
+
+Message 10HmbB-0005vi-00 Message 10HmbC-0005vi-00
+### default q
+ 0m sss 10HmbB-0005vi-00 <CALLER@the.local.host.name>
+ normal@test.ex
+
+ 0m sss 10HmbC-0005vi-00 <CALLER@the.local.host.name>
+ alternate@test.ex
+
+### alternate q
+### third q
******** SERVER ********
### default q
### alternate q
+### load messages
+### default q
+### alternate q
+### third q
+### default q
+### alternate q
+### third q
# 1 "TESTSUITE/aux-var/std_conf_prefix"
# 1 "TESTSUITE/aux-var/std_conf_prefix"
# 1 "TESTSUITE/aux-var/tls_conf_prefix"
-keep_environment = PATH:SSLKEYLOGFILE:EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK
+keep_environment = PATH:EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK
+add_environment = SSLKEYLOGFILE=TESTSUITE/spool/sslkeys
exim_path = TESTSUITE/eximdir/exim
host_lookup_order = bydns
spool_directory = TESTSUITE/spool
220 Greetings
EHLO testhost.test.ex
250-Hello there
+250 CHUNKING
+MAIL FROM:<>
+250 OK
+RCPT TO:<ebad@test.ex>
+550 sorry, no
+QUIT
+End of script
+Listening on port 1224 ...
+Connection request from [127.0.0.1]
+220 Greetings
+EHLO testhost.test.ex
+250-Hello there
250-PIPELINING
250 CHUNKING
MAIL FROM:<>
manualroute@test.ex
router = r2, transport = smtp
host 46.test.ex [V6NET:ffff:836f:a00:a:800:200a:c031]
- host 46.test.ex [V4NET.0.0.4]
+ host 46.test.ex [V4NET.0.0.4]
dnslookup@v6.test.ex
router = r1, transport = smtp
host v6.test.ex [V6NET:ffff:836f:a00:a:800:200a:c032]
x@46.test.ex
router = r1, transport = t1
host 46.test.ex [V6NET:ffff:836f:a00:a:800:200a:c031]
- host 46.test.ex [V4NET.0.0.4]
+ host 46.test.ex [V4NET.0.0.4]
x@mx46.test.ex
router = r1, transport = t1
host 46.test.ex [V6NET:ffff:836f:a00:a:800:200a:c031] MX=46
host 46.test.ex [V4NET.0.0.4] MX=46
x@mx46.test.ex
router = r0, transport = t1
- host 46.test.ex [V4NET.0.0.4]
+ host 46.test.ex [V4NET.0.0.4]
host 46.test.ex [V6NET:ffff:836f:a00:a:800:200a:c031]
x@mx46.test.ex
router = r0, transport = t1
userx@other99.test.ex cannot be resolved at this time: host non-exist.test.ex not found when translating other99.test.ex [V4NET.99.0.1]
userx@other99.test.ex
router = lookuphost, transport = smtp
- host non-exist.test.ex [unknown]
+ host non-exist.test.ex [unknown]