without &%-bd%&, this is the only way of causing Exim to write a pid file,
because in those cases, the normal pid file is not used.
+.new
+.vitem &%-oPX%&
+.oindex "&%-oPX%&"
+.cindex "pid (process id)" "of daemon"
+.cindex "daemon" "process id (pid)"
+This option is not intended for general use.
+The daemon uses it when terminating due to a SIGTEM, possibly in
+combination with &%-oP%&&~<&'path'&>.
+It causes the pid file to be removed.
+.wen
+
.vitem &%-or%&&~<&'time'&>
.oindex "&%-or%&"
.cindex "timeout" "for non-SMTP input"
to handle IPv6 literal addresses.
-.option dkim_verify_hashes main "string list" "sha256 : sha512 : sha1"
+.new
+.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.
-Note that the presence of sha1 violates RFC 8301.
-Signatures using the rsa-sha1 are however (as of writing) still common.
-The default inclusion of sha1 may be dropped in a future release.
+Acceptable values include:
+.code
+sha1
+sha256
+sha512
+.endd
+
+Note that the acceptance of sha1 violates RFC 8301.
.option dkim_verify_keytypes main "string list" "ed25519 : rsa"
This option gives a list of key types which are acceptable in signatures,
.cindex "RFC 3030" "CHUNKING"
This option provides a list of servers to which, provided they announce
CHUNKING support, Exim will attempt to use BDAT commands rather than DATA.
+.new
+Unless DKIM signing is being done,
+.wen
BDAT will not be used in conjunction with a transport filter.
.option hosts_try_dane smtp "host list&!!" *
non-issue, as a man-in-the-middle attack will cause the correct client and
server to see different identifiers and authentication will fail.
-This is currently only supported when using the GnuTLS library. This is
+.new
+This is
only usable by mechanisms which support "channel binding"; at time of
writing, that's the SCRAM family.
+.wen
This defaults off to ensure smooth upgrade across Exim releases, in case
this option causes some clients to start failing. Some future release
options, and new features, see the NewStuff file next to this ChangeLog.
+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
+ of TLS configuration problems is only done for the daemon startup.
+
+JH/02 Early-pipelining support code is now included unless disabled in Makefile.
+
+JH/03 DKIM verification defaults no long accept sha1 hashes, to conform to
+ RFC 8301. They can still be enabled, using the dkim_verify_hashes main
+ option.
+
+JH/04 Support CHUNKING from an smtp transport using a transport_filter, when
+ DKIM signing is being done. Previously a transport_filter would always
+ disable CHUNKING, falling back to traditional DATA.
+
+JH/05 Regard command-line receipients as tainted.
+
+JH/06 Bug 340: Remove the daemon pid file on exit, whe due to SIGTERM.
+
+
Exim version 4.93
-----------------
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.94
+------------
+
+ 1. EXPERIMENTAL_SRS_NATIVE optional build feature. See the experimental.spec
+ file.
+
+ 2. Channel-binding for authenticators is now supported under OpenSSL.
+ Previously it was GnuTLS-only.
+
+
Version 4.93
------------
-SRS (Sender Rewriting Scheme) Support
+SRS (Sender Rewriting Scheme) Support (using libsrs_alt)
--------------------------------------------------------------
+See also below, for an alternative native support implementation.
-Exiscan currently includes SRS support via Miles Wilton's
+Exim currently includes SRS support via Miles Wilton's
libsrs_alt library. The current version of the supported
library is 0.5, there are reports of 1.0 working.
+SRS (Sender Rewriting Scheme) Support (native)
+--------------------------------------------------------------
+This is less full-featured than the libsrs_alt version above.
+
+The Exim build needs to be done with this in Local/Makefile:
+EXPERIMENTAL_SRS_NATIVE=yes
+
+The following are provided:
+- an expansion item "srs_encode"
+ This takes three arguments:
+ - a site SRS secret
+ - the return_path
+ - the pre-forwarding domain
+
+- an expansion condition "inbound_srs"
+ This takes two arguments: the local_part to check, and a site SRS secret.
+ If the secret is zero-length, only the pattern of the local_part is checked.
+ The $srs_recipient variable is set as a side-effect.
+
+- an expansion variable $srs_recipient
+ This gets the original return_path encoded in the SRS'd local_part
+
+- predefined macros _HAVE_SRS and _HAVE_NATIVE_SRS
+
+Sample usage:
+
+ #macro
+ SRS_SECRET = <pick something unique for your site for this>
+
+ #routers
+
+ outbound:
+ driver = dnslookup
+ # if outbound, and forwarding has been done, use an alternate transport
+ domains = ! +my_domains
+ transport = ${if eq {$local_part@$domain} \
+ {$original_local_part@$original_domain} \
+ {remote_smtp} {remote_forwarded_smtp}}
+
+ inbound_srs:
+ driver = redirect
+ senders = :
+ domains = +my_domains
+ # detect inbound bounces which are SRS'd, and decode them
+ condition = ${if inbound_srs {$local_part} {SRS_SECRET}}
+ data = $srs_recipient
+
+ inbound_srs_failure:
+ driver = redirect
+ senders = :
+ domains = +my_domains
+ # detect inbound bounces which look SRS'd but are invalid
+ condition = ${if inbound_srs {$local_part} {}}
+ allow_fail
+ data = :fail: Invalid SRS recipient address
+
+ #... further routers here
+
+
+ # transport; should look like the non-forward outbound
+ # one, plus the max_rcpt and return_path options
+ remote_forwarded_smtp:
+ driver = smtp
+ # modify the envelope from, for mails that we forward
+ max_rcpt = 1
+ return_path = ${srs_encode {SRS_SECRET} {$return_path} {$original_domain}}
+
+
+
+
DCC Support
--------------------------------------------------------------
Distributed Checksum Clearinghouse; http://www.rhyolite.com/dcc/
os.h: $(SCRIPTS)/Configure-os.h \
$(O)/os.h-Darwin \
$(O)/os.h-FreeBSD \
+ $(O)/os.h-GNU \
$(O)/os.h-Linux \
$(O)/os.h-OpenBSD \
$(O)/os.h-SunOS5
os.c: ../src/os.c \
$(SCRIPTS)/Configure-os.c \
$(O)/os.c-FreeBSD \
+ $(O)/os.c-GNU \
$(O)/os.c-Linux \
$(O)/os.c-SunOS5
$(SHELL) $(SCRIPTS)/Configure-os.c
--- /dev/null
+# Exim: OS-specific make file for GNU and variants.
+
+HAVE_ICONV=yes
+
+BASENAME_COMMAND=look_for_it
+CHOWN_COMMAND=look_for_it
+CHGRP_COMMAND=look_for_it
+CHMOD_COMMAND=look_for_it
+
+CFLAGS ?= -O -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+
+DBMLIB = -ldb
+USE_DB = yes
+
+LIBS = -lnsl -lcrypt -lm
+LIBRESOLV = -lresolv
+
+X11=/usr/X11R6
+XINCLUDE=-I$(X11)/include
+XLFLAGS=-L$(X11)/lib
+X11_LD_LIB=$(X11)/lib
+
+EXIWHAT_PS_ARG=ax
+EXIWHAT_EGREP_ARG='/exim( |$$)'
+EXIWHAT_MULTIKILL_CMD=killall
+EXIWHAT_MULTIKILL_ARG=exim
+EXIWHAT_KILL_SIGNAL=-USR1
+
+# End
/*************
-* Sendfile *
+Sendfile shim
*************/
ssize_t
return (ssize_t)written;
}
+/*************************************************
+TCP Fast Open: check that the ioctl is accepted
+*************************************************/
+
+#ifndef COMPILE_UTILITY
+void
+tfo_probe(void)
+{
+# ifdef TCP_FASTOPEN
+int sock;
+
+if ( (sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0
+ && setsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, &on, sizeof(on) >= 0)
+ )
+ f.tcp_fastopen_ok = TRUE;
+close(sock);
+# endif
+}
+#endif
+
+
/* End of os.c-Linux */
--- /dev/null
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* GNU-specific code. This is concatenated onto the generic src/os.c file.
+GNU/Hurd has approximately the same way to determine the load average as NeXT,
+so a variant of this could also be in the generic os.c file. See the GNU EMacs
+getloadavg.c file, from which this snippet was derived. getloadavg.c from Emacs
+is copyrighted by the FSF under the terms of the GPLv2 or any later version.
+Changes are hereby placed under the same license, as requested by the GPL. */
+
+#ifndef OS_LOAD_AVERAGE
+#define OS_LOAD_AVERAGE
+
+#include <mach.h>
+
+static processor_set_t default_set;
+static int getloadavg_initialized;
+
+int
+os_getloadavg (void)
+{
+host_t host;
+struct processor_set_basic_info info;
+unsigned info_count;
+
+if (!getloadavg_initialized)
+ {
+ if (processor_set_default (mach_host_self(), &default_set) == KERN_SUCCESS)
+ getloadavg_initialized = 1;
+ }
+
+if (getloadavg_initialized)
+ {
+ info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
+ if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, &host,
+ (processor_set_info_t)&info, &info_count) != KERN_SUCCESS)
+ getloadavg_initialized = 0;
+ else
+ {
+ #if LOAD_SCALE == 1000
+ return info.load_average;
+ #else
+ return (int) (((double) info.load_average * 1000) / LOAD_SCALE));
+ #endif
+ }
+ }
+
+return -1;
+}
+#endif /* OS_LOAD_AVERAGE */
+
+/* End of os.c-GNU */
/*******************/
-/* TCP_FASTOPEN support. There does not seems to be a
-MSG_FASTOPEN defined yet... */
#define EXIM_TFO_PROBE
+#define EXIM_TFO_FREEBSD
-#include <netinet/tcp.h> /* for TCP_FASTOPEN */
-#include <sys/socket.h> /* for MSG_FASTOPEN */
-#if defined(TCP_FASTOPEN) && !defined(MSG_FASTOPEN)
-# define MSG_FASTOPEN 0x20000000
-#endif
/* for TCP state-variable values, for TFO logging */
#include <netinet/tcp_fsm.h>
--- /dev/null
+/* Exim: OS-specific C header file for GNU/Hurd */
+
+#define CRYPT_H
+#define GLIBC_IP_OPTIONS
+#define HAVE_BSD_GETLOADAVG
+#define HAVE_MMAP
+#define HAVE_SYS_VFS_H
+#define NO_IP_VAR_H
+#define SIG_IGN_WORKS
+#define SIOCGIFCONF_GIVES_ADDR
+
+#define F_FREESP O_TRUNC
+typedef struct flock flock_t;
+
+#define os_strsignal strsignal
+#define OS_STRSIGNAL
+
+/* Hurd-specific bits below */
+
+/* default is non-const */
+#define ICONV_ARG2_TYPE const char **
+
+/* End */
+++ /dev/null
-# Exim: OS-specific make file for GNU and variants.
-
-HAVE_ICONV=yes
-
-BASENAME_COMMAND=look_for_it
-CHOWN_COMMAND=look_for_it
-CHGRP_COMMAND=look_for_it
-CHMOD_COMMAND=look_for_it
-
-CFLAGS ?= -O -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
-
-DBMLIB = -ldb
-USE_DB = yes
-
-LIBS = -lnsl -lcrypt -lm
-LIBRESOLV = -lresolv
-
-X11=/usr/X11R6
-XINCLUDE=-I$(X11)/include
-XLFLAGS=-L$(X11)/lib
-X11_LD_LIB=$(X11)/lib
-
-EXIWHAT_PS_ARG=ax
-EXIWHAT_EGREP_ARG='/exim( |$$)'
-EXIWHAT_MULTIKILL_CMD=killall
-EXIWHAT_MULTIKILL_ARG=exim
-EXIWHAT_KILL_SIGNAL=-USR1
-
-# End
+++ /dev/null
-/*************************************************
-* Exim - an Internet mail transport agent *
-*************************************************/
-
-/* See the file NOTICE for conditions of use and distribution. */
-
-/* GNU-specific code. This is concatenated onto the generic src/os.c file.
-GNU/Hurd has approximately the same way to determine the load average as NeXT,
-so a variant of this could also be in the generic os.c file. See the GNU EMacs
-getloadavg.c file, from which this snippet was derived. getloadavg.c from Emacs
-is copyrighted by the FSF under the terms of the GPLv2 or any later version.
-Changes are hereby placed under the same license, as requested by the GPL. */
-
-#ifndef OS_LOAD_AVERAGE
-#define OS_LOAD_AVERAGE
-
-#include <mach.h>
-
-static processor_set_t default_set;
-static int getloadavg_initialized;
-
-int
-os_getloadavg (void)
-{
-host_t host;
-struct processor_set_basic_info info;
-unsigned info_count;
-
-if (!getloadavg_initialized)
- {
- if (processor_set_default (mach_host_self(), &default_set) == KERN_SUCCESS)
- getloadavg_initialized = 1;
- }
-
-if (getloadavg_initialized)
- {
- info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
- if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, &host,
- (processor_set_info_t)&info, &info_count) != KERN_SUCCESS)
- getloadavg_initialized = 0;
- else
- {
- #if LOAD_SCALE == 1000
- return info.load_average;
- #else
- return (int) (((double) info.load_average * 1000) / LOAD_SCALE));
- #endif
- }
- }
-
-return -1;
-}
-#endif /* OS_LOAD_AVERAGE */
-
-/* End of os.c-GNU */
+++ /dev/null
-/* Exim: OS-specific C header file for GNU/Hurd */
-
-#define CRYPT_H
-#define GLIBC_IP_OPTIONS
-#define HAVE_BSD_GETLOADAVG
-#define HAVE_MMAP
-#define HAVE_SYS_VFS_H
-#define NO_IP_VAR_H
-#define SIG_IGN_WORKS
-#define SIOCGIFCONF_GIVES_ADDR
-
-#define F_FREESP O_TRUNC
-typedef struct flock flock_t;
-
-#define os_strsignal strsignal
-#define OS_STRSIGNAL
-
-/* Hurd-specific bits below */
-
-/* default is non-const */
-#define ICONV_ARG2_TYPE const char **
-
-/* End */
# CFLAGS += -I/usr/local/include
# LDFLAGS += -lsrs_alt
+# Uncomment the following lines to add SRS (Sender rewriting scheme) support
+# using only native facilities.
+# EXPERIMENTAL_SRS_NATIVE=yes
+
# Uncomment the following line to add DMARC checking capability, implemented
# using libopendmarc libraries. You must have SPF and DKIM support enabled also.
# SUPPORT_DMARC=yes
/* Auxiliary function, passed in data to sasl_server_init(). */
static int
-mysasl_config(void *context,
- const char *plugin_name,
- const char *option,
- const char **result,
- unsigned int *len)
+mysasl_config(void *context, const char *plugin_name, const char *option,
+ const char **result, unsigned int *len)
{
if (context && !strcmp(option, "mech_list"))
{
*result = context;
- if (len != NULL) *len = strlen(*result);
+ if (len) *len = strlen(*result);
return SASL_OK;
}
return SASL_FAIL;
{SASL_CB_LIST_END, NULL, NULL}};
/* default the mechanism to our "public name" */
-if (ob->server_mech == NULL)
- ob->server_mech = string_copy(ablock->public_name);
-expanded_hostname = expand_string(ob->server_hostname);
-if (expanded_hostname == NULL)
+if (!ob->server_mech) ob->server_mech = string_copy(ablock->public_name);
+
+if (!(expanded_hostname = expand_string(ob->server_hostname)))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"couldn't expand server_hostname [%s]: %s",
ablock->name, ob->server_hostname, expand_string_message);
realm_expanded = NULL;
-if (ob->server_realm != NULL) {
- realm_expanded = CS expand_string(ob->server_realm);
- if (realm_expanded == NULL)
- log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
- "couldn't expand server_realm [%s]: %s",
- ablock->name, ob->server_realm, expand_string_message);
-}
+if ( ob->server_realm
+ && !(realm_expanded = CS expand_string(ob->server_realm)))
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
+ "couldn't expand server_realm [%s]: %s",
+ ablock->name, ob->server_realm, expand_string_message);
/* we're going to initialise the library to check that there is an
- * authenticator of type whatever mechanism we're using
- */
+authenticator of type whatever mechanism we're using */
cbs[0].proc = (int(*)(void)) &mysasl_config;
cbs[0].context = ob->server_mech;
-if ((rc = sasl_server_init(cbs, "exim")) != SASL_OK )
+if ((rc = sasl_server_init(cbs, "exim")) != SASL_OK)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"couldn't initialise Cyrus SASL library.", ablock->name);
if ((rc = sasl_server_new(CS ob->server_service, CS expanded_hostname,
- realm_expanded, NULL, NULL, NULL, 0, &conn)) != SASL_OK )
+ realm_expanded, NULL, NULL, NULL, 0, &conn)) != SASL_OK)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"couldn't initialise Cyrus SASL server connection.", ablock->name);
-if ((rc = sasl_listmech(conn, NULL, "", ":", "", (const char **)&list, &len, &i)) != SASL_OK )
+if ((rc = sasl_listmech(conn, NULL, "", ":", "", (const char **)&list, &len, &i)) != SASL_OK)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"couldn't get Cyrus SASL mechanism list.", ablock->name);
}
/* the store_get / store_reset mechanism is hierarchical
- * the hierarchy is stored for us behind our back. This point
- * creates a hierarchy point for this function.
- */
+ the hierarchy is stored for us behind our back. This point
+ creates a hierarchy point for this function. */
+
rs_point = store_mark();
/* loop until either we get to the end of the list, or we match the
- * public name of this authenticator
- */
-while ( ( buffer = string_nextinlist(&listptr, &i, NULL, 0) ) &&
- strcmpic(buffer,ob->server_mech) );
+public name of this authenticator */
+
+while ( (buffer = string_nextinlist(&listptr, &i, NULL, 0))
+ && strcmpic(buffer,ob->server_mech) );
if (!buffer)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
/* For interface, see auths/README */
/* note, we don't care too much about memory allocation in this, because this is entirely
- * within a shortlived child
- */
+within a shortlived child */
int
auth_cyrus_sasl_server(auth_instance *ablock, uschar *data)
}
else
HDEBUG(D_auth) debug_printf("Cyrus SASL set EXTERNAL SSF to %d\n", tls_in.bits);
+
+ /*XXX Set channel-binding here with sasl_channel_binding_t / SASL_CHANNEL_BINDING
+ Unclear what the "name" element does though, ditto the "critical" flag. */
}
else
HDEBUG(D_auth) debug_printf("Cyrus SASL: no TLS, no EXTERNAL SSF set\n");
/* Set properties for remote and local host-ip;port */
for (int i = 0; i < 2; ++i)
{
- struct sockaddr_storage ss;
- int (*query)(int, struct sockaddr *, socklen_t *);
- int propnum, port;
- const uschar *label;
- uschar *address, *address_port;
+ int propnum;
+ const uschar * label;
+ uschar * address_port;
const char *s_err;
socklen_t sslen;
if (i)
{
- query = &getpeername;
propnum = SASL_IPREMOTEPORT;
label = CUS"peer";
+ address_port = string_sprintf("%s;%d",
+ sender_host_address, sender_host_port);
}
else
{
- query = &getsockname;
propnum = SASL_IPLOCALPORT;
label = CUS"local";
+ address_port = string_sprintf("%s;%d", interface_address, interface_port);
}
- sslen = sizeof(ss);
- if ((rc = query(fileno(smtp_in), (struct sockaddr *) &ss, &sslen)) < 0)
- {
- HDEBUG(D_auth)
- debug_printf("Failed to get %s address information: %s\n",
- label, strerror(errno));
- break;
- }
-
- address = host_ntoa(-1, &ss, NULL, &port);
- address_port = string_sprintf("%s;%d", address, port);
-
if ((rc = sasl_setprop(conn, propnum, address_port)) != SASL_OK)
{
- s_err = sasl_errdetail(conn);
HDEBUG(D_auth)
+ {
+ s_err = sasl_errdetail(conn);
debug_printf("Failed to set %s SASL property: [%d] %s\n",
label, rc, s_err ? s_err : "<unknown reason>");
+ }
break;
}
HDEBUG(D_auth) debug_printf("Cyrus SASL set %s hostport to: %s\n",
if ((rc = auth_get_data(&input, out2, outlen)) != OK)
{
/* we couldn't get the data, so free up the library before
- * returning whatever error we get */
+ returning whatever error we get */
sasl_dispose(&conn);
sasl_done();
return rc;
case SASL_NOMECH:
/* this is a temporary failure, because the mechanism is not
- * available for this user. If it wasn't available at all, we
- * shouldn't have got here in the first place...
- */
+ available for this user. If it wasn't available at all, we
+ shouldn't have got here in the first place... */
+
HDEBUG(D_auth)
debug_printf("Cyrus SASL temporary failure %d (%s)\n", rc, sasl_errstring(rc, NULL, NULL));
auth_defer_msg =
the default for the mechanism name; we don't handle multiple mechanisms
in one authenticator, but the same driver can be used multiple times. */
-if (ob->server_mech == NULL)
+if (!ob->server_mech)
ob->server_mech = string_copy(ablock->public_name);
/* Can get multiple session contexts from one library context, so just
initialise the once. */
-if (gsasl_ctx == NULL) {
- rc = gsasl_init(&gsasl_ctx);
- if (rc != GSASL_OK) {
+
+if (!gsasl_ctx)
+ {
+ if ((rc = gsasl_init(&gsasl_ctx)) != GSASL_OK)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"couldn't initialise GNU SASL library: %s (%s)",
ablock->name, gsasl_strerror_name(rc), gsasl_strerror(rc));
- }
+
gsasl_callback_set(gsasl_ctx, main_callback);
-}
+ }
/* We don't need this except to log it for debugging. */
-rc = gsasl_server_mechlist(gsasl_ctx, &p);
-if (rc != GSASL_OK)
+
+if ((rc = gsasl_server_mechlist(gsasl_ctx, &p)) != GSASL_OK)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"failed to retrieve list of mechanisms: %s (%s)",
ablock->name, gsasl_strerror_name(rc), gsasl_strerror(rc));
+
HDEBUG(D_auth) debug_printf("GNU SASL supports: %s\n", p);
supported = gsasl_client_support_p(gsasl_ctx, CCS ob->server_mech);
"GNU SASL does not support mechanism \"%s\"",
ablock->name, ob->server_mech);
-if ((ablock->server_condition == NULL) &&
- (streqic(ob->server_mech, US"EXTERNAL") ||
- streqic(ob->server_mech, US"ANONYMOUS") ||
- streqic(ob->server_mech, US"PLAIN") ||
- streqic(ob->server_mech, US"LOGIN")))
+if ( !ablock->server_condition
+ && ( streqic(ob->server_mech, US"EXTERNAL")
+ || streqic(ob->server_mech, US"ANONYMOUS")
+ || streqic(ob->server_mech, US"PLAIN")
+ || streqic(ob->server_mech, US"LOGIN")
+ ) )
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"Need server_condition for %s mechanism",
ablock->name, ob->server_mech);
/* This does *not* scale to new SASL mechanisms. Need a better way to ask
which properties will be needed. */
-if ((ob->server_realm == NULL) &&
- streqic(ob->server_mech, US"DIGEST-MD5"))
+
+if ( !ob->server_realm
+ && streqic(ob->server_mech, US"DIGEST-MD5"))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
"Need server_realm for %s mechanism",
ablock->name, ob->server_mech);
So don't activate without server_condition, this might be relaxed in the future.
*/
-if (ablock->server_condition != NULL) ablock->server = TRUE;
+
+if (ablock->server_condition) ablock->server = TRUE;
ablock->client = FALSE;
}
debug_printf("GNU SASL Callback entered, prop=%d (loop prop=%d)\n",
prop, callback_loop);
-if (cb_state == NULL)
+if (!cb_state)
{
HDEBUG(D_auth) debug_printf(" not from our server/client processing.\n");
return GSASL_NO_CALLBACK;
debug_printf("GNU SASL: initialising session for %s, mechanism %s.\n",
ablock->name, ob->server_mech);
-rc = gsasl_server_start(gsasl_ctx, CCS ob->server_mech, &sctx);
-if (rc != GSASL_OK)
+if ((rc = gsasl_server_start(gsasl_ctx, CCS ob->server_mech, &sctx)) != GSASL_OK)
{
auth_defer_msg = string_sprintf("GNU SASL: session start failure: %s (%s)",
gsasl_strerror_name(rc), gsasl_strerror(rc));
}
/* We don't support protection layers. */
gsasl_property_set(sctx, GSASL_QOPS, "qop-auth");
+
#ifndef DISABLE_TLS
-if (tls_channelbinding_b64)
+if (tls_in.channelbinding)
{
/* Some auth mechanisms can ensure that both sides are talking withing the
same security context; for TLS, this means that even if a bad certificate
HDEBUG(D_auth) debug_printf("Auth %s: Enabling channel-binding\n",
ablock->name);
gsasl_property_set(sctx, GSASL_CB_TLS_UNIQUE,
- CCS tls_channelbinding_b64);
+ CCS tls_in.channelbinding);
}
else
- {
HDEBUG(D_auth)
debug_printf("Auth %s: Not enabling channel-binding (data available)\n",
ablock->name);
- }
}
else
HDEBUG(D_auth)
exim_error = exim_error_override = OK;
do {
- rc = gsasl_step64(sctx, received, &to_send);
-
- switch (rc)
+ switch (rc = gsasl_step64(sctx, received, &to_send))
{
case GSASL_OK:
if (!to_send)
goto STOP_INTERACTION;
}
- if ((rc == GSASL_NEEDS_MORE) ||
- (to_send && *to_send))
- exim_error =
- auth_get_no64_data((uschar **)&received, US to_send);
+ if ((rc == GSASL_NEEDS_MORE) || (to_send && *to_send))
+ exim_error = auth_get_no64_data((uschar **)&received, US to_send);
if (to_send)
{
static int
condition_check(auth_instance *ablock, uschar *label, uschar *condition_string)
{
-int exim_rc;
-
-exim_rc = auth_check_some_cond(ablock, label, condition_string, FAIL);
-
-if (exim_rc == OK)
- return GSASL_OK;
-else if (exim_rc == DEFER)
+int exim_rc = auth_check_some_cond(ablock, label, condition_string, FAIL);
+switch (exim_rc)
{
- sasl_error_should_defer = TRUE;
- return GSASL_AUTHENTICATION_ERROR;
+ case OK: return GSASL_OK;
+ case DEFER: sasl_error_should_defer = TRUE;
+ return GSASL_AUTHENTICATION_ERROR;
+ case FAIL: return GSASL_AUTHENTICATION_ERROR;
+ default: log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
+ "Unhandled return from checking %s: %d",
+ ablock->name, label, exim_rc);
}
-else if (exim_rc == FAIL)
- return GSASL_AUTHENTICATION_ERROR;
-log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: "
- "Unhandled return from checking %s: %d",
- ablock->name, label, exim_rc);
/* NOTREACHED */
return GSASL_AUTHENTICATION_ERROR;
}
static int
-server_callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop, auth_instance *ablock)
+server_callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop,
+ auth_instance *ablock)
{
char *tmps;
uschar *propval;
break;
case GSASL_VALIDATE_EXTERNAL:
- if (ablock->server_condition == NULL)
+ if (!ablock->server_condition)
{
HDEBUG(D_auth) debug_printf("No server_condition supplied, to validate EXTERNAL.\n");
cbrc = GSASL_AUTHENTICATION_ERROR;
break;
}
propval = US gsasl_property_fast(sctx, GSASL_AUTHZID);
+
/* We always set $auth1, even if only to empty string. */
auth_vars[0] = expand_nstring[1] = propval ? propval : US"";
expand_nlength[1] = Ustrlen(expand_nstring[1]);
break;
case GSASL_VALIDATE_ANONYMOUS:
- if (ablock->server_condition == NULL)
+ if (!ablock->server_condition)
{
HDEBUG(D_auth) debug_printf("No server_condition supplied, to validate ANONYMOUS.\n");
cbrc = GSASL_AUTHENTICATION_ERROR;
break;
}
propval = US gsasl_property_fast(sctx, GSASL_ANONYMOUS_TOKEN);
+
/* We always set $auth1, even if only to empty string. */
+
auth_vars[0] = expand_nstring[1] = propval ? propval : US"";
expand_nlength[1] = Ustrlen(expand_nstring[1]);
expand_nmax = 1;
by the SASL integration after authentication; protected against tampering
(if the SASL mechanism supports that, which Kerberos does) but is
unverified, same as normal for other mechanisms.
-
- First coding, we had these values swapped, but for consistency and prior
+ First coding, we had these values swapped, but for consistency and prior
to the first release of Exim with this authenticator, they've been
switched to match the ordering of GSASL_VALIDATE_SIMPLE. */
+
propval = US gsasl_property_fast(sctx, GSASL_GSSAPI_DISPLAY_NAME);
auth_vars[0] = expand_nstring[1] = propval ? propval : US"";
propval = US gsasl_property_fast(sctx, GSASL_AUTHZID);
/* In this one case, it perhaps makes sense to default back open?
But for consistency, let's just mandate server_condition here too. */
+
cbrc = condition_check(ablock,
US"server_condition (GSSAPI family)", ablock->server_condition);
checked_server_condition = TRUE;
tmps = CS expand_string(ob->server_scram_salt);
gsasl_property_set(sctx, GSASL_SCRAM_SALT, tmps);
}
+
/* Asking for GSASL_AUTHZID calls back into us if we use
gsasl_property_get(), thus the use of gsasl_property_fast().
Do we really want to hardcode limits per mechanism? What happens when
a new mechanism is added to the library. It *shouldn't* result in us
needing to add more glue, since avoiding that is a large part of the
point of SASL. */
+
propval = US gsasl_property_fast(sctx, GSASL_AUTHID);
auth_vars[0] = expand_nstring[1] = propval ? propval : US"";
propval = US gsasl_property_fast(sctx, GSASL_AUTHZID);
for (int i = 1; i <= 3; ++i)
expand_nlength[i] = Ustrlen(expand_nstring[i]);
- tmps = CS expand_string(ob->server_password);
- if (tmps == NULL)
+ if (!(tmps = CS expand_string(ob->server_password)))
{
sasl_error_should_defer = f.expand_string_forcedfail ? FALSE : TRUE;
HDEBUG(D_auth) debug_printf("server_password expansion failed, so "
return GSASL_AUTHENTICATION_ERROR;
}
gsasl_property_set(sctx, GSASL_PASSWORD, tmps);
+
/* This is inadequate; don't think Exim's store stacks are geared
for memory wiping, so expanding strings will leave stuff laying around.
But no need to compound the problem, so get rid of the one we can. */
+
memset(tmps, '\0', strlen(tmps));
cbrc = GSASL_OK;
break;
US"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uschar *
-b64encode(const uschar * clear, int len)
+b64encode_taint(const uschar * clear, int len, BOOL tainted)
{
-uschar *code = store_get(4*((len+2)/3) + 1, is_tainted(clear));
+uschar *code = store_get(4*((len+2)/3) + 1, tainted);
uschar *p = code;
while (len-- >0)
return code;
}
+uschar *
+b64encode(const uschar * clear, int len)
+{
+return b64encode_taint(clear, len, is_tainted(clear));
+}
+
/* End of base64.c */
/* vi: sw ai sw=2
#define DISABLE_DKIM
#define DISABLE_EVENT
#define DISABLE_OCSP
+#define DISABLE_PIPE_CONNECT
#define DISABLE_PRDR
#define DISABLE_TLS
#define DISABLE_D_OPTION
#define SUPPORT_MAILSTORE
#define SUPPORT_MBX
#define SUPPORT_MOVE_FROZEN_MESSAGES
-#define SUPPORT_PIPE_CONNECT
#define SUPPORT_PAM
#define SUPPORT_PROXY
#define SUPPORT_SOCKS
#define EXPERIMENTAL_LMDB
#define EXPERIMENTAL_QUEUEFILE
#define EXPERIMENTAL_SRS
+#define EXPERIMENTAL_SRS_NATIVE
#define EXPERIMENTAL_TLS_RESUME
static SIGNAL_BOOL sigchld_seen;
static SIGNAL_BOOL sighup_seen;
+static SIGNAL_BOOL sigterm_seen;
static int accept_retry_count = 0;
static int accept_retry_errno;
}
+/* SIGTERM handler. Try to get the damon pif file removed
+before exiting. */
+
+static void
+main_sigterm_handler(int sig)
+{
+sigterm_seen = TRUE;
+}
+
+
/*************************************************
#else
signal(SIGCHLD, SIG_IGN);
#endif
+ signal(SIGTERM, SIG_DFL);
/* Attempt to get an id from the sending machine via the RFC 1413
protocol. We do this in the sub-process in order not to hold up the
signal(SIGHUP, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
if (geteuid() != root_uid && !deliver_drop_privilege)
{
+static void
+set_pid_file_path(void)
+{
+if (override_pid_file_path)
+ pid_file_path = override_pid_file_path;
+
+if (!*pid_file_path)
+ pid_file_path = string_sprintf("%s/exim-daemon.pid", spool_directory);
+}
+
+
+/* Remove the daemon's pidfile. Note: runs with root privilege,
+as a direct child of the daemon. Does not return. */
+
+void
+delete_pid_file(void)
+{
+uschar * daemon_pid = string_sprintf("%d\n", (int)getppid());
+FILE * f;
+
+set_pid_file_path();
+if ((f = Ufopen(pid_file_path, "rb")))
+ {
+ if ( fgets(CS big_buffer, big_buffer_size, f)
+ && Ustrcmp(daemon_pid, big_buffer) == 0
+ )
+ if (Uunlink(pid_file_path) == 0)
+ {
+ DEBUG(D_any)
+ debug_printf("%s unlink: %s\n", pid_file_path, strerror(errno));
+ }
+ else
+ DEBUG(D_any)
+ debug_printf("unlinked %s\n", pid_file_path);
+ fclose(f);
+ }
+else
+ DEBUG(D_any)
+ debug_printf("%s\n", string_open_failed(errno, "pid file %s",
+ pid_file_path));
+exim_exit(EXIT_SUCCESS, US"pid file remover");
+}
+
+
+/* Called by the daemon; exec a child to get the pid file deleted
+since we may require privs for the containing directory */
+
+static void
+daemon_die(void)
+{
+int pid;
+
+if (f.running_in_test_harness || write_pid)
+ {
+ if ((pid = fork()) == 0)
+ {
+ if (override_pid_file_path)
+ (void)child_exec_exim(CEE_EXEC_PANIC, FALSE, NULL, FALSE, 3,
+ "-oP", override_pid_file_path, "-oPX");
+ else
+ (void)child_exec_exim(CEE_EXEC_PANIC, FALSE, NULL, FALSE, 1, "-oPX");
+
+ /* Control never returns here. */
+ }
+ if (pid > 0)
+ child_close(pid, 1);
+ }
+exim_exit(EXIT_SUCCESS, US"daemon");
+}
+
+
/*************************************************
* Exim Daemon Mainline *
*************************************************/
gstring * new_smtp_port = NULL;
gstring * new_local_interfaces = NULL;
- if (override_pid_file_path == NULL) write_pid = FALSE;
+ if (!override_pid_file_path) write_pid = FALSE;
list = override_local_interfaces;
sep = 0;
while ((s = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)))
{
uschar joinstr[4];
- gstring ** gp;
-
- if (Ustrpbrk(s, ".:") == NULL)
- gp = &new_smtp_port;
- else
- gp = &new_local_interfaces;
+ gstring ** gp = Ustrpbrk(s, ".:") ? &new_local_interfaces : &new_smtp_port;
if (!*gp)
{
{
FILE *f;
- if (override_pid_file_path)
- pid_file_path = override_pid_file_path;
-
- if (pid_file_path[0] == 0)
- pid_file_path = string_sprintf("%s/exim-daemon.pid", spool_directory);
-
+ set_pid_file_path();
if ((f = modefopen(pid_file_path, "wb", 0644)))
{
(void)fprintf(f, "%d\n", (int)getpid());
for (int i = 0; i < local_queue_run_max; i++) queue_pid_slots[i] = 0;
}
-/* Set up the handler for termination of child processes. */
+/* Set up the handler for termination of child processes, and the one
+telling us to die. */
sigchld_seen = FALSE;
os_non_restarting_signal(SIGCHLD, main_sigchld_handler);
+sigterm_seen = FALSE;
+os_non_restarting_signal(SIGTERM, main_sigterm_handler);
+
/* If we are to run the queue periodically, pretend the alarm has just gone
off. This will cause the first queue-runner to get kicked off straight away. */
(eg: compile regex) */
dns_pattern_init();
+smtp_deliver_init(); /* Used for callouts */
+
+#ifndef DISABLE_DKIM
+ {
+# ifdef MEASURE_TIMING
+ struct timeval t0;
+ gettimeofday(&t0, NULL);
+# endif
+ dkim_exim_init();
+# ifdef MEASURE_TIMING
+ report_time_since(&t0, US"dkim_exim_init (delta)");
+# endif
+ }
+#endif
#ifdef WITH_CONTENT_SCAN
malware_init();
EXIM_SOCKLEN_T len;
pid_t pid;
+ if (sigterm_seen)
+ daemon_die(); /* Does not return */
+
/* This code is placed first in the loop, so that it gets obeyed at the
start, before the first wait, for the queue-runner case, so that the first
one can be started immediately.
signal(SIGHUP, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
/* Re-exec if privilege has been given up, unless deliver_drop_
privilege is set. Reset SIGALRM before exec(). */
uschar bloom[40]; /* Bloom filter which may be larger than this */
} dbdata_ratelimit_unique;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
/* This structure records the EHLO responses, cleartext and crypted,
for an IP, as bitmasks (cf. OPTION_TLS) */
{
if (testflag(addr, af_pipelining))
g = string_catn(g, US" L", 2);
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (testflag(addr, af_early_pipe))
g = string_catn(g, US"*", 1);
#endif
case 'L':
switch (*subid)
{
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
case 2: setflag(addr, af_early_pipe); /*FALLTHROUGH*/
#endif
case 1: setflag(addr, af_pipelining); break;
#endif
if (testflag(addr, af_pipelining))
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (testflag(addr, af_early_pipe))
rmt_dlv_checked_write(fd, 'L', '2', NULL, 0);
else
/* Precompile some regex that are used to recognize parameters in response
to an EHLO command, if they aren't already compiled. */
- deliver_init();
+ smtp_deliver_init();
/* Now sort the addresses if required, and do the deliveries. The yield of
do_remote_deliveries is FALSE when mua_wrapper is set and all addresses
void
-deliver_init(void)
+tcp_init(void)
{
#ifdef EXIM_TFO_PROBE
tfo_probe();
#else
f.tcp_fastopen_ok = TRUE;
#endif
-
-
-if (!regex_PIPELINING) regex_PIPELINING =
- regex_must_compile(US"\\n250[\\s\\-]PIPELINING(\\s|\\n|$)", FALSE, TRUE);
-
-if (!regex_SIZE) regex_SIZE =
- regex_must_compile(US"\\n250[\\s\\-]SIZE(\\s|\\n|$)", FALSE, TRUE);
-
-if (!regex_AUTH) regex_AUTH =
- regex_must_compile(AUTHS_REGEX, FALSE, TRUE);
-
-#ifndef DISABLE_TLS
-if (!regex_STARTTLS) regex_STARTTLS =
- regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
-#endif
-
-if (!regex_CHUNKING) regex_CHUNKING =
- regex_must_compile(US"\\n250[\\s\\-]CHUNKING(\\s|\\n|$)", FALSE, TRUE);
-
-#ifndef DISABLE_PRDR
-if (!regex_PRDR) regex_PRDR =
- regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE);
-#endif
-
-#ifdef SUPPORT_I18N
-if (!regex_UTF8) regex_UTF8 =
- regex_must_compile(US"\\n250[\\s\\-]SMTPUTF8(\\s|\\n|$)", FALSE, TRUE);
-#endif
-
-if (!regex_DSN) regex_DSN =
- regex_must_compile(US"\\n250[\\s\\-]DSN(\\s|\\n|$)", FALSE, TRUE);
-
-if (!regex_IGNOREQUOTA) regex_IGNOREQUOTA =
- regex_must_compile(US"\\n250[\\s\\-]IGNOREQUOTA(\\s|\\n|$)", FALSE, TRUE);
-
-#ifdef SUPPORT_PIPE_CONNECT
-if (!regex_EARLY_PIPE) regex_EARLY_PIPE =
- regex_must_compile(US"\\n250[\\s\\-]" EARLY_PIPE_FEATURE_NAME "(\\s|\\n|$)", FALSE, TRUE);
-#endif
}
void
dkim_exim_init(void)
{
+if (f.dkim_init_done) return;
+f.dkim_init_done = TRUE;
pdkim_init();
}
void
dkim_exim_verify_init(BOOL dot_stuffing)
{
+dkim_exim_init();
+
/* There is a store-reset between header & body reception
so cannot use the main pool. Any allocs done by Exim
memory-handling must use the perm pool. */
dkim_exim_sign_init(void)
{
int old_pool = store_pool;
+
+dkim_exim_init();
store_pool = POOL_MAIN;
pdkim_init_context(&dkim_sign_ctx, FALSE, &dkim_exim_query_dns_txt);
store_pool = old_pool;
static void
term_handler(int sig)
{
- exit(1);
+exit(1);
}
#ifndef DISABLE_OCSP
fprintf(fp, " OCSP");
#endif
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
fprintf(fp, " PIPE_CONNECT");
#endif
#ifndef DISABLE_PRDR
fprintf(fp, " DMARC");
#endif
#ifdef TCP_FASTOPEN
- deliver_init();
+ tcp_init();
if (f.tcp_fastopen_ok) fprintf(fp, " TCP_Fast_Open");
#endif
#ifdef EXPERIMENTAL_LMDB
#ifdef EXPERIMENTAL_QUEUEFILE
fprintf(fp, " Experimental_QUEUEFILE");
#endif
-#ifdef EXPERIMENTAL_SRS
+#if defined(EXPERIMENTAL_SRS) || defined(EXPERIMENTAL_SRS_NATIVE)
fprintf(fp, " Experimental_SRS");
#endif
#ifdef EXPERIMENTAL_ARC
else if (Ustrcmp(argrest, "o") == 0) {}
- /* -oP <name>: set pid file path for daemon */
+ /* -oP <name>: set pid file path for daemon
+ -oPX: delete pid file of daemon */
else if (Ustrcmp(argrest, "P") == 0)
override_pid_file_path = argv[++i];
+ else if (Ustrcmp(argrest, "PX") == 0)
+ delete_pid_file();
+
/* -or <n>: set timeout for non-SMTP acceptance
-os <n>: set timeout for SMTP acceptance */
}
-/* Initialise subsystems as required */
-#ifndef DISABLE_DKIM
- {
-# ifdef MEASURE_TIMING
- struct timeval t0;
- gettimeofday(&t0, NULL);
-# endif
- dkim_exim_init();
-# ifdef MEASURE_TIMING
- report_time_since(&t0, US"dkim_exim_init (delta)");
-# endif
- }
-#endif
-
- {
-#ifdef MEASURE_TIMING
- struct timeval t0;
- gettimeofday(&t0, NULL);
-#endif
- deliver_init();
-#ifdef MEASURE_TIMING
- report_time_since(&t0, US"deliver_init (delta)");
-#endif
- }
+/* Initialise subsystems as required. */
+tcp_init();
/* Handle a request to deliver one or more messages that are already on the
queue. Values of msg_action other than MSG_DELIVER and MSG_LOAD are dealt with
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Daemon cannot be run when "
"mua_wrapper is set");
}
+
+# ifndef DISABLE_TLS
+ /* This also checks that the library linkage is working and we can call
+ routines in it, so call even if tls_require_ciphers is unset */
+ {
+# ifdef MEASURE_TIMING
+ struct timeval t0, diff;
+ (void)gettimeofday(&t0, NULL);
+# endif
+ if (!tls_dropprivs_validate_require_cipher(FALSE))
+ exit(1);
+# ifdef MEASURE_TIMING
+ report_time_since(&t0, US"validate_ciphers (delta)");
+# endif
+ }
+#endif
+
daemon_go();
}
{
while (recipients_arg < argc)
{
- uschar *s = argv[recipients_arg++];
- while (*s != 0)
+ /* Supplied addresses are tainted since they come from a user */
+ uschar * s = string_copy_taint(argv[recipients_arg++], TRUE);
+ while (*s)
{
BOOL finished = FALSE;
uschar *ss = parse_find_address_end(s, FALSE);
test_address(s, flags, &exit_value);
s = ss;
if (!finished)
- while (*(++s) != 0 && (*s == ',' || isspace(*s)));
+ while (*++s == ',' || isspace(*s)) ;
}
}
}
else for (;;)
{
- uschar *s = get_stdinput(NULL, NULL);
- if (s == NULL) break;
- test_address(s, flags, &exit_value);
+ uschar * s = get_stdinput(NULL, NULL);
+ if (!s) break;
+ test_address(string_copy_taint(s, TRUE), flags, &exit_value);
}
route_tidyup();
raw_sender = string_copy(sender_address);
- /* Loop for each argument */
+ /* Loop for each argument (supplied by user hence tainted) */
for (int i = 0; i < count; i++)
{
int start, end, domain;
- uschar *errmess;
- uschar *s = list[i];
+ uschar * errmess;
+ uschar * s = string_copy_taint(list[i], TRUE);
/* Loop for each comma-separated address */
#else
filename = string_sprintf("%s/%s", dirname, name);
#endif
-EXIM_DBOPEN(filename, dirname, flags, 0, &(dbblock->dbptr));
+EXIM_DBOPEN(filename, dirname, flags, 0, &dbblock->dbptr);
if (!dbblock->dbptr)
{
US"run",
US"sg",
US"sort",
+#ifdef EXPERIMENTAL_SRS_NATIVE
+ US"srs_encode",
+#endif
US"substr",
US"tr" };
EITEM_RUN,
EITEM_SG,
EITEM_SORT,
+#ifdef EXPERIMENTAL_SRS_NATIVE
+ EITEM_SRS_ENCODE,
+#endif
EITEM_SUBSTR,
EITEM_TR };
US"gei",
US"gt",
US"gti",
+#ifdef EXPERIMENTAL_SRS_NATIVE
+ US"inbound_srs",
+#endif
US"inlist",
US"inlisti",
US"isip",
ECOND_STR_GEI,
ECOND_STR_GT,
ECOND_STR_GTI,
+#ifdef EXPERIMENTAL_SRS_NATIVE
+ ECOND_INBOUND_SRS,
+#endif
ECOND_INLIST,
ECOND_INLISTI,
ECOND_ISIP,
{ "srs_db_key", vtype_stringptr, &srs_db_key },
{ "srs_orig_recipient", vtype_stringptr, &srs_orig_recipient },
{ "srs_orig_sender", vtype_stringptr, &srs_orig_sender },
+#endif
+#if defined(EXPERIMENTAL_SRS) || defined(EXPERIMENTAL_SRS_NATIVE)
{ "srs_recipient", vtype_stringptr, &srs_recipient },
+#endif
+#ifdef EXPERIMENTAL_SRS
{ "srs_status", vtype_stringptr, &srs_status },
#endif
{ "thisaddress", vtype_stringptr, &filter_thisaddress },
BOOL
expand_check_condition(uschar *condition, uschar *m1, uschar *m2)
{
-int rc;
-uschar *ss = expand_string(condition);
-if (ss == NULL)
+uschar * ss = expand_string(condition);
+if (!ss)
{
if (!f.expand_string_forcedfail && !f.search_find_defer)
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand condition \"%s\" "
"for %s %s: %s", condition, m1, m2, expand_string_message);
return FALSE;
}
-rc = ss[0] != 0 && Ustrcmp(ss, "0") != 0 && strcmpic(ss, US"no") != 0 &&
+return *ss && Ustrcmp(ss, "0") != 0 && strcmpic(ss, US"no") != 0 &&
strcmpic(ss, US"false") != 0;
-return rc;
}
read_name(uschar *name, int max, const uschar *s, uschar *extras)
{
int ptr = 0;
-while (*s != 0 && (isalnum(*s) || Ustrchr(extras, *s) != NULL))
+while (*s && (isalnum(*s) || Ustrchr(extras, *s) != NULL))
{
if (ptr < max-1) name[ptr++] = *s;
s++;
}
+/*************************************************
+* Handle MD5 or SHA-1 computation for HMAC *
+*************************************************/
+
+/* These are some wrapping functions that enable the HMAC code to be a bit
+cleaner. A good compiler will spot the tail recursion.
+
+Arguments:
+ type HMAC_MD5 or HMAC_SHA1
+ remaining are as for the cryptographic hash functions
+
+Returns: nothing
+*/
+
+static void
+chash_start(int type, void * base)
+{
+if (type == HMAC_MD5)
+ md5_start((md5 *)base);
+else
+ sha1_start((hctx *)base);
+}
+
+static void
+chash_mid(int type, void * base, const uschar * string)
+{
+if (type == HMAC_MD5)
+ md5_mid((md5 *)base, string);
+else
+ sha1_mid((hctx *)base, string);
+}
+
+static void
+chash_end(int type, void * base, const uschar * string, int length,
+ uschar * digest)
+{
+if (type == HMAC_MD5)
+ md5_end((md5 *)base, string, length, digest);
+else
+ sha1_end((hctx *)base, string, length, digest);
+}
+
+
+
+
+/* Do an hmac_md5. The result is _not_ nul-terminated, and is sized as
+the smaller of a full hmac_md5 result (16 bytes) or the supplied output buffer.
+
+Arguments:
+ key encoding key, nul-terminated
+ src data to be hashed, nul-terminated
+ buf output buffer
+ len size of output buffer
+*/
+
+static void
+hmac_md5(const uschar * key, const uschar * src, uschar * buf, unsigned len)
+{
+md5 md5_base;
+const uschar * keyptr;
+uschar * p;
+unsigned int keylen;
+
+#define MD5_HASHLEN 16
+#define MD5_HASHBLOCKLEN 64
+
+uschar keyhash[MD5_HASHLEN];
+uschar innerhash[MD5_HASHLEN];
+uschar finalhash[MD5_HASHLEN];
+uschar innerkey[MD5_HASHBLOCKLEN];
+uschar outerkey[MD5_HASHBLOCKLEN];
+
+keyptr = key;
+keylen = Ustrlen(keyptr);
+
+/* If the key is longer than the hash block length, then hash the key
+first */
+
+if (keylen > MD5_HASHBLOCKLEN)
+ {
+ chash_start(HMAC_MD5, &md5_base);
+ chash_end(HMAC_MD5, &md5_base, keyptr, keylen, keyhash);
+ keyptr = keyhash;
+ keylen = MD5_HASHLEN;
+ }
+
+/* Now make the inner and outer key values */
+
+memset(innerkey, 0x36, MD5_HASHBLOCKLEN);
+memset(outerkey, 0x5c, MD5_HASHBLOCKLEN);
+
+for (int i = 0; i < keylen; i++)
+ {
+ innerkey[i] ^= keyptr[i];
+ outerkey[i] ^= keyptr[i];
+ }
+
+/* Now do the hashes */
+
+chash_start(HMAC_MD5, &md5_base);
+chash_mid(HMAC_MD5, &md5_base, innerkey);
+chash_end(HMAC_MD5, &md5_base, src, Ustrlen(src), innerhash);
+
+chash_start(HMAC_MD5, &md5_base);
+chash_mid(HMAC_MD5, &md5_base, outerkey);
+chash_end(HMAC_MD5, &md5_base, innerhash, MD5_HASHLEN, finalhash);
+
+/* Encode the final hash as a hex string, limited by output buffer size */
+
+p = buf;
+for (int i = 0, j = len; i < MD5_HASHLEN; i++)
+ {
+ if (j-- <= 0) break;
+ *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
+ if (j-- <= 0) break;
+ *p++ = hex_digits[finalhash[i] & 0x0f];
+ }
+return;
+}
+
+
/*************************************************
* Read and evaluate a condition *
*************************************************/
/* first_delivery tests for first delivery attempt */
case ECOND_FIRST_DELIVERY:
- if (yield != NULL) *yield = f.deliver_firsttime == testfor;
+ if (yield) *yield = f.deliver_firsttime == testfor;
return s;
/* queue_running tests for any process started by a queue runner */
case ECOND_QUEUE_RUNNING:
- if (yield != NULL) *yield = (queue_run_pid != (pid_t)0) == testfor;
+ if (yield) *yield = (queue_run_pid != (pid_t)0) == testfor;
return s;
if (*s != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
sub[0] = expand_string_internal(s+1, TRUE, &s, yield == NULL, TRUE, resetok);
- if (sub[0] == NULL) return NULL;
+ if (!sub[0]) return NULL;
/* {-for-text-editors */
if (*s++ != '}') goto COND_FAILED_CURLY_END;
- if (yield == NULL) return s; /* No need to run the test if skipping */
+ if (!yield) return s; /* No need to run the test if skipping */
switch(cond_type)
{
case 3: return NULL;
}
- if (yield != NULL)
+ if (yield)
{
int rc;
*resetok = FALSE; /* eval_acl() might allocate; do not reclaim */
case 2:
case 3: return NULL;
}
- if (sub[2] == NULL) sub[3] = NULL; /* realm if no service */
- if (yield != NULL)
+ if (!sub[2]) sub[3] = NULL; /* realm if no service */
+ if (yield)
{
int rc = auth_call_saslauthd(sub[0], sub[1], sub[2], sub[3],
&expand_string_message);
conditions that compare numbers do not start with a letter. This just saves
checking for them individually. */
- if (!isalpha(opname[0]) && yield != NULL)
+ if (!isalpha(opname[0]) && yield)
if (sub[i][0] == 0)
{
num[i] = 0;
else
{
num[i] = expanded_string_integer(sub[i], FALSE);
- if (expand_string_message != NULL) return NULL;
+ if (expand_string_message) return NULL;
}
}
/* Result not required */
- if (yield == NULL) return s;
+ if (!yield) return s;
/* Do an appropriate comparison */
break;
case ECOND_MATCH: /* Regular expression match */
- re = pcre_compile(CS sub[1], PCRE_COPT, (const char **)&rerror, &roffset,
- NULL);
- if (re == NULL)
+ if (!(re = pcre_compile(CS sub[1], PCRE_COPT, (const char **)&rerror,
+ &roffset, NULL)))
{
expand_string_message = string_sprintf("regular expression error in "
"\"%s\": %s at offset %d", sub[1], rerror, roffset);
case ECOND_AND:
case ECOND_OR:
- subcondptr = (yield == NULL)? NULL : &tempcond;
+ subcondptr = (yield == NULL) ? NULL : &tempcond;
combined_cond = (cond_type == ECOND_AND);
while (isspace(*s)) s++;
return NULL;
}
- if (yield != NULL)
- {
+ if (yield)
if (cond_type == ECOND_AND)
{
combined_cond &= tempcond;
combined_cond |= tempcond;
if (combined_cond) subcondptr = NULL; /* once true, don't */
} /* evaluate any more */
- }
}
- if (yield != NULL) *yield = (combined_cond == testfor);
+ if (yield) *yield = (combined_cond == testfor);
return ++s;
while (isspace(*s)) s++;
if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
- sub[0] = expand_string_internal(s, TRUE, &s, (yield == NULL), TRUE, resetok);
- if (sub[0] == NULL) return NULL;
+ if (!(sub[0] = expand_string_internal(s, TRUE, &s, yield == NULL, TRUE, resetok)))
+ return NULL;
/* {-for-text-editors */
if (*s++ != '}') goto COND_FAILED_CURLY_END;
}
DEBUG(D_expand) debug_printf_indent("%s: condition evaluated to %s\n", ourname,
boolvalue? "true":"false");
- if (yield != NULL) *yield = (boolvalue == testfor);
+ if (yield) *yield = (boolvalue == testfor);
return s;
}
+#ifdef EXPERIMENTAL_SRS_NATIVE
+ case ECOND_INBOUND_SRS:
+ /* ${if inbound_srs {local_part}{secret} {yes}{no}} */
+ {
+ uschar * sub[2];
+ const pcre * re;
+ int ovec[3*(4+1)];
+ int n;
+ uschar cksum[4];
+ BOOL boolvalue = FALSE;
+
+ switch(read_subs(sub, 2, 2, CUSS &s, yield == NULL, FALSE, US"inbound_srs", resetok))
+ {
+ case 1: expand_string_message = US"too few arguments or bracketing "
+ "error for inbound_srs";
+ case 2:
+ case 3: return NULL;
+ }
+
+ /* Match the given local_part against the SRS-encoded pattern */
+
+ re = regex_must_compile(US"^(?i)SRS0=([^=]+)=([A-Z2-7]+)=([^=]*)=(.*)$",
+ TRUE, FALSE);
+ if (pcre_exec(re, NULL, CS sub[0], Ustrlen(sub[0]), 0, PCRE_EOPT,
+ ovec, nelem(ovec)) < 0)
+ {
+ DEBUG(D_expand) debug_printf("no match for SRS'd local-part pattern\n");
+ goto srs_result;
+ }
+
+ /* Side-effect: record the decoded recipient */
+
+ srs_recipient = string_sprintf("%.*S@%.*S", /* lowercased */
+ ovec[9]-ovec[8], sub[0] + ovec[8], /* substring 4 */
+ ovec[7]-ovec[6], sub[0] + ovec[6]); /* substring 3 */
+
+ /* If a zero-length secret was given, we're done. Otherwise carry on
+ and validate the given SRS local_part againt our secret. */
+
+ if (!*sub[1])
+ {
+ boolvalue = TRUE;
+ goto srs_result;
+ }
+
+ /* check the timestamp */
+ {
+ struct timeval now;
+ uschar * ss = sub[0] + ovec[4]; /* substring 2, the timestamp */
+ long d;
+
+ gettimeofday(&now, NULL);
+ now.tv_sec /= 86400; /* days since epoch */
+
+ /* Decode substring 2 from base32 to a number */
+
+ for (d = 0, n = ovec[5]-ovec[4]; n; n--)
+ {
+ uschar * t = Ustrchr(base32_chars, *ss++);
+ d = d * 32 + (t - base32_chars);
+ }
+
+ if (((now.tv_sec - d) & 0x3ff) > 10) /* days since SRS generated */
+ {
+ DEBUG(D_expand) debug_printf("SRS too old\n");
+ goto srs_result;
+ }
+ }
+
+ /* check length of substring 1, the offered checksum */
+
+ if (ovec[3]-ovec[2] != 4)
+ {
+ DEBUG(D_expand) debug_printf("SRS checksum wrong size\n");
+ goto srs_result;
+ }
+
+ /* Hash the address with our secret, and compare that computed checksum
+ with the one extracted from the arg */
+
+ hmac_md5(sub[1], srs_recipient, cksum, sizeof(cksum));
+ if (Ustrncmp(cksum, sub[0] + ovec[2], 4) != 0)
+ {
+ DEBUG(D_expand) debug_printf("SRS checksum mismatch\n");
+ goto srs_result;
+ }
+ boolvalue = TRUE;
+
+srs_result:
+ if (yield) *yield = (boolvalue == testfor);
+ return s;
+ }
+#endif /*EXPERIMENTAL_SRS_NATIVE*/
+
/* Unknown condition */
default:
-/*************************************************
-* Handle MD5 or SHA-1 computation for HMAC *
-*************************************************/
-
-/* These are some wrapping functions that enable the HMAC code to be a bit
-cleaner. A good compiler will spot the tail recursion.
-
-Arguments:
- type HMAC_MD5 or HMAC_SHA1
- remaining are as for the cryptographic hash functions
-
-Returns: nothing
-*/
-
-static void
-chash_start(int type, void * base)
-{
-if (type == HMAC_MD5)
- md5_start((md5 *)base);
-else
- sha1_start((hctx *)base);
-}
-
-static void
-chash_mid(int type, void * base, const uschar * string)
-{
-if (type == HMAC_MD5)
- md5_mid((md5 *)base, string);
-else
- sha1_mid((hctx *)base, string);
-}
-
-static void
-chash_end(int type, void * base, const uschar * string, int length,
- uschar * digest)
-{
-if (type == HMAC_MD5)
- md5_end((md5 *)base, string, length, digest);
-else
- sha1_end((hctx *)base, string, length, digest);
-}
-
-
-
-
-
/********************************************************
* prvs: Get last three digits of days since Jan 1, 1970 *
********************************************************/
uschar outerkey[64];
uschar *finalhash_hex;
-if (key_num == NULL)
+if (!key_num)
key_num = US"0";
if (Ustrlen(key) > 64)
{
uschar *s = *sptr;
int_eximarith_t x = eval_op_unary(&s, decimal, error);
-if (*error == NULL)
+if (!*error)
{
while (*s == '*' || *s == '/' || *s == '%')
{
int op = *s++;
int_eximarith_t y = eval_op_unary(&s, decimal, error);
- if (*error != NULL) break;
+ if (*error) break;
/* SIGFPE both on div/mod by zero and on INT_MIN / -1, which would give
* a value of INT_MAX+1. Note that INT_MIN * -1 gives INT_MIN for me, which
* is a bug somewhere in [gcc 4.2.1, FreeBSD, amd64]. In fact, -N*-M where
{
uschar *s = *sptr;
int_eximarith_t x = eval_op_sum(&s, decimal, error);
-if (*error == NULL)
+if (!*error)
{
while ((*s == '<' || *s == '>') && s[1] == s[0])
{
int op = *s++;
s++;
y = eval_op_sum(&s, decimal, error);
- if (*error != NULL) break;
+ if (*error) break;
if (op == '<') x <<= y; else x >>= y;
}
}
{
uschar *s = *sptr;
int_eximarith_t x = eval_op_shift(&s, decimal, error);
-if (*error == NULL)
+if (!*error)
{
while (*s == '&')
{
int_eximarith_t y;
s++;
y = eval_op_shift(&s, decimal, error);
- if (*error != NULL) break;
+ if (*error) break;
x &= y;
}
}
{
uschar *s = *sptr;
int_eximarith_t x = eval_op_and(&s, decimal, error);
-if (*error == NULL)
+if (!*error)
{
while (*s == '^')
{
int_eximarith_t y;
s++;
y = eval_op_and(&s, decimal, error);
- if (*error != NULL) break;
+ if (*error) break;
x ^= y;
}
}
{
uschar *s = *sptr;
int_eximarith_t x = eval_op_xor(&s, decimal, error);
-if (*error == NULL)
+if (!*error)
{
while (*s == '|')
{
int_eximarith_t y;
s++;
y = eval_op_xor(&s, decimal, error);
- if (*error != NULL) break;
+ if (*error) break;
x |= y;
}
}
if (!value)
{
- if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
+ if (Ustrchr(name, '}')) malformed_header = TRUE;
continue;
}
}
save_expand_strings(save_expand_nstring, save_expand_nlength);
while (isspace(*s)) s++;
- next_s = eval_condition(s, &resetok, skipping ? NULL : &cond);
- if (next_s == NULL) goto EXPAND_FAILED; /* message already set */
+ if (!(next_s = eval_condition(s, &resetok, skipping ? NULL : &cond)))
+ goto EXPAND_FAILED; /* message already set */
DEBUG(D_expand)
DEBUG(D_noutf8)
case 3: goto EXPAND_FAILED;
}
- if (sub_arg[1] == NULL) /* One argument */
+ if (!sub_arg[1]) /* One argument */
{
sub_arg[1] = US"/"; /* default separator */
sub_arg[2] = NULL;
if (!mac_islookup(stype, lookup_querystyle|lookup_absfilequery))
{
- if (key == NULL)
+ if (!key)
{
expand_string_message = string_sprintf("missing {key} for single-"
"key \"%s\" lookup", name);
}
else
{
- if (key != NULL)
+ if (key)
{
expand_string_message = string_sprintf("a single key was given for "
"lookup type \"%s\", which is not a single-key lookup type", name);
expand_string_message = US"missing '{' for lookup file-or-query arg";
goto EXPAND_FAILED_CURLY;
}
- filename = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
- if (filename == NULL) goto EXPAND_FAILED;
+ if (!(filename = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok)))
+ goto EXPAND_FAILED;
if (*s++ != '}')
{
expand_string_message = US"missing '}' closing lookup file-or-query arg";
else
{
void *handle = search_open(filename, stype, 0, NULL, NULL);
- if (handle == NULL)
+ if (!handle)
{
expand_string_message = search_error_message;
goto EXPAND_FAILED;
if (!opt_perl_started)
{
uschar *initerror;
- if (opt_perl_startup == NULL)
+ if (!opt_perl_startup)
{
expand_string_message = US"A setting of perl_startup is needed when "
"using the Perl interpreter";
goto EXPAND_FAILED;
}
DEBUG(D_any) debug_printf("Starting Perl interpreter\n");
- initerror = init_perl(opt_perl_startup);
- if (initerror != NULL)
+ if ((initerror = init_perl(opt_perl_startup)))
{
expand_string_message =
string_sprintf("error in perl_startup code: %s\n", initerror);
NULL, the yield was undef, indicating a forced failure. Otherwise the
message will indicate some kind of Perl error. */
- if (new_yield == NULL)
+ if (!new_yield)
{
- if (expand_string_message == NULL)
+ if (!expand_string_message)
{
expand_string_message =
string_sprintf("Perl subroutine \"%s\" returned undef to force "
if (*s == '{')
{
- if (expand_string_internal(s+1, TRUE, &s, TRUE, TRUE, &resetok) == NULL)
+ if (!expand_string_internal(s+1, TRUE, &s, TRUE, TRUE, &resetok))
goto EXPAND_FAILED;
if (*s++ != '}')
{
expand_string_message = US"missing '{' for command arg of run";
goto EXPAND_FAILED_CURLY;
}
- arg = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
- if (arg == NULL) goto EXPAND_FAILED;
+ if (!(arg = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok)))
+ goto EXPAND_FAILED;
while (isspace(*s)) s++;
if (*s++ != '}')
{
if (o2m >= 0) for (; oldptr < yield->ptr; oldptr++)
{
uschar *m = Ustrrchr(sub[1], yield->s[oldptr]);
- if (m != NULL)
+ if (m)
{
int o = m - sub[1];
yield->s[oldptr] = sub[2][(o < o2m)? o : o2m];
string to the last position and make ${length{n}{str}} equivalent to
${substr{0}{n}{str}}. See the defaults for val[] above. */
- if (sub[2] == NULL)
+ if (!sub[2])
{
sub[2] = sub[1];
sub[1] = NULL;
}
ret =
- (item_type == EITEM_HASH)?
- compute_hash(sub[2], val[0], val[1], &len) :
- (item_type == EITEM_NHASH)?
- compute_nhash(sub[2], val[0], val[1], &len) :
- extract_substr(sub[2], val[0], val[1], &len);
-
- if (ret == NULL) goto EXPAND_FAILED;
+ item_type == EITEM_HASH
+ ? compute_hash(sub[2], val[0], val[1], &len)
+ : item_type == EITEM_NHASH
+ ? compute_nhash(sub[2], val[0], val[1], &len)
+ : extract_substr(sub[2], val[0], val[1], &len);
+ if (!ret)
+ goto EXPAND_FAILED;
yield = string_catn(yield, ret, len);
continue;
}
/* Compile the regular expression */
- re = pcre_compile(CS sub[1], PCRE_COPT, (const char **)&rerror, &roffset,
- NULL);
-
- if (re == NULL)
+ if (!(re = pcre_compile(CS sub[1], PCRE_COPT, (const char **)&rerror,
+ &roffset, NULL)))
{
expand_string_message = string_sprintf("regular expression error in "
"\"%s\": %s at offset %d", sub[1], rerror, roffset);
/* Copy the characters before the match, plus the expanded insertion. */
yield = string_catn(yield, subject + moffset, ovector[0] - moffset);
- insert = expand_string(sub[2]);
- if (insert == NULL) goto EXPAND_FAILED;
+ if (!(insert = expand_string(sub[2])))
+ goto EXPAND_FAILED;
yield = string_cat(yield, insert);
moffset = ovector[1];
while (isspace(*s)) s++;
if (*s == '{') /*'}'*/
{
- sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
- if (sub[i] == NULL) goto EXPAND_FAILED; /*'{'*/
+ if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok)))
+ goto EXPAND_FAILED; /*'{'*/
if (*s++ != '}')
{
expand_string_message = string_sprintf(
goto EXPAND_FAILED_CURLY;
}
- list = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok);
- if (list == NULL) goto EXPAND_FAILED;
+ if (!(list = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok)))
+ goto EXPAND_FAILED;
if (*s++ != '}')
{
expand_string_message =
if (item_type == EITEM_FILTER)
{
- temp = eval_condition(expr, &resetok, NULL);
- if (temp != NULL) s = temp;
+ if ((temp = eval_condition(expr, &resetok, NULL)))
+ s = temp;
}
else
temp = expand_string_internal(s, TRUE, &s, TRUE, TRUE, &resetok);
- if (temp == NULL)
+ if (!temp)
{
expand_string_message = string_sprintf("%s inside \"%s\" item",
expand_string_message, name);
if (item_type == EITEM_FILTER)
{
BOOL condresult;
- if (eval_condition(expr, &resetok, &condresult) == NULL)
+ if (!eval_condition(expr, &resetok, &condresult))
{
iterate_item = save_iterate_item;
lookup_value = save_lookup_value;
{
uschar * t = expand_string_internal(expr, TRUE, NULL, skipping, TRUE, &resetok);
temp = t;
- if (temp == NULL)
+ if (!temp)
{
iterate_item = save_iterate_item;
expand_string_message = string_sprintf("%s inside \"%s\" item",
if (!(t = tree_search(dlobj_anchor, argv[0])))
{
void *handle = dlopen(CS argv[0], RTLD_LAZY);
- if (handle == NULL)
+ if (!handle)
{
expand_string_message = string_sprintf("dlopen \"%s\" failed: %s",
argv[0], dlerror());
/* Having obtained the dynamically loaded object handle, look up the
function pointer. */
- func = (exim_dlfunc_t *)dlsym(t->data.ptr, CS argv[1]);
- if (func == NULL)
+ if (!(func = (exim_dlfunc_t *)dlsym(t->data.ptr, CS argv[1])))
{
expand_string_message = string_sprintf("dlsym \"%s\" in \"%s\" failed: "
"%s", argv[1], argv[0], dlerror());
resetok = FALSE;
result = NULL;
- for (argc = 0; argv[argc] != NULL; argc++);
+ for (argc = 0; argv[argc]; argc++);
status = func(&result, argc - 2, &argv[2]);
if(status == OK)
{
- if (result == NULL) result = US"";
+ if (!result) result = US"";
yield = string_cat(yield, result);
continue;
}
else
{
- expand_string_message = result == NULL ? US"(no message)" : result;
- if(status == FAIL_FORCED) f.expand_string_forcedfail = TRUE;
- else if(status != FAIL)
- log_write(0, LOG_MAIN|LOG_PANIC, "dlfunc{%s}{%s} failed (%d): %s",
+ expand_string_message = result ? result : US"(no message)";
+ if (status == FAIL_FORCED)
+ f.expand_string_forcedfail = TRUE;
+ else if (status != FAIL)
+ log_write(0, LOG_MAIN|LOG_PANIC, "dlfunc{%s}{%s} failed (%d): %s",
argv[0], argv[1], status, expand_string_message);
goto EXPAND_FAILED;
}
}
continue;
}
+
+#ifdef EXPERIMENTAL_SRS_NATIVE
+ case EITEM_SRS_ENCODE:
+ /* ${srs_encode {secret} {return_path} {orig_domain}} */
+ {
+ uschar * sub[3];
+ uschar cksum[4];
+
+ switch (read_subs(sub, 3, 3, CUSS &s, skipping, TRUE, name, &resetok))
+ {
+ case 1: goto EXPAND_FAILED_CURLY;
+ case 2:
+ case 3: goto EXPAND_FAILED;
+ }
+
+ yield = string_catn(yield, US"SRS0=", 5);
+
+ /* ${l_4:${hmac{md5}{SRS_SECRET}{${lc:$return_path}}}}= */
+ hmac_md5(sub[0], string_copylc(sub[1]), cksum, sizeof(cksum));
+ yield = string_catn(yield, cksum, sizeof(cksum));
+ yield = string_catn(yield, US"=", 1);
+
+ /* ${base32:${eval:$tod_epoch/86400&0x3ff}}= */
+ {
+ struct timeval now;
+ unsigned long i;
+ gstring * g = NULL;
+
+ gettimeofday(&now, NULL);
+ for (unsigned long i = (now.tv_sec / 86400) & 0x3ff; i; i >>= 5)
+ g = string_catn(g, &base32_chars[i & 0x1f], 1);
+ if (g) while (g->ptr > 0)
+ yield = string_catn(yield, &g->s[--g->ptr], 1);
+ }
+ yield = string_catn(yield, US"=", 1);
+
+ /* ${domain:$return_path}=${local_part:$return_path} */
+ {
+ int start, end, domain;
+ uschar * t = parse_extract_address(sub[1], &expand_string_message,
+ &start, &end, &domain, FALSE);
+ if (!t)
+ goto EXPAND_FAILED;
+
+ if (domain > 0) yield = string_cat(yield, t + domain);
+ yield = string_catn(yield, US"=", 1);
+ yield = domain > 0
+ ? string_catn(yield, t, domain - 1) : string_cat(yield, t);
+ }
+
+ /* @$original_domain */
+ yield = string_catn(yield, US"@", 1);
+ yield = string_cat(yield, sub[2]);
+ continue;
+ }
+#endif /*EXPERIMENTAL_SRS_NATIVE*/
} /* EITEM_* switch */
/* Control reaches here if the name is not recognized as one of the more
if ((c = chop_match(name, op_table_underscore,
nelem(op_table_underscore))) < 0)
{
- arg = Ustrchr(name, '_');
- if (arg != NULL) *arg = 0;
- c = chop_match(name, op_table_main, nelem(op_table_main));
- if (c >= 0) c += nelem(op_table_underscore);
- if (arg != NULL) *arg++ = '_'; /* Put back for error messages */
+ if ((arg = Ustrchr(name, '_')))
+ *arg = 0;
+ if ((c = chop_match(name, op_table_main, nelem(op_table_main))) >= 0)
+ c += nelem(op_table_underscore);
+ if (arg) *arg++ = '_'; /* Put back for error messages */
}
/* Deal specially with operators that might take a certificate variable
{
uschar *tt = sub;
unsigned long int n = 0;
- uschar * s;
while (*tt)
{
uschar * t = Ustrchr(base32_chars, *tt++);
- if (t == NULL)
+ if (!t)
{
expand_string_message = string_sprintf("argument for base32d "
"operator is \"%s\", which is not a base 32 number", sub);
}
n = n * 32 + (t - base32_chars);
}
- s = string_sprintf("%ld", n);
- yield = string_cat(yield, s);
+ yield = string_fmt_append(yield, "%ld", n);
continue;
}
"operator is \"%s\", which is not a decimal number", sub);
goto EXPAND_FAILED;
}
- t = string_base62(n);
- yield = string_cat(yield, t);
+ yield = string_cat(yield, string_base62(n));
continue;
}
while (*tt != 0)
{
uschar *t = Ustrchr(base62_chars, *tt++);
- if (t == NULL)
+ if (!t)
{
expand_string_message = string_sprintf("argument for base62d "
"operator is \"%s\", which is not a base %d number", sub,
case EOP_EXPAND:
{
uschar *expanded = expand_string_internal(sub, FALSE, NULL, skipping, TRUE, &resetok);
- if (expanded == NULL)
+ if (!expanded)
{
expand_string_message =
string_sprintf("internal expansion of \"%s\" failed: %s", sub,
int sep = 0;
uschar buffer[256];
- while (string_nextinlist(CUSS &sub, &sep, buffer, sizeof(buffer)) != NULL) cnt++;
+ while (string_nextinlist(CUSS &sub, &sep, buffer, sizeof(buffer))) cnt++;
yield = string_fmt_append(yield, "%d", cnt);
continue;
}
uschar buffer[256];
if (*sub == '+') sub++;
- if (arg == NULL) /* no-argument version */
+ if (!arg) /* no-argument version */
{
if (!(t = tree_search(addresslist_anchor, sub)) &&
!(t = tree_search(domainlist_anchor, sub)) &&
case EOP_QUOTE:
case EOP_QUOTE_LOCAL_PART:
- if (arg == NULL)
+ if (!arg)
{
BOOL needs_quote = (*sub == 0); /* TRUE for empty string */
uschar *t = sub - 1;
int n;
uschar *opt = Ustrchr(arg, '_');
- if (opt != NULL) *opt++ = 0;
+ if (opt) *opt++ = 0;
- n = search_findtype(arg, Ustrlen(arg));
- if (n < 0)
+ if ((n = search_findtype(arg, Ustrlen(arg))) < 0)
{
expand_string_message = search_error_message;
goto EXPAND_FAILED;
}
- if (lookup_list[n]->quote != NULL)
+ if (lookup_list[n]->quote)
sub = (lookup_list[n]->quote)(sub, opt);
- else if (opt != NULL) sub = NULL;
+ else if (opt)
+ sub = NULL;
- if (sub == NULL)
+ if (!sub)
{
expand_string_message = string_sprintf(
"\"%s\" unrecognized after \"${quote_%s\"",
uschar *error;
uschar *decoded = rfc2047_decode(sub, check_rfc2047_length,
headers_charset, '?', &len, &error);
- if (error != NULL)
+ if (error)
{
expand_string_message = error;
goto EXPAND_FAILED;
/* Perform the required operation */
- ret =
- (c == EOP_HASH || c == EOP_H)?
- compute_hash(sub, value1, value2, &len) :
- (c == EOP_NHASH || c == EOP_NH)?
- compute_nhash(sub, value1, value2, &len) :
- extract_substr(sub, value1, value2, &len);
+ ret = c == EOP_HASH || c == EOP_H
+ ? compute_hash(sub, value1, value2, &len)
+ : c == EOP_NHASH || c == EOP_NH
+ ? compute_nhash(sub, value1, value2, &len)
+ : extract_substr(sub, value1, value2, &len);
+ if (!ret) goto EXPAND_FAILED;
- if (ret == NULL) goto EXPAND_FAILED;
yield = string_catn(yield, ret, len);
continue;
}
/* If expansion failed, expand_string_message will be set. */
-if (s == NULL) return -1;
+if (!s) return -1;
/* On an overflow, strtol() returns LONG_MAX or LONG_MIN, and sets errno
to ERANGE. When there isn't an overflow, errno is not changed, at least on some
uschar *svalue, BOOL *rvalue)
{
uschar *expanded;
-if (svalue == NULL) { *rvalue = bvalue; return OK; }
+if (!svalue) { *rvalue = bvalue; return OK; }
-expanded = expand_string(svalue);
-if (expanded == NULL)
+if (!(expanded = expand_string(svalue)))
{
if (f.expand_string_forcedfail)
{
extern void tls_close(void *, int);
extern BOOL tls_could_read(void);
extern void tls_daemon_init(void);
+extern BOOL tls_dropprivs_validate_require_cipher(BOOL);
extern BOOL tls_export_cert(uschar *, size_t, void *);
extern int tls_feof(void);
extern int tls_ferror(void);
#endif
extern uschar *b64encode(const uschar *, int);
+extern uschar *b64encode_taint(const uschar *, int, BOOL);
extern int b64decode(const uschar *, uschar **);
extern int bdat_getc(unsigned);
extern uschar *bdat_getbuf(unsigned *);
extern void debug_vprintf(int, const char *, va_list);
extern void decode_bits(unsigned int *, size_t, int *,
uschar *, bit_table *, int, uschar *, int);
+extern void delete_pid_file(void);
extern address_item *deliver_make_addr(uschar *, BOOL);
-extern void deliver_init(void);
extern void delivery_log(int, address_item *, int, uschar *);
extern int deliver_message(uschar *, BOOL, BOOL);
extern void deliver_msglog(const char *, ...) PRINTF_FUNCTION(1,2);
extern void smtp_command_sigterm_exit(void) NORETURN;
extern void smtp_data_timeout_exit(void) NORETURN;
extern void smtp_data_sigint_exit(void) NORETURN;
+extern void smtp_deliver_init(void);
extern uschar *smtp_cmd_hist(void);
extern int smtp_connect(smtp_connect_args *, const blob *);
extern int smtp_sock_connect(host_item *, int, int, uschar *,
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
.disable_logging = FALSE,
#ifndef DISABLE_DKIM
.dkim_disable_verify = FALSE,
+ .dkim_init_done = FALSE,
#endif
#ifdef SUPPORT_DMARC
.dmarc_has_been_checked = FALSE,
.sender_name_forced = FALSE,
.sender_set_untrusted = FALSE,
.smtp_authenticated = FALSE,
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
.smtp_in_early_pipe_advertised = FALSE,
.smtp_in_early_pipe_no_auth = FALSE,
.smtp_in_early_pipe_used = FALSE,
uschar *dkim_signers = NULL;
uschar *dkim_signing_domain = NULL;
uschar *dkim_signing_selector = NULL;
-uschar *dkim_verify_hashes = US"sha256:sha512:sha1";
+uschar *dkim_verify_hashes = US"sha256:sha512";
uschar *dkim_verify_keytypes = US"ed25519:rsa";
BOOL dkim_verify_minimal = FALSE;
uschar *dkim_verify_overall = NULL;
uschar *percent_hack_domains = NULL;
uschar *pid_file_path = US PID_FILE_PATH
"\0<--------------Space to patch pid_file_path->";
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
uschar *pipe_connect_advertise_hosts = US"*";
#endif
uschar *pipelining_advertise_hosts = US"*";
const pcre *regex_IGNOREQUOTA = NULL;
const pcre *regex_PIPELINING = NULL;
const pcre *regex_SIZE = NULL;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
const pcre *regex_EARLY_PIPE = NULL;
#endif
const pcre *regex_ismsgid = NULL;
uschar *srs_secrets = NULL;
uschar *srs_status = NULL;
#endif
+#ifdef EXPERIMENTAL_SRS_NATIVE
+uschar *srs_recipient = NULL;
+#endif
int string_datestamp_offset= -1;
int string_datestamp_length= 0;
int string_datestamp_type = -1;
void *peercert; /* Certificate of peer, binary */
uschar *peerdn; /* DN from peer */
uschar *sni; /* Server Name Indication */
+ uschar *channelbinding; /* b64'd data identifying channel, for authenticators */
enum {
OCSP_NOT_REQ=0, /* not requested */
OCSP_NOT_RESP, /* no response to request */
extern uschar *openssl_options; /* OpenSSL compatibility options */
extern const pcre *regex_STARTTLS; /* For recognizing STARTTLS settings */
extern uschar *tls_certificate; /* Certificate file */
-extern uschar *tls_channelbinding_b64; /* string of base64 channel binding */
extern uschar *tls_crl; /* CRL File */
extern int tls_dh_max_bits; /* don't accept higher lib suggestions */
extern uschar *tls_dhparam; /* DH param file */
BOOL disable_logging :1; /* Disables log writing when TRUE */
#ifndef DISABLE_DKIM
BOOL dkim_disable_verify :1; /* Set via ACL control statement. When set, DKIM verification is disabled for the current message */
+ BOOL dkim_init_done :1; /* lazy-init status */
#endif
#ifdef SUPPORT_DMARC
BOOL dmarc_has_been_checked :1; /* Global variable to check if test has been called yet */
BOOL sender_name_forced :1; /* Set by -F */
BOOL sender_set_untrusted :1; /* Sender set by untrusted caller */
BOOL smtp_authenticated :1; /* Sending client has authenticated */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
BOOL smtp_in_early_pipe_advertised :1; /* server advertised PIPE_CONNECT */
BOOL smtp_in_early_pipe_no_auth :1; /* too many authenticator names */
BOOL smtp_in_early_pipe_used :1; /* client did send early data */
extern uschar *percent_hack_domains; /* Local domains for which '% operates */
extern uschar *pid_file_path; /* For writing daemon pids */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
extern uschar *pipe_connect_advertise_hosts; /* for banner/EHLO pipelining */
#endif
extern uschar *pipelining_advertise_hosts; /* As it says */
extern const pcre *regex_IGNOREQUOTA; /* For recognizing IGNOREQUOTA (LMTP) */
extern const pcre *regex_PIPELINING; /* For recognizing PIPELINING */
extern const pcre *regex_SIZE; /* For recognizing SIZE settings */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
extern const pcre *regex_EARLY_PIPE; /* For recognizing PIPE_CONNCT */
#endif
extern const pcre *regex_ismsgid; /* Compiled r.e. for message it */
extern BOOL srs_usehash; /* SRS use hash flag */
extern BOOL srs_usetimestamp; /* SRS use timestamp flag */
#endif
+#ifdef EXPERIMENTAL_SRS_NATIVE
+extern uschar *srs_recipient; /* SRS recipient */
+#endif
extern BOOL strict_acl_vars; /* ACL variables have to be set before being used */
extern int string_datestamp_offset;/* After insertion by string_format */
extern int string_datestamp_length;/* After insertion by string_format */
#include "exim.h"
+#if defined(TCP_FASTOPEN)
+# if defined(MSG_FASTOPEN) || defined(EXIM_TFO_CONNECTX) || defined(EXIM_TFO_FREEBSD)
+# define EXIM_SUPPORT_TFO
+# endif
+#endif
+
/*************************************************
* Create a socket *
*************************************************/
-/*************************************************
-*************************************************/
-
-#ifdef EXIM_TFO_PROBE
-void
-tfo_probe(void)
-{
-# ifdef TCP_FASTOPEN
-int sock, backlog = 5;
-
-if ( (sock = socket(SOCK_STREAM, AF_INET, 0)) < 0
- && setsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, &backlog, sizeof(backlog))
- )
- f.tcp_fastopen_ok = TRUE;
-close(sock);
-# endif
-}
-#endif
-
-
/*************************************************
* Connect socket to remote host *
*************************************************/
sigalrm_seen = FALSE;
if (timeout > 0) ALARM(timeout);
-#ifdef TCP_FASTOPEN
+#ifdef EXIM_SUPPORT_TFO
/* TCP Fast Open, if the system has a cookie from a previous call to
this peer, can send data in the SYN packet. The peer can send data
before it gets our ACK of its SYN,ACK - the latter is useful for
if (fastopen_blob && f.tcp_fastopen_ok)
{
# ifdef MSG_FASTOPEN
- /* This is a Linux implementation. It might be useable on FreeBSD; I have
- not checked. */
+ /* This is a Linux implementation. */
if ((rc = sendto(sock, fastopen_blob->data, fastopen_blob->len,
MSG_FASTOPEN | MSG_DONTWAIT, s_ptr, s_len)) >= 0)
debug_printf("Tried TCP Fast Open but apparently not enabled by sysctl\n");
goto legacy_connect;
}
-# endif
-# ifdef EXIM_TFO_CONNECTX
+
+# elif defined(EXIM_TFO_FREEBSD)
+ /* Re: https://people.freebsd.org/~pkelsey/tfo-tools/tfo-client.c */
+
+ if (setsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, &on, sizeof(on)) < 0)
+ {
+ DEBUG(D_transport)
+ debug_printf("Tried TCP Fast Open but apparently not enabled by sysctl\n");
+ goto legacy_connect;
+ }
+ if ((rc = sendto(sock, fastopen_blob->data, fastopen_blob->len, 0,
+ s_ptr, s_len)) >= 0)
+ {
+ DEBUG(D_transport|D_v)
+ debug_printf(" TFO mode connection attempt to %s, %lu data\n",
+ address, (unsigned long)fastopen_blob->len);
+ tcp_out_fastopen = fastopen_blob->len > 0 ? TFO_ATTEMPTED_DATA : TFO_ATTEMPTED_NODATA;
+ }
+
+# elif defined(EXIM_TFO_CONNECTX)
/* MacOS */
sa_endpoints_t ends = {
.sae_srcif = 0, .sae_srcaddr = NULL, .sae_srcaddrlen = 0,
# endif
}
else
-#endif /*TCP_FASTOPEN*/
+#endif /*EXIM_SUPPORT_TFO*/
{
-#if defined(TCP_FASTOPEN) && defined(MSG_FASTOPEN)
+#if defined(EXIM_SUPPORT_TFO) && !defined(EXIM_TFO_CONNECTX)
legacy_connect:
#endif
#ifndef DISABLE_OCSP
builtin_macro_create(US"_HAVE_OCSP");
#endif
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
builtin_macro_create(US"_HAVE_PIPE_CONNECT");
#endif
#ifndef DISABLE_PRDR
#ifdef SUPPORT_SPF
builtin_macro_create(US"_HAVE_SPF");
#endif
-#ifdef EXPERIMENTAL_SRS
+#if defined(EXPERIMENTAL_SRS) || defined(EXPERIMENTAL_SRS_NATIVE)
builtin_macro_create(US"_HAVE_SRS");
#endif
+#if defined(EXPERIMENTAL_SRS_NATIVE)
+ builtin_macro_create(US"_HAVE_NATIVE_SRS"); /* beware clash with _HAVE_SRS */
+#endif
#ifdef EXPERIMENTAL_ARC
builtin_macro_create(US"_HAVE_ARC");
#endif
#define ERRNO_DATA4XX (-46) /* DATA gave 4xx error */
#define ERRNO_PROXYFAIL (-47) /* Negotiation failed for proxy configured host */
#define ERRNO_AUTHPROB (-48) /* Authenticator "other" failure */
-
-#ifdef SUPPORT_I18N
-# define ERRNO_UTF8_FWD (-49) /* target not supporting SMTPUTF8 */
-#endif
- /* -50 free for re-use */
+#define ERRNO_UTF8_FWD (-49) /* target not supporting SMTPUTF8 */
+#define ERRNO_HOST_IS_LOCAL (-50) /* Transport refuses to talk to localhost */
/* These must be last, so all retry deferments can easily be identified */
#endif
{ "pid_file_path", opt_stringptr, &pid_file_path },
{ "pipelining_advertise_hosts", opt_stringptr, &pipelining_advertise_hosts },
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
{ "pipelining_connect_advertise_hosts", opt_stringptr,
&pipe_connect_advertise_hosts },
#endif
-/*************************************************
-* Drop privs for checking TLS config *
-*************************************************/
-
-/* We want to validate TLS options during readconf, but do not want to be
-root when we call into the TLS library, in case of library linkage errors
-which cause segfaults; before this check, those were always done as the Exim
-runtime user and it makes sense to continue with that.
-
-Assumes: tls_require_ciphers has been set, if it will be
- exim_user has been set, if it will be
- exim_group has been set, if it will be
-
-Returns: bool for "okay"; false will cause caller to immediately exit.
-*/
-
-#ifndef DISABLE_TLS
-static BOOL
-tls_dropprivs_validate_require_cipher(BOOL nowarn)
-{
-const uschar *errmsg;
-pid_t pid;
-int rc, status;
-void (*oldsignal)(int);
-
-/* If TLS will never be used, no point checking ciphers */
-
-if ( !tls_advertise_hosts
- || !*tls_advertise_hosts
- || Ustrcmp(tls_advertise_hosts, ":") == 0
- )
- return TRUE;
-else if (!nowarn && !tls_certificate)
- log_write(0, LOG_MAIN,
- "Warning: No server certificate defined; will use a selfsigned one.\n"
- " Suggested action: either install a certificate or change tls_advertise_hosts option");
-
-oldsignal = signal(SIGCHLD, SIG_DFL);
-
-fflush(NULL);
-if ((pid = fork()) < 0)
- log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork failed for TLS check");
-
-if (pid == 0)
- {
- /* in some modes, will have dropped privilege already */
- if (!geteuid())
- exim_setugid(exim_uid, exim_gid, FALSE,
- US"calling tls_validate_require_cipher");
-
- if ((errmsg = tls_validate_require_cipher()))
- log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
- "tls_require_ciphers invalid: %s", errmsg);
- fflush(NULL);
- exim_underbar_exit(0);
- }
-
-do {
- rc = waitpid(pid, &status, 0);
-} while (rc < 0 && errno == EINTR);
-
-DEBUG(D_tls)
- debug_printf("tls_validate_require_cipher child %d ended: status=0x%x\n",
- (int)pid, status);
-
-signal(SIGCHLD, oldsignal);
-
-return status == 0;
-}
-#endif /*DISABLE_TLS*/
-
-
-
-
/*************************************************
* Read main configuration options *
*************************************************/
"tls_%sverify_hosts is set, but tls_verify_certificates is not set",
tls_verify_hosts ? "" : "try_");
-/* This also checks that the library linkage is working and we can call
-routines in it, so call even if tls_require_ciphers is unset */
-if (!tls_dropprivs_validate_require_cipher(nowarn))
- exit(1);
-
/* Magic number: at time of writing, 1024 has been the long-standing value
used by so many clients, and what Exim used to use always, that it makes
sense to just min-clamp this max-clamp at that. */
static void
auths_init(void)
{
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
int nauths = 0;
#endif
"(%s and %s) have the same public name (%s)",
au->client ? US"client" : US"server", au->name, bu->name,
au->public_name);
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
nauths++;
#endif
}
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
f.smtp_in_early_pipe_no_auth = nauths > 16;
#endif
}
if (LOGGING(pipelining) && f.smtp_in_pipelining_advertised)
{
g = string_catn(g, US" L", 2);
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (f.smtp_in_early_pipe_used)
g = string_catn(g, US"*", 1);
else if (f.smtp_in_early_pipe_advertised)
BOOL helo_verify :1;
BOOL helo_seen :1;
BOOL helo_accept_junk :1;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
BOOL pipe_connect_acceptable :1;
#endif
BOOL rcpt_smtp_response_same :1;
}
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
static BOOL
pipeline_connect_sends(void)
{
/* Now write the string */
+if (
#ifndef DISABLE_TLS
-if (tls_in.active.sock >= 0)
- {
- if (tls_write(NULL, gs.s, gs.ptr, more) < 0)
- smtp_write_error = -1;
- }
-else
+ tls_in.active.sock >= 0 ? (tls_write(NULL, gs.s, gs.ptr, more) < 0) :
#endif
-
-if (fprintf(smtp_out, "%s", gs.s) < 0) smtp_write_error = -1;
+ (fwrite(gs.s, gs.ptr, 1, smtp_out) == 0)
+ )
+ smtp_write_error = -1;
}
/* This function isn't currently used within Exim (it detects errors when it
tries to read the next SMTP input), but is available for use in local_scan().
-For non-TLS connections, it flushes the output and checks for errors. For
-TLS-connections, it checks for a previously-detected TLS write error.
+It flushes the output and checks for errors.
Arguments: none
Returns: 0 for no error; -1 after an error
smtp_fflush(void)
{
if (tls_in.active.sock < 0 && fflush(smtp_out) != 0) smtp_write_error = -1;
+
+if (
+#ifndef DISABLE_TLS
+ tls_in.active.sock >= 0 ? (tls_write(NULL, NULL, 0, FALSE) < 0) :
+#endif
+ (fflush(smtp_out) != 0)
+ )
+ smtp_write_error = -1;
+
return smtp_write_error;
}
static void
tfo_in_check(void)
{
-# ifdef TCP_INFO
+# ifdef __FreeBSD__
+int is_fastopen;
+socklen_t len = sizeof(is_fastopen);
+
+/* The tinfo TCPOPT_FAST_OPEN bit seems unreliable, and we don't see state
+TCP_SYN_RCV (as of 12.1) so no idea about data-use. */
+
+if (getsockopt(fileno(smtp_out), IPPROTO_TCP, TCP_FASTOPEN, &is_fastopen, &len) == 0)
+ {
+ if (is_fastopen)
+ {
+ DEBUG(D_receive)
+ debug_printf("TFO mode connection (TCP_FASTOPEN getsockopt)\n");
+ f.tcp_in_fastopen = TRUE;
+ }
+ }
+else DEBUG(D_receive)
+ debug_printf("TCP_INFO getsockopt: %s\n", strerror(errno));
+
+# elif defined(TCP_INFO)
struct tcp_info tinfo;
socklen_t len = sizeof(tinfo);
if (getsockopt(fileno(smtp_out), IPPROTO_TCP, TCP_INFO, &tinfo, &len) == 0)
-#ifdef TCPI_OPT_SYN_DATA /* FreeBSD 11 does not seem to have this yet */
+# ifdef TCPI_OPT_SYN_DATA /* FreeBSD 11,12 do not seem to have this yet */
if (tinfo.tcpi_options & TCPI_OPT_SYN_DATA)
{
- DEBUG(D_receive) debug_printf("TCP_FASTOPEN mode connection (ACKd data-on-SYN)\n");
+ DEBUG(D_receive)
+ debug_printf("TFO mode connection (ACKd data-on-SYN)\n");
f.tcp_in_fastopen_data = f.tcp_in_fastopen = TRUE;
}
else
-#endif
- if (tinfo.tcpi_state == TCP_SYN_RECV)
+# endif
+ if (tinfo.tcpi_state == TCP_SYN_RECV) /* Not seen on FreeBSD 12.1 */
{
- DEBUG(D_receive) debug_printf("TCP_FASTOPEN mode connection (state TCP_SYN_RECV)\n");
+ DEBUG(D_receive)
+ debug_printf("TFO mode connection (state TCP_SYN_RECV)\n");
f.tcp_in_fastopen = TRUE;
}
+else DEBUG(D_receive)
+ debug_printf("TCP_INFO getsockopt: %s\n", strerror(errno));
# endif
}
#endif
/* Before we write the banner, check that there is no input pending, unless
this synchronisation check is disabled. */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
fl.pipe_connect_acceptable =
sender_host_address && verify_check_host(&pipe_connect_advertise_hosts) == OK;
/*XXX the ehlo-resp code does its own tls/nontls bit. Maybe subroutine that? */
smtp_printf("%s",
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
fl.pipe_connect_acceptable && pipeline_connect_sends(),
#else
FALSE,
handshake arrived. If so we must have managed a TFO. */
#ifdef TCP_FASTOPEN
-tfo_in_check();
+if (sender_host_address && !f.sender_host_notsocket) tfo_in_check();
#endif
return TRUE;
switch(rc)
{
case OK:
- if (!au->set_id || set_id) /* Complete success */
- {
- if (set_id) authenticated_id = string_copy_perm(set_id, TRUE);
- sender_host_authenticated = au->name;
- sender_host_auth_pubname = au->public_name;
- authentication_failed = FALSE;
- authenticated_fail_id = NULL; /* Impossible to already be set? */
-
- received_protocol =
- (sender_host_address ? protocols : protocols_local)
- [pextend + pauthed + (tls_in.active.sock >= 0 ? pcrpted:0)];
- *s = *ss = US"235 Authentication succeeded";
- authenticated_by = au;
- break;
- }
+ if (!au->set_id || set_id) /* Complete success */
+ {
+ if (set_id) authenticated_id = string_copy_perm(set_id, TRUE);
+ sender_host_authenticated = au->name;
+ sender_host_auth_pubname = au->public_name;
+ authentication_failed = FALSE;
+ authenticated_fail_id = NULL; /* Impossible to already be set? */
- /* Authentication succeeded, but we failed to expand the set_id string.
- Treat this as a temporary error. */
+ received_protocol =
+ (sender_host_address ? protocols : protocols_local)
+ [pextend + pauthed + (tls_in.active.sock >= 0 ? pcrpted:0)];
+ *s = *ss = US"235 Authentication succeeded";
+ authenticated_by = au;
+ break;
+ }
+
+ /* Authentication succeeded, but we failed to expand the set_id string.
+ Treat this as a temporary error. */
- auth_defer_msg = expand_string_message;
- /* Fall through */
+ auth_defer_msg = expand_string_message;
+ /* Fall through */
case DEFER:
- if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
- *s = string_sprintf("435 Unable to authenticate at present%s",
- auth_defer_user_msg);
- *ss = string_sprintf("435 Unable to authenticate at present%s: %s",
- set_id, auth_defer_msg);
- break;
+ if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
+ *s = string_sprintf("435 Unable to authenticate at present%s",
+ auth_defer_user_msg);
+ *ss = string_sprintf("435 Unable to authenticate at present%s: %s",
+ set_id, auth_defer_msg);
+ break;
case BAD64:
- *s = *ss = US"501 Invalid base64 data";
- break;
+ *s = *ss = US"501 Invalid base64 data";
+ break;
case CANCELLED:
- *s = *ss = US"501 Authentication cancelled";
- break;
+ *s = *ss = US"501 Authentication cancelled";
+ break;
case UNEXPECTED:
- *s = *ss = US"553 Initial data not expected";
- break;
+ *s = *ss = US"553 Initial data not expected";
+ break;
case FAIL:
- if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
- *s = US"535 Incorrect authentication data";
- *ss = string_sprintf("535 Incorrect authentication data%s", set_id);
- break;
+ if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
+ *s = US"535 Incorrect authentication data";
+ *ss = string_sprintf("535 Incorrect authentication data%s", set_id);
+ break;
default:
- if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
- *s = US"435 Internal error";
- *ss = string_sprintf("435 Internal error%s: return %d from authentication "
- "check", set_id, rc);
- break;
+ if (set_id) authenticated_fail_id = string_copy_perm(set_id, TRUE);
+ *s = US"435 Internal error";
+ *ss = string_sprintf("435 Internal error%s: return %d from authentication "
+ "check", set_id, rc);
+ break;
}
return rc;
#endif
switch(smtp_read_command(
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
!fl.pipe_connect_acceptable,
#else
TRUE,
host_build_sender_fullhost(); /* Rebuild */
break;
}
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
else if (!fl.pipe_connect_acceptable && !check_sync())
#else
else if (!check_sync())
sync_cmd_limit = NON_SYNC_CMD_PIPELINING;
f.smtp_in_pipelining_advertised = TRUE;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (fl.pipe_connect_acceptable)
{
f.smtp_in_early_pipe_advertised = TRUE;
#ifndef DISABLE_TLS
if (tls_in.active.sock >= 0)
(void)tls_write(NULL, g->s, g->ptr,
-# ifdef SUPPORT_PIPE_CONNECT
+# ifndef DISABLE_PIPE_CONNECT
fl.pipe_connect_acceptable && pipeline_connect_sends());
# else
FALSE);
f.dot_ends = TRUE;
DATA_BDAT: /* Common code for DATA and BDAT */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
fl.pipe_connect_acceptable = FALSE;
#endif
if (!discarded && recipients_count <= 0)
static void
tfo_out_check(int sock)
{
-# if defined(TCP_INFO) && defined(EXIM_HAVE_TCPI_UNACKED)
+# ifdef __FreeBSD__
+struct tcp_info tinfo;
+int val;
+socklen_t len = sizeof(val);
+
+/* The observability as of 12.1 is not useful as a client, only telling us that
+a TFO option was used on SYN. It could have been a TFO-R, or ignored by the
+server. */
+
+/*
+if (tcp_out_fastopen == TFO_ATTEMPTED_NODATA || tcp_out_fastopen == TFO_ATTEMPTED_DATA)
+ if (getsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, &val, &len) == 0 && val != 0) {}
+*/
+switch (tcp_out_fastopen)
+ {
+ case TFO_ATTEMPTED_NODATA: tcp_out_fastopen = TFO_USED_NODATA; break;
+ case TFO_ATTEMPTED_DATA: tcp_out_fastopen = TFO_USED_DATA; break;
+ default: break; /* compiler quietening */
+ }
+
+# else /* Linux & Apple */
+# if defined(TCP_INFO) && defined(EXIM_HAVE_TCPI_UNACKED)
struct tcp_info tinfo;
socklen_t len = sizeof(tinfo);
default: break; /* compiler quietening */
}
-# endif
+# endif
+# endif /* Linux & Apple */
}
#endif
errno = 0; /* Ensure errno starts out zero */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (sx->pending_BANNER || sx->pending_EHLO)
{
int rc;
BOOL af_tcp_fastopen:1; /* delivery usefully used TCP Fast Open */
BOOL af_tcp_fastopen_data:1; /* delivery sent SMTP commands on TCP Fast Open */
BOOL af_pipelining:1; /* delivery used (traditional) pipelining */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
BOOL af_early_pipe:1; /* delivery used connect-time pipelining */
#endif
#ifndef DISABLE_PRDR
unsigned int domain_cache[(MAX_NAMED_LIST * 2)/32];
unsigned int localpart_cache[(MAX_NAMED_LIST * 2)/32];
int mode; /* mode for local transporting to a file */
+ int basic_errno; /* status after failure */
int more_errno; /* additional error information */
/* (may need to hold a timestamp) */
unsigned int delivery_usec; /* subsecond part of delivery time */
- short int basic_errno; /* status after failure */
unsigned short child_count; /* number of child addresses */
short int return_file; /* fileno of return data file */
short int special_action; /* ( used when when deferred or failed */
be set to point to content in one of these instances, as appropriate for
the stage of the process lifetime.
-Not handled here: global tls_channelbinding_b64.
+Not handled here: global tlsp->tls_channelbinding.
*/
typedef struct exim_gnutls_state {
tls_active fd
tls_bits strength indicator
tls_certificate_verified bool indicator
- tls_channelbinding_b64 for some SASL mechanisms
+ tls_channelbinding for some SASL mechanisms
tls_ver a string
tls_cipher a string
tls_peercert pointer to library internal
tlsp->dane_verified = state->peer_dane_verified;
#endif
-/* note that tls_channelbinding_b64 is not saved to the spool file, since it's
+/* note that tls_channelbinding is not saved to the spool file, since it's
only available for use for authenticators while this TLS session is running. */
-tls_channelbinding_b64 = NULL;
+tlsp->channelbinding = NULL;
#ifdef HAVE_GNUTLS_SESSION_CHANNEL_BINDING
channel.data = NULL;
channel.size = 0;
{ DEBUG(D_tls) debug_printf("Channel binding error: %s\n", gnutls_strerror(rc)); }
else
{
+ /* Declare the taintedness of the binding info. On server, untainted; on
+ client, tainted - being the Finish msg from the server. */
+
old_pool = store_pool;
store_pool = POOL_PERM;
- tls_channelbinding_b64 = b64encode(CUS channel.data, (int)channel.size);
+ tlsp->channelbinding = b64encode_taint(CUS channel.data, (int)channel.size,
+ !!state->host);
store_pool = old_pool;
- DEBUG(D_tls) debug_printf("Have channel bindings cached for possible auth usage.\n");
+ DEBUG(D_tls) debug_printf("Have channel bindings cached for possible auth usage\n");
}
#endif
DEBUG(D_tls) debug_printf("initialising GnuTLS as a server\n");
-if ((rc = tls_init(NULL, tls_certificate, tls_privatekey,
- NULL, tls_verify_certificates, tls_crl,
- require_ciphers, &state, &tls_in, errstr)) != OK) return rc;
+ {
+#ifdef MEASURE_TIMING
+ struct timeval t0;
+ gettimeofday(&t0, NULL);
+#endif
+
+ if ((rc = tls_init(NULL, tls_certificate, tls_privatekey,
+ NULL, tls_verify_certificates, tls_crl,
+ require_ciphers, &state, &tls_in, errstr)) != OK) return rc;
+
+#ifdef MEASURE_TIMING
+ report_time_since(&t0, US"server tls_init (delta)");
+#endif
+ }
#ifdef EXPERIMENTAL_TLS_RESUME
tls_server_resume_prehandshake(state);
if (!cipher_list)
cipher_list = ob->tls_require_ciphers;
-if (tls_init(host, ob->tls_certificate, ob->tls_privatekey,
- ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl,
- cipher_list, &state, tlsp, errstr) != OK)
- return FALSE;
+ {
+#ifdef MEASURE_TIMING
+ struct timeval t0;
+ gettimeofday(&t0, NULL);
+#endif
+
+ if (tls_init(host, ob->tls_certificate, ob->tls_privatekey,
+ ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl,
+ cipher_list, &state, tlsp, errstr) != OK)
+ return FALSE;
+
+#ifdef MEASURE_TIMING
+ report_time_since(&t0, US"client tls_init (delta)");
+#endif
+ }
{
int dh_min_bits = ob->tls_dh_min_bits;
tlsp->active.sock = -1;
tlsp->active.tls_ctx = NULL;
/* Leave bits, peercert, cipher, peerdn, certificate_verified set, for logging */
-tls_channelbinding_b64 = NULL;
+tlsp->channelbinding = NULL;
if (state->xfer_buffer) store_free(state->xfer_buffer);
len number of bytes
more more data expected soon
+Calling with len zero and more unset will flush buffered writes. The buff
+argument can be null for that case.
+
Returns: the number of bytes after a successful write,
-1 after a failed write
*/
tls_in.ourcert = crt ? X509_dup(crt) : NULL;
}
+/* Channel-binding info for authenticators
+See description in https://paquier.xyz/postgresql-2/channel-binding-openssl/ */
+ {
+ uschar c, * s;
+ size_t len = SSL_get_peer_finished(server_ssl, &c, 0);
+ int old_pool = store_pool;
+
+ SSL_get_peer_finished(server_ssl, s = store_get((int)len, FALSE), len);
+ store_pool = POOL_PERM;
+ tls_in.channelbinding = b64encode_taint(CUS s, (int)len, FALSE);
+ store_pool = old_pool;
+ DEBUG(D_tls) debug_printf("Have channel bindings cached for possible auth usage\n");
+ }
+
/* Only used by the server-side tls (tls_in), including tls_getc.
Client-side (tls_out) reads (seem to?) go via
smtp_read_response()/ip_recv().
tlsp->ourcert = crt ? X509_dup(crt) : NULL;
}
+/*XXX will this work with continued-TLS? */
+/* Channel-binding info for authenticators */
+ {
+ uschar c, * s;
+ size_t len = SSL_get_finished(exim_client_ctx->ssl, &c, 0);
+ int old_pool = store_pool;
+
+ SSL_get_finished(exim_client_ctx->ssl, s = store_get((int)len, TRUE), len);
+ store_pool = POOL_PERM;
+ tlsp->channelbinding = b64encode_taint(CUS s, (int)len, TRUE);
+ store_pool = old_pool;
+ DEBUG(D_tls) debug_printf("Have channel bindings cached for possible auth usage\n");
+ }
+
tlsp->active.sock = cctx->sock;
tlsp->active.tls_ctx = exim_client_ctx;
cctx->tls_ctx = exim_client_ctx;
Returns: the number of bytes after a successful write,
-1 after a failed write
-Used by both server-side and client-side TLS.
+Used by both server-side and client-side TLS. Calling with len zero and more unset
+will flush buffered writes; buff can be null for this case.
*/
int
-tls_write(void * ct_ctx, const uschar *buff, size_t len, BOOL more)
+tls_write(void * ct_ctx, const uschar * buff, size_t len, BOOL more)
{
size_t olen = len;
int outbytes, error;
if ((more || corked))
{
-#ifdef SUPPORT_PIPE_CONNECT
+ if (!len) buff = US &error; /* dummy just so that string_catn is ok */
+
+#ifndef DISABLE_PIPE_CONNECT
int save_pool = store_pool;
store_pool = POOL_PERM;
#endif
corked = string_catn(corked, buff, len);
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
store_pool = save_pool;
#endif
DEBUG(D_tls) debug_printf("outbytes=%d error=%d\n", outbytes, error);
switch (error)
{
+ case SSL_ERROR_NONE: /* the usual case */
+ left -= outbytes;
+ buff += outbytes;
+ break;
+
case SSL_ERROR_SSL:
ERR_error_string_n(ERR_get_error(), ssl_errstring, sizeof(ssl_errstring));
log_write(0, LOG_MAIN, "TLS error (SSL_write): %s", ssl_errstring);
return -1;
- case SSL_ERROR_NONE:
- left -= outbytes;
- buff += outbytes;
- break;
-
case SSL_ERROR_ZERO_RETURN:
log_write(0, LOG_MAIN, "SSL channel closed on write");
return -1;
static BOOL ssl_xfer_error = FALSE;
#endif
-uschar *tls_channelbinding_b64 = NULL;
-
/*************************************************
* Expand string; give error on failure *
unsetenv("SSLKEYLOGFILE");
}
}
+
+/*************************************************
+* Drop privs for checking TLS config *
+*************************************************/
+
+/* We want to validate TLS options during readconf, but do not want to be
+root when we call into the TLS library, in case of library linkage errors
+which cause segfaults; before this check, those were always done as the Exim
+runtime user and it makes sense to continue with that.
+
+Assumes: tls_require_ciphers has been set, if it will be
+ exim_user has been set, if it will be
+ exim_group has been set, if it will be
+
+Returns: bool for "okay"; false will cause caller to immediately exit.
+*/
+
+BOOL
+tls_dropprivs_validate_require_cipher(BOOL nowarn)
+{
+const uschar *errmsg;
+pid_t pid;
+int rc, status;
+void (*oldsignal)(int);
+
+/* If TLS will never be used, no point checking ciphers */
+
+if ( !tls_advertise_hosts
+ || !*tls_advertise_hosts
+ || Ustrcmp(tls_advertise_hosts, ":") == 0
+ )
+ return TRUE;
+else if (!nowarn && !tls_certificate)
+ log_write(0, LOG_MAIN,
+ "Warning: No server certificate defined; will use a selfsigned one.\n"
+ " Suggested action: either install a certificate or change tls_advertise_hosts option");
+
+oldsignal = signal(SIGCHLD, SIG_DFL);
+
+fflush(NULL);
+if ((pid = fork()) < 0)
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork failed for TLS check");
+
+if (pid == 0)
+ {
+ /* in some modes, will have dropped privilege already */
+ if (!geteuid())
+ exim_setugid(exim_uid, exim_gid, FALSE,
+ US"calling tls_validate_require_cipher");
+
+ if ((errmsg = tls_validate_require_cipher()))
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
+ "tls_require_ciphers invalid: %s", errmsg);
+ fflush(NULL);
+ exim_underbar_exit(0);
+ }
+
+do {
+ rc = waitpid(pid, &status, 0);
+} while (rc < 0 && errno == EINTR);
+
+DEBUG(D_tls)
+ debug_printf("tls_validate_require_cipher child %d ended: status=0x%x\n",
+ (int)pid, status);
+
+signal(SIGCHLD, oldsignal);
+
+return status == 0;
+}
+
+
+
+
#endif /*!DISABLE_TLS*/
#endif /*!MACRO_PREDEF*/
* Write block of data *
*************************************************/
+static int
+tpt_write(int fd, uschar * block, int len, BOOL more, int options)
+{
+return
+#ifndef DISABLE_TLS
+ tls_out.active.sock == fd
+ ? tls_write(tls_out.active.tls_ctx, block, len, more) :
+#endif
+#ifdef MSG_MORE
+ more && !(options & topt_not_socket) ? send(fd, block, len, MSG_MORE) :
+#endif
+ write(fd, block, len);
+}
+
/* Subroutine called by write_chunk() and at the end of the message actually
to write a data block. Also called directly by some transports to write
additional data to the file descriptor (e.g. prefix, suffix).
*/
static BOOL
-transport_write_block_fd(transport_ctx * tctx, uschar *block, int len, BOOL more)
+transport_write_block_fd(transport_ctx * tctx, uschar * block, int len, BOOL more)
{
int rc, save_errno;
int local_timeout = transport_write_timeout;
+int connretry = 1;
int fd = tctx->u.fd;
/* This loop is for handling incomplete writes and other retries. In most
debug_printf("writing data block fd=%d size=%d timeout=%d%s\n",
fd, len, local_timeout, more ? " (more expected)" : "");
- /* This code makes use of alarm() in order to implement the timeout. This
- isn't a very tidy way of doing things. Using non-blocking I/O with select()
- provides a neater approach. However, I don't know how to do this when TLS is
- in use. */
-
- if (transport_write_timeout <= 0) /* No timeout wanted */
- {
- rc =
-#ifndef DISABLE_TLS
- tls_out.active.sock == fd ? tls_write(tls_out.active.tls_ctx, block, len, more) :
-#endif
-#ifdef MSG_MORE
- more && !(tctx->options & topt_not_socket)
- ? send(fd, block, len, MSG_MORE) :
-#endif
- write(fd, block, len);
- save_errno = errno;
- }
+ /* When doing TCP Fast Open we may get this far before the 3-way handshake
+ is complete, and write returns ENOTCONN. Detect that, wait for the socket
+ to become writable, and retry once only. */
- /* Timeout wanted. */
-
- else
+ for(;;)
{
- ALARM(local_timeout);
+ fd_set fds;
+ /* This code makes use of alarm() in order to implement the timeout. This
+ isn't a very tidy way of doing things. Using non-blocking I/O with select()
+ provides a neater approach. However, I don't know how to do this when TLS is
+ in use. */
- rc =
-#ifndef DISABLE_TLS
- tls_out.active.sock == fd ? tls_write(tls_out.active.tls_ctx, block, len, more) :
-#endif
-#ifdef MSG_MORE
- more && !(tctx->options & topt_not_socket)
- ? send(fd, block, len, MSG_MORE) :
-#endif
- write(fd, block, len);
-
- save_errno = errno;
- local_timeout = ALARM_CLR(0);
- if (sigalrm_seen)
+ if (transport_write_timeout <= 0) /* No timeout wanted */
{
- errno = ETIMEDOUT;
- return FALSE;
+ rc = tpt_write(fd, block, len, more, tctx->options);
+ save_errno = errno;
}
+ else /* Timeout wanted. */
+ {
+ ALARM(local_timeout);
+ rc = tpt_write(fd, block, len, more, tctx->options);
+ save_errno = errno;
+ local_timeout = ALARM_CLR(0);
+ if (sigalrm_seen)
+ {
+ errno = ETIMEDOUT;
+ return FALSE;
+ }
+ }
+
+ if (rc >= 0 || errno != ENOTCONN || connretry <= 0)
+ break;
+
+ FD_ZERO(&fds); FD_SET(fd, &fds);
+ select(fd+1, NULL, &fds, NULL, NULL); /* could set timout? */
+ connretry--;
}
/* Hopefully, the most common case is success, so test that first. */
if (cache_fd < 0 || fstat(cache_fd, &statbuf) != 0)
{
addr->transport_return = DEFER;
+ addr->basic_errno = errno;
addr->message = string_sprintf("Failed to %s \"once\" file %s when "
"sending message from %s transport: %s",
- (cache_fd < 0)? "open" : "stat", oncelog, tblock->name,
- strerror(errno));
+ cache_fd < 0 ? "open" : "stat", oncelog, tblock->name, strerror(errno));
goto END_OFF;
}
if (!dbm_file)
{
addr->transport_return = DEFER;
+ addr->basic_errno = errno;
addr->message = string_sprintf("Failed to open %s file %s when sending "
"message from %s transport: %s", EXIM_DBTYPE, oncelog, tblock->name,
strerror(errno));
/* We are going to send a message. Ensure any requested file is available. */
-if (file)
+if (file && !(ff = Ufopen(file, "rb")) && !ob->file_optional)
{
- ff = Ufopen(file, "rb");
- if (!ff && !ob->file_optional)
- {
- addr->transport_return = DEFER;
- addr->message = string_sprintf("Failed to open file %s when sending "
- "message from %s transport: %s", file, tblock->name, strerror(errno));
- return FALSE;
- }
+ addr->transport_return = DEFER;
+ addr->basic_errno = errno;
+ addr->message = string_sprintf("Failed to open file %s when sending "
+ "message from %s transport: %s", file, tblock->name, strerror(errno));
+ return FALSE;
}
/* Make a subprocess to send the message */
if (pid < 0)
{
addr->transport_return = DEFER;
+ addr->basic_errno = errno;
addr->message = string_sprintf("Failed to create child process to send "
"message from %s transport: %s", tblock->name, strerror(errno));
DEBUG(D_transport) debug_printf("%s\n", addr->message);
if (envlist)
{
- envlist = expand_cstring(envlist);
- if (envlist == NULL)
+ if (!(envlist = expand_cstring(envlist)))
{
addr->transport_return = DEFER;
addr->message = string_sprintf("failed to expand string \"%s\" "
if (envcount > nelem(envp) - 2)
{
addr->transport_return = DEFER;
+ addr->basic_errno = E2BIG;
addr->message = string_sprintf("too many environment settings for "
"%s transport", tblock->name);
return FALSE;
#endif
{ "hosts_override", opt_bool,
(void *)offsetof(smtp_transport_options_block, hosts_override) },
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
{ "hosts_pipe_connect", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_pipe_connect) },
#endif
.hosts_avoid_tls = NULL,
.hosts_verify_avoid_tls = NULL,
.hosts_avoid_pipelining = NULL,
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
.hosts_pipe_connect = NULL,
#endif
.hosts_avoid_esmtp = NULL,
static unsigned ehlo_response(uschar * buf, unsigned checks);
+/******************************************************************************/
+
+void
+smtp_deliver_init(void)
+{
+if (!regex_PIPELINING) regex_PIPELINING =
+ regex_must_compile(US"\\n250[\\s\\-]PIPELINING(\\s|\\n|$)", FALSE, TRUE);
+
+if (!regex_SIZE) regex_SIZE =
+ regex_must_compile(US"\\n250[\\s\\-]SIZE(\\s|\\n|$)", FALSE, TRUE);
+
+if (!regex_AUTH) regex_AUTH =
+ regex_must_compile(AUTHS_REGEX, FALSE, TRUE);
+
+#ifndef DISABLE_TLS
+if (!regex_STARTTLS) regex_STARTTLS =
+ regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
+#endif
+
+if (!regex_CHUNKING) regex_CHUNKING =
+ regex_must_compile(US"\\n250[\\s\\-]CHUNKING(\\s|\\n|$)", FALSE, TRUE);
+
+#ifndef DISABLE_PRDR
+if (!regex_PRDR) regex_PRDR =
+ regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE);
+#endif
+
+#ifdef SUPPORT_I18N
+if (!regex_UTF8) regex_UTF8 =
+ regex_must_compile(US"\\n250[\\s\\-]SMTPUTF8(\\s|\\n|$)", FALSE, TRUE);
+#endif
+
+if (!regex_DSN) regex_DSN =
+ regex_must_compile(US"\\n250[\\s\\-]DSN(\\s|\\n|$)", FALSE, TRUE);
+
+if (!regex_IGNOREQUOTA) regex_IGNOREQUOTA =
+ regex_must_compile(US"\\n250[\\s\\-]IGNOREQUOTA(\\s|\\n|$)", FALSE, TRUE);
+
+#ifndef DISABLE_PIPE_CONNECT
+if (!regex_EARLY_PIPE) regex_EARLY_PIPE =
+ regex_must_compile(US"\\n250[\\s\\-]" EARLY_PIPE_FEATURE_NAME "(\\s|\\n|$)", FALSE, TRUE);
+#endif
+}
+
+
/*************************************************
* Setup entry point *
*************************************************/
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
static uschar *
ehlo_cache_key(const smtp_context * sx)
{
smtp_transport_options_block * ob = sx->conn_args.ob;
int yield = 0;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
int rc;
if ((rc = smtp_reap_early_pipe(sx, &count)) != OK)
return rc == FAIL ? -4 : -5;
host_item * host = sx->conn_args.host; /* host to deliver to */
smtp_transport_options_block * ob = sx->conn_args.ob; /* transport options */
int require_auth = verify_check_given_host(CUSS &ob->hosts_require_auth, host);
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
unsigned short authbits = tls_out.active.sock >= 0
? sx->ehlo_resp.crypted_auths : sx->ehlo_resp.cleartext_auths;
#endif
if ( sx->esmtp
&&
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
sx->early_pipe_active ? authbits
:
#endif
uschar * names = NULL;
expand_nmax = -1; /* reset */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (!sx->early_pipe_active)
#endif
names = string_copyn(expand_nstring[1], expand_nlength[1]);
DEBUG(D_transport) debug_printf("scanning authentication mechanisms\n");
fail_reason = US"no common mechanisms were found";
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (sx->early_pipe_active)
{
/* Scan our authenticators (which support use by a client and were offered
&& pcre_exec(regex_SIZE, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
checks &= ~OPTION_SIZE;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if ( checks & OPTION_EARLY_PIPE
&& pcre_exec(regex_EARLY_PIPE, NULL, CS buf, bsize, 0,
PCRE_EOPT, NULL, 0) < 0)
if (chunk_size > 0)
{
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
BOOL new_conn = !!(sx->outblock.conn_args);
#endif
if((cmd_count = smtp_write_command(sx,
) < 0) return ERROR;
if (flags & tc_chunk_last)
data_command = string_copy(big_buffer); /* Save for later error message */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
/* That command write could have been the one that made the connection.
Copy the fd from the client conn ctx (smtp transport specific) to the
generic transport ctx. */
case -5: errno = ERRNO_TLSFAILURE;
return DEFER;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
case -4: /* non-2xx for pipelined banner or EHLO */
#endif
case -1: /* Timeout on RCPT */
sx->dane_required =
verify_check_given_host(CUSS &ob->hosts_require_dane, sx->conn_args.host) == OK;
#endif
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
sx->early_pipe_active = sx->early_pipe_ok = FALSE;
sx->ehlo_resp.cleartext_features = sx->ehlo_resp.crypted_features = 0;
sx->pending_BANNER = sx->pending_EHLO = FALSE;
sx->inblock.cctx = sx->outblock.cctx = &sx->cctx;
sx->avoid_option = sx->peer_offered = smtp_peer_options = 0;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if ( verify_check_given_host(CUSS &ob->hosts_pipe_connect,
sx->conn_args.host) == OK)
if (!sx->smtps)
{
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (sx->early_pipe_active)
{
sx->pending_BANNER = TRUE; /* sync_responses() must eventually handle */
if (sx->esmtp)
{
if (smtp_write_command(sx,
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
sx->early_pipe_active ? SCMD_BUFFER :
#endif
SCMD_FLUSH,
goto SEND_FAILED;
sx->esmtp_sent = TRUE;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (sx->early_pipe_active)
{
sx->pending_EHLO = TRUE;
DEBUG(D_transport)
debug_printf("not sending EHLO (host matches hosts_avoid_esmtp)\n");
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (!sx->early_pipe_active)
#endif
if (!sx->esmtp)
if (sx->esmtp || sx->lmtp)
{
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (!sx->early_pipe_active)
#endif
{
sx->peer_offered = ehlo_response(sx->buffer,
OPTION_TLS /* others checked later */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
| (sx->early_pipe_ok
? OPTION_IGNQ
| OPTION_CHUNKING | OPTION_PRDR | OPTION_DSN | OPTION_PIPE | OPTION_SIZE
)
#endif
);
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (sx->early_pipe_ok)
{
sx->ehlo_resp.cleartext_features = sx->peer_offered;
if (smtp_write_command(sx, SCMD_FLUSH, "STARTTLS\r\n") < 0)
goto SEND_FAILED;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
/* If doing early-pipelining reap the banner and EHLO-response but leave
the response for the STARTTLS we just sent alone. */
goto SEND_QUIT;
}
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
/* For SMTPS there is no cleartext early-pipe; use the crypted permission bit.
We're unlikely to get the group sent and delivered before the server sends its
banner, but it's still worth sending as a group.
/* For SMTPS we need to wait for the initial OK response. */
if (sx->smtps)
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (sx->early_pipe_active)
{
sx->pending_BANNER = TRUE;
}
if (smtp_write_command(sx,
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
sx->early_pipe_active ? SCMD_BUFFER :
#endif
SCMD_FLUSH,
"%s %s\r\n", greeting_cmd, sx->helo_data) < 0)
goto SEND_FAILED;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (sx->early_pipe_active)
sx->pending_EHLO = TRUE;
else
{
if (sx->esmtp || sx->lmtp)
{
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (!sx->early_pipe_active)
#endif
{
sx->peer_offered = ehlo_response(sx->buffer,
0 /* no TLS */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
| (sx->lmtp && ob->lmtp_ignore_quota ? OPTION_IGNQ : 0)
| OPTION_DSN | OPTION_PIPE | OPTION_SIZE
| OPTION_CHUNKING | OPTION_PRDR | OPTION_UTF8
| (ob->size_addition >= 0 ? OPTION_SIZE : 0)
#endif
);
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (tls_out.active.sock >= 0)
sx->ehlo_resp.crypted_features = sx->peer_offered;
#endif
DEBUG(D_transport) debug_printf("%susing DSN\n",
sx->peer_offered & OPTION_DSN ? "" : "not ");
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if ( sx->early_pipe_ok
&& !sx->early_pipe_active
&& tls_out.active.sock >= 0
case -2: return -2; /* non-MAIL read i/o error */
default: return -1; /* any MAIL error */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
case -4: return -1; /* non-2xx for pipelined banner or EHLO */
case -5: return -1; /* TLS first-read error */
#endif
&& *transport_filter_argv
&& **transport_filter_argv
&& sx.peer_offered & OPTION_CHUNKING
+#ifndef DISABLE_DKIM
+ /* When dkim signing, chunking is handled even with a transport-filter */
+ && !(ob->dkim.dkim_private_key && ob->dkim.dkim_domain && ob->dkim.dkim_selector)
+ && !ob->dkim.force_bodyhash
+#endif
)
{
sx.peer_offered &= ~OPTION_CHUNKING;
case -1: goto END_OFF; /* Timeout on RCPT */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
case -5: /* TLS first-read error */
case -4: HDEBUG(D_transport)
debug_printf("failed reaping pipelined cmd responses\n");
case -1: goto END_OFF; /* Timeout on RCPT */
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
case -5: /* TLS first-read error */
case -4: HDEBUG(D_transport)
debug_printf("failed reaping pipelined cmd responses\n");
if (tcp_out_fastopen >= TFO_USED_DATA) setflag(addr, af_tcp_fastopen_data);
}
if (sx.pipelining_used) setflag(addr, af_pipelining);
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (sx.early_pipe_active) setflag(addr, af_early_pipe);
#endif
#ifndef DISABLE_PRDR
else
{
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
/* If we were early-pipelinng and the actual EHLO response did not match
the cached value we assumed, we could have detected it and passed a
custom errno through to here. It would be nice to RSET and retry right
{
for (address_item * addr = addrlist; addr; addr = addr->next)
{
- addr->basic_errno = 0;
+ addr->basic_errno = ERRNO_HOST_IS_LOCAL;
addr->message = string_sprintf("%s transport found host %s to be "
"local", tblock->name, host->name);
}
uschar *hosts_avoid_tls;
uschar *hosts_verify_avoid_tls;
uschar *hosts_avoid_pipelining;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
uschar *hosts_pipe_connect;
#endif
uschar *hosts_avoid_esmtp;
BOOL smtps:1;
BOOL ok:1;
BOOL setting_up:1;
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
BOOL early_pipe_ok:1;
BOOL early_pipe_active:1;
#endif
#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
BOOL dane_required:1;
#endif
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
BOOL pending_BANNER:1;
BOOL pending_EHLO:1;
#endif
uschar * smtp_greeting;
uschar * helo_response;
#endif
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
ehlo_resp_precis ehlo_resp;
#endif
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
"callout_random_local_part: %s", expand_string_message);
+ /* Compile regex' used by client-side smtp */
+
+ smtp_deliver_init();
+
/* Default the connect and overall callout timeouts if not set, and record the
time we are starting so that we can enforce it. */
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
address_reply:
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
send_to_server:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
# End
t1:
driver = smtp
hosts = V4NET.0.0.0
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
remote_smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
dummy:
driver = smtp
+ hosts_try_fastopen = :
# End
driver = smtp
connect_timeout = 1s
port = PORT_D
+ hosts_try_fastopen = :
smtp_connect_refused:
driver = smtp
port = PORT_N
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_N
+ hosts_try_fastopen = :
RETRY
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
filtered_smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
transport_filter = /bin/sh -c "echo 'X-Filtered: just checking'; cat"
local_delivery:
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
local_delivery:
driver = pipe
command_timeout = 1s
final_timeout = 1s
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_N
+ hosts_try_fastopen = :
allow_localhost
smtp:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
connect_timeout = 1s
local_delivery:
driver = smtp
interface = HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
debug_print = transport_name <$transport_name>
smtp:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
T1:
driver = smtp
+ hosts_try_fastopen = :
#----- ACL -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
remote_smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
appendfile:
driver = appendfile
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
max_rcpt = 1
connection_max_messages = 1
port = PORT_S
+ hosts_try_fastopen = :
smtp2:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
smtp3:
driver = smtp
max_rcpt = 2
connection_max_messages = 1
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
transport_filter = \
/bin/sh -c \
"cat >/dev/null; printf Line-without-end || /bin/echo -n Line-without-end"
pass_on:
driver = smtp
+ hosts_try_fastopen = :
connect_timeout = 1s
pass_on:
driver = smtp
+ hosts_try_fastopen = :
connect_timeout = 1s
gethostbyname
hosts = NEXTHOST
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
hosts = 127.0.0.1
allow_localhost
port = PORT_S
+ hosts_try_fastopen = :
transport_filter = /bin/sh -c 'cat; exit 99'
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
allow_localhost
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
allow_localhost
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
command_timeout = 1s
local_delivery:
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
allow_localhost
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
protocol = LMTP
lmtp_ignore_quota = IGNORE_QUOTA
AUTHS
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
max_rcpt = 0
HAP
command_timeout = 1s
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
HAP
max_rcpt = 1000
command_timeout = 1s
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
debug_print = T: $transport_name (${acl {expand_check}})
smtp:
driver = smtp
+ hosts_try_fastopen = :
local_delivery:
driver = appendfile
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
lmtp:
driver = smtp
driver = smtp
fallback_hosts = HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
127.0.0.1 : 127.0.0.1 : HOSTIPV4 : \
127.0.0.1 : 127.0.0.1 : HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
remote:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
# ----- Retry -----
headers_rewrite = *@domain1 $1-rewrite@domain2 f :\
*@domain1 $1-other@domain2
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
max_rcpt = 1
allow_localhost
return_path = pqr=$local_part+$domain@verp.domain
connect_timeout = 1s
fallback_hosts = ten-2.test.ex
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
begin retry
remote_delivery:
driver = smtp
hosts = V4NET.0.0.1
+ hosts_try_fastopen = :
bad_return:
driver = smtp
hosts = V4NET.0.0.0
+ hosts_try_fastopen = :
return_path = ${if
no_hosts:
t1:
driver = smtp
+ hosts_try_fastopen = :
# ----- Routers -----
t1:
driver = smtp
+ hosts_try_fastopen = :
# ----- Routers -----
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
# ----- Routers -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
max_rcpt = 2
connection_max_messages = 3
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
max_rcpt = 2
connection_max_messages = 3
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
max_rcpt = 1
connection_max_messages = 1
serialize_hosts = 127.0.0.1
t2:
driver = smtp
+ hosts_try_fastopen = :
debug_print = \$host=$host \$host_address=$host_address
# End
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
max_rcpt = 2
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
allow_localhost
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
# End
hosts = 127.0.0.1
hosts_override
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
hosts = 127.0.0.1
hosts_override
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
# End
remote_smtp:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
hosts = 127.0.0.1
allow_localhost
port = PORT_N
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
+ hosts_try_fastopen = :
t2:
driver = smtp
+ hosts_try_fastopen = :
t3:
driver = smtp
+ hosts_try_fastopen = :
t4:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
hosts = 127.0.0.1
allow_localhost
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
hosts = 127.0.0.1
allow_localhost
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
+ hosts_try_fastopen = :
t2:
driver = appendfile
t1:
driver = smtp
+ hosts_try_fastopen = :
t2:
driver = appendfile
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
t1:
driver = smtp
+ hosts_try_fastopen = :
t2:
driver = appendfile
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
connect_timeout = 1s
hosts_max_try = HOSTS_MAX_TRY
port = PORT_N
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
ut4:
driver = smtp
hosts = 127.0.0.1
+ hosts_try_fastopen = :
port = PORT_S
allow_localhost
max_rcpt = 1
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
max_rcpt = 1
disable_logging
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
max_rcpt = 1
disable_logging
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
max_rcpt = 1
disable_logging
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
driver = smtp
hosts_max_try = 1
port = PORT_S
+ hosts_try_fastopen = :
connect_timeout = 2s
address_retry_include_sender = false
t1:
driver = smtp
+ hosts_try_fastopen = :
t2:
driver = smtp
+ hosts_try_fastopen = :
# End
t2:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
hosts = 127.0.0.1
allow_localhost
port = PORT_S
+ hosts_try_fastopen = :
t2:
driver = smtp
hosts_override
allow_localhost
port = PORT_S
+ hosts_try_fastopen = :
# End
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
t1:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
hosts_avoid_esmtp = 127.0.0.1
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
AFFIX
driver = smtp
hosts = <; 127.0.0.1 ;
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
# End
t1:
driver = smtp
+ hosts_try_fastopen = :
t1:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
transport_filter = /bin/cat
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
connect_timeout = 999999s
t1:
driver = smtp
hosts = 127.0.0.1
+ hosts_try_fastopen = :
allow_localhost
port = ${if queue_running{PORT_D2}{PORT_D}}EXTRA
smtp:
driver = smtp
+ hosts_try_fastopen = :
connect_timeout = 1s
hosts_max_try = HOSTS_MAX_TRY
t1:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
connect_timeout = 1s
allow_localhost
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
driver = smtp
port = PORT_S
interface = 99.99.99.99
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
hosts = ${if !eq {$sender_host_address}{} {V4NET.0.0.2} \
{${if eq {127.0.0.1}{$local_part} {127.0.0.1} \
{${if eq {V4NET.0.0.1}{$local_part} {V4NET.0.0.1}}}}}}
driver = smtp
port = PORT_S
hosts = 127.0.0.1
+ hosts_try_fastopen = :
allow_localhost
connect_timeout = 1s
t1:
driver = smtp
hosts = 127.0.0.1
+ hosts_try_fastopen = :
allow_localhost
t2:
driver = smtp
hosts = 127.0.0.1 : HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
command_timeout = 1s
driver = smtp
hosts = V4NET.9.8.7
port = PORT_S
+ hosts_try_fastopen = :
t3:
driver = appendfile
driver = smtp
hosts = V4NET.10.10.10
port = nonexistent
+ hosts_try_fastopen = :
# End
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
final_timeout = 1s
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
transport_filter = /non/existent/file
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
# End
driver = smtp
hosts = 127.0.0.1 : 127.0.0.1 : 127.0.0.1 : 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
hosts_max_try = 1
HARDLIMIT
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
rcpt_include_affixes
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
# End
driver = smtp
hosts = 127.0.0.1 : non-exist.test.ex
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
# End
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
data_timeout = 1s
t1:
driver = smtp
+ hosts_try_fastopen = :
hosts_max_try = 20
allow_localhost
allow_localhost
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
protocol = LMTP
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
helo_data = ${if eq{$domain}{yes1}{localhost}{aname}}
hosts_max_try = 1
allow_localhost
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
hosts = 127.0.0.1
allow_localhost
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
hosts = HOSTIPV4 : thishost.test.ex
allow_localhost
port = PORT_D
+ hosts_try_fastopen = :
# ----- Retry -----
driver = smtp
hosts = 127.0.0.1 : HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
helo_data = \
${if eq{$sending_ip_address}{127.0.0.1}{Tweedledum}{Tweedledee}} \
t1:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
hosts = 127.0.0.1
allow_localhost
command_timeout = 2s
smtp:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
command_timeout = 2s
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
+ hosts_try_fastopen = :
t2:
driver = appendfile
t1:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
# End
remote_smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
remote_smtp_hdrs:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
headers_only
smtp:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
OPTION
max_parallel = 1
driver = smtp
interface = HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
debug_print = transport_name <$transport_name>
t1:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
# assumes that HOSTIPV4 can send to 127.0.0.1
interface = ${if eq {$sender_address_domain}{dustybelt.tld} {127.0.0.1}{HOSTIPV4}}
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
# assumes that HOSTIPV4 can sent to 127.0.0.1
interface = ${if eq {$sender_address_domain}{dustybelt.tld} {127.0.0.1}{HOSTIPV4}}
out:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
# End
hosts = 127.0.0.1
port = PORT_D
interface = 127.0.0.1
+ hosts_try_fastopen = :
t2:
driver = smtp
hosts = 127.0.0.1
port = PORT_D
interface = HOSTIPV4
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
max_rcpt = 1
connection_max_messages = 1
max_parallel = 2
remote_smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
event_action = ${acl {ev_log}}
+ hosts_try_fastopen = :
bad_tpt:
driver = smtp
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
command_timeout = 2s
final_timeout = 2s
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
command_timeout = 2s
final_timeout = 2s
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
command_timeout = 2s
final_timeout = 2s
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
command_timeout = 2s
final_timeout = 2s
driver = smtp
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
allow_localhost
remote_smtp_dkim:
driver = smtp
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
allow_localhost
.ifdef OPT
allow_localhost
hosts = ${if eq {$local_part}{user4} {127.0.0.1} {<; ::1}}
port = PORT_D
+ hosts_try_fastopen = :
interface = <; ::1 ; HOSTIPV4
send_to_server2:
allow_localhost
hosts = ${if eq {$local_part}{user4} {127.0.0.1} {<; ::1}}
port = PORT_D
+ hosts_try_fastopen = :
interface = <; HOSTIPV6 ; HOSTIPV4
send_to_server3:
allow_localhost
hosts = ${if eq {$local_part}{user4} {127.0.0.1} {<; ::1}}
port = PORT_D
+ hosts_try_fastopen = :
interface = <; ${if eq{0}{1}{HOSTIPV6}fail}
send_to_server4:
allow_localhost
hosts = ${if eq {$local_part}{user4} {127.0.0.1} {<; ::1}}
port = PORT_D
+ hosts_try_fastopen = :
interface = <; ${if eq{0}{1}{HOSTIPV6}{ }}
send_to_server5:
allow_localhost
hosts = ${if eq {$local_part}{user4} {127.0.0.1} {<; ::1}}
port = PORT_D
+ hosts_try_fastopen = :
interface = <; ${if
send_to_server:
allow_localhost
hosts = ${if eq {$local_part}{user4} {127.0.0.1} {<; ::1}}
port = PORT_D
+ hosts_try_fastopen = :
interface = ${expand:$h_interface:}
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
t1:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = DIR/aux-fixed/cert2
tls_privatekey = DIR/aux-fixed/cert2
tls_verify_certificates = DIR/aux-fixed/cert2
driver = smtp
allow_localhost
hosts = 127.0.0.1
+ hosts_try_fastopen = :
OPTION
port = PORT_D
tls_certificate = DIR/aux-fixed/cert2
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
send_to_server2:
driver = smtp
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
# End
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
send_to_server2:
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
# ----- Retry -----
driver = smtp
allow_localhost
hosts = 127.0.0.1
- hosts_avoid_tls = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_avoid_tls = 127.0.0.1
# End
driver = smtp
allow_localhost
hosts = HOSTS
- hosts_require_tls = *
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = *
# ----- Retry -----
driver = smtp
allow_localhost
hosts = HOSTIPV4
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
driver = smtp
allow_localhost
hosts = HOSTIPV4 : 127.0.0.1
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
driver = smtp
allow_localhost
hosts = HOSTIPV4
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts_override
hosts = 127.0.0.1
- hosts_noproxy_tls = PEX
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_noproxy_tls = PEX
tls_try_verify_hosts = :
# End
command_timeout = 1s
hosts_require_tls = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
driver = smtp
allow_localhost
hosts = 127.0.0.1
- hosts_nopass_tls = *
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_nopass_tls = *
# ----- Retry -----
allow_localhost
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
REQUIRE
TRYCLEAR
allow_localhost
hosts = HOSTIPV4 : 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
hosts_require_tls = HOSTIPV4
tls_require_ciphers = NORMAL:-VERS-ALL:+VERS-TLS1.2:-MAC-ALL:+SHA\
${if eq{$host}{HOSTIPV4} {384} {256} }
driver = smtp
hosts = 127.0.0.1 : HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
allow_localhost
t2:
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_sni = fred
send_to_server2:
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
# ----- Retry -----
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_sni = fred
send_to_server2:
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_sni = bill
driver = smtp
allow_localhost
hosts = HOSTIPV4
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
driver = smtp
allow_localhost
hosts = HOSTIPV4 : 127.0.0.1
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
driver = smtp
allow_localhost
hosts = HOSTIPV4
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTNAME
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTNAME
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = server1.example.com
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTNAME
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = DIR/aux-fixed/cert2
tls_privatekey = DIR/aux-fixed/cert2
tls_verify_certificates = DIR/aux-fixed/cert2
driver = smtp
allow_localhost
hosts = 127.0.0.1
+ hosts_try_fastopen = :
OPTION
port = PORT_D
tls_certificate = DIR/aux-fixed/cert2
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
send_to_server2:
driver = smtp
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
# End
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
send_to_server2:
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
# ----- Retry -----
driver = smtp
allow_localhost
hosts = 127.0.0.1
- hosts_avoid_tls = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_avoid_tls = 127.0.0.1
# End
driver = smtp
allow_localhost
hosts = HOSTS
- hosts_require_tls = *
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = *
# ----- Retry -----
driver = smtp
allow_localhost
hosts = HOSTIPV4 : 127.0.0.1
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = DIR/aux-fixed/cert2
tls_privatekey = DIR/aux-fixed/cert2
tls_require_ciphers = IDEA-CBC-MD5:\
driver = smtp
allow_localhost
hosts = HOSTIPV4
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
driver = smtp
allow_localhost
hosts = HOSTIPV4 : 127.0.0.1
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
driver = smtp
allow_localhost
hosts = HOSTIPV4
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts_override
hosts = 127.0.0.1
- hosts_noproxy_tls = PEX
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_noproxy_tls = PEX
tls_try_verify_hosts = :
# End
smtp:
driver = smtp
command_timeout = 1s
- hosts_require_tls = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
+ hosts_require_tls = 127.0.0.1
# ----- Retry -----
driver = smtp
allow_localhost
hosts = 127.0.0.1
- hosts_nopass_tls = *
port = PORT_D
+ hosts_try_fastopen = :
tls_try_verify_hosts = :
+ hosts_nopass_tls = *
# ----- Retry -----
hosts = thishost.test.ex
allow_localhost
port = PORT_D
+ hosts_try_fastopen = :
# ----- Retry -----
allow_localhost
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
REQUIRE
TRYCLEAR
driver = smtp
allow_localhost
hosts = HOSTIPV4 : 127.0.0.1
+ port = PORT_D
hosts_require_tls = HOSTIPV4
tls_require_ciphers = AES128-SHA
- port = PORT_D
+ hosts_try_fastopen = :
tls_try_verify_hosts = :
driver = smtp
hosts = 127.0.0.1 : HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
allow_localhost
tls_try_verify_hosts = :
allow_localhost
hosts = ${if eq{$local_part}{userx}{127.0.0.1}{HOSTIPV4}}
port = PORT_D
+ hosts_try_fastopen = :
tls_try_verify_hosts = :
# End
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_sni = fred
tls_try_verify_hosts = :
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_try_verify_hosts = :
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_sni = fred
hosts_require_tls = *
tls_try_verify_hosts = :
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_sni = bill
hosts_require_tls = *
tls_try_verify_hosts = :
driver = smtp
allow_localhost
hosts = HOSTIPV4
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
driver = smtp
allow_localhost
hosts = HOSTIPV4 : 127.0.0.1
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
driver = smtp
allow_localhost
hosts = HOSTIPV4
- hosts_require_tls = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_require_tls = HOSTIPV4
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTNAME
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTNAME
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = server1.example.com
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
allow_localhost
hosts = HOSTNAME
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = CERT2
tls_privatekey = CERT2
t1:
driver = smtp
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames = :
send_to_server:
driver = smtp
allow_localhost
- hosts_noproxy_tls = :
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_noproxy_tls = :
tls_try_verify_hosts = :
max_rcpt = 1
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
tls_try_verify_hosts = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/cert1
tls_verify_cert_hostnames = :
allow_localhost
hosts = 127.0.0.1
port = PORT_D2
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/cert1
tls_verify_cert_hostnames = :
hosts = 127.0.0.1
allow_localhost
port = PORT_D
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
# ----- Retry -----
smtp:
driver = smtp
+ hosts_try_fastopen = :
connect_timeout = 1s
smtp_try:
driver = smtp
- hosts_try_auth = *
port = PORT_S
+ hosts_try_fastopen = :
+ hosts_try_auth = *
authenticated_sender = ${if eq{$local_part}{forcesender}{force@x.y.z}fail}
smtp_force:
driver = smtp
- hosts_require_auth = *
port = PORT_S
+ hosts_try_fastopen = :
+ hosts_require_auth = *
# ----- Retry -----
smtp:
driver = smtp
- hosts_try_auth = *
port = PORT_S
+ hosts_try_fastopen = :
+ hosts_try_auth = *
# ----- Retry -----
smtp:
driver = smtp
+ port = PORT_S
+ hosts_try_fastopen = :
headers_add = X-TAID: >$authenticated_id<
hosts_try_auth = *
- port = PORT_S
# End
allow_localhost
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
hosts_try_auth = *
# End
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
hosts_try_auth = *
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
hosts_try_auth = *
authenticated_sender= brian
driver = smtp
allow_localhost
hosts = 127.0.0.1
+ port = PORT_D
+ hosts_try_fastopen = :
hosts_try_auth = *
hosts_noproxy_tls = PEX
- port = PORT_D
# End
driver = smtp
allow_localhost
hosts = 127.0.0.1
- hosts_try_auth = *
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_try_auth = *
# ----- Retry -----
driver = smtp
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
hosts_avoid_tls = HOSTS_AVOID_TLS
hosts_require_auth = *
allow_localhost
driver = smtp
allow_localhost
hosts = 127.0.0.1
+ port = PORT_D
+ hosts_try_fastopen = :
hosts_try_auth = *
hosts_noproxy_tls = PEX
- port = PORT_D
tls_try_verify_hosts = :
# End
driver = smtp
allow_localhost
hosts = 127.0.0.1
- hosts_try_auth = *
port = PORT_D
+ hosts_try_fastopen = :
+ hosts_try_auth = *
tls_try_verify_hosts = :
driver = smtp
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
hosts_avoid_tls = HOSTS_AVOID_TLS
tls_try_verify_hosts = :
hosts_require_auth = *
smtp_try:
driver = smtp
- hosts_try_auth = *
port = PORT_S
+ hosts_try_fastopen = :
+ hosts_try_auth = *
authenticated_sender = ${if eq{$local_part}{forcesender}{force@x.y.z}fail}
smtp_force:
driver = smtp
- hosts_require_auth = *
port = PORT_S
+ hosts_try_fastopen = :
+ hosts_require_auth = *
# ----- Retry -----
driver = smtp
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
allow_localhost
hosts_require_auth = *
driver = smtp
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
allow_localhost
tls_certificate = DIR/aux-fixed/cert2
tls_verify_certificates = DIR/aux-fixed/cert1
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
protocol = smtps
allow_localhost
tls_certificate = DIR/aux-fixed/cert2
driver = smtp
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
allow_localhost
tls_certificate = DIR/aux-fixed/cert2
tls_verify_certificates = DIR/aux-fixed/cert1
my_smtp:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
socks_proxy = 127.0.0.1 port=1080 OPT
tls_certificate = DIR/aux-fixed/cert2
tls_privatekey = DIR/aux-fixed/cert2
my_smtp:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
socks_proxy = 127.0.0.1 port=1080 OPT
tls_certificate = DIR/aux-fixed/cert2
tls_privatekey = DIR/aux-fixed/cert2
rmt_smtp:
driver = smtp
+ hosts_try_fastopen = :
.ifdef STRICT
utf8_downconvert = STRICT
.endif
rmt_smtp:
driver = smtp
+ hosts_try_fastopen = :
hosts_require_tls = *
tls_try_verify_hosts = :
rmt_smtp:
driver = smtp
+ hosts_try_fastopen = :
hosts_require_tls = *
tls_try_verify_hosts = :
acl_smtp_data = check_data
log_selector = +dkim_verbose
+dkim_verify_hashes = sha256 : sha512 : sha1
queue_only
queue_run_in_order
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
dkim_domain = test.ex
.ifdef SELECTOR
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
.ifdef FILTER
transport_filter = /bin/cat - DIR/aux-fixed/TESTNUM.mlistfooter
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
dkim_domain = ${if def:sender_address_local_part {test.ex}}
dkim_selector = sel
--- /dev/null
+# Exim test configuration 4620
+
+.include DIR/aux-var/std_conf_prefix
+
+SRS_SECRET = mysecret
+
+# ----- Main settings -----
+
+acl_smtp_rcpt = accept
+
+domainlist local_domains = test.ex
+domainlist remotesite_domains = remote.ex
+
+log_selector = +all_parents +received_recipients
+queue_only
+
+# ----- Routers -----
+
+begin routers
+
+remote_bouncer:
+ driver = redirect
+ condition = ${if eq {$sender_host_address}{127.0.0.1}}
+ data = :fail: account disabled
+ allow_fail
+
+external:
+ driver = manualroute
+ domains = !+local_domains
+ route_list = remote.ex 127.0.0.1::PORT_S
+ self = send
+ transport = ${if eq {$local_part@$domain} {$original_local_part@$original_domain} \
+ {to_external} {forwarded_external}}
+
+inbound_srs:
+ driver = redirect
+ senders = :
+ domains = +local_domains
+ # detect inbound bounces which are SRS'd, and decode them
+ condition = ${if inbound_srs {$local_part} {SRS_SECRET}}
+ data = $srs_recipient
+
+inbound_srs_failure:
+ driver = redirect
+ senders = :
+ domains = +local_domains
+ # detect inbound bounces which look SRS'd but are invalid
+ condition = ${if inbound_srs {$local_part} {}}
+ allow_fail
+ data = :fail: Invalid SRS recipient address
+
+
+local_redirect:
+ driver = redirect
+ local_parts = redirect
+ data = remote_user@remote.ex
+
+local:
+ driver = accept
+ transport = appendfile
+
+
+# ----- Transports -----
+
+begin transports
+
+to_external:
+ driver = smtp
+
+forwarded_external:
+ driver = smtp
+ max_rcpt = 1
+ return_path = ${srs_encode {SRS_SECRET} {$return_path} {$original_domain}}
+
+
+appendfile:
+ driver = appendfile
+ file = DIR/test-mail/$local_part
+ user = CALLER
+
+# ----- Retry -----
+
+begin retry
+
+* * F,5d,1d
+
+# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
local_delivery:
driver = appendfile
begin transports
smtp:
driver = smtp
+ hosts_try_fastopen = :
begin transports
smtp:
driver = smtp
+ hosts_try_fastopen = :
begin transports
smtp:
driver = smtp
+ hosts_try_fastopen = :
begin transports
smtp:
driver = smtp
+ hosts_try_fastopen = :
send_to_server:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
+ hosts_try_fastopen = :
other_smtp:
driver = smtp
+ hosts_try_fastopen = :
null:
driver = appendfile
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
t1:
driver = smtp
+ hosts_try_fastopen = :
# End
t1:
driver = smtp
+ hosts_try_fastopen = :
# ----- Routers -----
t1:
driver = smtp
+ hosts_try_fastopen = :
# ----- Routers -----
driver = smtp
interface = HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
headers_add = ${if def:h_X-hdr-rtr {X-hdr-tpt-new: new} {}}
smtp2:
driver = smtp
interface = HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
# End
driver = smtp
interface = HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
# End
driver = smtp
interface = HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
# End
driver = smtp
interface = HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
headers_add = ${if def:h_X-hdr-rtr {X-hdr-tpt-new: new} {}}
smtp2:
driver = smtp
interface = HOSTIPV4
port = PORT_S
+ hosts_try_fastopen = :
# End
driver = smtp
interface = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
hosts_avoid_tls = ${if eq {$address_data}{usery}{*}{:}}
hosts_verify_avoid_tls = ${if eq {$address_data}{userz}{*}{:}}
tls_try_verify_hosts = :
driver = smtp
interface = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
hosts_avoid_tls = ${if eq {$address_data}{usery}{*}{:}}
hosts_verify_avoid_tls = ${if eq {$address_data}{userz}{*}{:}}
driver = smtp
hosts = 127.0.0.1
port = PORT_S
+ hosts_try_fastopen = :
allow_localhost
hosts_try_prdr = *
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
#tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/server1.example.com/ca_chain.pem
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
#tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/server1.example.com/ca_chain.pem
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
remote_delivery:
driver = smtp
port = PORT_D
+ hosts_try_fastopen = :
hosts_require_tls = *
.ifdef _HAVE_GNUTLS
tls_require_ciphers = NONE:\
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
command_timeout = 1s
final_timeout = 1s
event_action = ${acl {logger}}
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
event_action = ${acl {logger}}
# End
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
event_action = ${acl {logger}}
# End
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = DIR/aux-fixed/exim-ca/example.com/server2.example.com/server2.example.com.pem
tls_privatekey = DIR/aux-fixed/exim-ca/example.com/server2.example.com/server2.example.com.unlocked.key
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
tls_certificate = DIR/aux-fixed/exim-ca/example.com/server2.example.com/server2.example.com.pem
tls_privatekey = DIR/aux-fixed/exim-ca/example.com/server2.example.com/server2.example.com.unlocked.key
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
#tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/server1.example.com/ca_chain.pem
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
#tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/server1.example.com/ca_chain.pem
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
hosts_require_tls = *
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
allow_localhost
hosts = 127.0.0.1
port = PORT_D
+ hosts_try_fastopen = :
helo_data = helo.data.changed
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/CA/CA.pem
tls_verify_cert_hostnames =
driver = smtp
allow_localhost
port = PORT_D
+ hosts_try_fastopen = :
hosts_try_dane = CONTROL
hosts_require_dane = HOSTIPV4
driver = smtp
allow_localhost
port = PORT_D
+ hosts_try_fastopen = :
hosts_try_dane = CONTROL
hosts_require_dane = HOSTIPV4
driver = smtp
allow_localhost
port = PORT_D
+ hosts_try_fastopen = :
# hosts_try_dane = *
hosts_require_dane = *
driver = smtp
allow_localhost
port = PORT_D
+ hosts_try_fastopen = :
hosts_try_dane = *
hosts_require_dane = HOSTIPV4
driver = smtp
allow_localhost
port = PORT_D
+ hosts_try_fastopen = :
# hosts_try_dane = *
hosts_require_dane = *
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = CDIR/CA/CA.pem
tls_verify_cert_hostnames = :
event_action = ${acl {log_resumption}}
allow_localhost
hosts = HOSTIPV4
port = PORT_D
+ hosts_try_fastopen = :
tls_verify_certificates = CDIR/CA/CA.pem
tls_verify_cert_hostnames = :
event_action = ${acl {log_resumption}}
smtp:
driver = smtp
port = PORT_S
+ hosts_try_fastopen = :
# ----- Retry -----
hosts = 127.0.0.1
hosts_override
port = PORT_D
+ hosts_try_fastopen = :
t2:
driver = appendfile
port = PORT_S
hosts = 127.0.0.1
allow_localhost
+ hosts_try_fastopen = :
# ----- Retry -----
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=localuser T=local_delivery defer (2): No such file or directory: creating lock file hitching post TESTSUITE/test-mail/subdir/userx.lock.test.ex.dddddddd.pppppppp (euid=CALLER_UID egid=CALLER_GID)
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=localuser T=local_delivery defer (EEE): No such file or directory: creating lock file hitching post TESTSUITE/test-mail/subdir/userx.lock.test.ex.dddddddd.pppppppp (euid=CALLER_UID egid=CALLER_GID)
1999-03-02 09:44:33 10HmaX-0005vi-00 == usery@test.ex R=mboxuser T=appendfile defer (-34): mailbox TESTSUITE/test-mail/../test-empty/usery does not exist, but creation outside the home directory is not permitted
1999-03-02 09:44:33 10HmaX-0005vi-00 => userz <userz@test.ex> R=mboxuser T=appendfile
1999-03-02 09:44:33 10HmaX-0005vi-00 => sub1 <sub1@test.ex> R=mboxuser T=appendfile
-1999-03-02 09:44:33 10HmaX-0005vi-00 == sub2@test.ex R=mboxuser T=appendfile defer (2): No such file or directory: creating lock file hitching post TESTSUITE/test-empty/s/sub2.lock.test.ex.dddddddd.pppppppp (euid=CALLER_UID egid=CALLER_GID)
+1999-03-02 09:44:33 10HmaX-0005vi-00 == sub2@test.ex R=mboxuser T=appendfile defer (EEE): No such file or directory: creating lock file hitching post TESTSUITE/test-empty/s/sub2.lock.test.ex.dddddddd.pppppppp (euid=CALLER_UID egid=CALLER_GID)
1999-03-02 09:44:33 10HmaX-0005vi-00 == sub3@test.ex R=mboxuser T=appendfile defer (-34): mailbox TESTSUITE/test-mail/link/sub3 does not exist, but creation outside the home directory is not permitted
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=reply T=reply defer (0): Failed to open DBM file TESTSUITE/spool when sending message from reply transport: Is a directory
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=reply T=reply defer (EEE): Is a directory: Failed to open DBM file TESTSUITE/spool when sending message from reply transport: Is a directory
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=local T=appendfile defer (6): Error: while opening named pipe TESTSUITE/test-fifo (could mean no process is reading it)
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=local T=appendfile defer (EEE): Error: while opening named pipe TESTSUITE/test-fifo (could mean no process is reading it)
1999-03-02 09:44:33 10HmaX-0005vi-00 == CALLER@test.ex R=caller T=local_delivery defer (-1)
1999-03-02 09:44:33 10HmaX-0005vi-00 Frozen
1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaY-0005vi-00 == EXIMUSER@test.ex R=caller T=local_delivery defer (13): Permission denied: creating lock file hitching post TESTSUITE/test-mail/EXIMUSER.lock.test.ex.dddddddd.pppppppp (euid=EXIM_UID egid=EXIM_GID)
+1999-03-02 09:44:33 10HmaY-0005vi-00 == EXIMUSER@test.ex R=caller T=local_delivery defer (EEE): Permission denied: creating lock file hitching post TESTSUITE/test-mail/EXIMUSER.lock.test.ex.dddddddd.pppppppp (euid=EXIM_UID egid=EXIM_GID)
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaZ-0005vi-00 == EXIMUSER@test.ex R=caller T=local_delivery defer (13): Permission denied: creating lock file hitching post TESTSUITE/test-mail/EXIMUSER.lock.test.ex.dddddddd.pppppppp (euid=EXIM_UID egid=EXIM_GID)
+1999-03-02 09:44:33 10HmaZ-0005vi-00 == EXIMUSER@test.ex R=caller T=local_delivery defer (EEE): Permission denied: creating lock file hitching post TESTSUITE/test-mail/EXIMUSER.lock.test.ex.dddddddd.pppppppp (euid=EXIM_UID egid=EXIM_GID)
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmaZ-0005vi-00 == hdefer@test.ex <useryy@test.ex> R=halias defer (-1): not just yet
1999-03-02 09:44:33 10HmaZ-0005vi-00 == defer@test.ex <userxy@test.ex> R=alias defer (-1): not just yet
-1999-03-02 09:44:33 10HmaZ-0005vi-00 == /no/such/file <file@test.ex> R=alias T=address_file defer (13): Permission denied: failed to create directories for /no/such: Permission denied
+1999-03-02 09:44:33 10HmaZ-0005vi-00 == /no/such/file <file@test.ex> R=alias T=address_file defer (EEE): Permission denied: failed to create directories for /no/such: Permission denied
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
1999-03-02 09:44:33 10HmaZ-0005vi-00 == hdefer@test.ex <useryy@test.ex> R=halias defer (-1): not just yet
1999-03-02 09:44:33 10HmaZ-0005vi-00 == defer@test.ex <userxy@test.ex> R=alias defer (-1): not just yet
-1999-03-02 09:44:33 10HmaZ-0005vi-00 == /no/such/file <file@test.ex> R=alias T=address_file defer (13): Permission denied: failed to create directories for /no/such: Permission denied
+1999-03-02 09:44:33 10HmaZ-0005vi-00 == /no/such/file <file@test.ex> R=alias T=address_file defer (EEE): Permission denied: failed to create directories for /no/such: Permission denied
1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> R=10HmaZ-0005vi-00 U=EXIMUSER P=local S=sss
1999-03-02 09:44:33 10HmbA-0005vi-00 => CALLER <CALLER@test.ex> R=localuser T=local_delivery
1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmaX-0005vi-00 H=127.0.0.1 [127.0.0.1] Connection refused
-1999-03-02 09:44:33 10HmaX-0005vi-00 == abcd@x.y.z R=all T=smtp defer (0): smtp transport found host ip4.ip4.ip4.ip4 to be local
+1999-03-02 09:44:33 10HmaX-0005vi-00 == abcd@x.y.z R=all T=smtp defer (-50): smtp transport found host ip4.ip4.ip4.ip4 to be local
1999-03-02 09:44:33 10HmaX-0005vi-00 Failed to expand return path "${if" in bad_return transport: condition name expected, but found ""
1999-03-02 09:44:33 10HmaX-0005vi-00 == bad.return@test.ex R=bad_return T=bad_return defer (-27): Failed to expand return path "${if" in bad_return transport: condition name expected, but found ""
1999-03-02 09:44:33 10HmaX-0005vi-00 == bad.return2@test.ex R=bad_return T=bad_return defer (-27): Failed to expand return path "${if" in bad_return transport: condition name expected, but found ""
-1999-03-02 09:44:33 10HmaX-0005vi-00 == bad.uid@test.ex R=bad_uid T=bad_uid defer (13): Permission denied: creating lock file hitching post TESTSUITE/test-mail/bad_uid.lock.test.ex.dddddddd.pppppppp (euid=EXIM_UID egid=EXIM_GID)
+1999-03-02 09:44:33 10HmaX-0005vi-00 == bad.uid@test.ex R=bad_uid T=bad_uid defer (EEE): Permission denied: creating lock file hitching post TESTSUITE/test-mail/bad_uid.lock.test.ex.dddddddd.pppppppp (euid=EXIM_UID egid=EXIM_GID)
1999-03-02 09:44:33 10HmaX-0005vi-00 home directory "${if rhubarb" failed to expand for exp_fail transport: unknown condition "rhubarb"
1999-03-02 09:44:33 10HmaX-0005vi-00 == exp.fail@test.ex R=exp_fail T=exp_fail defer (-27): home directory "${if rhubarb" failed to expand for exp_fail transport: unknown condition "rhubarb"
1999-03-02 09:44:33 10HmaX-0005vi-00 => userx <userx@test.ex> R=good T=local_delivery
1999-03-02 09:44:33 10HmaX-0005vi-00 Failed to expand return path "${if" in bad_return transport: condition name expected, but found ""
1999-03-02 09:44:33 10HmaX-0005vi-00 == bad.return@test.ex R=bad_return T=bad_return defer (-27): Failed to expand return path "${if" in bad_return transport: condition name expected, but found ""
1999-03-02 09:44:33 10HmaX-0005vi-00 == bad.return2@test.ex R=bad_return T=bad_return defer (-27): Failed to expand return path "${if" in bad_return transport: condition name expected, but found ""
-1999-03-02 09:44:33 10HmaX-0005vi-00 == bad.uid@test.ex R=bad_uid T=bad_uid defer (13): Permission denied: creating lock file hitching post TESTSUITE/test-mail/bad_uid.lock.test.ex.dddddddd.pppppppp (euid=EXIM_UID egid=EXIM_GID)
+1999-03-02 09:44:33 10HmaX-0005vi-00 == bad.uid@test.ex R=bad_uid T=bad_uid defer (EEE): Permission denied: creating lock file hitching post TESTSUITE/test-mail/bad_uid.lock.test.ex.dddddddd.pppppppp (euid=EXIM_UID egid=EXIM_GID)
1999-03-02 09:44:33 10HmaX-0005vi-00 home directory "${if rhubarb" failed to expand for exp_fail transport: unknown condition "rhubarb"
1999-03-02 09:44:33 10HmaX-0005vi-00 == exp.fail@test.ex R=exp_fail T=exp_fail defer (-27): home directory "${if rhubarb" failed to expand for exp_fail transport: unknown condition "rhubarb"
1999-03-02 09:44:33 End queue run: pid=pppp -qf
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=good T=pipe defer (0): too many environment settings for pipe transport
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=good T=pipe defer (EEE): Argument list too long: too many environment settings for pipe transport
1999-03-02 09:44:33 10HmaX-0005vi-00 => userx <userx@test.ex> R=all T=local_delivery
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaY-0005vi-00 == userx@test.ex R=all T=local_delivery defer (17): File exists: while renaming TESTSUITE/test-mail/temp.pppp.the.local.host.name as TESTSUITE/test-mail/userx
+1999-03-02 09:44:33 10HmaY-0005vi-00 == userx@test.ex R=all T=local_delivery defer (EEE): File exists: while renaming TESTSUITE/test-mail/temp.pppp.the.local.host.name as TESTSUITE/test-mail/userx
******** 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 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
+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 Warning: No server certificate defined; will use a selfsigned one.
- Suggested action: either install a certificate or change tls_advertise_hosts option
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@thishost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 Warning: No server certificate defined; will use a selfsigned one.
- Suggested action: either install a certificate or change tls_advertise_hosts option
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@thishost.test.ex R=abc T=t1 H=thishost.test.ex [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no DN="C=UK,O=Exim Developers,CN=thishost.test.ex" C="250 OK id=10HmaY-0005vi-00"
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
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 Warning: No server certificate defined; will use a selfsigned one.
- Suggested action: either install a certificate or change tls_advertise_hosts option
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@thishost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 Warning: No server certificate defined; will use a selfsigned one.
- Suggested action: either install a certificate or change tls_advertise_hosts option
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
1999-03-02 09:44:33 10HmaX-0005vi-00 [127.0.0.1] SSL verify error: depth=0 error=self signed certificate cert=/C=UK/O=Exim Developers/CN=thishost.test.ex
1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@thishost.test.ex R=abc T=t1 H=thishost.test.ex [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no DN="/C=UK/O=Exim Developers/CN=thishost.test.ex" C="250 OK id=10HmaY-0005vi-00"
1999-03-02 09:44:33 10HmaX-0005vi-00 failed to expand dkim_timestamps: unknown variable in "${bogus}"
1999-03-02 09:44:33 10HmaX-0005vi-00 DKIM: message could not be signed, and dkim_strict is set. Deferring message delivery.
1999-03-02 09:44:33 10HmaX-0005vi-00 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4]: send() to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] failed: failed to expand dkim_timestamps: unknown variable in "${bogus}": No such file or directory
-1999-03-02 09:44:33 10HmaX-0005vi-00 == e0@test.ex R=client T=send_to_server defer (2): No such file or directory H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4]: send() to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] failed: failed to expand dkim_timestamps: unknown variable in "${bogus}"
+1999-03-02 09:44:33 10HmaX-0005vi-00 == e0@test.ex R=client T=send_to_server defer (EEE): No such file or directory H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4]: send() to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] failed: failed to expand dkim_timestamps: unknown variable in "${bogus}"
1999-03-02 09:44:33 10HmaX-0005vi-00 ** e0@test.ex: retry timeout exceeded
1999-03-02 09:44:33 10HmaX-0005vi-00 e0@test.ex: error ignored
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for b@test.ex
1999-03-02 09:44:33 10HmaZ-0005vi-00 => b@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbA-0005vi-00"
1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for b@test.ex
-1999-03-02 09:44:33 10HmbB-0005vi-00 => b@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbC-0005vi-00"
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for c@test.ex
+1999-03-02 09:44:33 10HmbB-0005vi-00 => c@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] K C="250- 7nn byte chunk, total 7nn\\n250 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 b@test.ex
+1999-03-02 09:44:33 10HmbD-0005vi-00 => b@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbE-0005vi-00"
+1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for c@test.ex
+1999-03-02 09:44:33 10HmbF-0005vi-00 => c@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] K C="250- 7nn byte chunk, total 7nn\\n250 OK id=10HmbG-0005vi-00"
+1999-03-02 09:44:33 10HmbF-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 rcpt acl: macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
1999-03-02 09:44:33 10HmbC-0005vi-00 dkim_acl: signer: test.ex bits: 1024 h=From
1999-03-02 09:44:33 10HmbC-0005vi-00 data acl: dkim status pass
-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 DKIM=test.ex id=E10HmbB-0005vi-00@myhost.test.ex for b@test.ex
-1999-03-02 09:44:33 10HmbC-0005vi-00 => b <b@test.ex> R=server_store T=file
+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 K S=sss DKIM=test.ex id=E10HmbB-0005vi-00@myhost.test.ex for c@test.ex
+1999-03-02 09:44:33 10HmbC-0005vi-00 => c <c@test.ex> R=server_store T=file
1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
+1999-03-02 09:44:33 rcpt acl: macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbE-0005vi-00 dkim_acl: signer: test.ex bits: 1024 h=From
+1999-03-02 09:44:33 10HmbE-0005vi-00 data acl: dkim status pass
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss DKIM=test.ex id=E10HmbD-0005vi-00@myhost.test.ex for b@test.ex
+1999-03-02 09:44:33 10HmbE-0005vi-00 => b <b@test.ex> R=server_store T=file
+1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
+1999-03-02 09:44:33 rcpt acl: macro: From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive
+1999-03-02 09:44:33 10HmbG-0005vi-00 dkim_acl: signer: test.ex bits: 1024 h=From
+1999-03-02 09:44:33 10HmbG-0005vi-00 data acl: dkim status pass
+1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp K S=sss DKIM=test.ex id=E10HmbF-0005vi-00@myhost.test.ex for c@test.ex
+1999-03-02 09:44:33 10HmbG-0005vi-00 => c <c@test.ex> R=server_store T=file
+1999-03-02 09:44:33 10HmbG-0005vi-00 Completed
--- /dev/null
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss for redirect@test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 => remote_user@remote.ex <redirect@test.ex> R=external T=forwarded_external H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmaY-0005vi-00 ** remote_user@remote.ex R=remote_bouncer: account disabled
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= <> R=10HmaY-0005vi-00 U=EXIMUSER P=local S=sss for SRS0=ZZZZ=YY=the.local.host.name=CALLER@test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => CALLER <SRS0=ZZZZ=YY=the.local.host.name=CALLER@test.ex> R=local T=appendfile
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on [127.0.0.1]:PORT_S
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= SRS0=ZZZZ=YY=the.local.host.name=CALLER@test.ex H=localhost (the.local.host.name) [127.0.0.1] P=esmtp S=sss id=E10HmaX-0005vi-00@the.local.host.name for remote_user@remote.ex
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=scan T=scan defer (2): No such file or directory: scan transport accessing directory: TESTSUITE/test-mail/subdir failed with error: No such file or directory
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=scan T=scan defer (EEE): No such file or directory: scan transport accessing directory: TESTSUITE/test-mail/subdir failed with error: No such file or directory
Received: from the.local.host.name ([ip4.ip4.ip4.ip4] helo=myhost.test.ex)
by myhost.test.ex with esmtp (Exim x.yz)
(envelope-from <CALLER@myhost.test.ex>)
- id 10HmbC-0005vi-00
+ id 10HmbE-0005vi-00
for b@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=test.ex;
s=sel; h=From; bh=bzHKix52TV0ojCi2kd18gmIw/tcd5TnhO3QM+89xwyk=; b=LcQAFwKN9DL
ygZGjs=;
Received: from CALLER by myhost.test.ex with local (Exim x.yz)
(envelope-from <CALLER@myhost.test.ex>)
- id 10HmbB-0005vi-00
+ id 10HmbD-0005vi-00
for b@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
From: nobody@example.com
-Message-Id: <E10HmbB-0005vi-00@myhost.test.ex>
+Message-Id: <E10HmbD-0005vi-00@myhost.test.ex>
Sender: CALLER_NAME <CALLER@myhost.test.ex>
Date: Tue, 2 Mar 1999 09:44:33 +0000
--- /dev/null
+From CALLER@myhost.test.ex Tue Mar 02 09:44:33 1999
+Received: from the.local.host.name ([ip4.ip4.ip4.ip4] helo=myhost.test.ex)
+ by myhost.test.ex with esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbC-0005vi-00
+ for c@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=test.ex;
+ s=sel; h=From; bh=bzHKix52TV0ojCi2kd18gmIw/tcd5TnhO3QM+89xwyk=; b=LcQAFwKN9DL
+ wCbK0mcUtjmEoLaNUjwHmVrilQI1nBWJDoDUzpUl96U8YzdS/+Xut+pdS/YZf3m/Qbcw6ohO9pEmM
+ ncfURg55wr8fftAyRFA/L/svtP8h3Qv/+jv8gJ9nHyjk3z7Zmzzo8S54h9Ct9pJwkv0cpmdeLiDrL
+ ygZGjs=;
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbB-0005vi-00
+ for c@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+From: nobody@example.com
+Message-Id: <E10HmbB-0005vi-00@myhost.test.ex>
+Sender: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+content
+
+--
+This is a generic mailinglist footer, using a traditional .sig-separator line
+----
+
+From CALLER@myhost.test.ex Tue Mar 02 09:44:33 1999
+Received: from the.local.host.name ([ip4.ip4.ip4.ip4] helo=myhost.test.ex)
+ by myhost.test.ex with esmtp (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbG-0005vi-00
+ for c@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=test.ex;
+ s=sel; h=From; bh=bzHKix52TV0ojCi2kd18gmIw/tcd5TnhO3QM+89xwyk=; b=LcQAFwKN9DL
+ wCbK0mcUtjmEoLaNUjwHmVrilQI1nBWJDoDUzpUl96U8YzdS/+Xut+pdS/YZf3m/Qbcw6ohO9pEmM
+ ncfURg55wr8fftAyRFA/L/svtP8h3Qv/+jv8gJ9nHyjk3z7Zmzzo8S54h9Ct9pJwkv0cpmdeLiDrL
+ ygZGjs=;
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmbF-0005vi-00
+ for c@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+From: nobody@example.com
+Message-Id: <E10HmbF-0005vi-00@myhost.test.ex>
+Sender: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+content
+
+--
+This is a generic mailinglist footer, using a traditional .sig-separator line
+----
+
--- /dev/null
+From MAILER-DAEMON Tue Mar 02 09:44:33 1999
+Received: from EXIMUSER by the.local.host.name with local (Exim x.yz)
+ id 10HmaZ-0005vi-00
+ for SRS0=ZZZZ=YY=the.local.host.name=CALLER@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+X-Failed-Recipients: remote_user@remote.ex
+Auto-Submitted: auto-replied
+From: Mail Delivery System <Mailer-Daemon@the.local.host.name>
+To: SRS0=ZZZZ=YY=the.local.host.name=CALLER@test.ex
+References: <E10HmaX-0005vi-00@the.local.host.name>
+Content-Type: multipart/report; report-type=delivery-status; boundary=NNNNNNNNNN-eximdsn-MMMMMMMMMM
+MIME-Version: 1.0
+Subject: Mail delivery failed: returning message to sender
+Message-Id: <E10HmaZ-0005vi-00@the.local.host.name>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: text/plain; charset=us-ascii
+
+This message was created automatically by mail delivery software.
+
+A message that you sent could not be delivered to one or more of its
+recipients. This is a permanent error. The following address(es) failed:
+
+ remote_user@remote.ex
+ account disabled
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: message/delivery-status
+
+Reporting-MTA: dns; the.local.host.name
+
+Action: failed
+Final-Recipient: rfc822;remote_user@remote.ex
+Status: 5.0.0
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: message/rfc822
+
+Return-path: <SRS0=ZZZZ=YY=the.local.host.name=CALLER@test.ex>
+Received: from localhost ([127.0.0.1] helo=the.local.host.name)
+ by the.local.host.name with esmtp (Exim x.yz)
+ (envelope-from <SRS0=ZZZZ=YY=the.local.host.name=CALLER@test.ex>)
+ id 10HmaY-0005vi-00
+ for remote_user@remote.ex; Tue, 2 Mar 1999 09:44:33 +0000
+Received: from CALLER by the.local.host.name with local (Exim x.yz)
+ (envelope-from <CALLER@the.local.host.name>)
+ id 10HmaX-0005vi-00
+ for redirect@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmaX-0005vi-00@the.local.host.name>
+From: CALLER_NAME <CALLER@the.local.host.name>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+Message body
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM--
+
1999-03-02 09:44:33 Received from CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 userx@test.ex R=localuser T=local_delivery defer (2): No such file or directory: creating lock file hitching post TESTSUITE/test-mail/subdir/userx.lock.test.ex.dddddddd.pppppppp (euid=CALLER_UID egid=CALLER_GID)
+1999-03-02 09:44:33 userx@test.ex R=localuser T=local_delivery defer (EEE): No such file or directory: creating lock file hitching post TESTSUITE/test-mail/subdir/userx.lock.test.ex.dddddddd.pppppppp (euid=CALLER_UID egid=CALLER_GID)
1999-03-02 09:44:33 usery@test.ex R=mboxuser T=appendfile defer (-34): mailbox TESTSUITE/test-mail/../test-empty/usery does not exist, but creation outside the home directory is not permitted
1999-03-02 09:44:33 userz@test.ex: appendfile transport succeeded
1999-03-02 09:44:33 sub1@test.ex: appendfile transport succeeded
-1999-03-02 09:44:33 sub2@test.ex R=mboxuser T=appendfile defer (2): No such file or directory: creating lock file hitching post TESTSUITE/test-empty/s/sub2.lock.test.ex.dddddddd.pppppppp (euid=CALLER_UID egid=CALLER_GID)
+1999-03-02 09:44:33 sub2@test.ex R=mboxuser T=appendfile defer (EEE): No such file or directory: creating lock file hitching post TESTSUITE/test-empty/s/sub2.lock.test.ex.dddddddd.pppppppp (euid=CALLER_UID egid=CALLER_GID)
1999-03-02 09:44:33 sub3@test.ex R=mboxuser T=appendfile defer (-34): mailbox TESTSUITE/test-mail/link/sub3 does not exist, but creation outside the home directory is not permitted
1999-03-02 09:44:33 Received from CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 userx@test.ex R=reply T=reply defer (0): Failed to open DBM file TESTSUITE/spool when sending message from reply transport: Is a directory
+1999-03-02 09:44:33 userx@test.ex R=reply T=reply defer (EEE): Is a directory: Failed to open DBM file TESTSUITE/spool when sending message from reply transport: Is a directory
1999-03-02 09:44:33 Received from CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 userx@test.ex R=local T=appendfile defer (6): Error: while opening named pipe TESTSUITE/test-fifo (could mean no process is reading it)
+1999-03-02 09:44:33 userx@test.ex R=local T=appendfile defer (EEE): Error: while opening named pipe TESTSUITE/test-fifo (could mean no process is reading it)
-1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=scan T=scan defer (2): No such file or directory: scan transport accessing directory: TESTSUITE/test-mail/subdir failed with error: No such file or directory
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=scan T=scan defer (EEE): No such file or directory: scan transport accessing directory: TESTSUITE/test-mail/subdir failed with error: No such file or directory
last if !defined $_;
+ # SRS timestamps and signatures vary by hostname and from run to run
+
+ s/SRS0=....=..=[^=]+=[^@]+\@test.ex/SRS0=ZZZZ=YY=the.local.host.name=CALLER\@test.ex/;
+
+
# ======== Output from the "fd" program about open descriptors ========
# The statuses seem to be different on different operating systems, but
# at least we'll still be checking the number of open fd's.
s/(?<=^>>>>>>>>>>>>>>>> Exim pid=)\d+(?= terminating)/pppp/;
s/^(proxy-proc \w{5}-pid) \d+$/$1 pppp/;
+ s/^(?:\s*\d+ )(exec .* -oPX)$/pppp $1/;
# IP address lookups use gethostbyname() when IPv6 is not supported,
# and gethostbyname2() or getipnodebyname() when it is.
next if /OpenSSL compile-time version: OpenSSL \d+[\.\da-z]+/;
next if /OpenSSL runtime version: OpenSSL \d+[\.\da-z]+/;
+ # this is timing-dependent
+ next if /^OpenSSL: creating STEK$/;
+
# drop lookups
next if /^Lookups \(built-in\):/;
next if /^Loading lookup modules from/;
next if /^DKIM \[[^[]+\] (Header hash|b) computed:/;
# Not all platforms support TCP Fast Open, and the compile omits the check
- if (s/\S+ in hosts_try_fastopen\? (no \(option unset\)|yes \(matched "\*"\))\n$//)
+ if (s/\S+ in hosts_try_fastopen\? (no \(option unset\)|no \(end of list\)|yes \(matched "\*"\))\n$//)
{
chomp;
$_ .= <IN>;
# Platform differences in errno strings
s/ SMTP\(Operation timed out\)<</ SMTP(Connection timed out)<</;
+ # Platform differences for errno values (eg. Hurd)
+ s/^errno = \d+$/errno = EEE/;
+ s/^writing error \d+: /writing error EEE: /;
+
# When Exim is checking the size of directories for maildir, it uses
# the check_dir_size() function to scan directories. Of course, the order
# of the files that are obtained using readdir() varies from system to
s/(?:\[[^\]]*\]:|port )\K$parm_port_n/PORT_N/;
s/I=\[[^\]]*\]:\K\d+/ppppp/;
+ # Platform differences for errno values (eg. Hurd). Leave 0 and negative numbers alone.
+ s/R=\w+ T=\w+ defer\K \([1-9]\d*\): / (EEE): /;
}
# ======== mail ========
log_failure($log_failed_filename, $testno, $rf);
log_test($log_summary_filename, $testno, 'F') if ($force_continue);
}
- return 1 if /^c$/i && $rf !~ /paniclog/ && $rsf !~ /paniclog/;
+ return 1 if /^c$/i && $rf !~ /paniclog/ && (!defined $rsf || $rsf !~ /paniclog/);
last if (/^[sc]$/);
}
{
if (/^(?:[0-9]+: )?([a-z0-9]+): /) { $ifname = $1; }
- if (not $parm_ipv4 and /^\s*inet(?:\saddr)?:?\s?(\d+\.\d+\.\d+\.\d+)(?:\/\d+)?\s/i)
+ if (not $parm_ipv4 and /^\s*inet(?:\saddr(?:ess))?:?\s*(\d+\.\d+\.\d+\.\d+)(?:\/\d+)?\s/i)
{
# 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.
}
if ( (not $parm_ipv6 or $parm_ipv6 =~ /%/)
- and /^\s*inet6(?:\saddr)?:?\s?([abcdef\d:]+)(?:%[^ \/]+)?(?:\/\d+)?/i)
+ 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;
exim -d -DSERVER=server -bd -oX PORT_D -oP DIR/spool/exim-daemon.anotherpid
****
killdaemon
+#
+# Check for a SIGTERM daemon kill removing the pid file
+exim -d -DSERVER=server -bd -oX PORT_D -oP DIR/spool/mypidfile
+****
+sleep 1
+ls DIR/spool
+sudo perl
+open(IN, "<", "DIR/spool/mypidfile");
+while (<IN>) { kill "TERM", $_; }
+****
+sleep 1
+ls DIR/spool
+#
# which might do the job. But how to manipulate it?
#
#
+# FreeBSD: it looks like you have to compile a custom kernel, with
+# 'options TCP_RFC7413' in the config. Also set
+# 'net.inet.tcp.fastopen.server_enable=1' in /etc/sysctl.conf
+# Seems to always claim TFO used by transport, if tried.
+#
sudo perl
system ("tc qdisc add dev lo root netem delay 50ms");
****
#
#
#
-# FreeBSD: it looks like you have to compile a custom kernel, with
-# 'options TCP_RFC7413' in the config. Also set
-# 'net.inet.tcp.fastopen.enabled=1' in /etc/sysctl.conf
-# Untested.
-#
exim -DSERVER=server -bd -oX PORT_D
****
#
exim -be
badCrypt: ${if crypteq{MySecret}{}{yes}{no}}
+
+# Defined-routine, and default, crypt mehods. These fail on FreeBSD because
+# the crypt() call does something different to that on Linux. The output
+# is therefore different, and the compare fails.
+
mySecret: ${if crypteq{MySecret}{azrazPWCQJhyg}{yes}{no}}
mySecret: ${if crypteq{MySecret}{aarazPWCQJhyg}{yes}{no}}
mySecret: ${if crypteq{MySecret}{\{crypt\}azrazPWCQJhyg}{yes}{no}}
crypt16: ${if crypteq{MySecretRhubarb}{\{crypt16\}azrazPWCQJhyg}{yes}{no}}
crypt16: ${if crypteq{MySecretRhubarb}{\{CRYPT16\}azrazPWCQJhygdJWzb77lQMA}{yes}{no}}
-test: ${if crypteq{test}{\{md5\}CY9rzUYh03PK3k6DJie09g==}{yes}{no}}
-test: ${if crypteq{test}{\{MD5\}CY9rzUYh03PK3k6DJie09g==}{yes}{no}}
-test: ${if crypteq{test}{\{md5\}AY9rzUYh03PK3k6DJie09g==}{yes}{no}}
-test: ${if crypteq{test}{\{md5\}098f6bcd4621d373cade4e832627b4f6}{yes}{no}}
-test: ${if crypteq{test}{\{md5\}198f6bcd4621d373cade4e832627b4f6}{yes}{no}}
-test: ${if crypteq{test}{\{md5\}098f6bcd4621d373cade4e832627b4f}{yes}{no}}
-abc: ${if crypteq{abc}{\{sha1\}A9993E364706816ABA3E25717850C26C9CD0D89D}{yes}{no}}
-abc: ${if crypteq{abc}{\{SHA1\}A9993E364706816ABA3E25717850C26C9CD0D89D}{yes}{no}}
-abc: ${if crypteq{abc}{\{sha1\}qZk+NkcGgWq6PiVxeFDCbJzQ2J0=}{yes}{no}}
-abd: ${if crypteq{abd}{\{sha1\}A9993E364706816ABA3E25717850C26C9CD0D89D}{yes}{no}}
+# Defined-algo methods.
+
+md5: ${if crypteq{test}{\{md5\}CY9rzUYh03PK3k6DJie09g==}{yes}{no}}
+md5: ${if crypteq{test}{\{MD5\}CY9rzUYh03PK3k6DJie09g==}{yes}{no}}
+md5: ${if crypteq{test}{\{md5\}AY9rzUYh03PK3k6DJie09g==}{yes}{no}}
+md5: ${if crypteq{test}{\{md5\}098f6bcd4621d373cade4e832627b4f6}{yes}{no}}
+md5: ${if crypteq{test}{\{md5\}198f6bcd4621d373cade4e832627b4f6}{yes}{no}}
+md5: ${if crypteq{test}{\{md5\}098f6bcd4621d373cade4e832627b4f}{yes}{no}}
+
+sha1: ${if crypteq{abc}{\{sha1\}A9993E364706816ABA3E25717850C26C9CD0D89D}{yes}{no}}
+sha1: ${if crypteq{abc}{\{SHA1\}A9993E364706816ABA3E25717850C26C9CD0D89D}{yes}{no}}
+sha1: ${if crypteq{abc}{\{sha1\}qZk+NkcGgWq6PiVxeFDCbJzQ2J0=}{yes}{no}}
+sha1: ${if crypteq{abd}{\{sha1\}A9993E364706816ABA3E25717850C26C9CD0D89D}{yes}{no}}
+
-# Combinations
+# Combinations. These fail on FreeBSD as above.
y: ${if and {{crypteq{MySecret}{azrazPWCQJhyg}}{exists{/etc/passwd}}}{Y}{N}}
y: ${if or {{crypteq{MySecret}{azrazQWCQJhyg}}{exists{/etc/passwd}}}{Y}{N}}
content
****
millisleep 500
-## with transport_filter and CHUNKING
-#exim -DOPT=From -DFILTER=y -DALLOW=y -odf c@test.ex
-#From: nobody@example.com
-#
-#content
-#****
-#millisleep 500
+# with transport_filter and CHUNKING
+exim -DOPT=From -DFILTER=y -DALLOW=y -odf c@test.ex
+From: nobody@example.com
+
+content
+****
+millisleep 500
#
# for comparison, mails that should get identical sigs, though not using a transport_filter
exim -DOPT=From -odf b@test.ex
----
****
millisleep 500
-#exim -DOPT=From -DALLOW=y -odf c@test.ex
-#From: nobody@example.com
-#
-#content
-#
-#--
-#This is a generic mailinglist footer, using a traditional .sig-separator line
-#----
-#****
-#millisleep 500
+exim -DOPT=From -DALLOW=y -odf c@test.ex
+From: nobody@example.com
+
+content
+
+--
+This is a generic mailinglist footer, using a traditional .sig-separator line
+----
+****
+millisleep 500
#
#
killdaemon
--- /dev/null
+# SRS native implementation
+#
+exim -bd -DSERVER=server -oX 127.0.0.1:PORT_S
+****
+# Inject a message; will be passed on to remote and queued there
+exim -odi redirect@test.ex
+Message body
+****
+# Run the queue for the remote, will generate bounce which is queued
+exim -q
+****
+# Run the queue for the remote, will send bounce to origin
+exim -q
+****
+#
+killdaemon
--- /dev/null
+support Experimental_SRS
+feature _HAVE_NATIVE_SRS
file check: ! TESTSUITE/aux-fixed/0084.$local_part
expanded file: TESTSUITE/aux-fixed/0084.no
stat() yielded -1
-errno = 2
+errno = EEE
calling smart router
smart router called for no@myhost.test.ex
domain = myhost.test.ex
argv[0] = 'TESTSUITE/bin/iefbr14'
Writing message to pipe
writing data block fd=dddd size=sss timeout=3600
-writing error 32: Broken pipe
+writing error EEE: Broken pipe
transport error EPIPE ignored
t1 transport yielded 0
t1 transport returned OK for |TESTSUITE/bin/iefbr14
set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225
daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID
Listening...
+Exim version x.yz ....
+changed uid/gid: forcing real = effective
+ uid=uuuu gid=CALLER_GID pid=pppp
+configuration file is TESTSUITE/test-config
+admin user
+dropping to exim gid; retaining priv uid
+originator: uid=CALLER_UID gid=CALLER_GID login=CALLER name=CALLER_NAME
+daemon_smtp_port overridden by -oX:
+ <: 1225
+listening on all interfaces (IPv4) port 1225
+pid written to TESTSUITE/spool/mypidfile
+changed uid/gid: running as a daemon
+ uid=EXIM_UID gid=EXIM_GID pid=pppp
+LOG: MAIN
+ exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+set_process_info: pppp daemon(x.yz): no queue runs, listening for SMTP on port 1225
+daemon running with uid=EXIM_UID gid=EXIM_GID euid=EXIM_UID egid=EXIM_GID
+Listening...
+pppp exec TESTSUITE/eximdir/exim -DEXIM_PATH=TESTSUITE/eximdir/exim -DSERVER=server -C TESTSUITE/test-config -d=0xf7795cfd -oP TESTSUITE/spool/mypidfile -oPX
+search_tidyup called
+>>>>>>>>>>>>>>>> Exim pid=pppp (daemon) terminating with rc=0 >>>>>>>>>>>>>>>>
>>> host in helo_try_verify_hosts? no (option unset)
>>> host in helo_accept_junk_hosts? no (option unset)
>>> xxx in helo_lookup_domains? no (end of list)
->>> processing "accept" (TESTSUITE/test-config 43)
+>>> processing "accept" (TESTSUITE/test-config 44)
>>> accept: condition test succeeded in inline ACL
>>> end of inline ACL: ACCEPT
>>> host in ignore_fromline_hosts? no (option unset)
>>> using ACL "check_dkim"
->>> processing "warn" (TESTSUITE/test-config 34)
+>>> processing "warn" (TESTSUITE/test-config 35)
>>> check logwrite = signer: $dkim_cur_signer bits: $dkim_key_length
>>> = signer: test.ex bits: 1024
LOG: 10HmaX-0005vi-00 signer: test.ex bits: 1024
>>> warn: condition test succeeded in ACL "check_dkim"
->>> processing "accept" (TESTSUITE/test-config 37)
+>>> processing "accept" (TESTSUITE/test-config 38)
>>> accept: condition test succeeded in ACL "check_dkim"
>>> end of ACL "check_dkim": ACCEPT
LOG: 10HmaX-0005vi-00 DKIM: d=test.ex s=sel c=simple/simple a=rsa-sha1 b=1024 [verification succeeded]
>>> using ACL "check_data"
->>> processing "accept" (TESTSUITE/test-config 41)
+>>> processing "accept" (TESTSUITE/test-config 42)
>>> check logwrite = ${authresults {$primary_hostname}}
>>> = Authentication-Results: myhost.test.ex;
>>> dkim=pass header.d=test.ex header.s=sel header.a=rsa-sha1
host in dsn_advertise_hosts? no (option unset)
host in pipelining_advertise_hosts? yes (matched "*")
host in chunking_advertise_hosts? no (end of list)
-processing "accept" (TESTSUITE/test-config 76)
+processing "accept" (TESTSUITE/test-config 78)
check verify = recipient
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
routing "FAIL cannot route this one (FAIL)"@some.host
SMTP<< 250 Accepted
holding verify callout open for cutthrough delivery
----------- end cutthrough setup ------------
-processing "accept" (TESTSUITE/test-config 55)
+processing "accept" (TESTSUITE/test-config 56)
accept: condition test succeeded in inline ACL
end of inline ACL: ACCEPT
SMTP>> DATA
SMTP<< 250 Accepted
holding verify callout open for cutthrough delivery
----------- end cutthrough setup ------------
-processing "accept" (TESTSUITE/test-config 55)
+processing "accept" (TESTSUITE/test-config 56)
accept: condition test succeeded in inline ACL
end of inline ACL: ACCEPT
SMTP>> DATA
SMTP<< 250 Accepted
holding verify callout open for cutthrough delivery
----------- end cutthrough setup ------------
-processing "accept" (TESTSUITE/test-config 55)
+processing "accept" (TESTSUITE/test-config 56)
accept: condition test succeeded in inline ACL
end of inline ACL: ACCEPT
SMTP>> DATA
SMTP<< 250 Accepted
holding verify callout open for cutthrough delivery
----------- end cutthrough setup ------------
-processing "accept" (TESTSUITE/test-config 54)
+processing "accept" (TESTSUITE/test-config 55)
accept: condition test succeeded in inline ACL
end of inline ACL: ACCEPT
SMTP>> DATA
SMTP<< 250 Accepted
holding verify callout open for cutthrough delivery
----------- end cutthrough setup ------------
-processing "accept" (TESTSUITE/test-config 54)
+processing "accept" (TESTSUITE/test-config 55)
accept: condition test succeeded in inline ACL
end of inline ACL: ACCEPT
SMTP>> DATA
SMTP<< 250 Accepted
holding verify callout open for cutthrough delivery
----------- end cutthrough setup ------------
-processing "accept" (TESTSUITE/test-config 54)
+processing "accept" (TESTSUITE/test-config 55)
accept: condition test succeeded in inline ACL
end of inline ACL: ACCEPT
SMTP>> DATA
>>> host in helo_verify_hosts? no (option unset)
>>> host in helo_try_verify_hosts? no (option unset)
>>> host in helo_accept_junk_hosts? no (option unset)
->>> processing "accept" (TESTSUITE/test-config 86)
+>>> processing "accept" (TESTSUITE/test-config 87)
>>> check verify = recipient/callout
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing rcptuser@dane256ee.test.ex
>>> host in helo_verify_hosts? no (option unset)
>>> host in helo_try_verify_hosts? no (option unset)
>>> host in helo_accept_junk_hosts? no (option unset)
->>> processing "accept" (TESTSUITE/test-config 91)
+>>> processing "accept" (TESTSUITE/test-config 92)
>>> check verify = recipient/callout
>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>> routing rcptuser@dane256ee.test.ex
--- /dev/null
+log
+mypidfile
+log
hosts_require_auth =
hosts_try_auth =
hosts_try_chunking = *
-hosts_try_fastopen = *
+hosts_try_fastopen = :
hosts_try_prdr = *
interface = ip4.ip4.ip4.ip4
keepalive
driver = smtp
interface = ip4.ip4.ip4.ip4
port = 1224
+ hosts_try_fastopen = :
debug_print = transport_name <$transport_name>
# Exim Configuration (X)
# 1 "TESTSUITE/test-config"
driver = smtp
interface = ip4.ip4.ip4.ip4
port = 1224
+hosts_try_fastopen = :
debug_print = transport_name <$transport_name>
> badCrypt: no
+>
+> # Defined-routine, and default, crypt mehods. These fail on FreeBSD because
+> # the crypt() call does something different to that on Linux. The output
+> # is therefore different, and the compare fails.
+>
> mySecret: yes
> mySecret: no
> mySecret: yes
> crypt16: no
> crypt16: yes
>
-> test: yes
-> test: yes
-> test: no
-> test: yes
-> test: no
-> test: no
>
-> abc: yes
-> abc: yes
-> abc: yes
-> abd: no
+> # Defined-algo methods.
+>
+> md5: yes
+> md5: yes
+> md5: no
+> md5: yes
+> md5: no
+> md5: no
+>
+> sha1: yes
+> sha1: yes
+> sha1: yes
+> sha1: no
+>
>
-> # Combinations
+> # Combinations. These fail on FreeBSD as above.
>
> y: Y
> y: Y