. Copyright year. Update this (only) when changing content.
.macro copyyear
-2013
+2014
.endmacro
. ===========================================================================
+.option dnssec_request_domains dnslookup "domain list&!!" unset
+.cindex "MX record" "security"
+.cindex "DNSSEC" "MX lookup"
+.cindex "security" "MX lookup"
+.cindex "DNS" "DNSSEC"
+DNS lookups for domains matching &%dnssec_request_domains%& will be done with
+the dnssec request bit set.
+This applies to all of the SRV, MX A6, AAAA, A lookup sequence.
+
+
+
+.option dnssec_require_domains dnslookup "domain list&!!" unset
+.cindex "MX record" "security"
+.cindex "DNSSEC" "MX lookup"
+.cindex "security" "MX lookup"
+.cindex "DNS" "DNSSEC"
+DNS lookups for domains matching &%dnssec_request_domains%& will be done with
+the dnssec request bit set. Any returns not having the Authenticated Data bit
+(AD bit) set wil be ignored and logged as a host-lookup failure.
+This applies to all of the SRV, MX A6, AAAA, A lookup sequence.
+
+
+
.option mx_domains dnslookup "domain list&!!" unset
.cindex "MX record" "required to exist"
.cindex "SRV record" "required to exist"
.code
exim -bpu
.endd
-to obtain a queue listing with undelivered recipients only, and then greps the
-output to select messages that match given criteria. The following selection
-options are available:
+or (in case &*-a*& switch is specified)
+.code
+exim -bp
+.endd
+
+to obtain a queue listing, and then greps the output to select messages
+that match given criteria. The following selection options are available:
.vlist
.vitem &*-f*&&~<&'regex'&>
.vitem &*-R*&
Display messages in reverse order.
+
+.vitem &*-a*&
+Include delivered recipients in queue listing.
.endlist
There is one more option, &%-h%&, which outputs a list of options.
is a combined value of both the record presence and the result of the
analysis.
+JH/13 Fix handling of $tls_cipher et.al. in (non-verify) transport. Bug 1455.
+
+JH/14 New options dnssec_request_domains, dnssec_require_domains on the
+ dnslookup router (applying to the forward lookup).
+
+
Exim version 4.82
-----------------
3. In the ACL's the following expansion variables are available.
-proxy_host_address The src IP of the proxy server making the connection
-proxy_host_port The src port the proxy server is using
-proxy_session Boolean, yes/no, the connected host is required to use
- Proxy Protocol.
+proxy_host_address The (internal) src IP of the proxy server
+ making the connection to the Exim server.
+proxy_host_port The (internal) src port the proxy server is
+ using to connect to the Exim server.
+proxy_target_address The dest (public) IP of the remote host to
+ the proxy server.
+proxy_target_port The dest port the remote host is using to
+ connect to the proxy server.
+proxy_session Boolean, yes/no, the connected host is required
+ to use Proxy Protocol.
There is no expansion for a failed proxy session, however you can detect
it by checking if $proxy_session is true but $proxy_host is empty. As
[$sender_host_address] through proxy protocol \
host $proxy_host_address
+ # Possibly more clear
+ warn logwrite = Remote Source Address: $sender_host_address:$sender_host_port
+ logwrite = Proxy Target Address: $proxy_target_address:$proxy_target_port
+ logwrite = Proxy Internal Address: $proxy_host_address:$proxy_host_port
+ logwrite = Internal Server Address: $received_ip_address:$received_port
+
+
4. Runtime issues to be aware of:
- Since the real connections are all coming from your proxy, and the
per host connection tracking is done before Proxy Protocol is
# appropriate links, and then creating and running the main makefile in that
# directory.
-# Copyright (c) University of Cambridge, 1995 - 2013
+# Copyright (c) University of Cambridge, 1995 - 2014
# See the file NOTICE for conditions of use and distribution.
# IRIX make uses the shell that is in the SHELL variable, which often defaults
cscope.files: FRC
echo "-q" > $@
echo "-p3" >> $@
- find src Local -name "*.[cshyl]" -print \
+ find src Local OS -name "*.[cshyl]" -print \
+ -o -name "os.h*" -print \
-o -name "*akefile*" -print \
-o -name EDITME -print >> $@
* Exim Monitor *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* This module contains code for scanning the main log,
fi
if [ ".$need_this" != "." ]; then
tls_include=`pkg-config --cflags $pc_value`
+ if [ $? -ne 0 ]; then
+ echo >&2 "*** Missing pkg-config for package $pc_value (for Exim $var build option)"
+ exit 1
+ fi
tls_libs=`pkg-config --libs $pc_value`
echo "TLS_INCLUDE=$tls_include"
echo "TLS_LIBS=$tls_libs"
else
# main binary
cflags=`pkg-config --cflags $pc_value`
+ if [ $? -ne 0 ]; then
+ echo >&2 "*** Missing pkg-config for package $pc_value (for Exim $var build option)"
+ exit 1
+ fi
libs=`pkg-config --libs $pc_value`
if [ "$var" != "${var#LOOKUP_}" ]; then
echo "LOOKUP_INCLUDE += $cflags"
case $PCRE_CONFIG in
yes|YES|y|Y)
cflags=`pcre-config --cflags`
+ if [ $? -ne 0 ]; then
+ echo >&2 "*** Missing pcre-config for regular expression support"
+ exit 1
+ fi
libs=`pcre-config --libs`
if [ ".$cflags" != "." ]; then
echo "INCLUDE += $cflags"
echo "# End of pkg-config fixups"
echo
) >> $mft
+ subexit=$?
+ if [ $subexit -ne 0 ]; then
+ exit $subexit
+ fi
fi
rm -f $mftt
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for handling Access Control Lists (ACLs) */
/*
* Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
- * Copyright (c) 2006-2013 The Exim Maintainers
+ * Copyright (c) 2006-2014 The Exim Maintainers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* The default settings for Exim configuration variables. A #define without
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions concerned with running Exim as a daemon */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* The main code for delivering a message. */
* Exim - an Internet mail transport agent *
*************************************************/
/* Experimental DMARC support.
- Copyright (c) Todd Lyons <tlyons@exim.org> 2012, 2013
+ Copyright (c) Todd Lyons <tlyons@exim.org> 2012 - 2014
License: GPL */
/* Portions Copyright (c) 2012, 2013, The Trusted Domain Project;
*************************************************/
/* Experimental DMARC support.
- Copyright (c) Todd Lyons <tlyons@exim.org> 2012, 2013
+ Copyright (c) Todd Lyons <tlyons@exim.org> 2012 - 2014
License: GPL */
/* Portions Copyright (c) 2012, 2013, The Trusted Domain Project;
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for interfacing with the DNS. */
Arguments:
qualify_single TRUE to set the RES_DEFNAMES option
search_parents TRUE to set the RES_DNSRCH option
+ use_dnssec TRUE to set the RES_USE_DNSSEC option
Returns: nothing
*/
void
-dns_init(BOOL qualify_single, BOOL search_parents)
+dns_init(BOOL qualify_single, BOOL search_parents, BOOL use_dnssec)
{
res_state resp = os_get_dns_resolver_res();
# ifndef RES_USE_EDNS0
# error Have RES_USE_DNSSEC but not RES_USE_EDNS0? Something hinky ...
# endif
+if (use_dnssec)
+ resp->options |= RES_USE_DNSSEC;
if (dns_dnssec_ok >= 0)
{
if (dns_use_edns0 == 0 && dns_dnssec_ok != 0)
DEBUG(D_resolver)
debug_printf("Unable to %sset DNSSEC without resolver support.\n",
dns_dnssec_ok ? "" : "un");
+if (use_dnssec)
+ DEBUG(D_resolver)
+ debug_printf("Unable to set DNSSEC without resolver support.\n");
# endif
#endif /* DISABLE_DNSSEC */
return yield;
}
+/* vi: aw ai sw=2
+*/
/* End of dns.c */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
use strict;
-# Copyright (c) 2007-2013 University of Cambridge.
+# Copyright (c) 2007-2014 University of Cambridge.
# See the file NOTICE for conditions of use and distribution.
# Except when they appear in comments, the following placeholders in this
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
#!PERL_COMMAND -w
-# Copyright (c) 2001-2013 University of Cambridge.
+# Copyright (c) 2001-2014 University of Cambridge.
# See the file NOTICE for conditions of use and distribution.
# Perl script to generate statistics from one or more Exim log files.
$base = 62;
};
-getopts('hf:r:y:o:s:zxlibRc',\%opt);
+getopts('hf:r:y:o:s:zxlibRca',\%opt);
if ($opt{h}) { &help; exit;}
+if ($opt{a}) { $eargs = '-bp'; }
# Read message queue output into hash
&collect();
-i Message IDs only
-b Brief Format
-R Reverse order
+ -a All recipients (including delivered)
EOF
}
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
{ "proxy_host_address", vtype_stringptr, &proxy_host_address },
{ "proxy_host_port", vtype_int, &proxy_host_port },
{ "proxy_session", vtype_bool, &proxy_session },
+ { "proxy_target_address",vtype_stringptr, &proxy_target_address },
+ { "proxy_target_port", vtype_int, &proxy_target_port },
#endif
{ "prvscheck_address", vtype_stringptr, &prvscheck_address },
{ "prvscheck_keynum", vtype_stringptr, &prvscheck_keynum },
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
#ifndef USE_GNUTLS
extern BOOL tls_openssl_options_parse(uschar *, long *);
#endif
-#endif
+#endif /*SUPPORT_TLS*/
/* Everything else... */
#endif
extern dns_address *dns_address_from_rr(dns_answer *, dns_record *);
extern void dns_build_reverse(uschar *, uschar *);
-extern void dns_init(BOOL, BOOL);
+extern void dns_init(BOOL, BOOL, BOOL);
extern int dns_basic_lookup(dns_answer *, uschar *, int);
extern BOOL dns_is_secure(dns_answer *);
extern int dns_lookup(dns_answer *, uschar *, int, uschar **);
extern void host_build_sender_fullhost(void);
extern BOOL host_find_byname(host_item *, uschar *, int, uschar **, BOOL);
extern int host_find_bydns(host_item *, uschar *, int, uschar *, uschar *,
- uschar *,uschar **, BOOL *);
+ uschar *, uschar *, uschar *, uschar **, BOOL *);
extern ip_address_item *host_find_interfaces(void);
extern BOOL host_is_in_net(uschar *, uschar *, int);
extern BOOL host_is_tls_on_connect_port(int);
extern uschar *strstric(uschar *, uschar *, BOOL);
extern uschar *tod_stamp(int);
+extern void tls_modify_variables(tls_support *);
extern BOOL transport_check_waiting(uschar *, uschar *, int, uschar *,
BOOL *);
extern void transport_init(void);
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* All the global variables are defined together in this one module, so
uschar *proxy_required_hosts = US"";
BOOL proxy_session = FALSE;
BOOL proxy_session_failed = FALSE;
+uschar *proxy_target_address = US"";
+int proxy_target_port = 0;
#endif
uschar *prvscheck_address = NULL;
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Almost all the global variables are defined together in this one header, so
extern BOOL prod_requires_admin; /* TRUE if prodding requires admin */
#ifdef EXPERIMENTAL_PROXY
-extern uschar *proxy_host_address; /* IP of proxy server */
-extern int proxy_host_port; /* Port of proxy server */
+extern uschar *proxy_host_address; /* IP of host being proxied */
+extern int proxy_host_port; /* Port of host being proxied */
extern uschar *proxy_required_hosts; /* Hostlist which (require) use proxy protocol */
extern BOOL proxy_session; /* TRUE if receiving mail from valid proxy */
extern BOOL proxy_session_failed; /* TRUE if required proxy negotiation failed */
+extern uschar *proxy_target_address; /* IP of proxy server inbound */
+extern int proxy_target_port; /* Port of proxy server inbound */
#endif
extern uschar *prvscheck_address; /* Set during prvscheck expansion item */
{
if (strcmpic(ordername, US"bydns") == 0)
{
- dns_init(FALSE, FALSE);
+ dns_init(FALSE, FALSE, FALSE); /*XXX dnssec? */
dns_build_reverse(sender_host_address, buffer);
rc = dns_lookup(&dnsa, buffer, T_PTR, NULL);
some circumstances when the get..byname() function actually calls the DNS. */
dns_init((flags & HOST_FIND_QUALIFY_SINGLE) != 0,
- (flags & HOST_FIND_SEARCH_PARENTS) != 0);
+ (flags & HOST_FIND_SEARCH_PARENTS) != 0,
+ FALSE); /*XXX dnssec? */
/* In an IPv6 world, unless IPv6 has been disabled, we need to scan for both
kinds of address, so go round the loop twice. Note that we have ensured that
fully_qualified_name if not NULL, return fully qualified name here if
the contents are different (i.e. it must be preset
to something)
+ dnnssec_require if TRUE check the DNS result AD bit
Returns: HOST_FIND_FAILED couldn't find A record
HOST_FIND_AGAIN try again later
static int
set_address_from_dns(host_item *host, host_item **lastptr,
- uschar *ignore_target_hosts, BOOL allow_ip, uschar **fully_qualified_name)
+ uschar *ignore_target_hosts, BOOL allow_ip, uschar **fully_qualified_name,
+ BOOL dnssec_require)
{
dns_record *rr;
host_item *thishostlast = NULL; /* Indicates not yet filled in anything */
if (rc != DNS_NOMATCH && rc != DNS_NODATA) v6_find_again = TRUE;
continue;
}
+ if (dnssec_require && !dns_is_secure(&dnsa))
+ {
+ log_write(L_host_lookup_failed, LOG_MAIN, "dnssec fail on %s for %.256s",
+ i>1 ? "A6" : i>0 ? "AAAA" : "A", host->name);
+ continue;
+ }
/* Lookup succeeded: fill in the given host item with the first non-ignored
address found; create additional items for any others. A single A6 record
srv_service when SRV used, the service name
srv_fail_domains DNS errors for these domains => assume nonexist
mx_fail_domains DNS errors for these domains => assume nonexist
+ dnssec_request_domains => make dnssec request
+ dnssec_require_domains => ditto and nonexist failures
fully_qualified_name if not NULL, return fully-qualified name
removed set TRUE if local host was removed from the list
int
host_find_bydns(host_item *host, uschar *ignore_target_hosts, int whichrrs,
uschar *srv_service, uschar *srv_fail_domains, uschar *mx_fail_domains,
+ uschar *dnssec_request_domains, uschar *dnssec_require_domains,
uschar **fully_qualified_name, BOOL *removed)
{
host_item *h, *last;
int yield;
dns_answer dnsa;
dns_scan dnss;
+BOOL dnssec_request = match_isinlist(host->name, &dnssec_request_domains,
+ 0, NULL, NULL, MCL_DOMAIN, TRUE, NULL) == OK;
+BOOL dnssec_require = match_isinlist(host->name, &dnssec_require_domains,
+ 0, NULL, NULL, MCL_DOMAIN, TRUE, NULL) == OK;
/* Set the default fully qualified name to the incoming name, initialize the
resolver if necessary, set up the relevant options, and initialize the flag
if (fully_qualified_name != NULL) *fully_qualified_name = host->name;
dns_init((whichrrs & HOST_FIND_QUALIFY_SINGLE) != 0,
- (whichrrs & HOST_FIND_SEARCH_PARENTS) != 0);
+ (whichrrs & HOST_FIND_SEARCH_PARENTS) != 0,
+ dnssec_request || dnssec_require
+ );
host_find_failed_syntax = FALSE;
/* First, if requested, look for SRV records. The service name is given; we
/* On DNS failures, we give the "try again" error unless the domain is
listed as one for which we continue. */
+ if (rc == DNS_SUCCEED && dnssec_require && !dns_is_secure(&dnsa))
+ {
+ log_write(L_host_lookup_failed, LOG_MAIN,
+ "dnssec fail on SRV for %.256s", host->name);
+ rc = DNS_FAIL;
+ }
if (rc == DNS_FAIL || rc == DNS_AGAIN)
{
#ifndef STAND_ALONE
if (match_isinlist(host->name, &srv_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
TRUE, NULL) != OK)
#endif
- return HOST_FIND_AGAIN;
+ { yield = HOST_FIND_AGAIN; goto out; }
DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
"(domain in srv_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
}
{
ind_type = T_MX;
rc = dns_lookup(&dnsa, host->name, ind_type, fully_qualified_name);
- if (rc == DNS_NOMATCH) return HOST_FIND_FAILED;
- if (rc == DNS_FAIL || rc == DNS_AGAIN)
- {
- #ifndef STAND_ALONE
- if (match_isinlist(host->name, &mx_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
- TRUE, NULL) != OK)
- #endif
- return HOST_FIND_AGAIN;
- DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
- "(domain in mx_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
+ switch (rc)
+ {
+ case DNS_NOMATCH:
+ yield = HOST_FIND_FAILED; goto out;
+
+ case DNS_SUCCEED:
+ if (!dnssec_require || dns_is_secure(&dnsa))
+ break;
+ log_write(L_host_lookup_failed, LOG_MAIN,
+ "dnssec fail on MX for %.256s", host->name);
+ rc = DNS_FAIL;
+ /*FALLTRHOUGH*/
+
+ case DNS_FAIL:
+ case DNS_AGAIN:
+ #ifndef STAND_ALONE
+ if (match_isinlist(host->name, &mx_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
+ TRUE, NULL) != OK)
+ #endif
+ { yield = HOST_FIND_AGAIN; goto out; }
+ DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
+ "(domain in mx_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
+ break;
}
}
if ((whichrrs & HOST_FIND_BY_A) == 0)
{
DEBUG(D_host_lookup) debug_printf("Address records are not being sought\n");
- return HOST_FIND_FAILED;
+ yield = HOST_FIND_FAILED;
+ goto out;
}
last = host; /* End of local chainlet */
host->mx = MX_NONE;
host->port = PORT_NONE;
rc = set_address_from_dns(host, &last, ignore_target_hosts, FALSE,
- fully_qualified_name);
+ fully_qualified_name, dnssec_require);
/* If one or more address records have been found, check that none of them
are local. Since we know the host items all have their IP addresses
}
}
- return rc;
+ yield = rc;
+ goto out;
}
/* We have found one or more MX or SRV records. Sort them according to
if (host == last && host->name[0] == 0)
{
DEBUG(D_host_lookup) debug_printf("the single SRV record is \".\"\n");
- return HOST_FIND_FAILED;
+ yield = HOST_FIND_FAILED;
+ goto out;
}
DEBUG(D_host_lookup)
if they happen to match something local. */
yield = HOST_FIND_FAILED; /* Default yield */
-dns_init(FALSE, FALSE); /* Disable qualify_single and search_parents */
+dns_init(FALSE, FALSE, /* Disable qualify_single and search_parents */
+ dnssec_request || dnssec_require);
for (h = host; h != last->next; h = h->next)
{
if (h->address != NULL) continue; /* Inserted by a multihomed host */
- rc = set_address_from_dns(h, &last, ignore_target_hosts, allow_mx_to_ip, NULL);
+ rc = set_address_from_dns(h, &last, ignore_target_hosts, allow_mx_to_ip,
+ NULL, dnssec_require);
if (rc != HOST_FOUND)
{
h->status = hstatus_unusable;
}
}
+out:
+
+dns_init(FALSE, FALSE, FALSE); /* clear the dnssec bit for getaddrbyname */
return yield;
}
BOOL byname = FALSE;
BOOL qualify_single = TRUE;
BOOL search_parents = FALSE;
+BOOL request_dnssec = FALSE;
+BOOL require_dnssec = FALSE;
uschar **argv = USS cargv;
uschar buffer[256];
/* So that debug level changes can be done first */
-dns_init(qualify_single, search_parents);
+dns_init(qualify_single, search_parents, FALSE);
printf("Testing host lookup\n");
printf("> ");
whichrrs = HOST_FIND_BY_SRV | HOST_FIND_BY_MX;
else if (Ustrcmp(buffer, "srv+mx+a") == 0)
whichrrs = HOST_FIND_BY_SRV | HOST_FIND_BY_MX | HOST_FIND_BY_A;
- else if (Ustrcmp(buffer, "qualify_single") == 0) qualify_single = TRUE;
+ else if (Ustrcmp(buffer, "qualify_single") == 0) qualify_single = TRUE;
else if (Ustrcmp(buffer, "no_qualify_single") == 0) qualify_single = FALSE;
- else if (Ustrcmp(buffer, "search_parents") == 0) search_parents = TRUE;
+ else if (Ustrcmp(buffer, "search_parents") == 0) search_parents = TRUE;
else if (Ustrcmp(buffer, "no_search_parents") == 0) search_parents = FALSE;
+ else if (Ustrcmp(buffer, "request_dnssec") == 0) request_dnssec = TRUE;
+ else if (Ustrcmp(buffer, "no_request_dnssec") == 0) request_dnssec = FALSE;
+ else if (Ustrcmp(buffer, "require_dnssec") == 0) require_dnssec = TRUE;
+ else if (Ustrcmp(buffer, "no_reqiret_dnssec") == 0) require_dnssec = FALSE;
else if (Ustrcmp(buffer, "test_harness") == 0)
running_in_test_harness = !running_in_test_harness;
else if (Ustrcmp(buffer, "ipv6") == 0) disable_ipv6 = !disable_ipv6;
if (qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
if (search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
- rc = byname?
- host_find_byname(&h, NULL, flags, &fully_qualified_name, TRUE)
- :
- host_find_bydns(&h, NULL, flags, US"smtp", NULL, NULL,
- &fully_qualified_name, NULL);
+ rc = byname
+ ? host_find_byname(&h, NULL, flags, &fully_qualified_name, TRUE)
+ : host_find_bydns(&h, NULL, flags, US"smtp", NULL, NULL,
+ request_dnssec ? &h.name : NULL,
+ require_dnssec ? &h.name : NULL,
+ &fully_qualified_name, NULL);
if (rc == HOST_FIND_FAILED) printf("Failed\n");
else if (rc == HOST_FIND_AGAIN) printf("Again\n");
}
#endif /* STAND_ALONE */
+/* vi: aw ai sw=2
+*/
/* End of host.c */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for doing things with sockets. With the advent of IPv6 this has
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for writing log files. The code for maintaining datestamped
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
#include "../exim.h"
/* Initialize the resolver in case this is the first time it has been used. */
-dns_init(FALSE, FALSE);
+dns_init(FALSE, FALSE, FALSE); /*XXX dnssec? */
/* The remainder of the string must be a list of domains. As long as the lookup
for at least one of them succeeds, we return success. Failure means that none
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Many thanks to Stuart Lynne for contributing the original code for this
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2003-2013 */
+/* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2003-2014 */
/* License: GPL */
/* Code for calling virus (malware) scanners. Called from acl.c. */
NULL, /* service name not relevant */
NULL, /* srv_fail_domains not relevant */
NULL, /* mx_fail_domains not relevant */
+ NULL, /* no dnssec request XXX ? */
+ NULL, /* no dnssec require XXX ? */
NULL, /* no feedback FQDN */
&removed); /* feedback if local removed */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for sending messages to sender or to mailmaster. */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for reading the configuration file, and for displaying
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions concerned with routing, and the list of generic router options. */
(void *)(offsetof(dnslookup_router_options_block, check_secondary_mx)) },
{ "check_srv", opt_stringptr,
(void *)(offsetof(dnslookup_router_options_block, check_srv)) },
+ { "dnssec_request_domains", opt_stringptr,
+ (void *)(offsetof(dnslookup_router_options_block, dnssec_request_domains)) },
+ { "dnssec_require_domains", opt_stringptr,
+ (void *)(offsetof(dnslookup_router_options_block, dnssec_require_domains)) },
{ "mx_domains", opt_stringptr,
(void *)(offsetof(dnslookup_router_options_block, mx_domains)) },
{ "mx_fail_domains", opt_stringptr,
NULL, /* mx_domains */
NULL, /* mx_fail_domains */
NULL, /* srv_fail_domains */
- NULL /* check_srv */
+ NULL, /* check_srv */
+ NULL, /* dnssec_request_domains */
+ NULL /* dnssec_require_domains */
};
}
rc = host_find_bydns(&h, rblock->ignore_target_hosts, flags, srv_service,
- ob->srv_fail_domains, ob->mx_fail_domains, &fully_qualified_name, &removed);
+ ob->srv_fail_domains, ob->mx_fail_domains,
+ ob->dnssec_request_domains, ob->dnssec_require_domains,
+ &fully_qualified_name, &removed);
if (removed) setflag(addr, af_local_host_removed);
/* If host found with only address records, test for the domain's being in
uschar *mx_fail_domains;
uschar *srv_fail_domains;
uschar *check_srv;
+ uschar *dnssec_request_domains;
+ uschar *dnssec_require_domains;
} dnslookup_router_options_block;
/* Data for reading the private options. */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
#include "../exim.h"
NULL, /* SRV service not relevant */
NULL, /* failing srv domains not relevant */
NULL, /* no special mx failing domains */
+ NULL, /* no dnssec request XXX ? */
+ NULL, /* no dnssec require XXX ? */
NULL, /* fully_qualified_name */
NULL); /* indicate local host removed */
}
BOOL removed;
DEBUG(D_route|D_host_lookup) debug_printf("doing DNS lookup\n");
rc = host_find_bydns(h, ignore_target_hosts, HOST_FIND_BY_A, NULL, NULL,
- NULL, &canonical_name, &removed);
+ NULL,
+ NULL, NULL, /*XXX dnssec? */
+ &canonical_name, &removed);
if (rc == HOST_FOUND)
{
if (removed) setflag(addr, af_local_host_removed);
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for handling an incoming SMTP call. */
}
-/*************************************************
-* Flush waiting input string *
-*************************************************/
-static void
-flush_input()
-{
-int rc;
-
-rc = smtp_getc();
-while (rc != '\n') /* End of input string */
- {
- rc = smtp_getc();
- }
-}
-
-
/*************************************************
* Setup host for proxy protocol *
*************************************************/
} v2;
} hdr;
+/* Temp variables used in PPv2 address:port parsing */
+uint16_t tmpport;
+char tmpip[INET_ADDRSTRLEN];
+struct sockaddr_in tmpaddr;
+char tmpip6[INET6_ADDRSTRLEN];
+struct sockaddr_in6 tmpaddr6;
+
+int get_ok = 0;
int size, ret, fd;
-uschar *tmpip;
const char v2sig[13] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x02";
uschar *iptype; /* To display debug info */
struct timeval tv;
-int get_ok = 0;
socklen_t vslen = 0;
struct timeval tvtmp;
do
{
- ret = recv(fd, &hdr, sizeof(hdr), MSG_PEEK);
+ /* The inbound host was declared to be a Proxy Protocol host, so
+ don't do a PEEK into the data, actually slurp it up. */
+ ret = recv(fd, &hdr, sizeof(hdr), 0);
}
while (ret == -1 && errno == EINTR);
case 0x01: /* PROXY command */
switch (hdr.v2.fam)
{
- case 0x11: /* TCPv4 */
- tmpip = string_sprintf("%s", hdr.v2.addr.ip4.src_addr);
- if (!string_is_ip_address(tmpip,NULL))
+ case 0x11: /* TCPv4 address type */
+ iptype = US"IPv4";
+ tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.src_addr;
+ inet_ntop(AF_INET, &(tmpaddr.sin_addr), (char *)&tmpip, sizeof(tmpip));
+ if (!string_is_ip_address(US tmpip,NULL))
+ {
+ DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
return ERRNO_PROXYFAIL;
- sender_host_address = tmpip;
- sender_host_port = hdr.v2.addr.ip4.src_port;
+ }
+ proxy_host_address = sender_host_address;
+ sender_host_address = string_copy(US tmpip);
+ tmpport = ntohs(hdr.v2.addr.ip4.src_port);
+ proxy_host_port = sender_host_port;
+ sender_host_port = tmpport;
+ /* Save dest ip/port */
+ tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.dst_addr;
+ inet_ntop(AF_INET, &(tmpaddr.sin_addr), (char *)&tmpip, sizeof(tmpip));
+ if (!string_is_ip_address(US tmpip,NULL))
+ {
+ DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
+ return ERRNO_PROXYFAIL;
+ }
+ proxy_target_address = string_copy(US tmpip);
+ tmpport = ntohs(hdr.v2.addr.ip4.dst_port);
+ proxy_target_port = tmpport;
goto done;
- case 0x21: /* TCPv6 */
- tmpip = string_sprintf("%s", hdr.v2.addr.ip6.src_addr);
- if (!string_is_ip_address(tmpip,NULL))
+ case 0x21: /* TCPv6 address type */
+ iptype = US"IPv6";
+ memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.src_addr, 16);
+ inet_ntop(AF_INET6, &(tmpaddr6.sin6_addr), (char *)&tmpip6, sizeof(tmpip6));
+ if (!string_is_ip_address(US tmpip6,NULL))
+ {
+ DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
return ERRNO_PROXYFAIL;
- sender_host_address = tmpip;
- sender_host_port = hdr.v2.addr.ip6.src_port;
+ }
+ proxy_host_address = sender_host_address;
+ sender_host_address = string_copy(US tmpip6);
+ tmpport = ntohs(hdr.v2.addr.ip6.src_port);
+ proxy_host_port = sender_host_port;
+ sender_host_port = tmpport;
+ /* Save dest ip/port */
+ memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.dst_addr, 16);
+ inet_ntop(AF_INET6, &(tmpaddr6.sin6_addr), (char *)&tmpip6, sizeof(tmpip6));
+ if (!string_is_ip_address(US tmpip6,NULL))
+ {
+ DEBUG(D_receive) debug_printf("Invalid %s dest port\n", iptype);
+ return ERRNO_PROXYFAIL;
+ }
+ proxy_target_address = string_copy(US tmpip6);
+ tmpport = ntohs(hdr.v2.addr.ip6.dst_port);
+ proxy_target_port = tmpport;
goto done;
+ default:
+ DEBUG(D_receive)
+ debug_printf("Unsupported PROXYv2 connection type: 0x%02x\n",
+ hdr.v2.fam);
+ goto proxyfail;
}
/* Unsupported protocol, keep local connection address */
break;
/* Keep local connection address for LOCAL */
break;
default:
- DEBUG(D_receive) debug_printf("Unsupported PROXYv2 command\n");
+ DEBUG(D_receive)
+ debug_printf("Unsupported PROXYv2 command: 0x%02x\n",
+ hdr.v2.cmd);
goto proxyfail;
}
}
debug_printf("Proxy dest arg is not an %s address\n", iptype);
goto proxyfail;
}
- /* Should save dest ip somewhere? */
+ proxy_target_address = p;
p = sp + 1;
if ((sp = Ustrchr(p, ' ')) == NULL)
{
debug_printf("Proxy dest port '%s' not an integer\n", p);
goto proxyfail;
}
- /* Should save dest port somewhere? */
+ proxy_target_port = tmp_port;
/* Already checked for /r /n above. Good V1 header received. */
goto done;
}
else
{
/* Wrong protocol */
- DEBUG(D_receive) debug_printf("Wrong proxy protocol specified\n");
+ DEBUG(D_receive) debug_printf("Invalid proxy protocol version negotiation\n");
goto proxyfail;
}
proxyfail:
restore_socket_timeout(fd, get_ok, tvtmp, vslen);
/* Don't flush any potential buffer contents. Any input should cause a
-synchronization failure or we just don't want to speak SMTP to them */
+ synchronization failure */
return FALSE;
done:
restore_socket_timeout(fd, get_ok, tvtmp, vslen);
-flush_input();
DEBUG(D_receive)
- debug_printf("Valid %s sender from Proxy Protocol header\n",
- iptype);
+ debug_printf("Valid %s sender from Proxy Protocol header\n", iptype);
return proxy_session;
}
#endif
#ifdef SUPPORT_TLS
+/* Append TLS-related information to a log line
+
+Arguments:
+ s String under construction: allocated string to extend, or NULL
+ sizep Pointer to current allocation size (update on return), or NULL
+ ptrp Pointer to index for new entries in string (update on return), or NULL
+
+Returns: Allocated string or NULL
+*/
static uschar *
s_tlslog(uschar * s, int * sizep, int * ptrp)
{
if (sizep) *sizep = size;
if (ptrp) *ptrp = ptr;
}
- else
- s = US"";
return s;
}
#endif
is closing if required and return 2. */
if (log_reject_target != 0)
- log_write(0, log_reject_target, "%s%s %s%srejected %s%s",
- host_and_ident(TRUE),
+ {
#ifdef SUPPORT_TLS
- s_tlslog(NULL, NULL, NULL),
+ uschar * s = s_tlslog(NULL, NULL, NULL);
+ if (!s) s = US"";
#else
- "",
+ uschar * s = US"";
#endif
+ log_write(0, log_reject_target, "%s%s %s%srejected %s%s",
+ host_and_ident(TRUE), s,
sender_info, (rc == FAIL)? US"" : US"temporarily ", what, log_msg);
+ }
if (!drop) return 0;
*************************************************/
/* Experimental SPF support.
- Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
+ Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004 - 2014
License: GPL */
/* Code for calling spf checks via libspf-alt. Called from acl.c. */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Miscellaneous string-handling functions. Some are not required for
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Copyright (c) Phil Pennock 2012 */
*error = NULL;
-rc = peer_status(state);
-if (rc != OK)
+if ((rc = peer_status(state)) != OK)
{
verify = GNUTLS_CERT_INVALID;
- *error = "not supplied";
+ *error = "certificate not supplied";
}
else
- {
rc = gnutls_certificate_verify_peers2(state->session, &verify);
- }
/* Handle the result of verification. INVALID seems to be set as well
as REVOKED, but leave the test for both. */
-if ((rc < 0) || (verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) != 0)
+if (rc < 0 || verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED))
{
state->peer_cert_verified = FALSE;
- if (*error == NULL)
- *error = ((verify & GNUTLS_CERT_REVOKED) != 0) ? "revoked" : "invalid";
+ if (!*error)
+ *error = verify & GNUTLS_CERT_REVOKED
+ ? "certificate revoked" : "certificate invalid";
DEBUG(D_tls)
debug_printf("TLS certificate verification failed (%s): peerdn=%s\n",
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Portions Copyright (c) The OpenSSL Project 1999 */
it can result in serious failures, including crashing with a SIGSEGV. So
report the version found by the compiler and the run-time version.
+Note: some OS vendors backport security fixes without changing the version
+number/string, and the version date remains unchanged. The _build_ date
+will change, so we can more usefully assist with version diagnosis by also
+reporting the build date.
+
Arguments: a FILE* to print the results to
Returns: nothing
*/
tls_version_report(FILE *f)
{
fprintf(f, "Library version: OpenSSL: Compile: %s\n"
- " Runtime: %s\n",
+ " Runtime: %s\n"
+ " : %s\n",
OPENSSL_VERSION_TEXT,
- SSLeay_version(SSLEAY_VERSION));
+ SSLeay_version(SSLEAY_VERSION),
+ SSLeay_version(SSLEAY_BUILT_ON));
+/* third line is 38 characters for the %s and the line is 73 chars long;
+the OpenSSL output includes a "built on: " prefix already. */
}
#endif /* SUPPORT_TLS */
+void
+tls_modify_variables(tls_support * dest_tsp)
+{
+modify_variable(US"tls_bits", &dest_tsp->bits);
+modify_variable(US"tls_certificate_verified", &dest_tsp->certificate_verified);
+modify_variable(US"tls_cipher", &dest_tsp->cipher);
+modify_variable(US"tls_peerdn", &dest_tsp->peerdn);
+#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
+modify_variable(US"tls_sni", &dest_tsp->sni);
+#endif
+}
+
/* End of tls.c */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* General functions concerned with transportation, and generic options for all
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Private structure for the private options. */
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
#include "../exim.h"
/* Reset the parameters of a TLS session. */
-tls_in.bits = 0;
-tls_in.cipher = NULL; /* for back-compatible behaviour */
-tls_in.peerdn = NULL;
-#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
-tls_in.sni = NULL;
-#endif
-
tls_out.bits = 0;
tls_out.cipher = NULL; /* the one we may use for this transport */
tls_out.peerdn = NULL;
tls_out.sni = NULL;
#endif
+/* Flip the legacy TLS-related variables over to the outbound set in case
+they're used in the context of the transport. Don't bother resetting
+afterward as we're in a subprocess. */
+
+tls_modify_variables(&tls_out);
+
#ifndef SUPPORT_TLS
if (smtps)
{
rc = host_find_byname(host, NULL, flags, &canonical_name, TRUE);
else
rc = host_find_bydns(host, NULL, flags, NULL, NULL, NULL,
+ NULL, NULL, /*XXX todo: smtp tpt hosts_require_dnssec */
&canonical_name, NULL);
/* Update the host (and any additional blocks, resulting from
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2013 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Private structure for the private options and other private data. */
they're used in the context of a transport used by verification. Reset them
at exit from this routine. */
-modify_variable(US"tls_bits", &tls_out.bits);
-modify_variable(US"tls_certificate_verified", &tls_out.certificate_verified);
-modify_variable(US"tls_cipher", &tls_out.cipher);
-modify_variable(US"tls_peerdn", &tls_out.peerdn);
-#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
-modify_variable(US"tls_sni", &tls_out.sni);
-#endif
+tls_modify_variables(&tls_out);
/* Save a copy of the sender address for re-instating if we change it to <>
while verifying a sender address (a nice bit of self-reference there). */
(void)host_find_byname(host, NULL, flags, &canonical_name, TRUE);
else
(void)host_find_bydns(host, NULL, flags, NULL, NULL, NULL,
+ NULL, NULL, /*XXX todo: dnssec */
&canonical_name, NULL);
}
}
the -bv or -bt case). */
out:
-
-modify_variable(US"tls_bits", &tls_in.bits);
-modify_variable(US"tls_certificate_verified", &tls_in.certificate_verified);
-modify_variable(US"tls_cipher", &tls_in.cipher);
-modify_variable(US"tls_peerdn", &tls_in.peerdn);
-#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
-modify_variable(US"tls_sni", &tls_in.sni);
-#endif
+tls_modify_variables(&tls_in);
return yield;
}
/* In case this is the first time the DNS resolver is being used. */
-dns_init(FALSE, FALSE);
+dns_init(FALSE, FALSE, FALSE); /*XXX dnssec? */
/* Loop through all the domains supplied, until something matches */
--- /dev/null
+#!/usr/bin/perl
+#
+# Copyright (C) 2014 Todd Lyons
+# License GPLv2: GNU GPL version 2
+# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
+#
+# This script emulates a proxy which uses Proxy Protocol to communicate
+# to a backend server. It should be run from an IP which is configured
+# to be a Proxy Protocol connection (or not, if you are testing error
+# scenarios) because Proxy Protocol specs require not to fall back to a
+# non-proxied mode.
+#
+# The script is interactive, so when you run it, you are expected to
+# perform whatever conversation is required for the protocol being
+# tested. It uses STDIN/STDOUT, so you can also pipe output to/from the
+# script. It was originally written to test Exim's Proxy Protocol
+# code, and it could be tested like this:
+#
+# swaks --pipe 'perl proxy_protocol_client.pl --server-ip
+# host.internal.lan' --from user@example.com --to user@example.net
+#
+use strict;
+use warnings;
+use IO::Select;
+use IO::Socket;
+use Getopt::Long;
+use Data::Dumper;
+
+my %opts;
+GetOptions( \%opts,
+ 'help',
+ '6|ipv6',
+ 'dest-ip:s',
+ 'dest-port:i',
+ 'source-ip:s',
+ 'source-port:i',
+ 'server-ip:s',
+ 'server-port:i',
+ 'version:i'
+);
+&usage() if ($opts{help} || !$opts{'server-ip'});
+
+my ($dest_ip,$source_ip,$dest_port,$source_port);
+my %socket_map;
+my $status_line = "Testing Proxy Protocol Version " .
+ ($opts{version} ? $opts{version} : '2') .
+ ":\n";
+
+# All ip's and ports are in network byte order in version 2 mode, but are
+# simple strings when in version 1 mode. The binary_pack_*() functions
+# return the required data for the Proxy Protocol version being used.
+
+# Use provided source or fall back to www.mrball.net
+$source_ip = $opts{'source-ip'} ? binary_pack_ip($opts{'source-ip'}) :
+ $opts{6} ?
+ binary_pack_ip("2001:470:d:367::50") :
+ binary_pack_ip("208.89.139.252");
+$source_port = $opts{'source-port'} ?
+ binary_pack_port($opts{'source-port'}) :
+ binary_pack_port(43118);
+
+$status_line .= "-> " if (!$opts{version} || $opts{version} == 2);
+
+# Use provided dest or fall back to mail.exim.org
+$dest_ip = $opts{'dest-ip'} ? binary_pack_ip($opts{'dest-ip'}) :
+ $opts{6} ?
+ binary_pack_ip("2001:630:212:8:204:23ff:fed6:b664") :
+ binary_pack_ip("131.111.8.192");
+$dest_port = $opts{'dest-port'} ?
+ binary_pack_port($opts{'dest-port'}) :
+ binary_pack_port(25);
+
+# The IP and port of the Proxy Protocol backend real server being tested,
+# don't binary pack it.
+my $server_ip = $opts{'server-ip'};
+my $server_port = $opts{'server-port'} ? $opts{'server-port'} : 25;
+
+my $s = IO::Select->new(); # for socket polling
+
+sub generate_preamble {
+ my @preamble;
+ if (!$opts{version} || $opts{version} == 2) {
+ @preamble = (
+ "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A", # 12 byte v2 header
+ "\x02", # declares v2
+ "\x01", # connection is proxied
+ $opts{6} ? "\x21" : "\x11", # inet6/4 and TCP (stream)
+ $opts{6} ? "\x24" : "\x0b", # 36 bytes / 12 bytes
+ $source_ip,
+ $dest_ip,
+ $source_port,
+ $dest_port
+ );
+ }
+ else {
+ @preamble = (
+ "PROXY", " ", # Request proxy mode
+ $opts{6} ? "TCP6" : "TCP4", " ", # inet6/4 and TCP (stream)
+ $source_ip, " ",
+ $dest_ip, " ",
+ $source_port, " ",
+ $dest_port,
+ "\x0d\x0a"
+ );
+ $status_line .= join "", @preamble;
+ }
+ print "\n", $status_line, "\n";
+ print "\n" if (!$opts{version} || $opts{version} == 2);
+ return @preamble;
+}
+
+sub binary_pack_port {
+ my $port = shift();
+ if ($opts{version} && $opts{version} == 1) {
+ return $port
+ if ($port && $port =~ /^\d+$/ && $port > 0 && $port < 65536);
+ die "Not a valid port: $port";
+ }
+ $status_line .= $port." ";
+ $port = pack "S", $port;
+ return $port;
+}
+
+sub binary_pack_ip {
+ my $ip = shift();
+ if ( $ip =~ m/\./ && !$opts{6}) {
+ if (IP4_valid($ip)) {
+ return $ip if ($opts{version} && $opts{version} == 1);
+ $status_line .= $ip.":";
+ $ip = pack "C*", split /\./, $ip;
+ }
+ else { die "Invalid IPv4: $ip"; }
+ }
+ elsif ($ip =~ m/:/ && $opts{6}) {
+ $ip = pad_ipv6($ip);
+ if (IP6_valid($ip)) {
+ return $ip if ($opts{version} && $opts{version} == 1);
+ $status_line .= $ip.":";
+ $ip = pack "S>*", map hex, split /:/, $ip;
+ }
+ else { die "Invalid IPv6: $ip"; }
+ }
+ else { die "Mismatching IP families passed: $ip"; }
+ return $ip;
+}
+
+sub pad_ipv6 {
+ my $ip = shift();
+ my @ip = split /:/, $ip;
+ my $segments = scalar @ip;
+ return $ip if ($segments == 8);
+ $ip = "";
+ for (my $count=1; $count <= $segments; $count++) {
+ my $block = $ip[$count-1];
+ if ($block) {
+ $ip .= $block;
+ $ip .= ":" unless $count == $segments;
+ }
+ elsif ($count == 1) {
+ # Somebody passed us ::1, fix it, but it's not really valid
+ $ip = "0:";
+ }
+ else {
+ $ip .= join ":", map "0", 0..(8-$segments);
+ $ip .= ":";
+ }
+ }
+ return $ip;
+}
+
+sub IP6_valid {
+ my $ip = shift;
+ $ip = lc($ip);
+ return 0 unless ($ip =~ /^[0-9a-f:]+$/);
+ my @ip = split /:/, $ip;
+ return 0 if (scalar @ip != 8);
+ return 1;
+}
+
+sub IP4_valid {
+ my $ip = shift;
+ $ip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
+ foreach ($1,$2,$3,$4){
+ if ($_ <256 && $_ >0) {next;}
+ return 0;
+ }
+ return 1;
+}
+
+sub go_interactive {
+ my $continue = 1;
+ while($continue) {
+ # Check for input on both ends, recheck every 5 sec
+ for my $socket ($s->can_read(5)) {
+ my $remote = $socket_map{$socket};
+ my $buffer;
+ my $read = $socket->sysread($buffer, 4096);
+ if ($read) {
+ $remote->syswrite($buffer);
+ }
+ else {
+ $continue = 0;
+ }
+ }
+ }
+}
+
+sub connect_stdin_to_proxy {
+ my $sock = new IO::Socket::INET(
+ PeerAddr => $server_ip,
+ PeerPort => $server_port,
+ Proto => 'tcp'
+ );
+
+ die "Could not create socket: $!\n" unless $sock;
+ # Add sockets to the Select group
+ $s->add(\*STDIN);
+ $s->add($sock);
+ # Tie the sockets together using this hash
+ $socket_map{\*STDIN} = $sock;
+ $socket_map{$sock} = \*STDOUT;
+ return $sock;
+}
+
+sub usage {
+ chomp(my $prog = `basename $0`);
+ print <<EOF;
+Usage: $prog [required] [optional]
+ Required:
+ --server-ip IP of server to test proxy configuration,
+ a hostname is ok, but for only this setting
+ Optional:
+ --server-port Port server is listening on (default 25)
+ --6 IPv6 source/dest (default IPv4), if none specified,
+ some default, reverse resolvable IP's are used for
+ the source and dest ip/port
+ --dest-ip Public IP of the proxy server
+ --dest-port Port of public IP of proxy server
+ --source-ip IP connecting to the proxy server
+ --source-port Port of IP connecting to the proxy server
+ --help This output
+EOF
+ exit;
+}
+
+
+my $sock = connect_stdin_to_proxy();
+my @preamble = generate_preamble();
+print $sock @preamble;
+go_interactive();
tls_privatekey = CERT
tls_verify_hosts = HOSTIPV4
-tls_verify_certificates = TVC
+#tls_verify_certificates = TVC
+tls_verify_certificates = CERT
# End
primary_hostname = myhost.test.ex
rfc1413_query_timeout = 0s
spool_directory = DIR/spool
+.ifdef SERVER
log_file_path = DIR/spool/log/%slog
+.else
+log_file_path = DIR/spool/log/%D-%slog
+.endif
gecos_pattern = ""
gecos_name = CALLER_NAME
acl_smtp_rcpt = check_rcpt
log_selector = +tls_peerdn
+
tls_advertise_hosts = HOSTIPV4
tls_certificate = DIR/aux-fixed/cert1
tls_privatekey = DIR/aux-fixed/cert1
check_rcpt:
accept local_parts = userx
+ control = queue_only
defer local_parts = usery
hosts = 127.0.0.1
- accept
-
+ accept control = queue_only
# ----- Routers -----
hosts_require_auth = *
allow_localhost
+ # These can be made visible by adding "-d-all+deliver+transport+tls" to the script 1st queuerun
+ headers_add = X-tls-cipher: <$tls_cipher>
+ headers_add = X-tls-out-cipher: <$tls_out_cipher>
+
# End
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 no MAIL in SMTP connection from [127.0.0.1] D=0s
1999-03-02 09:44:33 no MAIL in SMTP connection from [127.0.0.1] D=0s C=QUIT
1999-03-02 09:44:33 H=(x.y.z) [127.0.0.1] rejected VRFY a@b.c
1999-03-02 09:44:33 no MAIL in SMTP connection from (x.y.z) [127.0.0.1] D=0s C=EHLO,VRFY,QUIT
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
-1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to 127.0.0.1 [127.0.0.1] (certificate verification failed): invalid
+1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to 127.0.0.1 [127.0.0.1] (certificate verification failed): certificate invalid
1999-03-02 09:44:33 10HmaX-0005vi-00 TLS session failure: delivering unencrypted to 127.0.0.1 [127.0.0.1] (not in hosts_require_tls)
1999-03-02 09:44:33 10HmaX-0005vi-00 => CALLER@test.ex R=client T=send_to_server 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 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
-1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to 127.0.0.1 [127.0.0.1] (certificate verification failed): invalid
+1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to 127.0.0.1 [127.0.0.1] (certificate verification failed): certificate invalid
1999-03-02 09:44:33 10HmaX-0005vi-00 == CALLER@test.ex R=client T=send_to_server defer (-37): failure while setting up TLS session
1999-03-02 09:44:33 End queue run: pid=pppp -qf
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
-1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to 127.0.0.1 [127.0.0.1] (certificate verification failed): invalid
+1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to 127.0.0.1 [127.0.0.1] (certificate verification failed): certificate invalid
1999-03-02 09:44:33 10HmaX-0005vi-00 == CALLER@test.ex R=client T=send_to_server defer (-37): failure while setting up TLS session
1999-03-02 09:44:33 End queue run: pid=pppp -qf
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
-1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (certificate verification failed): invalid
+1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (certificate verification failed): certificate invalid
1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=client_x T=send_to_server_failcert defer (-37): failure while setting up TLS session
1999-03-02 09:44:33 10HmaX-0005vi-00 ** userx@test.ex: retry timeout exceeded
1999-03-02 09:44:33 10HmaX-0005vi-00 userx@test.ex: error ignored
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
-1999-03-02 09:44:33 10HmaY-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (certificate verification failed): invalid
+1999-03-02 09:44:33 10HmaY-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (certificate verification failed): certificate invalid
1999-03-02 09:44:33 10HmaY-0005vi-00 => usery@test.ex R=client_y T=send_to_server_retry H=127.0.0.1 [127.0.0.1] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=yes DN="C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock" C="250 OK id=10HmbB-0005vi-00"
1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
1999-03-02 09:44:33 10HmaZ-0005vi-00 => userz@test.ex R=client_z T=send_to_server_crypt H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no DN="C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock" C="250 OK id=10HmbC-0005vi-00"
1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
-1999-03-02 09:44:33 10HmbA-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (certificate verification failed): invalid
+1999-03-02 09:44:33 10HmbA-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (certificate verification failed): certificate invalid
1999-03-02 09:44:33 10HmbA-0005vi-00 TLS session failure: delivering unencrypted to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (not in hosts_require_tls)
1999-03-02 09:44:33 10HmbA-0005vi-00 => userq@test.ex R=client_q T=send_to_server_req_fail H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbD-0005vi-00"
1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
1999-03-02 09:44:33 TLS error on connection from (rhu1.barb) [ip4.ip4.ip4.ip4] (gnutls_handshake): The peer did not send any certificate.
1999-03-02 09:44:33 H=(rhu2tls.barb) [127.0.0.1] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 F=<userx@test.ex> rejected RCPT <userx@test.ex>: certificate not verified: peerdn=
-1999-03-02 09:44:33 TLS error on connection from (rhu5.barb) [ip4.ip4.ip4.ip4] (certificate verification failed): invalid
+1999-03-02 09:44:33 TLS error on connection from (rhu5.barb) [ip4.ip4.ip4.ip4] (certificate verification failed): certificate invalid
1999-03-02 09:44:33 H=[127.0.0.1] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 DN="C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock" F=<userx@test.ex> rejected RCPT <userx@test.ex>: certificate not verified: peerdn=C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 TLS error on connection from (rhu7.barb) [ip4.ip4.ip4.ip4] (certificate verification failed): revoked
+1999-03-02 09:44:33 TLS error on connection from (rhu7.barb) [ip4.ip4.ip4.ip4] (certificate verification failed): certificate revoked
1999-03-02 09:44:33 H=[127.0.0.1] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 DN="C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock" F=<userx@test.ex> rejected RCPT <userx@test.ex>: certificate not verified: peerdn=C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 TLS error on connection from (rhu.barb) [ip4.ip4.ip4.ip4] (gnutls_handshake): The peer did not send any certificate.
+1999-03-02 09:44:33 TLS error on connection from (rhu.barb) [ip4.ip4.ip4.ip4] (certificate verification failed): certificate invalid
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
1999-03-02 09:44:33 TLS error on connection from (rhu.barb) [ip4.ip4.ip4.ip4] (cert/key setup: cert=/non/exist key=/non/exist): Error while reading file.
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
-1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (gnutls_handshake): A TLS packet with unexpected length was received.
+1999-03-02 09:44:33 10HmaX-0005vi-00 a TLS session is required for ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4], but an attempt to start TLS failed
1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no DN="C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock" C="250 OK id=10HmaY-0005vi-00"
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
1999-03-02 09:44:33 End queue run: pid=pppp -qf
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
1999-03-02 09:44:33 H=localhost (myhost.test.ex) [127.0.0.1] F=<CALLER@myhost.test.ex> temporarily rejected RCPT <usery@myhost.test.ex>
-1999-03-02 09:44:33 10HmaX-0005vi-00 SMTP error from remote mail server after RCPT TO:<usery@myhost.test.ex>: host 127.0.0.1 [127.0.0.1]: 451 Temporary local problem - please try later
-1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex
-1999-03-02 09:44:33 10HmaY-0005vi-00 => userx <userx@myhost.test.ex> R=r0 T=t2
-1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
-1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 S=sss id=E10HmaX-0005vi-00@myhost.test.ex
-1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@myhost.test.ex R=r1 T=t1 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 => usery@myhost.test.ex R=r1 T=t1 H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 DN="C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock" C="250 OK id=10HmaZ-0005vi-00"
-1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
-1999-03-02 09:44:33 10HmaZ-0005vi-00 => usery <usery@myhost.test.ex> R=r0 T=t2
-1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaY-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 no immediate delivery: queued by ACL
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 S=sss id=E10HmaY-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 no immediate delivery: queued by ACL
1999-03-02 09:44:33 Start queue run: pid=pppp -qf
1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 C="250 OK id=10HmaZ-0005vi-00"
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
-1999-03-02 09:44:33 10HmaY-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (gnutls_handshake): A TLS packet with unexpected length was received.
+1999-03-02 09:44:33 10HmaY-0005vi-00 a TLS session is required for ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4], but an attempt to start TLS failed
1999-03-02 09:44:33 10HmaY-0005vi-00 TLS session failure: delivering unencrypted to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (not in hosts_require_tls)
1999-03-02 09:44:33 10HmaY-0005vi-00 => usery@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 10HmaY-0005vi-00 Completed
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection from [127.0.0.1] (recv): A TLS packet with unexpected length was received.
+1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection from [127.0.0.1] (recv): The TLS connection was non-properly terminated.
1999-03-02 09:44:33 10HmaX-0005vi-00 SMTP connection lost after final dot H=[127.0.0.1] P=smtps
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 TLS error on connection from [127.0.0.1] (recv): A TLS packet with unexpected length was received.
+1999-03-02 09:44:33 TLS error on connection from [127.0.0.1] (recv): The TLS connection was non-properly terminated.
1999-03-02 09:44:33 TLS error on connection from [127.0.0.1] (send): The specified session has been invalidated for some reason.
1999-03-02 09:44:33 no MAIL in SMTP connection from [127.0.0.1] D=0s X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 C=EHLO,STARTTLS,AUTH
1999-03-02 09:44:33 no MAIL in SMTP connection from (foobar) [127.0.0.1] D=0s A=plain:userx X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 C=EHLO,STARTTLS,EHLO,AUTH,QUIT
s/\bDHE-RSA-AES256-SHA\b/AES256-SHA/g;
# GnuTLS have seen:
+ # TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256
+ # TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128
# TLS1.2:RSA_AES_256_CBC_SHA1:256 (canonical)
# TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128
#
# X=TLS1.1:RSA_AES_256_CBC_SHA1:256
# X=TLS1.0:DHE_RSA_AES_256_CBC_SHA1:256
# and as stand-alone cipher:
+ # ECDHE-RSA-AES256-SHA
# DHE-RSA-AES256-SHA256
# DHE-RSA-AES256-SHA
# picking latter as canonical simply because regex easier that way.
s/\bDHE_RSA_AES_128_CBC_SHA1:128/RSA_AES_256_CBC_SHA1:256/g;
- s/TLS1.[012]:(DHE_)?RSA_AES_256_CBC_SHA(1|256):256/TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256/g;
- s/\bDHE-RSA-AES256-SHA256\b/DHE-RSA-AES256-SHA/g;
+ s/TLS1.[012]:((EC)?DHE_)?RSA_AES_(256|128)_(CBC|GCM)_SHA(1|256|384):(256|128)/TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256/g;
+ s/\b(ECDHE-RSA-AES256-SHA|DHE-RSA-AES256-SHA256)\b/AES256-SHA/g;
+
+ # GnuTLS library error message changes
+ s/No certificate was found/The peer did not send any certificate/g;
+#(dodgy test?) s/\(certificate verification failed\): invalid/\(gnutls_handshake\): The peer did not send any certificate./g;
+ s/\(gnutls_priority_set\): No or insufficient priorities were set/\(gnutls_handshake\): Could not negotiate a supported cipher suite/g;
+
+ # (replace old with new, hoping that old only happens in one situation)
+ s/TLS error on connection to \d{1,3}(.\d{1,3}){3} \[\d{1,3}(.\d{1,3}){3}\] \(gnutls_handshake\): A TLS packet with unexpected length was received./a TLS session is required for ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4], but an attempt to start TLS failed/g;
+ s/TLS error on connection from \[127.0.0.1\] \(recv\): A TLS packet with unexpected length was received./TLS error on connection from [127.0.0.1] (recv): The TLS connection was non-properly terminated./g;
# ======== Caller's login, uid, gid, home, gecos ========
# Wait to allow delivery to finish before killing the daemon
sleep 1
killdaemon
+no_msglog_check
??? 220
<<< 220 TLS go ahead
Attempting to start TLS
-Failed to start TLS
+Succeeded in starting TLS
End of script
Connecting to ip4.ip4.ip4.ip4 port 1225 ... connected
Certificate file = aux-fixed/cert2