From d51dbacf4da044f797cb4c07e026adc608f1bc98 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Fri, 30 Mar 2018 16:08:56 +0100 Subject: DANE: smtp transport option dane_require_tls_ciphers --- src/src/tls-gnu.c | 20 ++++++++++++++++++-- src/src/tls-openssl.c | 21 ++++++++++++++++++--- src/src/transports/smtp.c | 5 +++++ src/src/transports/smtp.h | 1 + 4 files changed, 42 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index eed8c06dc..d73188277 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -1681,7 +1681,7 @@ else 1, 0)) || (rc = dane_verify_crt_raw(s, certlist, lsize, gnutls_certificate_type_get(state->session), - r, 0, + r, 0, # ifdef GNUTLS_BROKEN_DANE_VALIDATION usage == (1 << DANESSL_USAGE_DANE_EE) ? DANE_VFLAG_ONLY_CHECK_EE_USAGE : 0, @@ -2260,6 +2260,7 @@ smtp_transport_options_block *ob = (smtp_transport_options_block *)tb->options_block; int rc; exim_gnutls_state_st * state = NULL; +uschar *cipher_list = NULL; #ifndef DISABLE_OCSP BOOL require_ocsp = verify_check_given_host(&ob->hosts_require_ocsp, host) == OK; @@ -2269,9 +2270,24 @@ BOOL request_ocsp = require_ocsp ? TRUE DEBUG(D_tls) debug_printf("initialising GnuTLS as a client on fd %d\n", fd); +#ifdef SUPPORT_DANE +if (tlsa_dnsa && ob->dane_require_tls_ciphers) + { + /* not using expand_check_tlsvar because not yet in state */ + if (!expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers", + &cipher_list, errstr)) + return DEFER; + cipher_list = cipher_list && *cipher_list + ? ob->dane_require_tls_ciphers : ob->tls_require_ciphers; + } +#endif + +if (!cipher_list) + cipher_list = ob->tls_require_ciphers; + if ((rc = tls_init(host, ob->tls_certificate, ob->tls_privatekey, ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl, - ob->tls_require_ciphers, &state, errstr)) != OK) + cipher_list, &state, errstr)) != OK) return rc; { diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 969a99d99..c142bd059 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -904,7 +904,7 @@ We do not free the stack since it could be needed a second time for SNI handling. Separately we might try to replace using OCSP_basic_verify() - which seems to not -be a public interface into the OpenSSL library (there's no manual entry) - +be a public interface into the OpenSSL library (there's no manual entry) - But what with? We also use OCSP_basic_verify in the client stapling callback. And there we NEED it; we must verify that status... unless the library does it for us anyway? */ @@ -2300,8 +2300,23 @@ if (rc != OK) return rc; tls_out.certificate_verified = FALSE; client_verify_callback_called = FALSE; -if (!expand_check(ob->tls_require_ciphers, US"tls_require_ciphers", - &expciphers, errstr)) +expciphers = NULL; +#ifdef SUPPORT_DANE +if (tlsa_dnsa) + { + /* We fall back to tls_require_ciphers if unset, empty or forced failure, but + other failures should be treated as problems. */ + if (ob->dane_require_tls_ciphers && + !expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers", + &expciphers, errstr)) + return FAIL; + if (expciphers && *expciphers == '\0') + expciphers = NULL; + } +#endif +if (!expciphers && + !expand_check(ob->tls_require_ciphers, US"tls_require_ciphers", + &expciphers, errstr)) return FAIL; /* In OpenSSL, cipher components are separated by hyphens. In GnuTLS, they diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index c4a6c0283..bd1e20d7f 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -38,6 +38,10 @@ optionlist smtp_transport_options[] = { (void *)offsetof(smtp_transport_options_block, connect_timeout) }, { "connection_max_messages", opt_int | opt_public, (void *)offsetof(transport_instance, connection_max_messages) }, +# ifdef SUPPORT_DANE + { "dane_require_tls_ciphers", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, dane_require_tls_ciphers) }, +# endif { "data_timeout", opt_time, (void *)offsetof(smtp_transport_options_block, data_timeout) }, { "delay_after_cutoff", opt_bool, @@ -225,6 +229,7 @@ smtp_transport_options_block smtp_transport_option_defaults = { #ifdef SUPPORT_DANE .hosts_try_dane = NULL, .hosts_require_dane = NULL, + .dane_require_tls_ciphers = NULL, #endif .hosts_try_fastopen = NULL, #ifndef DISABLE_PRDR diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h index 749c6f778..7727c0c6d 100644 --- a/src/src/transports/smtp.h +++ b/src/src/transports/smtp.h @@ -32,6 +32,7 @@ typedef struct { #ifdef SUPPORT_DANE uschar *hosts_try_dane; uschar *hosts_require_dane; + uschar *dane_require_tls_ciphers; #endif uschar *hosts_try_fastopen; #ifndef DISABLE_PRDR -- cgit v1.2.3 From d3e58fcb87faf7131a2712fcfaef200ffd191f05 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Fri, 30 Mar 2018 22:54:55 +0100 Subject: Avoid doing logging in signal-handlers. Bug 1007 --- doc/doc-docbook/spec.xfpt | 7 +- doc/doc-txt/ChangeLog | 9 +++ src/src/config.h.defaults | 1 + src/src/expand.c | 2 + src/src/functions.h | 4 + src/src/globals.c | 6 ++ src/src/globals.h | 6 ++ src/src/readconf.c | 2 + src/src/receive.c | 201 ++++++++++++++++++++++++++-------------------- src/src/smtp_in.c | 82 ++++++++++++++----- src/src/spool_in.c | 4 + src/src/spool_out.c | 6 +- src/src/tls-gnu.c | 20 +++-- src/src/tls-openssl.c | 11 ++- test/confs/0001 | 1 - test/stderr/0465 | 2 - test/stderr/0471 | 2 - test/stderr/0487 | 2 - test/stderr/0489 | 16 ---- test/stderr/0575 | 2 - test/stderr/2600 | 2 - test/stderr/2610 | 2 - test/stderr/2620 | 2 - test/stderr/5004 | 2 - test/stderr/5005 | 8 -- test/stderr/5006 | 2 - test/stdout/0574 | 2 - 27 files changed, 246 insertions(+), 160 deletions(-) (limited to 'src') diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 8e78c7bad..cf2be5654 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -32692,10 +32692,15 @@ code. The incident is logged on the main and reject logs. .section "Building Exim to use a local scan function" "SECID207" .cindex "&[local_scan()]& function" "building Exim to use" To make use of the local scan function feature, you must tell Exim where your -function is before building Exim, by setting LOCAL_SCAN_SOURCE in your +function is before building Exim, by setting +.new +both HAVE_LOCAL_SCAN and +.wen +LOCAL_SCAN_SOURCE in your &_Local/Makefile_&. A recommended place to put it is in the &_Local_& directory, so you might set .code +HAVE_LOCAL_SCAN=yes LOCAL_SCAN_SOURCE=Local/local_scan.c .endd for example. The function must be called &[local_scan()]&. It is called by diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index ef62b2d07..af186d2e3 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -5,6 +5,15 @@ affect Exim's operation, with an unchanged configuration file. For new options, and new features, see the NewStuff file next to this ChangeLog. +Exim 4.next +---------- + +JH/01 Remove code calling the customisable local_scan function, unless a new + definition "HAVE_LOCAL_SCAN=yes" is present in the Local/Makefile. + +JH/02 Bug 1007: Avoid doing logging from signal-handlers, as that can result in + non-signal-safe funxtions being used. + Since Exim version 4.90 ----------------------- diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults index ce478d558..0f348fa40 100644 --- a/src/src/config.h.defaults +++ b/src/src/config.h.defaults @@ -71,6 +71,7 @@ Do not put spaces between # and the 'define'. #define FIXED_NEVER_USERS "root" #define HAVE_CRYPT16 +#define HAVE_LOCAL_SCAN #define HAVE_SA_LEN #define HEADERS_CHARSET "ISO-8859-1" #define HEADER_ADD_BUFFER_SIZE (8192 * 4) diff --git a/src/src/expand.c b/src/src/expand.c index 6f67ab138..10fadfd89 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -563,7 +563,9 @@ static var_entry var_table[] = { { "local_part_data", vtype_stringptr, &deliver_localpart_data }, { "local_part_prefix", vtype_stringptr, &deliver_localpart_prefix }, { "local_part_suffix", vtype_stringptr, &deliver_localpart_suffix }, +#ifdef HAVE_LOCAL_SCAN { "local_scan_data", vtype_stringptr, &local_scan_data }, +#endif { "local_user_gid", vtype_gid, &local_user_gid }, { "local_user_uid", vtype_uid, &local_user_uid }, { "localhost_number", vtype_int, &host_number }, diff --git a/src/src/functions.h b/src/src/functions.h index 0b261177c..496bd9985 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -423,6 +423,10 @@ extern int sieve_interpret(uschar *, int, uschar *, uschar *, uschar *, extern void sigalrm_handler(int); extern BOOL smtp_buffered(void); extern void smtp_closedown(uschar *); +extern void smtp_command_timeout_exit(void); +extern void smtp_command_sigterm_exit(void); +extern void smtp_data_timeout_exit(void); +extern void smtp_data_sigint_exit(void); extern uschar *smtp_cmd_hist(void); extern int smtp_connect(host_item *, int, uschar *, int, transport_instance *); diff --git a/src/src/globals.c b/src/src/globals.c index e8faa9c02..705b1dd0c 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -770,6 +770,10 @@ uschar *gecos_name = NULL; uschar *gecos_pattern = NULL; rewrite_rule *global_rewrite_rules = NULL; +volatile sig_atomic_t had_command_timeout = 0; +volatile sig_atomic_t had_command_sigterm = 0; +volatile sig_atomic_t had_data_timeout = 0; +volatile sig_atomic_t had_data_sigint = 0; uschar *headers_charset = US HEADERS_CHARSET; int header_insert_maxlen = 64 * 1024; header_line *header_last = NULL; @@ -853,8 +857,10 @@ uschar *local_interfaces = US"<; ::0 ; 0.0.0.0"; uschar *local_interfaces = US"0.0.0.0"; #endif +#ifdef HAVE_LOCAL_SCAN uschar *local_scan_data = NULL; int local_scan_timeout = 5*60; +#endif BOOL local_sender_retain = FALSE; gid_t local_user_gid = (gid_t)(-1); uid_t local_user_uid = (uid_t)(-1); diff --git a/src/src/globals.h b/src/src/globals.h index 63e0e424c..dbc706037 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -492,6 +492,10 @@ extern uschar *gecos_name; /* To be expanded when pattern matches */ extern uschar *gecos_pattern; /* Pattern to match */ extern rewrite_rule *global_rewrite_rules; /* Chain of rewriting rules */ +extern volatile sig_atomic_t had_command_timeout; /* Alarm sighandler called */ +extern volatile sig_atomic_t had_command_sigterm; /* TERM sighandler called */ +extern volatile sig_atomic_t had_data_timeout; /* Alarm sighandler called */ +extern volatile sig_atomic_t had_data_sigint; /* TERM/INT sighandler called */ extern int header_insert_maxlen; /* Max for inserting headers */ extern int header_maxsize; /* Max total length for header */ extern int header_line_maxsize; /* Max for an individual line */ @@ -544,10 +548,12 @@ extern BOOL local_from_check; /* For adding Sender: (global value) */ extern uschar *local_from_prefix; /* Permitted prefixes */ extern uschar *local_from_suffix; /* Permitted suffixes */ extern uschar *local_interfaces; /* For forcing specific interfaces */ +#ifdef HAVE_LOCAL_SCAN extern uschar *local_scan_data; /* Text returned by local_scan() */ extern optionlist local_scan_options[];/* Option list for local_scan() */ extern int local_scan_options_count; /* Size of the list */ extern int local_scan_timeout; /* Timeout for local_scan() */ +#endif extern BOOL local_sender_retain; /* Retain Sender: (with no From: check) */ extern gid_t local_user_gid; /* As it says; may be set in routers */ extern uid_t local_user_uid; /* As it says; may be set in routers */ diff --git a/src/src/readconf.c b/src/src/readconf.c index cbbef6efd..658719dff 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -195,7 +195,9 @@ static optionlist optionlist_config[] = { { "local_from_prefix", opt_stringptr, &local_from_prefix }, { "local_from_suffix", opt_stringptr, &local_from_suffix }, { "local_interfaces", opt_stringptr, &local_interfaces }, +#ifdef HAVE_LOCAL_SCAN { "local_scan_timeout", opt_time, &local_scan_timeout }, +#endif { "local_sender_retain", opt_bool, &local_sender_retain }, { "localhost_number", opt_stringptr, &host_number_string }, { "log_file_path", opt_stringptr, &log_file_path }, diff --git a/src/src/receive.c b/src/src/receive.c index 6a534dc87..39a0ed577 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -8,6 +8,7 @@ /* Code for receiving a message and setting up spool files. */ #include "exim.h" +#include #ifdef EXPERIMENTAL_DCC extern int dcc_ok; @@ -27,6 +28,12 @@ static uschar *spool_name = US""; enum CH_STATE {LF_SEEN, MID_LINE, CR_SEEN}; +#ifdef HAVE_LOCAL_SCAN +jmp_buf local_scan_env; /* error-handling context for local_scan */ +unsigned had_local_scan_crash; +unsigned had_local_scan_timeout; +#endif + /************************************************* * Non-SMTP character reading functions * @@ -40,7 +47,27 @@ changing the pointer variables.) */ int stdin_getc(unsigned lim) { -return getc(stdin); +int c = getc(stdin); + +if (had_data_timeout) + { + fprintf(stderr, "exim: timed out while reading - message abandoned\n"); + log_write(L_lost_incoming_connection, + LOG_MAIN, "timed out while reading local message"); + receive_bomb_out(US"data-timeout", NULL); /* Does not return */ + } +if (had_data_sigint) + { + if (filter_test == FTEST_NONE) + { + fprintf(stderr, "\nexim: %s received - message abandoned\n", + had_data_sigint == SIGTERM ? "SIGTERM" : "SIGINT"); + log_write(0, LOG_MAIN, "%s received while reading local message", + had_data_sigint == SIGTERM ? "SIGTERM" : "SIGINT"); + } + receive_bomb_out(US"signal-exit", NULL); /* Does not return */ + } +return c; } int @@ -316,11 +343,13 @@ if (spool_name[0] != '\0') /* Now close the file if it is open, either as a fd or a stream. */ -if (data_file != NULL) +if (data_file) { (void)fclose(data_file); data_file = NULL; -} else if (data_fd >= 0) { + } +else if (data_fd >= 0) + { (void)close(data_fd); data_fd = -1; } @@ -361,37 +390,29 @@ Returns: nothing static void data_timeout_handler(int sig) { -uschar *msg = NULL; - -sig = sig; /* Keep picky compilers happy */ - -if (smtp_input) - { - msg = US"SMTP incoming data timeout"; - log_write(L_lost_incoming_connection, - LOG_MAIN, "SMTP data timeout (message abandoned) on connection " - "from %s F=<%s>", - (sender_fullhost != NULL)? sender_fullhost : US"local process", - sender_address); - } -else - { - fprintf(stderr, "exim: timed out while reading - message abandoned\n"); - log_write(L_lost_incoming_connection, - LOG_MAIN, "timed out while reading local message"); - } - -receive_bomb_out(US"data-timeout", msg); /* Does not return */ +had_data_timeout = sig; } +#ifdef HAVE_LOCAL_SCAN /************************************************* * local_scan() timeout * *************************************************/ /* Handler function for timeouts that occur while running a local_scan() -function. +function. Posix recommends against calling longjmp() from a signal-handler, +but the GCC manual says you can so we will, and trust that it's better than +calling probably non-signal-safe funxtions during logging from within the +handler, even with other compilers. + +See also https://cwe.mitre.org/data/definitions/745.html which also lists +it as unsafe. + +This is all because we have no control over what might be written for a +local-scan function, so cannot sprinkle had-signal checks after each +call-site. At least with the default "do-nothing" function we won't +ever get here. Argument: the signal number Returns: nothing @@ -400,11 +421,8 @@ Returns: nothing static void local_scan_timeout_handler(int sig) { -sig = sig; /* Keep picky compilers happy */ -log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function timed out - " - "message temporarily rejected (size %d)", message_size); -/* Does not return */ -receive_bomb_out(US"local-scan-timeout", US"local verification problem"); +had_local_scan_timeout = sig; +siglongjmp(local_scan_env, 1); } @@ -423,12 +441,12 @@ Returns: nothing static void local_scan_crash_handler(int sig) { -log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function crashed with " - "signal %d - message temporarily rejected (size %d)", sig, message_size); -/* Does not return */ -receive_bomb_out(US"local-scan-error", US"local verification problem"); +had_local_scan_crash = sig; +siglongjmp(local_scan_env, 1); } +#endif /*HAVE_LOCAL_SCAN*/ + /************************************************* * SIGTERM or SIGINT received * @@ -444,26 +462,7 @@ Returns: nothing static void data_sigterm_sigint_handler(int sig) { -uschar *msg = NULL; - -if (smtp_input) - { - msg = US"Service not available - SIGTERM or SIGINT received"; - log_write(0, LOG_MAIN, "%s closed after %s", smtp_get_connection_info(), - (sig == SIGTERM)? "SIGTERM" : "SIGINT"); - } -else - { - if (filter_test == FTEST_NONE) - { - fprintf(stderr, "\nexim: %s received - message abandoned\n", - (sig == SIGTERM)? "SIGTERM" : "SIGINT"); - log_write(0, LOG_MAIN, "%s received while reading local message", - (sig == SIGTERM)? "SIGTERM" : "SIGINT"); - } - } - -receive_bomb_out(US"signal-exit", msg); /* Does not return */ +had_data_sigint = sig; } @@ -1678,6 +1677,7 @@ int dmarc_up = 0; uschar *timestamp; int tslen; + /* Release any open files that might have been cached while preparing to accept the message - e.g. by verifying addresses - because reading a message might take a fair bit of real time. */ @@ -1751,7 +1751,9 @@ received_time = message_id_tv; /* If SMTP input, set the special handler for timeouts. The alarm() calls happen in the smtp_getc() function when it refills its buffer. */ -if (smtp_input) os_non_restarting_signal(SIGALRM, data_timeout_handler); +had_data_timeout = 0; +if (smtp_input) + os_non_restarting_signal(SIGALRM, data_timeout_handler); /* If not SMTP input, timeout happens only if configured, and we just set a single timeout for the whole message. */ @@ -1764,6 +1766,7 @@ else if (receive_timeout > 0) /* SIGTERM and SIGINT are caught always. */ +had_data_sigint = 0; signal(SIGTERM, data_sigterm_sigint_handler); signal(SIGINT, data_sigterm_sigint_handler); @@ -3633,47 +3636,70 @@ dcc_ok = 0; #endif +#ifdef HAVE_LOCAL_SCAN /* The final check on the message is to run the scan_local() function. The version supplied with Exim always accepts, but this is a hook for sysadmins to supply their own checking code. The local_scan() function is run even when all the recipients have been discarded. */ -/*XXS could we avoid this for the standard case, given that few people will use it? */ lseek(data_fd, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET); /* Arrange to catch crashes in local_scan(), so that the -D file gets deleted, and the incident gets logged. */ -os_non_restarting_signal(SIGSEGV, local_scan_crash_handler); -os_non_restarting_signal(SIGFPE, local_scan_crash_handler); -os_non_restarting_signal(SIGILL, local_scan_crash_handler); -os_non_restarting_signal(SIGBUS, local_scan_crash_handler); - -DEBUG(D_receive) debug_printf("calling local_scan(); timeout=%d\n", - local_scan_timeout); -local_scan_data = NULL; - -os_non_restarting_signal(SIGALRM, local_scan_timeout_handler); -if (local_scan_timeout > 0) alarm(local_scan_timeout); -rc = local_scan(data_fd, &local_scan_data); -alarm(0); -os_non_restarting_signal(SIGALRM, sigalrm_handler); - -enable_dollar_recipients = FALSE; - -store_pool = POOL_MAIN; /* In case changed */ -DEBUG(D_receive) debug_printf("local_scan() returned %d %s\n", rc, - local_scan_data); - -os_non_restarting_signal(SIGSEGV, SIG_DFL); -os_non_restarting_signal(SIGFPE, SIG_DFL); -os_non_restarting_signal(SIGILL, SIG_DFL); -os_non_restarting_signal(SIGBUS, SIG_DFL); +if (sigsetjmp(local_scan_env, 1) == 0) + { + had_local_scan_crash = 0; + os_non_restarting_signal(SIGSEGV, local_scan_crash_handler); + os_non_restarting_signal(SIGFPE, local_scan_crash_handler); + os_non_restarting_signal(SIGILL, local_scan_crash_handler); + os_non_restarting_signal(SIGBUS, local_scan_crash_handler); + + DEBUG(D_receive) debug_printf("calling local_scan(); timeout=%d\n", + local_scan_timeout); + local_scan_data = NULL; + + had_local_scan_timeout = 0; + os_non_restarting_signal(SIGALRM, local_scan_timeout_handler); + if (local_scan_timeout > 0) alarm(local_scan_timeout); + rc = local_scan(data_fd, &local_scan_data); + alarm(0); + os_non_restarting_signal(SIGALRM, sigalrm_handler); + + enable_dollar_recipients = FALSE; + + store_pool = POOL_MAIN; /* In case changed */ + DEBUG(D_receive) debug_printf("local_scan() returned %d %s\n", rc, + local_scan_data); + + os_non_restarting_signal(SIGSEGV, SIG_DFL); + os_non_restarting_signal(SIGFPE, SIG_DFL); + os_non_restarting_signal(SIGILL, SIG_DFL); + os_non_restarting_signal(SIGBUS, SIG_DFL); + } +else + { + if (had_local_scan_crash) + { + log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function crashed with " + "signal %d - message temporarily rejected (size %d)", + had_local_scan_crash, message_size); + /* Does not return */ + receive_bomb_out(US"local-scan-error", US"local verification problem"); + } + if (had_local_scan_timeout) + { + log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function timed out - " + "message temporarily rejected (size %d)", message_size); + /* Does not return */ + receive_bomb_out(US"local-scan-timeout", US"local verification problem"); + } + } /* The length check is paranoia against some runaway code, and also because (for a success return) lines in the spool file are read into big_buffer. */ -if (local_scan_data != NULL) +if (local_scan_data) { int len = Ustrlen(local_scan_data); if (len > LOCAL_SCAN_MAX_RETURN) len = LOCAL_SCAN_MAX_RETURN; @@ -3705,7 +3731,7 @@ the spool file gets corrupted. Ensure that all recipients are qualified. */ if (rc == LOCAL_SCAN_ACCEPT) { - if (local_scan_data != NULL) + if (local_scan_data) { uschar *s; for (s = local_scan_data; *s != 0; s++) if (*s == '\n') *s = ' '; @@ -3798,6 +3824,7 @@ the message to be abandoned. */ signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); +#endif /* HAVE_LOCAL_SCAN */ /* Ensure the first time flag is set in the newly-received message. */ @@ -4328,9 +4355,11 @@ starting. */ if (blackholed_by) { - const uschar *detail = local_scan_data - ? string_printing(local_scan_data) - : string_sprintf("(%s discarded recipients)", blackholed_by); + const uschar *detail = +#ifdef HAVE_LOCAL_SCAN + local_scan_data ? string_printing(local_scan_data) : +#endif + string_sprintf("(%s discarded recipients)", blackholed_by); log_write(0, LOG_MAIN, "=> blackhole %s%s", detail, blackhole_log_msg); log_write(0, LOG_MAIN, "Completed"); message_id[0] = 0; diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 6cac7d2e2..823fcd27d 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -427,6 +427,53 @@ log_write(L_smtp_incomplete_transaction, LOG_MAIN|LOG_SENDER|LOG_RECIPIENTS, +void +smtp_command_timeout_exit(void) +{ +log_write(L_lost_incoming_connection, + LOG_MAIN, "SMTP command timeout on%s connection from %s", + tls_in.active >= 0 ? " TLS" : "", host_and_ident(FALSE)); +if (smtp_batched_input) + moan_smtp_batch(NULL, "421 SMTP command timeout"); /* Does not return */ +smtp_notquit_exit(US"command-timeout", US"421", + US"%s: SMTP command timeout - closing connection", + smtp_active_hostname); +exim_exit(EXIT_FAILURE, US"receiving"); +} + +void +smtp_command_sigterm_exit(void) +{ +log_write(0, LOG_MAIN, "%s closed after SIGTERM", smtp_get_connection_info()); +if (smtp_batched_input) + moan_smtp_batch(NULL, "421 SIGTERM received"); /* Does not return */ +smtp_notquit_exit(US"signal-exit", US"421", + US"%s: Service not available - closing connection", smtp_active_hostname); +exim_exit(EXIT_FAILURE, US"receiving"); +} + +void +smtp_data_timeout_exit(void) +{ +log_write(L_lost_incoming_connection, + LOG_MAIN, "SMTP data timeout (message abandoned) on connection from %s F=<%s>", + sender_fullhost ? sender_fullhost : US"local process", sender_address); +receive_bomb_out(US"data-timeout", US"SMTP incoming data timeout"); +/* Does not return */ +} + +void +smtp_data_sigint_exit(void) +{ +log_write(0, LOG_MAIN, "%s closed after %s", + smtp_get_connection_info(), had_data_sigint == SIGTERM ? "SIGTERM":"SIGINT"); +receive_bomb_out(US"signal-exit", + US"Service not available - SIGTERM or SIGINT received"); +/* Does not return */ +} + + + /* Refill the buffer, and notify DKIM verification code. Return false for error or EOF. */ @@ -443,18 +490,28 @@ if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout); rc = read(fileno(smtp_in), smtp_inbuffer, MIN(IN_BUFFER_SIZE, lim)); save_errno = errno; -alarm(0); +if (smtp_receive_timeout > 0) alarm(0); if (rc <= 0) { /* Must put the error text in fixed store, because this might be during header reading, where it releases unused store above the header. */ if (rc < 0) { + if (had_command_timeout) /* set by signal handler */ + smtp_command_timeout_exit(); /* does not return */ + if (had_command_sigterm) + smtp_command_sigterm_exit(); + if (had_data_timeout) + smtp_data_timeout_exit(); + if (had_data_sigint) + smtp_data_sigint_exit(); + smtp_had_error = save_errno; smtp_read_error = string_copy_malloc( string_sprintf(" (error: %s)", strerror(save_errno))); } - else smtp_had_eof = 1; + else + smtp_had_eof = 1; return FALSE; } #ifndef DISABLE_DKIM @@ -916,16 +973,7 @@ Returns: nothing static void command_timeout_handler(int sig) { -sig = sig; /* Keep picky compilers happy */ -log_write(L_lost_incoming_connection, - LOG_MAIN, "SMTP command timeout on%s connection from %s", - (tls_in.active >= 0)? " TLS" : "", - host_and_ident(FALSE)); -if (smtp_batched_input) - moan_smtp_batch(NULL, "421 SMTP command timeout"); /* Does not return */ -smtp_notquit_exit(US"command-timeout", US"421", - US"%s: SMTP command timeout - closing connection", smtp_active_hostname); -exim_exit(EXIT_FAILURE, US"receiving"); +had_command_timeout = sig; } @@ -943,13 +991,7 @@ Returns: nothing static void command_sigterm_handler(int sig) { -sig = sig; /* Keep picky compilers happy */ -log_write(0, LOG_MAIN, "%s closed after SIGTERM", smtp_get_connection_info()); -if (smtp_batched_input) - moan_smtp_batch(NULL, "421 SIGTERM received"); /* Does not return */ -smtp_notquit_exit(US"signal-exit", US"421", - US"%s: Service not available - closing connection", smtp_active_hostname); -exim_exit(EXIT_FAILURE, US"receiving"); +had_command_sigterm = sig; } @@ -1509,6 +1551,7 @@ int ptr = 0; smtp_cmd_list *p; BOOL hadnull = FALSE; +had_command_timeout = 0; os_non_restarting_signal(SIGALRM, command_timeout_handler); while ((c = (receive_getc)(buffer_lim)) != '\n' && c != EOF) @@ -3801,6 +3844,7 @@ cmd_list[CMD_LIST_STARTTLS].is_mail_cmd = TRUE; /* Set the local signal handler for SIGTERM - it tries to end off tidily */ +had_command_sigterm = 0; os_non_restarting_signal(SIGTERM, command_sigterm_handler); /* Batched SMTP is handled in a different function. */ diff --git a/src/src/spool_in.c b/src/src/spool_in.c index e34b54171..0a281f432 100644 --- a/src/src/spool_in.c +++ b/src/src/spool_in.c @@ -231,7 +231,9 @@ host_lookup_failed = FALSE; interface_address = NULL; interface_port = 0; local_error_message = FALSE; +#ifdef HAVE_LOCAL_SCAN local_scan_data = NULL; +#endif max_received_linelength = 0; message_linecount = 0; received_protocol = NULL; @@ -589,8 +591,10 @@ for (;;) sender_local = TRUE; else if (Ustrcmp(big_buffer, "-localerror") == 0) local_error_message = TRUE; +#ifdef HAVE_LOCAL_SCAN else if (Ustrncmp(p, "ocal_scan ", 10) == 0) local_scan_data = string_copy(big_buffer + 12); +#endif break; case 'm': diff --git a/src/src/spool_out.c b/src/src/spool_out.c index 8bebf1074..a6ab3754e 100644 --- a/src/src/spool_out.c +++ b/src/src/spool_out.c @@ -221,7 +221,9 @@ if (host_lookup_deferred) fprintf(f, "-host_lookup_deferred\n"); if (host_lookup_failed) fprintf(f, "-host_lookup_failed\n"); if (sender_local) fprintf(f, "-local\n"); if (local_error_message) fprintf(f, "-localerror\n"); -if (local_scan_data != NULL) fprintf(f, "-local_scan %s\n", local_scan_data); +#ifdef HAVE_LOCAL_SCAN +if (local_scan_data) fprintf(f, "-local_scan %s\n", local_scan_data); +#endif #ifdef WITH_CONTENT_SCAN if (spam_bar) fprintf(f,"-spam_bar %s\n", spam_bar); if (spam_score) fprintf(f,"-spam_score %s\n", spam_score); @@ -231,7 +233,7 @@ if (deliver_manual_thaw) fprintf(f, "-manual_thaw\n"); if (sender_set_untrusted) fprintf(f, "-sender_set_untrusted\n"); #ifdef EXPERIMENTAL_BRIGHTMAIL -if (bmi_verdicts != NULL) fprintf(f, "-bmi_verdicts %s\n", bmi_verdicts); +if (bmi_verdicts) fprintf(f, "-bmi_verdicts %s\n", bmi_verdicts); #endif #ifdef SUPPORT_TLS diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index d73188277..35816cd60 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -2511,12 +2511,20 @@ sigalrm_seen = FALSE; if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout); inbytes = gnutls_record_recv(state->session, state->xfer_buffer, MIN(ssl_xfer_buffer_size, lim)); -alarm(0); - -/* Timeouts do not get this far; see command_timeout_handler(). - A zero-byte return appears to mean that the TLS session has been - closed down, not that the socket itself has been closed down. Revert to - non-TLS handling. */ +if (smtp_receive_timeout > 0) alarm(0); + +if (had_command_timeout) /* set by signal handler */ + smtp_command_timeout_exit(); /* does not return */ +if (had_command_sigterm) + smtp_command_sigterm_exit(); +if (had_data_timeout) + smtp_data_timeout_exit(); +if (had_data_sigint) + smtp_data_sigint_exit(); + +/* Timeouts do not get this far. A zero-byte return appears to mean that the +TLS session has been closed down, not that the socket itself has been closed +down. Revert to non-TLS handling. */ if (sigalrm_seen) { diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index c142bd059..5e3edbb40 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -2469,7 +2469,16 @@ if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout); inbytes = SSL_read(server_ssl, CS ssl_xfer_buffer, MIN(ssl_xfer_buffer_size, lim)); error = SSL_get_error(server_ssl, inbytes); -alarm(0); +if (smtp_receive_timeout > 0) alarm(0); + +if (had_command_timeout) /* set by signal handler */ + smtp_command_timeout_exit(); /* does not return */ +if (had_command_sigterm) + smtp_command_sigterm_exit(); +if (had_data_timeout) + smtp_data_timeout_exit(); +if (had_data_sigint) + smtp_data_sigint_exit(); /* SSL_ERROR_ZERO_RETURN appears to mean that the SSL session has been closed down, not that the socket itself has been closed down. Revert to diff --git a/test/confs/0001 b/test/confs/0001 index 471c8f817..fc2ae3eaf 100644 --- a/test/confs/0001 +++ b/test/confs/0001 @@ -95,7 +95,6 @@ no_local_from_check local_from_prefix = *- local_from_suffix = =* local_interfaces = -local_scan_timeout = 10s local_sender_retain localhost_number = "3 " log_selector = \ diff --git a/test/stderr/0465 b/test/stderr/0465 index 52dcbf3d5..68bba6ee1 100644 --- a/test/stderr/0465 +++ b/test/stderr/0465 @@ -84,8 +84,6 @@ processing "accept" check verify = header_syntax accept: condition test succeeded in ACL "check_data" end of ACL "check_data": ACCEPT -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 diff --git a/test/stderr/0471 b/test/stderr/0471 index fb5c986dd..3a5aa1c7b 100644 --- a/test/stderr/0471 +++ b/test/stderr/0471 @@ -25375,8 +25375,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaX-0005vi-00 for r1@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 diff --git a/test/stderr/0487 b/test/stderr/0487 index ad2daa2f8..9064bef64 100644 --- a/test/stderr/0487 +++ b/test/stderr/0487 @@ -59,8 +59,6 @@ P Received: from CALLER (helo=x.y) (envelope-from ) id 10HmaX-0005vi-00 for userx@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 diff --git a/test/stderr/0489 b/test/stderr/0489 index e1b955b4f..2834338ff 100644 --- a/test/stderr/0489 +++ b/test/stderr/0489 @@ -23,8 +23,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaX-0005vi-00 for X@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp Renaming spool header file: TESTSUITE/spool//input//10HmaX-0005vi-00-H Size of headers = sss @@ -57,8 +55,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaY-0005vi-00 for X@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp Renaming spool header file: TESTSUITE/spool//input//10HmaY-0005vi-00-H Size of headers = sss @@ -90,8 +86,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaZ-0005vi-00 for X@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp Renaming spool header file: TESTSUITE/spool//input//10HmaZ-0005vi-00-H Size of headers = sss @@ -123,8 +117,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmbA-0005vi-00 for X@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp Renaming spool header file: TESTSUITE/spool//input//10HmbA-0005vi-00-H Size of headers = sss @@ -156,8 +148,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmbB-0005vi-00 for X@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp Renaming spool header file: TESTSUITE/spool//input//10HmbB-0005vi-00-H Size of headers = sss @@ -189,8 +179,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmbC-0005vi-00 for X@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp Renaming spool header file: TESTSUITE/spool//input//10HmbC-0005vi-00-H Size of headers = sss @@ -222,8 +210,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmbD-0005vi-00 for X@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp Renaming spool header file: TESTSUITE/spool//input//10HmbD-0005vi-00-H Size of headers = sss @@ -255,8 +241,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmbE-0005vi-00 for X@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp Renaming spool header file: TESTSUITE/spool//input//10HmbE-0005vi-00-H Size of headers = sss diff --git a/test/stderr/0575 b/test/stderr/0575 index 73467881a..480cef4b8 100644 --- a/test/stderr/0575 +++ b/test/stderr/0575 @@ -48,8 +48,6 @@ P Received: from [V4NET.0.0.0] (envelope-from ) id 10HmaX-0005vi-00 for x@y; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL LOG: MAIN <= x@y H=[V4NET.0.0.0] P=smtp S=sss SMTP>> 250 OK id=10HmaX-0005vi-00 diff --git a/test/stderr/2600 b/test/stderr/2600 index 700e78589..47ee39a4a 100644 --- a/test/stderr/2600 +++ b/test/stderr/2600 @@ -319,8 +319,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaX-0005vi-00 for userx@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 diff --git a/test/stderr/2610 b/test/stderr/2610 index 0a16c1109..58b508f3c 100644 --- a/test/stderr/2610 +++ b/test/stderr/2610 @@ -312,8 +312,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaX-0005vi-00 for ph10@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 diff --git a/test/stderr/2620 b/test/stderr/2620 index 32e83b03f..29a4f629c 100644 --- a/test/stderr/2620 +++ b/test/stderr/2620 @@ -330,8 +330,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaX-0005vi-00 for CALLER@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 diff --git a/test/stderr/5004 b/test/stderr/5004 index 95ccd88cc..21fad61cc 100644 --- a/test/stderr/5004 +++ b/test/stderr/5004 @@ -35,8 +35,6 @@ P Received: from CALLER by mail.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaX-0005vi-00 for userx@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 diff --git a/test/stderr/5005 b/test/stderr/5005 index 463d71c3c..76d2851dd 100644 --- a/test/stderr/5005 +++ b/test/stderr/5005 @@ -33,8 +33,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaX-0005vi-00 for nofile@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 @@ -223,8 +221,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaY-0005vi-00 for userx@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 @@ -413,8 +409,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaZ-0005vi-00 for userx@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 @@ -612,8 +606,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmbA-0005vi-00 for userx@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 diff --git a/test/stderr/5006 b/test/stderr/5006 index 2a0b9d10f..8e120f627 100644 --- a/test/stderr/5006 +++ b/test/stderr/5006 @@ -33,8 +33,6 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz) (envelope-from ) id 10HmaX-0005vi-00 for userx@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -calling local_scan(); timeout=300 -local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp DSN: Write SPOOL :-dsn_envid NULL DSN: Write SPOOL :-dsn_ret 0 diff --git a/test/stdout/0574 b/test/stdout/0574 index a9d9cd9d2..36d612eae 100644 --- a/test/stdout/0574 +++ b/test/stdout/0574 @@ -33,8 +33,6 @@ Connecting to 127.0.0.1 port 1225 ... connected End of script accept: condition test succeeded in ACL "chk_data" end of ACL "chk_data": ACCEPT -calling local_scan(); timeout=300 -local_scan() returned 0 NULL ┌considering: ${tod_full} ├──expanding: ${tod_full} └─────result: Tue, 2 Mar 1999 09:44:33 +0000 -- cgit v1.2.3 From 27a79307f48631bbefe9abb6f399da0e8e4b46d1 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 20 Mar 2018 19:58:00 +0000 Subject: ARC: on the smtp transport option take empty or forced-fail to disable signing --- doc/doc-txt/experimental-spec.txt | 1 + src/src/transports/smtp.c | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 839200c6c..3389632a2 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -802,6 +802,7 @@ arc_sign = : : An option on the smtp transport, which constructs and prepends to the message an ARC set of headers. The textually-first Authentication-Results: header is used as a basis (you must have added one on entry to the ADMD). +Expanded; if unset, empty or forced-failure then no signing is done. diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index bd1e20d7f..2dfb5b73a 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -3004,15 +3004,21 @@ else uschar * s = sx.ob->arc_sign; if (s) { - if (!(sx.ob->dkim.arc_signspec = expand_string(s))) + if (!(sx.ob->dkim.arc_signspec = s = expand_string(s))) { - message = US"failed to expand arc_sign"; - sx.ok = FALSE; - goto SEND_FAILED; + if (!expand_string_forcedfail) + { + message = US"failed to expand arc_sign"; + sx.ok = FALSE; + goto SEND_FAILED; + } + } + else if (*s) + { + /* Ask dkim code to hash the body for ARC */ + (void) arc_ams_setup_sign_bodyhash(); + sx.ob->dkim.force_bodyhash = TRUE; } - /* Ask dkim code to hash the body for ARC */ - (void) arc_ams_setup_sign_bodyhash(); - sx.ob->dkim.force_bodyhash = TRUE; } } # endif -- cgit v1.2.3 From 59066f8faa347e2d1858f30066cbba6d82ffce0c Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 20 Mar 2018 22:11:24 +0000 Subject: ARC: AS header should have no c= tag --- src/src/arc.c | 2 +- test/mail/4560.a | 88 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 45 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/src/arc.c b/src/src/arc.c index a749c78ef..e1fef6fb8 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -1416,7 +1416,7 @@ arcset = string_append(NULL, 10, ARC_HDR_AS, US" i=", string_sprintf("%d", instance), US"; cv=", status, - US"; a=rsa-sha256; c=relaxed; d=", identity, /*XXX hardwired */ + US"; a=rsa-sha256; d=", identity, /*XXX hardwired */ US"; s=", selector, /*XXX same as AMS */ US";\r\n\t b=;"); diff --git a/test/mail/4560.a b/test/mail/4560.a index 9ddcd2ae1..04e723698 100644 --- a/test/mail/4560.a +++ b/test/mail/4560.a @@ -7,10 +7,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmaY-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=1; cv=none; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=XLcAAITo9Vf1e7bfAAZQGHFU1YySleXuf5+r2KI9kYNg8hmFsv6p91L679/gYfo7XGzo6pl9Xh - +CXJIttJnXkgGx+zRg4hRoAqr3VNqDYA/IDvvglQCdBVu2/4JS1cPCznuW6RdTLR6b7kMx11Cu - jd3NsmP38X0Zo8mRETF+TLU=; +ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; + b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA + +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN + mh1ISayCaAxP5vZXsxKJ7Sk=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; @@ -39,10 +39,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbB-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=2; cv=pass; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=p0S5hu7O1X0QEtH5WHBKTSlksX8Q09cpDll3kZxgLv8bcq4aAVc+hk2ajkzlwplg3ArBTSx79R - D4CB+BB3x5p4oB+VwgVSS+Fz/EFFxgEht4xKqPFJ/Xqi3SFdy0+vxdZ6d0z7sOE6pchlxooFhH - QMpkkGVVGT+uT4MqnexuTjY=; +ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel; + b=Gw0rnpSzWYrk0pESlvrgJ6U9Fv1r7BxNxp1uNw+OvylVt9JuuFEfTQ1+wJzu1RkJK9yctGI//X + FiHjdEexgjjU38fOxWlVQyfhpPReuXs+dO0vHDfipIvIFuAkTXczUlRSRr+N+he6JTL33eDeFd + mpyVa6MMt2CdB8mUulbMEdE=; ARC-Authentication-Results: i=2; test.ex; iprev=pass (localhost); arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 @@ -60,10 +60,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbA-0005vi-00 for za@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=1; cv=none; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=XLcAAITo9Vf1e7bfAAZQGHFU1YySleXuf5+r2KI9kYNg8hmFsv6p91L679/gYfo7XGzo6pl9Xh - +CXJIttJnXkgGx+zRg4hRoAqr3VNqDYA/IDvvglQCdBVu2/4JS1cPCznuW6RdTLR6b7kMx11Cu - jd3NsmP38X0Zo8mRETF+TLU=; +ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; + b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA + +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN + mh1ISayCaAxP5vZXsxKJ7Sk=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; @@ -92,10 +92,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbF-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=3; cv=pass; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=f9LBNUaiOCFYXDo/Qj0MeW9NwX4CszFtZjfvnjvlfDc6WM28bQyEqMQBWNt+vApDne+LPsLGW/ - 28MQ4CQf6a3OZDtENt704sxqrwFPgaJhjNx79Yn5yWfqX6YFcTc/tI3DZzLMScUCPSfVGTsNwB - J9vb4zPdN+QJ+viTsyMRQ4Y=; +ARC-Seal: i=3; cv=pass; a=rsa-sha256; d=test.ex; s=sel; + b=RcSJycBgTIQO9dOXE36ESKpl/550ykTZwQdtDPlGKaj4bZdbtSEeIRkdKOkwAwuQb+uSCGeaSH + 36LmxlBJzZ+hs8l7WoTEv/514qyEbaokW1DkfSDQ7IRsHOB0roVUliAIcbc7fiO9Fiuo4M1yIT + asqHipuA9TCAMIeqO4QuyT4=; ARC-Authentication-Results: i=3; test.ex; iprev=pass (localhost); arc=pass (i=2) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1 @@ -113,10 +113,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbE-0005vi-00 for za@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=2; cv=pass; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=VFGK3ThSLHrT5Zn9w3dPive+GXVNu/sYyfb6i64d8GiAf0fAcD8cSqiQizsuABJIkJzcTfQEw/ - g4ihDDhg3Mz3FgvWbsNbBfoDVy/PZ3xCp0XFEOh7joTr1N42yolOwt1BFbZw8CvKLv0x+p1Zhb - ZIdrz8ZGocPUB2HB8m0h+NA=; +ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel; + b=PisKqTHCNjT5OBFxx3tSp8wLuNXxL9kN8owfn6ueRBSUjWjRx/GFUpa/gPut04/qcTt8MHvamq + rG8f6KBkoD4D8+zZrE9J13RI0v2vR3DUSdhzGjAHRwyAIWaHm7lvu3R5ze6GF0vHmtvFZpApCa + hbMYARUVb7VvXJAhQdLE3oE=; ARC-Authentication-Results: i=2; test.ex; iprev=pass (localhost); arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 @@ -134,10 +134,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbD-0005vi-00 for mza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=1; cv=none; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=XLcAAITo9Vf1e7bfAAZQGHFU1YySleXuf5+r2KI9kYNg8hmFsv6p91L679/gYfo7XGzo6pl9Xh - +CXJIttJnXkgGx+zRg4hRoAqr3VNqDYA/IDvvglQCdBVu2/4JS1cPCznuW6RdTLR6b7kMx11Cu - jd3NsmP38X0Zo8mRETF+TLU=; +ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; + b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA + +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN + mh1ISayCaAxP5vZXsxKJ7Sk=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; @@ -170,10 +170,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbK-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=3; cv=fail; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=uamKZbfYVEc5YSkTjyr588o4KIEF8g6bZ1RzC46wkJifmP0pML666Vvc0lTSsf5MmMcBLl+fTV - kVUTGZYjjRU1eTVNShszYPk5LBUPH2nY8h1th4PFsHNxLRzP4sSOEGc4yZjYsG8zYkDGgEPzLH - Uw0J+Oa0vRcx2ZW+jZrrd5U=; +ARC-Seal: i=3; cv=fail; a=rsa-sha256; d=test.ex; s=sel; + b=cdGeRgKBXmi4ZuxBGCLHkZN5io4rurCl7k7ESImcC4FcQFq1giqpFeD2lipCeWvSpx9FpRbXCI + OQyRZB3ZVbjSsuacqUWz78Y5Z15M6g/OrNRwC+wLyGI/Dfg1jwJCp7dtxUMvOfvX/fnII57Y9D + ULyV72U2yGs4E+khjk2Fgdw=; ARC-Authentication-Results: i=3; test.ex; iprev=pass (localhost); arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1 @@ -199,10 +199,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbI-0005vi-00 for mza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=2; cv=pass; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=p0S5hu7O1X0QEtH5WHBKTSlksX8Q09cpDll3kZxgLv8bcq4aAVc+hk2ajkzlwplg3ArBTSx79R - D4CB+BB3x5p4oB+VwgVSS+Fz/EFFxgEht4xKqPFJ/Xqi3SFdy0+vxdZ6d0z7sOE6pchlxooFhH - QMpkkGVVGT+uT4MqnexuTjY=; +ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel; + b=Gw0rnpSzWYrk0pESlvrgJ6U9Fv1r7BxNxp1uNw+OvylVt9JuuFEfTQ1+wJzu1RkJK9yctGI//X + FiHjdEexgjjU38fOxWlVQyfhpPReuXs+dO0vHDfipIvIFuAkTXczUlRSRr+N+he6JTL33eDeFd + mpyVa6MMt2CdB8mUulbMEdE=; ARC-Authentication-Results: i=2; test.ex; iprev=pass (localhost); arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 @@ -220,10 +220,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbH-0005vi-00 for zmza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=1; cv=none; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=XLcAAITo9Vf1e7bfAAZQGHFU1YySleXuf5+r2KI9kYNg8hmFsv6p91L679/gYfo7XGzo6pl9Xh - +CXJIttJnXkgGx+zRg4hRoAqr3VNqDYA/IDvvglQCdBVu2/4JS1cPCznuW6RdTLR6b7kMx11Cu - jd3NsmP38X0Zo8mRETF+TLU=; +ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; + b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA + +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN + mh1ISayCaAxP5vZXsxKJ7Sk=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; @@ -264,10 +264,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbM-0005vi-00 for za@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=1; cv=none; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=XLcAAITo9Vf1e7bfAAZQGHFU1YySleXuf5+r2KI9kYNg8hmFsv6p91L679/gYfo7XGzo6pl9Xh - +CXJIttJnXkgGx+zRg4hRoAqr3VNqDYA/IDvvglQCdBVu2/4JS1cPCznuW6RdTLR6b7kMx11Cu - jd3NsmP38X0Zo8mRETF+TLU=; +ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; + b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA + +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN + mh1ISayCaAxP5vZXsxKJ7Sk=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; @@ -299,10 +299,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex) (envelope-from ) id 10HmbP-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 -ARC-Seal: i=2; cv=fail; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; - b=MQwdR5nlxQNXdo/J3hK8voFybIpzoj3/32eQHLm8rJ0zOfAiJEOB4TKsvhRvn+ErtTRzoQsCrk - aY4hSDnUsxPbgawzMeC3QpidYlXOyfNrS6B4wBoaRM2pbAIZytVT0MjZu9g+qrUnv2cOsveQI3 - ApDVpyZaYfDdcepyBOm5//4=; +ARC-Seal: i=2; cv=fail; a=rsa-sha256; d=test.ex; s=sel; + b=bID/N3wfd1l6ac20RCPn+pVvXigyjdZRMuub+N4VGA/c6Nw41LDmhgxEHqSUhNxri2KYGV3BPw + Qp9RWx7lS2o6nnrrKBi/tdlE164GWpFNH5qetZZKuaEtZ0box3qUNwMpjzZZOhHNPzDXsztTLG + M4/bKjEuvxwND7oliqhn3mg=; ARC-Authentication-Results: i=2; test.ex; dkim=pass header.d=dmarc.org header.s=clochette header.a=rsa-sha256; dkim=fail (body hash mismatch; body probably modified in transit) -- cgit v1.2.3 From d64f251592db09252ac0584adbe72a2eeb9ca122 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Fri, 23 Mar 2018 11:06:35 +0000 Subject: ARC: add independent-source testcase. Fix signatures by not line-terminating last header line being hashed. --- src/src/arc.c | 16 ++-- src/src/pdkim/pdkim.c | 14 ++- test/aux-fixed/4560.msg1.txt | 8 ++ test/aux-fixed/dkim/sign_arc.pl | 51 +++++++++++ test/log/4560 | 124 +++++++++++++------------ test/mail/4560.a | 198 +++++++++++++++++++++++----------------- test/scripts/4560-ARC/4560 | 42 +++++++++ 7 files changed, 298 insertions(+), 155 deletions(-) create mode 100644 test/aux-fixed/4560.msg1.txt create mode 100644 test/aux-fixed/dkim/sign_arc.pl (limited to 'src') diff --git a/src/src/arc.c b/src/src/arc.c index e1fef6fb8..a0e2184bd 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -564,11 +564,11 @@ while ((hn = string_nextinlist(&headernames, &sep, NULL, 0))) break; } -/* Finally add in the signature header (with the b= tag stripped) */ +/* Finally add in the signature header (with the b= tag stripped); no CRLF */ s = ams->rawsig_no_b_val.data, len = ams->rawsig_no_b_val.len; if (relaxed) - len = Ustrlen(s = pdkim_relax_header_n(s, len, TRUE)); + len = Ustrlen(s = pdkim_relax_header_n(s, len, FALSE)); DEBUG(D_acl) pdkim_quoteprint(s, len); exim_sha_update(&hhash_ctx, s, len); @@ -865,6 +865,8 @@ if (!exim_sha_init(&hhash_ctx, pdkim_hashes[hashtype].exim_hashmethod)) header canonicalization defined in Section 3.4.2 of [RFC6376]. Pass the canonicalized result to the hash function. + +Headers are CRLF-separated, but the last one is not crlf-terminated. */ DEBUG(D_acl) debug_printf("ARC: AS header data for verification:\n"); @@ -895,7 +897,7 @@ for (as2 = ctx->arcset_chain; al = as2->hdr_as; if (as2->instance == as->instance) s = pdkim_relax_header_n(al->rawsig_no_b_val.data, - al->rawsig_no_b_val.len, TRUE); + al->rawsig_no_b_val.len, FALSE); else if (!(s = al->relaxed)) al->relaxed = s = pdkim_relax_header_n(al->complete->text, al->complete->slen, TRUE); @@ -952,7 +954,7 @@ if ((errstr = exim_dkim_verify(&vctx, { DEBUG(D_acl) debug_printf("ARC i=%d AS headers verify: %s\n", as->instance, errstr); - arc_state_reason = US"seal sigverify init error"; + arc_state_reason = US"seal sigverify error"; return US"fail"; } @@ -1328,10 +1330,8 @@ if (g->s[g->ptr - 1] == ':') g->ptr--; g = string_catn(g, US";\r\n\tb=;", 7); /* Include the pseudo-header in the accumulation */ -/*XXX should that be prepended rather than appended? */ -/*XXX also need to include at the verify stage */ -s = pdkim_relax_header_n(g->s + ams_off, g->ptr - ams_off, TRUE); +s = pdkim_relax_header_n(g->s + ams_off, g->ptr - ams_off, FALSE); hdata = string_cat(hdata, s); /* Calculate the signature from the accumulation */ @@ -1440,7 +1440,7 @@ for (as = Ustrcmp(status, US"fail") == 0 h = as->hdr_ams->complete; hdata = string_cat(hdata, pdkim_relax_header_n(h->text, h->slen, TRUE)); h = as->hdr_as->complete; - hdata = string_cat(hdata, pdkim_relax_header_n(h->text, h->slen, TRUE)); + hdata = string_cat(hdata, pdkim_relax_header_n(h->text, h->slen, !!as->next)); } /* Calculate the signature from the accumulation */ diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index 457d83efc..2a66909ba 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -1712,11 +1712,19 @@ for (sig = ctx->sig; sig; sig = sig->next) sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR; DEBUG(D_acl) debug_printf( - " Error in DKIM-Signature header: tags missing or invalid\n" - "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); + " Error in DKIM-Signature header: tags missing or invalid (%s)\n" + "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", + !(sig->domain && *sig->domain) ? "d=" + : !(sig->selector && *sig->selector) ? "s=" + : !(sig->headernames && *sig->headernames) ? "h=" + : !sig->bodyhash.data ? "bh=" + : !sig->sighash.data ? "b=" + : sig->keytype < 0 || sig->hashtype < 0 ? "a=" + : "v=" + ); goto NEXT_VERIFY; } - + /* Make sure sig uses supported DKIM version (only v1) */ if (sig->version != 1) { diff --git a/test/aux-fixed/4560.msg1.txt b/test/aux-fixed/4560.msg1.txt new file mode 100644 index 000000000..d35aaae14 --- /dev/null +++ b/test/aux-fixed/4560.msg1.txt @@ -0,0 +1,8 @@ +Authentication-Results: test.ex; arc=none +From: mrgus@text.ex +To: bakawolf@yahoo.com +Date: Thu, 19 Nov 2015 17:00:07 -0700 +Message-ID: +Subject: simple test + +This is a simple test. diff --git a/test/aux-fixed/dkim/sign_arc.pl b/test/aux-fixed/dkim/sign_arc.pl new file mode 100644 index 000000000..acf40ca9f --- /dev/null +++ b/test/aux-fixed/dkim/sign_arc.pl @@ -0,0 +1,51 @@ +use Mail::DKIM::ARC::Signer; +use Mail::DKIM::TextWrap; #recommended +use Getopt::Long; + +# default option values +my $method = "simple/simple"; +my $selector = "sel"; +my $keyfile = "aux-fixed/dkim/dkim.private"; +my $algorithm = "rsa-sha256"; + +GetOptions( + "method=s" => \$method, + "selector=s" => \$selector, + "keyfile=s" => \$keyfile, + "algorithm=s" => \$algorithm, +); + +# create a signer object +my $signer = Mail::DKIM::ARC::Signer->new( + Algorithm => $algorithm, + Chain => 'none', # or pass|fail|ar + Domain => 'test.ex', + SrvId => 'test.ex', + Selector => $selector, + KeyFile => $keyfile, + Headers => 'x-header:x-header2', + ); + + + # NOTE: any email being ARC signed must have an Authentication-Results + # header so that the ARC seal can cover those results copied into + # an ARC-Authentication-Results header. + +# read an email and pass it into the signer, one line at a time +while () +{ + # remove local line terminators + chomp; + s/\015$//; + + # use SMTP line terminators + $signer->PRINT("$_\015\012"); +} +$signer->CLOSE; + +die 'Failed' . $signer->result_details() unless $signer->result() eq 'sealed'; + +# Get all the signature headers to prepend to the message +# ARC-Seal, ARC-Message-Signature and ARC-Authentication-Results +# in that order. +print $signer->as_string; diff --git a/test/log/4560 b/test/log/4560 index 887655969..88f7ff2f7 100644 --- a/test/log/4560 +++ b/test/log/4560 @@ -1,127 +1,133 @@ ******** SERVER ******** 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 -1999-03-02 09:44:33 10HmaX-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for za@test.ex +1999-03-02 09:44:33 10HmaX-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss ARC id=qwerty1234@disco-zombie.net for a@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp -1999-03-02 09:44:33 10HmaY-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex -1999-03-02 09:44:33 10HmaX-0005vi-00 => a@test.ex R=fwd T=tsmtp 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 => a R=d1 T=tfile 1999-03-02 09:44:33 10HmaX-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmaY-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for za@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp -1999-03-02 09:44:33 10HmaY-0005vi-00 => a R=d1 T=tfile +1999-03-02 09:44:33 10HmaZ-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex +1999-03-02 09:44:33 10HmaY-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaZ-0005vi-00" 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 10HmaZ-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zza@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp -1999-03-02 09:44:33 10HmbA-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex -1999-03-02 09:44:33 10HmaZ-0005vi-00 => za@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbA-0005vi-00" +1999-03-02 09:44:33 10HmaZ-0005vi-00 => a R=d1 T=tfile 1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmbA-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zza@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp 1999-03-02 09:44:33 10HmbB-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex -1999-03-02 09:44:33 10HmbA-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbB-0005vi-00" +1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex +1999-03-02 09:44:33 10HmbA-0005vi-00 => za@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbB-0005vi-00" 1999-03-02 09:44:33 10HmbA-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp 1999-03-02 09:44:33 Start queue run: pid=pppp -1999-03-02 09:44:33 10HmbB-0005vi-00 => a R=d1 T=tfile +1999-03-02 09:44:33 10HmbC-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex +1999-03-02 09:44:33 10HmbB-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbC-0005vi-00" 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp -1999-03-02 09:44:33 10HmbC-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zmza@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp -1999-03-02 09:44:33 10HmbD-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@test.ex -1999-03-02 09:44:33 10HmbC-0005vi-00 => mza@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbD-0005vi-00" +1999-03-02 09:44:33 10HmbC-0005vi-00 => a R=d1 T=tfile 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmbD-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zmza@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp 1999-03-02 09:44:33 10HmbE-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex -1999-03-02 09:44:33 10HmbD-0005vi-00 => za@test.ex R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbE-0005vi-00" +1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@test.ex +1999-03-02 09:44:33 10HmbD-0005vi-00 => mza@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbE-0005vi-00" 1999-03-02 09:44:33 10HmbD-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 10HmbF-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex -1999-03-02 09:44:33 10HmbE-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbF-0005vi-00" +1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex +1999-03-02 09:44:33 10HmbE-0005vi-00 => za@test.ex R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbF-0005vi-00" 1999-03-02 09:44:33 10HmbE-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 10HmbF-0005vi-00 => a R=d1 T=tfile +1999-03-02 09:44:33 10HmbG-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex +1999-03-02 09:44:33 10HmbF-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbG-0005vi-00" 1999-03-02 09:44:33 10HmbF-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp -1999-03-02 09:44:33 10HmbG-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zzmza@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp -1999-03-02 09:44:33 10HmbH-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for zmza@test.ex -1999-03-02 09:44:33 10HmbG-0005vi-00 => zmza@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbH-0005vi-00" +1999-03-02 09:44:33 10HmbG-0005vi-00 => a R=d1 T=tfile 1999-03-02 09:44:33 10HmbG-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmbH-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zzmza@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp 1999-03-02 09:44:33 10HmbI-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbI-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@test.ex -1999-03-02 09:44:33 10HmbH-0005vi-00 => mza@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbI-0005vi-00" +1999-03-02 09:44:33 10HmbI-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for zmza@test.ex +1999-03-02 09:44:33 10HmbH-0005vi-00 => zmza@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbI-0005vi-00" 1999-03-02 09:44:33 10HmbH-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 10HmbJ-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbJ-0005vi-00 reason: -1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for za@test.ex -1999-03-02 09:44:33 10HmbI-0005vi-00 => za@test.ex R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbJ-0005vi-00" +1999-03-02 09:44:33 10HmbJ-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@test.ex +1999-03-02 09:44:33 10HmbI-0005vi-00 => mza@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbJ-0005vi-00" 1999-03-02 09:44:33 10HmbI-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 10HmbK-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbK-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for a@test.ex -1999-03-02 09:44:33 10HmbJ-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbK-0005vi-00" +1999-03-02 09:44:33 10HmbK-0005vi-00 reason: +1999-03-02 09:44:33 10HmbK-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for za@test.ex +1999-03-02 09:44:33 10HmbJ-0005vi-00 => za@test.ex R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbK-0005vi-00" 1999-03-02 09:44:33 10HmbJ-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 10HmbK-0005vi-00 => a R=d1 T=tfile +1999-03-02 09:44:33 10HmbL-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for a@test.ex +1999-03-02 09:44:33 10HmbK-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbL-0005vi-00" 1999-03-02 09:44:33 10HmbK-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp -1999-03-02 09:44:33 10HmbL-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zza@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp -1999-03-02 09:44:33 10HmbM-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbM-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex -1999-03-02 09:44:33 10HmbL-0005vi-00 => za@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbM-0005vi-00" +1999-03-02 09:44:33 10HmbL-0005vi-00 => a R=d1 T=tfile 1999-03-02 09:44:33 10HmbL-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp +1999-03-02 09:44:33 10HmbM-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbM-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zza@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp 1999-03-02 09:44:33 10HmbN-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbN-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex -1999-03-02 09:44:33 10HmbM-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbN-0005vi-00" +1999-03-02 09:44:33 10HmbN-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex +1999-03-02 09:44:33 10HmbM-0005vi-00 => za@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbN-0005vi-00" 1999-03-02 09:44:33 10HmbM-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 10HmbN-0005vi-00 => a R=d1 T=tfile +1999-03-02 09:44:33 10HmbO-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbO-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex +1999-03-02 09:44:33 10HmbN-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbO-0005vi-00" 1999-03-02 09:44:33 10HmbN-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp -1999-03-02 09:44:33 10HmbO-0005vi-00 DKIM: d=dmarc.org s=clochette c=simple/simple a=rsa-sha256 b=1024 t=1517535263 [verification succeeded] -1999-03-02 09:44:33 10HmbO-0005vi-00 DKIM: d=convivian.com s=default c=simple/simple a=rsa-sha256 b=1024 t=1517535248 [verification failed - body hash mismatch (body probably modified in transit)] -1999-03-02 09:44:33 10HmbO-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbO-0005vi-00 reason: -1999-03-02 09:44:33 10HmbO-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@convivian.com for za@test.ex 1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 10HmbO-0005vi-00 => a R=d1 T=tfile +1999-03-02 09:44:33 10HmbO-0005vi-00 Completed +1999-03-02 09:44:33 End queue run: pid=pppp 1999-03-02 09:44:33 10HmbP-0005vi-00 DKIM: d=dmarc.org s=clochette c=simple/simple a=rsa-sha256 b=1024 t=1517535263 [verification succeeded] 1999-03-02 09:44:33 10HmbP-0005vi-00 DKIM: d=convivian.com s=default c=simple/simple a=rsa-sha256 b=1024 t=1517535248 [verification failed - body hash mismatch (body probably modified in transit)] 1999-03-02 09:44:33 10HmbP-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbP-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@convivian.com for a@test.ex -1999-03-02 09:44:33 10HmbO-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbP-0005vi-00" -1999-03-02 09:44:33 10HmbO-0005vi-00 Completed +1999-03-02 09:44:33 10HmbP-0005vi-00 reason: +1999-03-02 09:44:33 10HmbP-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@convivian.com for za@test.ex +1999-03-02 09:44:33 Start queue run: pid=pppp +1999-03-02 09:44:33 10HmbQ-0005vi-00 DKIM: d=dmarc.org s=clochette c=simple/simple a=rsa-sha256 b=1024 t=1517535263 [verification succeeded] +1999-03-02 09:44:33 10HmbQ-0005vi-00 DKIM: d=convivian.com s=default c=simple/simple a=rsa-sha256 b=1024 t=1517535248 [verification failed - body hash mismatch (body probably modified in transit)] +1999-03-02 09:44:33 10HmbQ-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbQ-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@convivian.com for a@test.ex +1999-03-02 09:44:33 10HmbP-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbQ-0005vi-00" +1999-03-02 09:44:33 10HmbP-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 10HmbP-0005vi-00 => a R=d1 T=tfile -1999-03-02 09:44:33 10HmbP-0005vi-00 Completed +1999-03-02 09:44:33 10HmbQ-0005vi-00 => a R=d1 T=tfile +1999-03-02 09:44:33 10HmbQ-0005vi-00 Completed 1999-03-02 09:44:33 End queue run: pid=pppp 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 10HmbQ-0005vi-00 H=(xxx) [127.0.0.1] Warning: ARC-FAIL -1999-03-02 09:44:33 10HmbQ-0005vi-00 arc_state: -1999-03-02 09:44:33 10HmbQ-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for a@test.ex +1999-03-02 09:44:33 10HmbR-0005vi-00 H=(xxx) [127.0.0.1] Warning: ARC-FAIL +1999-03-02 09:44:33 10HmbR-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbR-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for a@test.ex diff --git a/test/mail/4560.a b/test/mail/4560.a index 04e723698..4d3d3bde0 100644 --- a/test/mail/4560.a +++ b/test/mail/4560.a @@ -1,3 +1,31 @@ +From CALLER@bloggs.com Tue Mar 02 09:44:33 1999 +Authentication-Results: test.ex; + arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 +Received: from [127.0.0.1] (helo=xxx) + by test.ex with smtp (Exim x.yz) + (envelope-from ) + id 10HmaX-0005vi-00 + for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 +ARC-Seal: i=1; a=rsa-sha256; cv=none; d=test.ex; s=sel; t=1521752658; b= + xcIN0OEpAc3s8riODm31Q6JgmIECch3iVd1LXWwsypGpCY2UFFuo5HhCEf4a043q + YZ+zn/MbFFkvwIqleeQkJ7S5UcvfM8dv/V4YnwAe+JD8r79glh/FRq6uKlc0ixLS + CllJMwj98J1P1K9+gwmO5TrD1eTZV68caZj77P+X2kw= +ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=test.ex; + h=from:to:date:message-id:subject; s=sel; bh=3UbbJTudPxmejzh7U1 + Zg33U3QT+16kfV2eOTvMeiEis=; b=WgE+YWSm48w/P448gPlBBNCKt2SJ4gosPx + 0JQ98aZJhun2RaVcUO3INc+kZv8YOijofMzFqJxVn1cgMjoU8/QSHIyyt40FzkQB + oSGmSrCjtRnzS8pbp491NX3kGuetidaWE5muPSdOystg6mm1rBnl9sqVrwaynCmr + fu2jTuUfw= +ARC-Authentication-Results: i=1; test.ex; arc=none +Authentication-Results: test.ex; arc=none +From: mrgus@text.ex +To: bakawolf@yahoo.com +Date: Tue, 2 Mar 1999 09:44:33 +0000 +Message-ID: +Subject: simple test + +This is a simple test. + From CALLER@bloggs.com Tue Mar 02 09:44:33 1999 Authentication-Results: test.ex; iprev=pass (localhost); @@ -5,26 +33,26 @@ Authentication-Results: test.ex; Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmaY-0005vi-00 + id 10HmaZ-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; - b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA - +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN - mh1ISayCaAxP5vZXsxKJ7Sk=; + b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72 + AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC + s8DrtRVB3Tt8T/4g8L2SRY0=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=; h=Subject; - b=CbJ1YQLNAWyRqMXq9y0WN10HlKn8Ylu+sVGztkUklgxaqQJCVKUiS7dZaKCBA0B7UqesGogzb5 - y1aeJRCnWnUSL1gKXCjalHTp9XuWxGjd5cARh0AN/nmkXOFkgcIan7o4vB3UBF/T3NwLdewza+ - caLY3oRoBpLwh0IBzibHKl0=; + b=HaqbXBWR7eLrt4KfDPd/G3iSS6Uc4tXEScE4sTS/xjR/poJETiM+Dz2DYWib1f3F7ryccIi7sE + kwsTfpqQsHu/rwNs9X3WL0iW5fyTYeh4ruPd7ZvDmvRhiFJApW7wPejI5ZLCaYz4XWgzBeGKvm + JAg9i5woZbwcXE/SLYOaw/I=; Authentication-Results: test.ex; arc=none Received: from [127.0.0.1] (helo=xxx) by test.ex with smtp (Exim x.yz) (envelope-from ) - id 10HmaX-0005vi-00 + id 10HmaY-0005vi-00 for za@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 Subject: Test @@ -37,47 +65,47 @@ Authentication-Results: test.ex; Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbB-0005vi-00 + id 10HmbC-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel; - b=Gw0rnpSzWYrk0pESlvrgJ6U9Fv1r7BxNxp1uNw+OvylVt9JuuFEfTQ1+wJzu1RkJK9yctGI//X - FiHjdEexgjjU38fOxWlVQyfhpPReuXs+dO0vHDfipIvIFuAkTXczUlRSRr+N+he6JTL33eDeFd - mpyVa6MMt2CdB8mUulbMEdE=; + b=yjlE1/MuuhrLFWK1L1/4OyMyvK47vEmb9dlUF0JGxKTUgJRTqd725Qqzv5ArRQDbCGDah3Pttx + NfKYLDijgST4z5MSTQbiQAoXuGEIfwPSJjMm/cQ37FMcBA2l0gVLNoQIT6GlO8B0i4cigHGEZx + fhUOLvI8pYW8KY8ZiBLY4qE=; ARC-Authentication-Results: i=2; test.ex; iprev=pass (localhost); arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=; h=Subject; - b=T2xYov0qVT77eX6s3g2M3CB4ulYuxbD0o+iTCpfB/40nZTzl5LdIVEyk2ph/ijyqY2PJTpBjjt - iTHoJ4CBtVAkDwq75Wj+lh1OfrArWJatMyimkMwxX6b54KcXldIwB+7w6Tn3D9/sydBEduL82C - p1kh+Bb/X0QGczb0CzdXwhM=; + b=MbmYcNxs4+glho4XUCPLvynpuuZJraZk6B+FDLYWKiNqqTeVjhIj6EnAsUACML3M6wj5d03DAr + P4RkRsmKXqHCoaOiSOqLvBvc8822Ap0l7F/cT2Gk3VRR5ITZI2piAsgLzFpLOEJsGwGVdYsNdx + 5rxBKMPvXAWZip//tBngMRw=; Authentication-Results: test.ex; iprev=pass (localhost); arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbA-0005vi-00 + id 10HmbB-0005vi-00 for za@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; - b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA - +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN - mh1ISayCaAxP5vZXsxKJ7Sk=; + b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72 + AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC + s8DrtRVB3Tt8T/4g8L2SRY0=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=; h=Subject; - b=CbJ1YQLNAWyRqMXq9y0WN10HlKn8Ylu+sVGztkUklgxaqQJCVKUiS7dZaKCBA0B7UqesGogzb5 - y1aeJRCnWnUSL1gKXCjalHTp9XuWxGjd5cARh0AN/nmkXOFkgcIan7o4vB3UBF/T3NwLdewza+ - caLY3oRoBpLwh0IBzibHKl0=; + b=HaqbXBWR7eLrt4KfDPd/G3iSS6Uc4tXEScE4sTS/xjR/poJETiM+Dz2DYWib1f3F7ryccIi7sE + kwsTfpqQsHu/rwNs9X3WL0iW5fyTYeh4ruPd7ZvDmvRhiFJApW7wPejI5ZLCaYz4XWgzBeGKvm + JAg9i5woZbwcXE/SLYOaw/I=; Authentication-Results: test.ex; arc=none Received: from [127.0.0.1] (helo=xxx) by test.ex with smtp (Exim x.yz) (envelope-from ) - id 10HmaZ-0005vi-00 + id 10HmbA-0005vi-00 for zza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 Subject: Test @@ -90,68 +118,68 @@ Authentication-Results: test.ex; Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbF-0005vi-00 + id 10HmbG-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=3; cv=pass; a=rsa-sha256; d=test.ex; s=sel; - b=RcSJycBgTIQO9dOXE36ESKpl/550ykTZwQdtDPlGKaj4bZdbtSEeIRkdKOkwAwuQb+uSCGeaSH - 36LmxlBJzZ+hs8l7WoTEv/514qyEbaokW1DkfSDQ7IRsHOB0roVUliAIcbc7fiO9Fiuo4M1yIT - asqHipuA9TCAMIeqO4QuyT4=; + b=HfcLGHnX3KFIqq4Hj5/+WI4kkcNEpDCTHUbuLlB8PAdwgW2ZwwD2keARxqpkeFUz0KeedU/XZc + 54F5otXO+EkfzVP7l3nugFl4CAOGHqPOnXNU83o/tZmFb9OWDUpfB0AKN7pQZCcNbLaEdDjWuk + YkuDNVDM0PBQ2EXpLCIbTrE=; ARC-Authentication-Results: i=3; test.ex; iprev=pass (localhost); arc=pass (i=2) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1 ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=31zA4VNQZ2yhHUh+7vWASIL9kKqo6pSym1QghgPyUkM=; h=Subject; - b=Lf2jJs8SwbiYLrylYAOjQO4iIa+7tnGighj2gE5NWZj+SiJNQFgu+gHgkmA4xZc2meG58S7WPf - nG6rkqTU/uqBRAbWaEHP1VYDss/x47a/GImRx89dR1P7ZTRLMGgk0AusbvtFDMsKvOTd8QeWLc - DsScgtJ2MqYbikFuA0LxRIA=; + b=nnO3laDgWwUq0y1lOzltunxk1urdDH5ucui5FqCJSJDzvVRYsydYtlp7iayY4QQt9WtbCnvcOH + Ke1FhjdC7iXPv/Dj86J40D9yib5y7YC9Ce3px0xJSXDD+ml1eDi45rVo9GDkm1zVG3eZdESktT + Iv0EvpWIFn7dpelS30IKk78=; Authentication-Results: test.ex; iprev=pass (localhost); arc=pass (i=2) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1 Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbE-0005vi-00 + id 10HmbF-0005vi-00 for za@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel; - b=PisKqTHCNjT5OBFxx3tSp8wLuNXxL9kN8owfn6ueRBSUjWjRx/GFUpa/gPut04/qcTt8MHvamq - rG8f6KBkoD4D8+zZrE9J13RI0v2vR3DUSdhzGjAHRwyAIWaHm7lvu3R5ze6GF0vHmtvFZpApCa - hbMYARUVb7VvXJAhQdLE3oE=; + b=l/OY+REy6qXxE2df0mxzk2Fyv4C9dTuIr2GfnpylYmIr2m/9a8uJRahXa7Ygk9wR8ofnJS+7mr + PTM33+jhCQidq7ZgE28Q7XVMPGmqE4Frs+OmzIL4j7UpK1CYktEzYwOOCSAf8/Yu1XH5w2XNqA + rfIrGPWlAcSoxwfnbyYxVXQ=; ARC-Authentication-Results: i=2; test.ex; iprev=pass (localhost); arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=31zA4VNQZ2yhHUh+7vWASIL9kKqo6pSym1QghgPyUkM=; h=Subject; - b=v3N5ukPvIJskEefYQVq9la9YvMbtrEETkzRVbExhcuf52gWH6PY6L8MWQr2BN4VZbWHPIfZN3S - GMQ21ewl0ZaHC4bAzidgK7NsViw8cfKnJwkvSm4FejpBDto93vQ0Jn2dntbjGZeDSaFx8AuV0m - oZRTJp3w8FnuMJ8Pl0bDLDM=; + b=SBrsiAzbKlKDKB7we5Z0VxUcWT/uiE6YpMtePFkyQ5vR/lD0AooKmluD1HxMGonlbz8WXcwa1C + Avoox5GkxPCBgYfO6wzh801k7F12Usgo7ryY8lOgQ/4OQ77TawNHFnlQ1WxhpaR/lUYkTXZXm2 + LDzSoSVOQ0uFYg3cFzp54OA=; Authentication-Results: test.ex; iprev=pass (localhost); arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbD-0005vi-00 + id 10HmbE-0005vi-00 for mza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; - b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA - +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN - mh1ISayCaAxP5vZXsxKJ7Sk=; + b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72 + AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC + s8DrtRVB3Tt8T/4g8L2SRY0=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=; h=Subject; - b=CbJ1YQLNAWyRqMXq9y0WN10HlKn8Ylu+sVGztkUklgxaqQJCVKUiS7dZaKCBA0B7UqesGogzb5 - y1aeJRCnWnUSL1gKXCjalHTp9XuWxGjd5cARh0AN/nmkXOFkgcIan7o4vB3UBF/T3NwLdewza+ - caLY3oRoBpLwh0IBzibHKl0=; + b=HaqbXBWR7eLrt4KfDPd/G3iSS6Uc4tXEScE4sTS/xjR/poJETiM+Dz2DYWib1f3F7ryccIi7sE + kwsTfpqQsHu/rwNs9X3WL0iW5fyTYeh4ruPd7ZvDmvRhiFJApW7wPejI5ZLCaYz4XWgzBeGKvm + JAg9i5woZbwcXE/SLYOaw/I=; Authentication-Results: test.ex; arc=none Received: from [127.0.0.1] (helo=xxx) by test.ex with smtp (Exim x.yz) (envelope-from ) - id 10HmbC-0005vi-00 + id 10HmbD-0005vi-00 for zmza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 Subject: Test @@ -168,28 +196,28 @@ Authentication-Results: test.ex; Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbK-0005vi-00 + id 10HmbL-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=3; cv=fail; a=rsa-sha256; d=test.ex; s=sel; - b=cdGeRgKBXmi4ZuxBGCLHkZN5io4rurCl7k7ESImcC4FcQFq1giqpFeD2lipCeWvSpx9FpRbXCI - OQyRZB3ZVbjSsuacqUWz78Y5Z15M6g/OrNRwC+wLyGI/Dfg1jwJCp7dtxUMvOfvX/fnII57Y9D - ULyV72U2yGs4E+khjk2Fgdw=; + b=kz0kMxmRu3kimu9tZvLx4HCAt6Scs+hbhEjjE30exA6FCQtaT9UjBekWGRtMLFSmR7CBlRRmOq + Rl6lWMahfAvmdnLVKyX2FrfQLiCGBadOFeZVv5uGX0sdZXDqgjGJLGlNfnk1dtP/y4durC28LL + 8PiM7An58gtCVWyiygt1Qk4=; ARC-Authentication-Results: i=3; test.ex; iprev=pass (localhost); arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1 ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=31zA4VNQZ2yhHUh+7vWASIL9kKqo6pSym1QghgPyUkM=; h=Subject; - b=Lf2jJs8SwbiYLrylYAOjQO4iIa+7tnGighj2gE5NWZj+SiJNQFgu+gHgkmA4xZc2meG58S7WPf - nG6rkqTU/uqBRAbWaEHP1VYDss/x47a/GImRx89dR1P7ZTRLMGgk0AusbvtFDMsKvOTd8QeWLc - DsScgtJ2MqYbikFuA0LxRIA=; + b=nnO3laDgWwUq0y1lOzltunxk1urdDH5ucui5FqCJSJDzvVRYsydYtlp7iayY4QQt9WtbCnvcOH + Ke1FhjdC7iXPv/Dj86J40D9yib5y7YC9Ce3px0xJSXDD+ml1eDi45rVo9GDkm1zVG3eZdESktT + Iv0EvpWIFn7dpelS30IKk78=; Authentication-Results: test.ex; iprev=pass (localhost); arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1 Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbJ-0005vi-00 + id 10HmbK-0005vi-00 for za@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 Authentication-Results: test.ex; iprev=pass (localhost); @@ -197,47 +225,47 @@ Authentication-Results: test.ex; Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbI-0005vi-00 + id 10HmbJ-0005vi-00 for mza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel; - b=Gw0rnpSzWYrk0pESlvrgJ6U9Fv1r7BxNxp1uNw+OvylVt9JuuFEfTQ1+wJzu1RkJK9yctGI//X - FiHjdEexgjjU38fOxWlVQyfhpPReuXs+dO0vHDfipIvIFuAkTXczUlRSRr+N+he6JTL33eDeFd - mpyVa6MMt2CdB8mUulbMEdE=; + b=yjlE1/MuuhrLFWK1L1/4OyMyvK47vEmb9dlUF0JGxKTUgJRTqd725Qqzv5ArRQDbCGDah3Pttx + NfKYLDijgST4z5MSTQbiQAoXuGEIfwPSJjMm/cQ37FMcBA2l0gVLNoQIT6GlO8B0i4cigHGEZx + fhUOLvI8pYW8KY8ZiBLY4qE=; ARC-Authentication-Results: i=2; test.ex; iprev=pass (localhost); arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=; h=Subject; - b=T2xYov0qVT77eX6s3g2M3CB4ulYuxbD0o+iTCpfB/40nZTzl5LdIVEyk2ph/ijyqY2PJTpBjjt - iTHoJ4CBtVAkDwq75Wj+lh1OfrArWJatMyimkMwxX6b54KcXldIwB+7w6Tn3D9/sydBEduL82C - p1kh+Bb/X0QGczb0CzdXwhM=; + b=MbmYcNxs4+glho4XUCPLvynpuuZJraZk6B+FDLYWKiNqqTeVjhIj6EnAsUACML3M6wj5d03DAr + P4RkRsmKXqHCoaOiSOqLvBvc8822Ap0l7F/cT2Gk3VRR5ITZI2piAsgLzFpLOEJsGwGVdYsNdx + 5rxBKMPvXAWZip//tBngMRw=; Authentication-Results: test.ex; iprev=pass (localhost); arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1 Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbH-0005vi-00 + id 10HmbI-0005vi-00 for zmza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; - b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA - +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN - mh1ISayCaAxP5vZXsxKJ7Sk=; + b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72 + AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC + s8DrtRVB3Tt8T/4g8L2SRY0=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=; h=Subject; - b=CbJ1YQLNAWyRqMXq9y0WN10HlKn8Ylu+sVGztkUklgxaqQJCVKUiS7dZaKCBA0B7UqesGogzb5 - y1aeJRCnWnUSL1gKXCjalHTp9XuWxGjd5cARh0AN/nmkXOFkgcIan7o4vB3UBF/T3NwLdewza+ - caLY3oRoBpLwh0IBzibHKl0=; + b=HaqbXBWR7eLrt4KfDPd/G3iSS6Uc4tXEScE4sTS/xjR/poJETiM+Dz2DYWib1f3F7ryccIi7sE + kwsTfpqQsHu/rwNs9X3WL0iW5fyTYeh4ruPd7ZvDmvRhiFJApW7wPejI5ZLCaYz4XWgzBeGKvm + JAg9i5woZbwcXE/SLYOaw/I=; Authentication-Results: test.ex; arc=none Received: from [127.0.0.1] (helo=xxx) by test.ex with smtp (Exim x.yz) (envelope-from ) - id 10HmbG-0005vi-00 + id 10HmbH-0005vi-00 for zzmza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 Subject: Test @@ -254,7 +282,7 @@ Authentication-Results: test.ex; Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbN-0005vi-00 + id 10HmbO-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 Authentication-Results: test.ex; iprev=pass (localhost); @@ -262,26 +290,26 @@ Authentication-Results: test.ex; Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbM-0005vi-00 + id 10HmbN-0005vi-00 for za@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel; - b=FUok5m+OoEqd8QIlc2ch4c9dWRBkoljL2vOaxOFd5V9JME/6PrlYQ8oF88sIAcMnrQyffjVtDA - +kcb1AYzjO2TDaoH873Yu62CMTB6KBtC3+9B7eadXd24d3sNhTOxzJaK+TWid2iVNfEUU3rKXN - mh1ISayCaAxP5vZXsxKJ7Sk=; + b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72 + AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC + s8DrtRVB3Tt8T/4g8L2SRY0=; ARC-Authentication-Results: i=1; test.ex; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=; h=Subject; - b=CbJ1YQLNAWyRqMXq9y0WN10HlKn8Ylu+sVGztkUklgxaqQJCVKUiS7dZaKCBA0B7UqesGogzb5 - y1aeJRCnWnUSL1gKXCjalHTp9XuWxGjd5cARh0AN/nmkXOFkgcIan7o4vB3UBF/T3NwLdewza+ - caLY3oRoBpLwh0IBzibHKl0=; + b=HaqbXBWR7eLrt4KfDPd/G3iSS6Uc4tXEScE4sTS/xjR/poJETiM+Dz2DYWib1f3F7ryccIi7sE + kwsTfpqQsHu/rwNs9X3WL0iW5fyTYeh4ruPd7ZvDmvRhiFJApW7wPejI5ZLCaYz4XWgzBeGKvm + JAg9i5woZbwcXE/SLYOaw/I=; Authentication-Results: test.ex; arc=none Received: from [127.0.0.1] (helo=xxx) by test.ex with smtp (Exim x.yz) (envelope-from ) - id 10HmbL-0005vi-00 + id 10HmbM-0005vi-00 for zza@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 Subject: Test @@ -297,12 +325,12 @@ Authentication-Results: test.ex; Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) - id 10HmbP-0005vi-00 + id 10HmbQ-0005vi-00 for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 ARC-Seal: i=2; cv=fail; a=rsa-sha256; d=test.ex; s=sel; - b=bID/N3wfd1l6ac20RCPn+pVvXigyjdZRMuub+N4VGA/c6Nw41LDmhgxEHqSUhNxri2KYGV3BPw - Qp9RWx7lS2o6nnrrKBi/tdlE164GWpFNH5qetZZKuaEtZ0box3qUNwMpjzZZOhHNPzDXsztTLG - M4/bKjEuvxwND7oliqhn3mg=; + b=cTfJCdk2kBIo+p9qyn5XD99OoJsGq5B2olKU9zbU2P7YrfsGYva+utsBO1hI4jAHUfJj191WV/ + YuxNGgTxlBHZxmKOEj4QeHSgYNXRx/0iJKFLGPX3k/oNFcjD2L35YhtpEfctsRawU3wU8QMm05 + m516OWV1S6tg0YR9MtS7kMc=; ARC-Authentication-Results: i=2; test.ex; dkim=pass header.d=dmarc.org header.s=clochette header.a=rsa-sha256; dkim=fail (body hash mismatch; body probably modified in transit) @@ -313,9 +341,9 @@ ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=sel; h=Sender:Content-Type:Reply-To:From:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:Cc:MIME-Version:References: In-Reply-To:Message-ID:To:Date:DKIM-Signature:DKIM-Signature; - b=ZDh/1Pns8xp2aOFUIDqAIU8rNK+Wx+xBtsUqn+P8an0dPJIja0AexTNoPagabvXjNzT86Uf6dm - 6gO1oFpzn63XNNaRJSrUDOMLe3pe5D8IS/0AFlqU9iwyDjmZqsnc8VnxXMgkDvEhrF5e1Mj9E+ - Rw80B9DQMRhl1Va7HMZsLlI=; + b=m3z/6RMe+O4S3C647SM44td4xa+4BtIPQXbP+SJfmXrB/eNcbm2PlOGzdGALfrNJ1IkwDl3waA + nQwOSOgmNvyYQyrYcZZu7A2+y4NtjhXAyaAwhd/tp+PcMH52/wSXkMJKRwppbmROo89TtABsOE + CW1KtSgWheAYLf32Mhhws20=; Authentication-Results: test.ex; dkim=pass header.d=dmarc.org header.s=clochette header.a=rsa-sha256; dkim=fail (body hash mismatch; body probably modified in transit) @@ -324,7 +352,7 @@ Authentication-Results: test.ex; Received: from [127.0.0.1] (helo=xxx) by test.ex with smtp (Exim x.yz) (envelope-from ) - id 10HmbO-0005vi-00 + id 10HmbP-0005vi-00 for za@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 Received: from dragon.trusteddomain.org (localhost [127.0.0.1]) by dragon.trusteddomain.org (8.14.5/8.14.5) with ESMTP id w121YG2q036577; diff --git a/test/scripts/4560-ARC/4560 b/test/scripts/4560-ARC/4560 index 3e0f8e922..1a0086f47 100644 --- a/test/scripts/4560-ARC/4560 +++ b/test/scripts/4560-ARC/4560 @@ -3,6 +3,48 @@ exim -DSERVER=server -bd -oX PORT_D **** # +# This should pass. +# Mail original in aux-fixed/4560.msg1.txt +# Sig generated by: perl aux-fixed/dkim/sign_arc.pl < aux-fixed/4560.msg1.txt +client 127.0.0.1 PORT_D +??? 220 +HELO xxx +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +ARC-Seal: i=1; a=rsa-sha256; cv=none; d=test.ex; s=sel; t=1521752658; b= + xcIN0OEpAc3s8riODm31Q6JgmIECch3iVd1LXWwsypGpCY2UFFuo5HhCEf4a043q + YZ+zn/MbFFkvwIqleeQkJ7S5UcvfM8dv/V4YnwAe+JD8r79glh/FRq6uKlc0ixLS + CllJMwj98J1P1K9+gwmO5TrD1eTZV68caZj77P+X2kw= +ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=test.ex; + h=from:to:date:message-id:subject; s=sel; bh=3UbbJTudPxmejzh7U1 + Zg33U3QT+16kfV2eOTvMeiEis=; b=WgE+YWSm48w/P448gPlBBNCKt2SJ4gosPx + 0JQ98aZJhun2RaVcUO3INc+kZv8YOijofMzFqJxVn1cgMjoU8/QSHIyyt40FzkQB + oSGmSrCjtRnzS8pbp491NX3kGuetidaWE5muPSdOystg6mm1rBnl9sqVrwaynCmr + fu2jTuUfw= +ARC-Authentication-Results: i=1; test.ex; arc=none +Authentication-Results: test.ex; arc=none +From: mrgus@text.ex +To: bakawolf@yahoo.com +Date: Thu, 19 Nov 2015 17:00:07 -0700 +Message-ID: +Subject: simple test + +This is a simple test. +. +??? 250 +QUIT +??? 221 +**** +exim -DSERVER=server -DNOTDAEMON -q +**** +# +# +# # We send this one through one forwarding hop. # It starts off bare, so the forwarder reception gets an ARC status of "none". # The outbound signs it with that, and the final receiver is happy to pass it. -- cgit v1.2.3 From abc01b4f3ea60198b92c397df5aa8c5cc2c07fb2 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Fri, 23 Mar 2018 16:45:03 +0000 Subject: ARC: For signing, accept A-R header lacking ARC info as equivalent to "none" --- src/src/arc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/src/arc.c b/src/src/arc.c index a0e2184bd..f4ae096bc 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -1375,7 +1375,7 @@ while ((methodspec = string_nextinlist(&resinfo, &sep, NULL, 0))) (c = *s) && c != ';' && c != ' ' && c != '\r' && c != '\n'; ) s++; return string_copyn(methodspec, s - methodspec); } -return NULL; +return US"none"; } -- cgit v1.2.3 From 47dc3814944d1b0365e196e1f48190fe220c2a5f Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sat, 24 Mar 2018 13:53:50 +0000 Subject: ARC: give more detail with "bad signing-spec" message --- doc/doc-txt/experimental-spec.txt | 3 ++- src/src/arc.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 3389632a2..bc5bab77d 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -802,7 +802,8 @@ arc_sign = : : An option on the smtp transport, which constructs and prepends to the message an ARC set of headers. The textually-first Authentication-Results: header is used as a basis (you must have added one on entry to the ADMD). -Expanded; if unset, empty or forced-failure then no signing is done. +Expanded as a whole; if unset, empty or forced-failure then no signing is done. +If it is set, all three elements must be non-empty. diff --git a/src/src/arc.c b/src/src/arc.c index f4ae096bc..eb143b697 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -1536,7 +1536,8 @@ selector = string_nextinlist(&signspec, &sep, NULL, 0); if ( !*identity | !*selector || !(privkey = string_nextinlist(&signspec, &sep, NULL, 0)) || !*privkey) { - log_write(0, LOG_MAIN|LOG_PANIC, "ARC: bad signing-specification"); + log_write(0, LOG_MAIN|LOG_PANIC, "ARC: bad signing-specification (%s)", + !*identity ? "identity" : !*selector ? "selector" : "private-key"); return NULL; } if (*privkey == '/' && !(privkey = expand_file_big_buffer(privkey))) -- cgit v1.2.3 From cb387849bcd092eab3a7dbebb7580db044eff0bd Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 26 Mar 2018 15:53:49 +0100 Subject: Cutthrough: enforce non-use in combination with DKIM signing or transport filter Broken-by: 02b41d7106 --- doc/doc-txt/ChangeLog | 4 ++++ src/src/verify.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'src') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index af186d2e3..9a05c3471 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -160,6 +160,10 @@ JH/28 Ensure that variables possibly set during message acceptance are marked PP/02 DANE: add dane_require_tls_ciphers SMTP Transport option; if unset, tls_require_ciphers is used as before. +JH/34 Re-introduce enforcement of no cutthrough delivery on transports having + transport-filters or DKIM-signing. The restriction was lost in the + consolidation of verify-callout and delivery SMTP handling. + Exim version 4.90 ----------------- diff --git a/src/src/verify.c b/src/src/verify.c index 9582fe5b7..1df856604 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -1026,6 +1026,20 @@ no_conn: here is where we want to leave the conn open. Ditto for a lazy-close verify. */ + if (cutthrough.delivery) + { + if (addr->transport->filter_command) + { + cutthrough.delivery= FALSE; + HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of transport filter\n"); + } + if (ob->dkim.dkim_domain) + { + cutthrough.delivery= FALSE; + HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM signing\n"); + } + } + if ( (cutthrough.delivery || options & vopt_callout_hold) && rcpt_count == 1 && done -- cgit v1.2.3 From ca5c132adacf024c8140446b7cb402dd923bc4c3 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 26 Mar 2018 15:59:25 +0100 Subject: ARC: cutthrough delivery may not be used with ARC signing --- doc/doc-txt/ChangeLog | 1 + doc/doc-txt/experimental-spec.txt | 4 ++++ src/src/verify.c | 4 ++-- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 9a05c3471..61fd30bf8 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -163,6 +163,7 @@ PP/02 DANE: add dane_require_tls_ciphers SMTP Transport option; if unset, JH/34 Re-introduce enforcement of no cutthrough delivery on transports having transport-filters or DKIM-signing. The restriction was lost in the consolidation of verify-callout and delivery SMTP handling. + Extend the restriction to also cover ARC-signing. Exim version 4.90 diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 0828e9b67..4e8e59148 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -819,6 +819,10 @@ Caveats: should try to stick to one ADMD, so pick a primary domain and use that for AR headers and outbound signing. +Signing is not compatible with cutthrough delivery; any (before expansion) +value set for the option will result in cutthrough delivery not being +used via the transport in question. + -------------------------------------------------------------- diff --git a/src/src/verify.c b/src/src/verify.c index 1df856604..1555838ac 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -1033,10 +1033,10 @@ no_conn: cutthrough.delivery= FALSE; HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of transport filter\n"); } - if (ob->dkim.dkim_domain) + if (ob->dkim.dkim_domain || ob->arc_sign) { cutthrough.delivery= FALSE; - HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM signing\n"); + HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM or ARC signing\n"); } } -- cgit v1.2.3 From 0ed25f66ccc56d56b3b5b7d64f4537bafbb42697 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 26 Mar 2018 17:30:47 +0100 Subject: ARC: add guard in verify against lack of the dkim-verify context needed for body-hashing --- src/src/arc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/src/arc.c b/src/src/arc.c index eb143b697..06ca93736 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -993,6 +993,12 @@ acl_verify_arc(void) arc_ctx ctx = { NULL }; const uschar * res; +if (!dkim_verify_ctx) + { + DEBUG(D_acl) debug_printf("ARC: no DKIM verify context\n"); + return NULL; + } + /* AS evaluation, per https://tools.ietf.org/html/draft-ietf-dmarc-arc-protocol-10#section-6 */ -- cgit v1.2.3 From d7e9db66df01a2ca6ea06e1d99c39f09c6eff93a Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 26 Mar 2018 18:44:33 +0100 Subject: Fix non-ARC build --- src/src/verify.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/src/verify.c b/src/src/verify.c index 1555838ac..ffa6a14f9 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -1033,11 +1033,20 @@ no_conn: cutthrough.delivery= FALSE; HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of transport filter\n"); } - if (ob->dkim.dkim_domain || ob->arc_sign) +#ifndef DISABLE_DKIM + if (ob->dkim.dkim_domain) { cutthrough.delivery= FALSE; - HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM or ARC signing\n"); + HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM signing\n"); } +#endif +#ifdef EXPERIMENTAL_ARC + if (ob->arc_sign) + { + cutthrough.delivery= FALSE; + HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of ARC signing\n"); + } +#endif } if ( (cutthrough.delivery || options & vopt_callout_hold) -- cgit v1.2.3 From dde9989b7d8e04baa017b2537cc2614f75b4362f Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 27 Mar 2018 22:01:03 +0100 Subject: ARC: enhance debug for signing; explicitly init signing context --- src/src/arc.c | 56 +++++++++++++++++++++++++++++---------------- src/src/dkim_transport.c | 9 +++++++- src/src/functions.h | 1 + test/confs/4561 | 1 + test/log/4560 | 2 ++ test/mail/4560.a | 4 ++-- test/scripts/4560-ARC/4561 | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 108 insertions(+), 22 deletions(-) create mode 120000 test/confs/4561 create mode 100644 test/scripts/4560-ARC/4561 (limited to 'src') diff --git a/src/src/arc.c b/src/src/arc.c index 06ca93736..5f51d614d 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -631,6 +631,7 @@ arc_ams_setup_vfy_bodyhash(arc_line * ams) int canon_head, canon_body; long bodylen; +if (!ams->c.data) ams->c.data = US"simple"; /* RFC 6376 (DKIM) default */ pdkim_cstring_to_canons(ams->c.data, ams->c.len, &canon_head, &canon_body); bodylen = ams->l.data ? strtol(CS string_copyn(ams->l.data, ams->l.len), NULL, 10) : -1; @@ -771,10 +772,10 @@ for(inst = 0; as; as = as->next) || arc_cv_match(as->hdr_as, US"fail") ) { - arc_state_reason = string_sprintf("i=%d fail" + arc_state_reason = string_sprintf("i=%d" " (cv, sequence or missing header)", as->instance); - DEBUG(D_acl) debug_printf("ARC %s\n", arc_state_reason); - ret = US"fail"; + DEBUG(D_acl) debug_printf("ARC chain fail at %s\n", arc_state_reason); + return US"fail"; } /* Evaluate the oldest-pass AMS validation while we're here. @@ -1102,8 +1103,7 @@ return r; /* Walk the given headers strings identifying each header, and construct -a reverse-order list. Also parse ARC-chain headers and build the chain -struct, retaining pointers into the string. +a reverse-order list. */ static hdr_rlist * @@ -1486,6 +1486,14 @@ return pdkim_set_bodyhash(&dkim_sign_ctx, +void +arc_sign_init(void) +{ +memset(&arc_sign_ctx, 0, sizeof(arc_sign_ctx)); +} + + + /* A "normal" header line, identified by DKIM processing. These arrive before the call to arc_sign(), which carries any newly-created DKIM headers - and those go textually before the normal ones in the message. @@ -1551,12 +1559,8 @@ if (*privkey == '/' && !(privkey = expand_file_big_buffer(privkey))) DEBUG(D_transport) debug_printf("ARC: sign for %s\n", identity); -/* -- scan headers for existing ARC chain & A-R (with matching system-identfier) - - paniclog & skip on problems (no A-R) -*/ - -/* Make an rlist of any new DKIM headers, then add the "normals" rlist to it */ +/* Make an rlist of any new DKIM headers, then add the "normals" rlist to it. +Then scan the list for an A-R header. */ string_from_gstring(sigheaders); if ((rheaders = arc_sign_scan_headers(&arc_sign_ctx, sigheaders))) @@ -1568,16 +1572,15 @@ if ((rheaders = arc_sign_scan_headers(&arc_sign_ctx, sigheaders))) } else rheaders = headers_rlist; + /* Finally, build a normal-order headers list */ /*XXX only needed for hunt-the-AR? */ -{ -header_line * hnext = NULL; -for (; rheaders; hnext = rheaders->h, rheaders = rheaders->prev) - rheaders->h->next = hnext; -headers = hnext; -} - -instance = arc_sign_ctx.arcset_chain_last ? arc_sign_ctx.arcset_chain_last->instance + 1 : 1; + { + header_line * hnext = NULL; + for (; rheaders; hnext = rheaders->h, rheaders = rheaders->prev) + rheaders->h->next = hnext; + headers = hnext; + } if (!(arc_sign_find_ar(headers, identity, &ar))) { @@ -1585,6 +1588,19 @@ if (!(arc_sign_find_ar(headers, identity, &ar))) return sigheaders ? sigheaders : string_get(0); } +/* We previously built the data-struct for the existing ARC chain, if any, using a headers +feed from the DKIM module. Use that to give the instance number for the ARC set we are +about to build. */ + +DEBUG(D_transport) + if (arc_sign_ctx.arcset_chain_last) + debug_printf("ARC: existing chain highest instance: %d\n", + arc_sign_ctx.arcset_chain_last->instance); + else + debug_printf("ARC: no existing chain\n"); + +instance = arc_sign_ctx.arcset_chain_last ? arc_sign_ctx.arcset_chain_last->instance + 1 : 1; + /* - Generate AAR - copy the A-R; prepend i= & identity @@ -1732,6 +1748,8 @@ if (arc_state) if (sender_host_address) g = string_append(g, 2, US" smtp.client-ip=", sender_host_address); } + else if (arc_state_reason) + g = string_append(g, 3, US" (", arc_state_reason, US")"); DEBUG(D_acl) debug_printf("ARC: authres '%.*s'\n", g->ptr - start - 3, g->s + start + 3); } diff --git a/src/src/dkim_transport.c b/src/src/dkim_transport.c index 28d567b03..114586803 100644 --- a/src/src/dkim_transport.c +++ b/src/src/dkim_transport.c @@ -151,8 +151,11 @@ if (!rc) return FALSE; /* Get signatures for headers plus spool data file */ -dkim->dot_stuffed = !!(save_options & topt_end_dot); +#ifdef EXPERIMENTAL_ARC +arc_sign_init(); +#endif +dkim->dot_stuffed = !!(save_options & topt_end_dot); if (!(dkim_signature = dkim_exim_sign(deliver_datafile, SPOOL_DATA_START_OFFSET, hdrs, dkim, &errstr))) if (!(rc = dkt_sign_fail(dkim, &errno))) @@ -264,6 +267,10 @@ if (!rc) goto CLEANUP; } +#ifdef EXPERIMENTAL_ARC +arc_sign_init(); +#endif + /* Feed the file to the goats^W DKIM lib */ dkim->dot_stuffed = !!(options & topt_end_dot); diff --git a/src/src/functions.h b/src/src/functions.h index 496bd9985..05621548b 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -93,6 +93,7 @@ extern void acl_var_write(uschar *, uschar *, void *); extern void *arc_ams_setup_sign_bodyhash(void); extern const uschar *arc_header_feed(gstring *, BOOL); extern gstring *arc_sign(const uschar *, gstring *, uschar **); +extern void arc_sign_init(void); extern const uschar *acl_verify_arc(void); #endif diff --git a/test/confs/4561 b/test/confs/4561 new file mode 120000 index 000000000..359a76cee --- /dev/null +++ b/test/confs/4561 @@ -0,0 +1 @@ +4560 \ No newline at end of file diff --git a/test/log/4560 b/test/log/4560 index 88f7ff2f7..a89738027 100644 --- a/test/log/4560 +++ b/test/log/4560 @@ -84,6 +84,7 @@ 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 10HmbL-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbL-0005vi-00 reason: 1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for a@test.ex 1999-03-02 09:44:33 10HmbK-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbL-0005vi-00" 1999-03-02 09:44:33 10HmbK-0005vi-00 Completed @@ -119,6 +120,7 @@ 1999-03-02 09:44:33 10HmbQ-0005vi-00 DKIM: d=dmarc.org s=clochette c=simple/simple a=rsa-sha256 b=1024 t=1517535263 [verification succeeded] 1999-03-02 09:44:33 10HmbQ-0005vi-00 DKIM: d=convivian.com s=default c=simple/simple a=rsa-sha256 b=1024 t=1517535248 [verification failed - body hash mismatch (body probably modified in transit)] 1999-03-02 09:44:33 10HmbQ-0005vi-00 arc_state: +1999-03-02 09:44:33 10HmbQ-0005vi-00 reason: 1999-03-02 09:44:33 10HmbQ-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@convivian.com for a@test.ex 1999-03-02 09:44:33 10HmbP-0005vi-00 => a@test.ex R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbQ-0005vi-00" 1999-03-02 09:44:33 10HmbP-0005vi-00 Completed diff --git a/test/mail/4560.a b/test/mail/4560.a index 4d3d3bde0..dd38aa6da 100644 --- a/test/mail/4560.a +++ b/test/mail/4560.a @@ -192,7 +192,7 @@ This is a generic mailinglist footer From CALLER@bloggs.com Tue Mar 02 09:44:33 1999 Authentication-Results: test.ex; iprev=pass (localhost); - arc=fail (i=3) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1 + arc=fail (i=3 (cv, sequence or missing header)) Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) @@ -321,7 +321,7 @@ Authentication-Results: test.ex; dkim=pass header.d=dmarc.org header.s=clochette header.a=rsa-sha256; dkim=fail (body hash mismatch; body probably modified in transit) header.d=convivian.com header.s=default header.a=rsa-sha256; - arc=fail (i=2) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1 + arc=fail (i=2 (cv, sequence or missing header)) Received: from localhost ([127.0.0.1] helo=test.ex) by test.ex with esmtp (Exim x.yz) (envelope-from ) diff --git a/test/scripts/4560-ARC/4561 b/test/scripts/4560-ARC/4561 new file mode 100644 index 000000000..76f7f375a --- /dev/null +++ b/test/scripts/4560-ARC/4561 @@ -0,0 +1,57 @@ +# ARC verify, bad chain +# +exim -DSERVER=server -bd -oX PORT_D +**** +# +# This should fail verify (not a complete chain). +client 127.0.0.1 PORT_D +??? 220 +HELO xxx +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 +DATA +??? 354 +ARC-Seal: i=2; cv=none; a=rsa-sha256; d=test.ex; s=r201803; + b=HxjMzNcj7OX+I9Vr1Xr14AGgAci/CI8JxspaeoNT7TBsiOAtZ+YDBBSqXe6fqX3mHQEwpnXrdz + PCMIU1SF3ZiBtqWaLBPhStfuNQl5cw+TWXC60rOwCD2bxuBqubM/3AZLMPzIpm62MUYUUGaxwi + +LssT4F237WN88Lu4g5vqi8=; +ARC-Authentication-Results: i=2; test.ex; + iprev=fail; + auth=pass (PLAIN) smtp.auth=fred@test.ex +ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=r201803; + bh=52LTOZoDLUGP5RZMMrrjLkwTKuJ59wx4n3rL9RKBtgg=; + h=Content-Transfer-Encoding:Content-Type:MIME-Version:Date:Message-ID:Subject: + From:To:Content-Transfer-Encoding:Content-Type:MIME-Version:Date:Message-ID: + Subject:From:To; + b=LYAs/k3m790qXfftAVQxqHFCUkqcavgcpKnbEje3MgCmpCiYzeeusloVSjyFx6Mdo0XkN0GSZb + HXOCRGaJVnpU9V1QzdIqvz/I7DAyWl53XsKxl9YhsuaeuMMgPpqWpYkp0mOIo3Mtg+VdbF2DKd + O8BRJnqfkZkGUqMUJzdaYMU=; +Authentication-Results: test.ex; + iprev=fail; + auth=pass (PLAIN) smtp.auth=fred@test.ex +Received: from [127.0.0.1] +To: a@test.ex +From: Jeremy Harris +Subject: another test +Message-ID: <3885245d-3bae-66a2-7a1e-0dbceae2fb50@test.ex> +Date: Mon, 26 Mar 2018 10:55:18 +0100 + +This is a simple test. +. +??? 250 +QUIT +??? 221 +**** +exim -DSERVER=server -DNOTDAEMON -q +**** +# +# +# +# +# +killdaemon +no_stdout_check +no_msglog_check -- cgit v1.2.3 From 17c5a47a633ea70bb33670695aac3b75612189fa Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Wed, 28 Mar 2018 14:15:23 +0100 Subject: ARC: log signing-spec errors in mainlog only, not paniclog --- src/src/arc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/src/arc.c b/src/src/arc.c index 5f51d614d..dedf64c44 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -1239,7 +1239,7 @@ else if ( (errstr = exim_dkim_signing_init(privkey, &sctx)) || (errstr = exim_dkim_sign(&sctx, hm, &hhash, sig))) { - log_write(0, LOG_MAIN|LOG_PANIC, "ARC: %s signing: %s\n", why, errstr); + log_write(0, LOG_MAIN, "ARC: %s signing: %s\n", why, errstr); return FALSE; } return TRUE; @@ -1550,12 +1550,12 @@ selector = string_nextinlist(&signspec, &sep, NULL, 0); if ( !*identity | !*selector || !(privkey = string_nextinlist(&signspec, &sep, NULL, 0)) || !*privkey) { - log_write(0, LOG_MAIN|LOG_PANIC, "ARC: bad signing-specification (%s)", + log_write(0, LOG_MAIN, "ARC: bad signing-specification (%s)", !*identity ? "identity" : !*selector ? "selector" : "private-key"); - return NULL; + return sigheaders ? sigheaders : string_get(0); } if (*privkey == '/' && !(privkey = expand_file_big_buffer(privkey))) - return NULL; + return sigheaders ? sigheaders : string_get(0); DEBUG(D_transport) debug_printf("ARC: sign for %s\n", identity); @@ -1584,7 +1584,7 @@ else if (!(arc_sign_find_ar(headers, identity, &ar))) { - log_write(0, LOG_MAIN|LOG_PANIC, "ARC: no Authentication-Results header for signing"); + log_write(0, LOG_MAIN, "ARC: no Authentication-Results header for signing"); return sigheaders ? sigheaders : string_get(0); } -- cgit v1.2.3 From 95f006eff4b1ee4038bf93a9aa4686f226114eea Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Wed, 4 Apr 2018 00:22:49 +0100 Subject: ARC: add optional t= tags to signing --- doc/doc-txt/experimental-spec.txt | 9 ++++++++- src/src/arc.c | 41 +++++++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 4e8e59148..3c348d0df 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -798,13 +798,20 @@ Receive log lines for an ARC pass will be tagged "ARC". Signing -- -arc_sign = : : +arc_sign = : : [ : ] An option on the smtp transport, which constructs and prepends to the message an ARC set of headers. The textually-first Authentication-Results: header is used as a basis (you must have added one on entry to the ADMD). Expanded as a whole; if unset, empty or forced-failure then no signing is done. If it is set, all three elements must be non-empty. +The fourth element is optional, and if present consists of a comma-separated list +of options. The only option implemented so far is + timestamps Add a t= tag to the generated AMS and AS headers, with the + current time. + +[As of writing, gmail insist that a t= tag on the AS is mandatory] + Caveats: * There must be an Authentication-Results header, presumably added by an ACL while receiving the message, for the same ADMD, for arc_sign to succeed. diff --git a/src/src/arc.c b/src/src/arc.c index dedf64c44..fdc280eb6 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -21,6 +21,8 @@ extern pdkim_ctx * dkim_verify_ctx; extern pdkim_ctx dkim_sign_ctx; +#define ARC_SIGN_OPT_TSTAMP BIT(0) + /******************************************************************************/ typedef struct hdr_rlist { @@ -1273,7 +1275,7 @@ return g; static gstring * arc_sign_append_ams(gstring * g, arc_ctx * ctx, int instance, const uschar * identity, const uschar * selector, blob * bodyhash, - hdr_rlist * rheaders, const uschar * privkey) + hdr_rlist * rheaders, const uschar * privkey, unsigned options) { uschar * s; gstring * hdata = NULL; @@ -1289,11 +1291,15 @@ header_line * h = (header_line *)(al+1); /* Construct the to-be-signed AMS pseudo-header: everything but the sig. */ ams_off = g->ptr; -g = string_append(g, 10, +g = string_append(g, 7, ARC_HDR_AMS, US" i=", string_sprintf("%d", instance), US"; a=rsa-sha256; c=relaxed; d=", identity, /*XXX hardwired */ - US"; s=", selector, + US"; s=", selector); +if (options & ARC_SIGN_OPT_TSTAMP) + g = string_append(g, 2, + US"; t=", string_sprintf("%lu", (u_long)time(NULL))); +g = string_append(g, 3, US";\r\n\tbh=", pdkim_encode_base64(bodyhash), US";\r\n\th="); @@ -1391,7 +1397,7 @@ return US"none"; static gstring * arc_sign_prepend_as(gstring * arcset_interim, arc_ctx * ctx, int instance, const uschar * identity, const uschar * selector, blob * ar, - const uschar * privkey) + const uschar * privkey, unsigned options) { gstring * arcset; arc_set * as; @@ -1418,12 +1424,16 @@ blob sig; /* Construct the AS except for the signature */ -arcset = string_append(NULL, 10, +arcset = string_append(NULL, 9, ARC_HDR_AS, US" i=", string_sprintf("%d", instance), US"; cv=", status, US"; a=rsa-sha256; d=", identity, /*XXX hardwired */ - US"; s=", selector, /*XXX same as AMS */ + US"; s=", selector); /*XXX same as AMS */ +if (options & ARC_SIGN_OPT_TSTAMP) + arcset = string_append(arcset, 2, + US"; t=", string_sprintf("%lu", (u_long)time(NULL))); +arcset = string_cat(arcset, US";\r\n\t b=;"); h->slen = arcset->ptr; @@ -1521,7 +1531,8 @@ The dkim_exim_sign() function has already been called, so will have hashed the message body for us so long as we requested a hash previously. Arguments: - signspec Three-element colon-sep list: identity, selector, privkey + signspec Three-element colon-sep list: identity, selector, privkey. + Optional fourth element: comma-sep list of options. Already expanded sigheaders Any signature headers already generated, eg. by DKIM, or NULL errstr Error string @@ -1534,7 +1545,8 @@ Return value gstring * arc_sign(const uschar * signspec, gstring * sigheaders, uschar ** errstr) { -const uschar * identity, * selector, * privkey; +const uschar * identity, * selector, * privkey, * opts, * s; +unsigned options = 0; int sep = 0; header_line * headers; hdr_rlist * rheaders; @@ -1557,6 +1569,14 @@ if ( !*identity | !*selector if (*privkey == '/' && !(privkey = expand_file_big_buffer(privkey))) return sigheaders ? sigheaders : string_get(0); +if ((opts = string_nextinlist(&signspec, &sep, NULL, 0))) + { + int osep = ','; + while ((s = string_nextinlist(&opts, &osep, NULL, 0))) + if (Ustrcmp(s, "timestamps") == 0) + options |= ARC_SIGN_OPT_TSTAMP; + } + DEBUG(D_transport) debug_printf("ARC: sign for %s\n", identity); /* Make an rlist of any new DKIM headers, then add the "normals" rlist to it. @@ -1619,7 +1639,7 @@ g = arc_sign_append_aar(g, &arc_sign_ctx, identity, instance, &ar); b = arc_ams_setup_sign_bodyhash(); g = arc_sign_append_ams(g, &arc_sign_ctx, instance, identity, selector, - &b->bh, headers_rlist, privkey); + &b->bh, headers_rlist, privkey, options); /* - Generate AS @@ -1634,7 +1654,8 @@ g = arc_sign_append_ams(g, &arc_sign_ctx, instance, identity, selector, including self (but with an empty b= in self) */ -g = arc_sign_prepend_as(g, &arc_sign_ctx, instance, identity, selector, &ar, privkey); +g = arc_sign_prepend_as(g, &arc_sign_ctx, instance, identity, selector, &ar, + privkey, options); /* Finally, append the dkim headers and return the lot. */ -- cgit v1.2.3 From 114016404c82ae4a21b4c7ecff14323ad9886014 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sat, 31 Mar 2018 00:24:28 +0100 Subject: local_scan: add note on Makefile requirement --- src/src/local_scan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/src/local_scan.c b/src/src/local_scan.c index 3500047ca..4dd0b2baa 100644 --- a/src/src/local_scan.c +++ b/src/src/local_scan.c @@ -12,6 +12,7 @@ If you want to implement your own version, you should copy this file to, say Local/local_scan.c, and edit the copy. To use your version instead of the default, you must set +HAVE_LOCAL_SCAN=yes LOCAL_SCAN_SOURCE=Local/local_scan.c in your Local/Makefile. This makes it easy to copy your version for use with -- cgit v1.2.3 From 4398228719841b08524520b8c07faeb3bee89705 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Wed, 4 Apr 2018 11:10:56 +0100 Subject: ARC: add optional x= tag to signing --- doc/doc-txt/experimental-spec.txt | 12 +++++++++--- src/src/arc.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 3c348d0df..b981f3b7a 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -806,9 +806,15 @@ Expanded as a whole; if unset, empty or forced-failure then no signing is done. If it is set, all three elements must be non-empty. The fourth element is optional, and if present consists of a comma-separated list -of options. The only option implemented so far is - timestamps Add a t= tag to the generated AMS and AS headers, with the - current time. +of options. The options implemented are + + timestamps Add a t= tag to the generated AMS and AS headers, with the + current time. + expire[=] Add an x= tag to the generated AMS header, with an expiry time. + If the value is an plain number it is used unchanged. + If it starts with a '+' then the following number is added + to the current time, as an offset in seconds. + If a value is not given it defaults to a one month offset. [As of writing, gmail insist that a t= tag on the AS is mandatory] diff --git a/src/src/arc.c b/src/src/arc.c index fdc280eb6..c860aed36 100644 --- a/src/src/arc.c +++ b/src/src/arc.c @@ -22,6 +22,9 @@ extern pdkim_ctx * dkim_verify_ctx; extern pdkim_ctx dkim_sign_ctx; #define ARC_SIGN_OPT_TSTAMP BIT(0) +#define ARC_SIGN_OPT_EXPIRE BIT(1) + +#define ARC_SIGN_DEFAULT_EXPIRE_DELTA (60 * 60 * 24 * 30) /* one month */ /******************************************************************************/ @@ -86,6 +89,8 @@ typedef struct arc_ctx { #define HDR_AR US"Authentication-Results:" #define HDRLEN_AR 23 +static time_t now; +static time_t expire; static hdr_rlist * headers_rlist; static arc_ctx arc_sign_ctx = { NULL }; @@ -1298,7 +1303,10 @@ g = string_append(g, 7, US"; s=", selector); if (options & ARC_SIGN_OPT_TSTAMP) g = string_append(g, 2, - US"; t=", string_sprintf("%lu", (u_long)time(NULL))); + US"; t=", string_sprintf("%lu", (u_long)now)); +if (options & ARC_SIGN_OPT_EXPIRE) + g = string_append(g, 2, + US"; x=", string_sprintf("%lu", (u_long)expire)); g = string_append(g, 3, US";\r\n\tbh=", pdkim_encode_base64(bodyhash), US";\r\n\th="); @@ -1432,7 +1440,7 @@ arcset = string_append(NULL, 9, US"; s=", selector); /*XXX same as AMS */ if (options & ARC_SIGN_OPT_TSTAMP) arcset = string_append(arcset, 2, - US"; t=", string_sprintf("%lu", (u_long)time(NULL))); + US"; t=", string_sprintf("%lu", (u_long)now)); arcset = string_cat(arcset, US";\r\n\t b=;"); @@ -1555,6 +1563,8 @@ int instance; gstring * g = NULL; pdkim_bodyhash * b; +expire = now = 0; + /* Parse the signing specification */ identity = string_nextinlist(&signspec, &sep, NULL, 0); @@ -1574,7 +1584,29 @@ if ((opts = string_nextinlist(&signspec, &sep, NULL, 0))) int osep = ','; while ((s = string_nextinlist(&opts, &osep, NULL, 0))) if (Ustrcmp(s, "timestamps") == 0) + { options |= ARC_SIGN_OPT_TSTAMP; + if (!now) now = time(NULL); + } + else if (Ustrncmp(s, "expire", 6) == 0) + { + options |= ARC_SIGN_OPT_EXPIRE; + if (*(s += 6) == '=') + if (*++s == '+') + { + if (!(expire = (time_t)atoi(++s))) + expire = ARC_SIGN_DEFAULT_EXPIRE_DELTA; + if (!now) now = time(NULL); + expire += now; + } + else + expire = (time_t)atol(s); + else + { + if (!now) now = time(NULL); + expire = now + ARC_SIGN_DEFAULT_EXPIRE_DELTA; + } + } } DEBUG(D_transport) debug_printf("ARC: sign for %s\n", identity); -- cgit v1.2.3 From d31eceff66d5dfc5a901846c6c3fd60f13ca8718 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Wed, 4 Apr 2018 16:15:22 +0100 Subject: Add client-ip info to iprev ${authres } line --- src/src/expand.c | 4 +++- test/mail/3700.smtps | 4 ++-- test/mail/3700.x | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/src/expand.c b/src/src/expand.c index 10fadfd89..a5ddb277d 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1672,7 +1672,9 @@ static gstring * authres_iprev(gstring * g) { if (sender_host_name) - return string_append(g, 3, US";\n\tiprev=pass (", sender_host_name, US")"); + return string_append(g, sender_host_address ? 5 : 3, + US";\n\tiprev=pass (", sender_host_name, US")", + US" smtp.client-ip=", sender_host_address); if (host_lookup_deferred) return string_catn(g, US";\n\tiprev=temperror", 19); if (host_lookup_failed) diff --git a/test/mail/3700.smtps b/test/mail/3700.smtps index 60a3d234b..ff57e01ed 100644 --- a/test/mail/3700.smtps +++ b/test/mail/3700.smtps @@ -1,9 +1,9 @@ From ok@test.ex Tue Mar 02 09:44:33 1999 Authentication-Results: myhost.test.ex; - iprev=pass (localhost); + iprev=pass (localhost) smtp.client-ip=127.0.0.1; auth=pass (tls) x509.auth="Phil Pennock" Received: from localhost ([127.0.0.1] helo=myhost.test.ex) - by myhost.test.ex with esmtpsa (TLSv1:ke-RSA-AES256-SHA:xxx) + by myhost.test.ex with esmtpsa (TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256) (Exim x.yz) (envelope-from ) id 10HmbA-0005vi-00 diff --git a/test/mail/3700.x b/test/mail/3700.x index 81544998d..d1f269a37 100644 --- a/test/mail/3700.x +++ b/test/mail/3700.x @@ -1,9 +1,9 @@ From ok@test.ex Tue Mar 02 09:44:33 1999 Authentication-Results: myhost.test.ex; - iprev=pass (localhost); + iprev=pass (localhost) smtp.client-ip=127.0.0.1; auth=pass (tls) x509.auth="Phil Pennock" Received: from localhost ([127.0.0.1] helo=myhost.test.ex) - by myhost.test.ex with esmtpsa (TLSv1:ke-RSA-AES256-SHA:xxx) + by myhost.test.ex with esmtpsa (TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256) (Exim x.yz) (envelope-from ) id 10HmaZ-0005vi-00 -- cgit v1.2.3 From 50891fa36050cd6e1ff902bc0cf3b82ad4399417 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sat, 7 Apr 2018 20:58:14 +0100 Subject: Clear more globals between messages --- src/src/dkim.c | 6 +++--- src/src/dmarc.c | 62 +++++++++++++++++++++++++++---------------------------- src/src/globals.c | 1 + src/src/globals.h | 1 + src/src/smtp_in.c | 9 +++++++- 5 files changed, 44 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/src/dkim.c b/src/src/dkim.c index 043fcc6dc..e26ae7bbd 100644 --- a/src/src/dkim.c +++ b/src/src/dkim.c @@ -30,7 +30,6 @@ pdkim_ctx dkim_sign_ctx; int dkim_verify_oldpool; pdkim_ctx *dkim_verify_ctx = NULL; -pdkim_signature *dkim_signatures = NULL; pdkim_signature *dkim_cur_sig = NULL; static const uschar * dkim_collect_error = NULL; @@ -313,7 +312,8 @@ dkim_collect_input = FALSE; /* Finish DKIM operation and fetch link to signatures chain */ -rc = pdkim_feed_finish(dkim_verify_ctx, &dkim_signatures, &errstr); +rc = pdkim_feed_finish(dkim_verify_ctx, (pdkim_signature **)&dkim_signatures, + &errstr); if (rc != PDKIM_OK && errstr) log_write(0, LOG_MAIN, "DKIM: validation error: %s", errstr); @@ -395,7 +395,7 @@ for (sig = dkim_signatures; sig; sig = sig->next) them here. This is easy since a domain and selector is guaranteed to be in a signature. The other dkim_* expansion items are dynamically fetched from dkim_cur_sig at expansion time (see - function below). */ + dkim_exim_expand_query() below). */ dkim_cur_sig = sig; dkim_signing_domain = US sig->domain; diff --git a/src/src/dmarc.c b/src/src/dmarc.c index 0032afe87..eb4d63620 100644 --- a/src/src/dmarc.c +++ b/src/src/dmarc.c @@ -28,7 +28,6 @@ OPENDMARC_STATUS_T libdm_status, action, dmarc_policy; OPENDMARC_STATUS_T da, sa, action; BOOL dmarc_abort = FALSE; uschar *dmarc_pass_fail = US"skipped"; -extern pdkim_signature *dkim_signatures; header_line *from_header = NULL; extern SPF_response_t *spf_response; int dmarc_spf_ares_result = 0; @@ -217,7 +216,7 @@ dmarc_process() int sr, origin; /* used in SPF section */ int dmarc_spf_result = 0; /* stores spf into dmarc conn ctx */ int tmp_ans, c; -pdkim_signature *sig = NULL; +pdkim_signature * sig = dkim_signatures; BOOL has_dmarc_record = TRUE; u_char **ruf; /* forensic report addressees, if called for */ @@ -238,27 +237,27 @@ if (!from_header || dmarc_abort) dmarc_abort = TRUE; else { - uschar * errormsg; - int dummy, domain; - uschar * p; - uschar saveend; - - parse_allow_group = TRUE; - p = parse_find_address_end(from_header->text, FALSE); - saveend = *p; *p = '\0'; - if ((header_from_sender = parse_extract_address(from_header->text, &errormsg, - &dummy, &dummy, &domain, FALSE))) - header_from_sender += domain; - *p = saveend; - - /* The opendmarc library extracts the domain from the email address, but - * only try to store it if it's not empty. Otherwise, skip out of DMARC. */ - if (!header_from_sender || (strcmp( CCS header_from_sender, "") == 0)) - dmarc_abort = TRUE; - libdm_status = dmarc_abort ? - DMARC_PARSE_OKAY : - opendmarc_policy_store_from_domain(dmarc_pctx, header_from_sender); - if (libdm_status != DMARC_PARSE_OKAY) + uschar * errormsg; + int dummy, domain; + uschar * p; + uschar saveend; + + parse_allow_group = TRUE; + p = parse_find_address_end(from_header->text, FALSE); + saveend = *p; *p = '\0'; + if ((header_from_sender = parse_extract_address(from_header->text, &errormsg, + &dummy, &dummy, &domain, FALSE))) + header_from_sender += domain; + *p = saveend; + + /* The opendmarc library extracts the domain from the email address, but + * only try to store it if it's not empty. Otherwise, skip out of DMARC. */ + if (!header_from_sender || (strcmp( CCS header_from_sender, "") == 0)) + dmarc_abort = TRUE; + libdm_status = dmarc_abort + ? DMARC_PARSE_OKAY + : opendmarc_policy_store_from_domain(dmarc_pctx, header_from_sender); + if (libdm_status != DMARC_PARSE_OKAY) { log_write(0, LOG_MAIN|LOG_PANIC, "failure to store header From: in DMARC: %s, header was '%s'", @@ -271,6 +270,8 @@ else * instead do this in the ACLs. */ if (!dmarc_abort && !sender_host_authenticated) { + uschar * dmarc_domain; + /* Use the envelope sender domain for this part of DMARC */ spf_sender_domain = expand_string(US"$sender_address_domain"); if (!spf_response) @@ -325,11 +326,11 @@ if (!dmarc_abort && !sender_host_authenticated) /* Now we cycle through the dkim signature results and put into * the opendmarc context, further building the DMARC reply. */ - sig = dkim_signatures; dkim_history_buffer = US""; while (sig) { int dkim_result, dkim_ares_result, vs, ves; + vs = sig->verify_status & ~PDKIM_VERIFY_POLICY; ves = sig->verify_ext_status; dkim_result = vs == PDKIM_VERIFY_PASS ? DMARC_POLICY_DKIM_OUTCOME_PASS : @@ -398,9 +399,9 @@ if (!dmarc_abort && !sender_host_authenticated) } /* Can't use exim's string manipulation functions so allocate memory - * for libopendmarc using its max hostname length definition. */ + for libopendmarc using its max hostname length definition. */ - uschar *dmarc_domain = US calloc(DMARC_MAXHOSTNAMELEN, sizeof(uschar)); + dmarc_domain = US calloc(DMARC_MAXHOSTNAMELEN, sizeof(uschar)); libdm_status = opendmarc_policy_fetch_utilized_domain(dmarc_pctx, dmarc_domain, DMARC_MAXHOSTNAMELEN-1); dmarc_used_domain = string_copy(dmarc_domain); @@ -411,8 +412,7 @@ if (!dmarc_abort && !sender_host_authenticated) "failure to read domainname used for DMARC lookup: %s", opendmarc_policy_status_to_str(libdm_status)); - libdm_status = opendmarc_get_policy_to_enforce(dmarc_pctx); - dmarc_policy = libdm_status; + dmarc_policy = libdm_status = opendmarc_get_policy_to_enforce(dmarc_pctx); switch(libdm_status) { case DMARC_POLICY_ABSENT: /* No DMARC record found */ @@ -464,7 +464,7 @@ if (!dmarc_abort && !sender_host_authenticated) log_write(0, LOG_MAIN|LOG_PANIC, "failure to read DMARC alignment: %s", opendmarc_policy_status_to_str(libdm_status)); - if (has_dmarc_record == TRUE) + if (has_dmarc_record) { log_write(0, LOG_MAIN, "DMARC results: spf_domain=%s dmarc_domain=%s " "spf_align=%s dkim_align=%s enforcement='%s'", @@ -483,9 +483,9 @@ if (!dmarc_abort && !sender_host_authenticated) dmarc_ar_header = dmarc_auth_results_header(from_header, NULL); /* shut down libopendmarc */ -if ( dmarc_pctx != NULL ) +if (dmarc_pctx) (void) opendmarc_policy_connect_shutdown(dmarc_pctx); -if ( dmarc_disable_verify == FALSE ) +if (!dmarc_disable_verify) (void) opendmarc_policy_library_shutdown(&dmarc_ctx); return OK; diff --git a/src/src/globals.c b/src/src/globals.c index 705b1dd0c..16a5ab42e 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -672,6 +672,7 @@ BOOL dkim_collect_input = FALSE; uschar *dkim_cur_signer = NULL; BOOL dkim_disable_verify = FALSE; int dkim_key_length = 0; +void *dkim_signatures = NULL; uschar *dkim_signers = NULL; uschar *dkim_signing_domain = NULL; uschar *dkim_signing_selector = NULL; diff --git a/src/src/globals.h b/src/src/globals.h index dbc706037..7e3b69260 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -395,6 +395,7 @@ extern BOOL dkim_collect_input; /* Runtime flag that tracks wether SMTP i extern uschar *dkim_cur_signer; /* Expansion variable, holds the current "signer" domain or identity during a acl_smtp_dkim run */ extern BOOL dkim_disable_verify; /* Set via ACL control statement. When set, DKIM verification is disabled for the current message */ extern int dkim_key_length; /* Expansion variable, length of signing key in bits */ +extern void *dkim_signatures; /* Actually a (pdkim_signature *) but most files do not need to know */ extern uschar *dkim_signers; /* Expansion variable, holds colon-separated list of domains and identities that have signed a message */ extern uschar *dkim_signing_domain; /* Expansion variable, domain used for signing a message. */ extern uschar *dkim_signing_selector; /* Expansion variable, selector used for signing a message. */ diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 823fcd27d..2881dd959 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -2040,9 +2040,16 @@ bmi_verdicts = NULL; #endif dnslist_domain = dnslist_matched = NULL; #ifndef DISABLE_DKIM -dkim_cur_signer = dkim_signers = NULL; +dkim_cur_signer = dkim_signers = +dkim_signing_domain = dkim_signing_selector = dkim_signatures = NULL; dkim_disable_verify = dkim_collect_input = FALSE; #endif +#ifdef EXPERIMENTAL_DMARC +dmarc_has_been_checked = dmarc_disable_verify = dmarc_enable_forensic = FALSE; +dmarc_ar_header = dmarc_domain_policy = dmarc_forensic_sender = +dmarc_history_file = dmarc_status = dmarc_status_text = dmarc_tld_file = +dmarc_used_domain = NULL; +#endif dsn_ret = 0; dsn_envid = NULL; deliver_host = deliver_host_address = NULL; /* Can be set by ACL */ -- cgit v1.2.3 From fdfe718d5ed9f551120a29af214883d59ddb85d1 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Fri, 13 Apr 2018 17:17:37 +0100 Subject: Logging: fix syslog logging for syslog_timestamp=no and log_selector +millisec --- doc/doc-txt/ChangeLog | 5 +++ src/src/log.c | 110 ++++++++++++++++++++++++++------------------------ 2 files changed, 63 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 61fd30bf8..5a910c4e1 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -14,6 +14,11 @@ JH/01 Remove code calling the customisable local_scan function, unless a new JH/02 Bug 1007: Avoid doing logging from signal-handlers, as that can result in non-signal-safe funxtions being used. +JH/03 Fix syslog logging for syslog_timestamp=no and log_selector +millisec. + Previously the millisecond value corrupted the output. + Fix also for syslog_pid=no and log_selector +pid, for which the pid + corrupted the output. + Since Exim version 4.90 ----------------------- diff --git a/src/src/log.c b/src/src/log.c index 755119813..9cde369c0 100644 --- a/src/src/log.c +++ b/src/src/log.c @@ -134,33 +134,38 @@ can get here if there is a failure to open the panic log.) Arguments: priority syslog priority - s the string to be written, the string may be modified! + s the string to be written Returns: nothing */ static void -write_syslog(int priority, uschar *s) +write_syslog(int priority, const uschar *s) { int len, pass; int linecount = 0; if (running_in_test_harness) return; -if (!syslog_timestamp) s += log_timezone ? 26 : 20; if (!syslog_pid && LOGGING(pid)) - memmove(s + pid_position[0], s + pid_position[1], pid_position[1] - pid_position[0]); + s = string_sprintf("%.*s%s", (int)pid_position[0], s, s + pid_position[1]); +if (!syslog_timestamp) + { + len = log_timezone ? 26 : 20; + if (LOGGING(millisec)) len += 4; + s += len; + } len = Ustrlen(s); #ifndef NO_OPENLOG if (!syslog_open) { - #ifdef SYSLOG_LOG_PID +# ifdef SYSLOG_LOG_PID openlog(CS syslog_processname, LOG_PID|LOG_CONS, syslog_facility); - #else +# else openlog(CS syslog_processname, LOG_CONS, syslog_facility); - #endif +# endif syslog_open = TRUE; } #endif @@ -172,15 +177,15 @@ for (pass = 0; pass < 2; pass++) { int i; int tlen; - uschar *ss = s; + const uschar * ss = s; for (i = 1, tlen = len; tlen > 0; i++) { int plen = tlen; uschar *nlptr = Ustrchr(ss, '\n'); if (nlptr != NULL) plen = nlptr - ss; - #ifndef SYSLOG_LONG_LINES +#ifndef SYSLOG_LONG_LINES if (plen > MAX_SYSLOG_LEN) plen = MAX_SYSLOG_LEN; - #endif +#endif tlen -= plen; if (ss[plen] == '\n') tlen--; /* chars left */ @@ -190,7 +195,7 @@ for (pass = 0; pass < 2; pass++) syslog(priority, "%.*s", plen, ss); else syslog(priority, "[%d%c%d] %.*s", i, - (ss[plen] == '\n' && tlen != 0)? '\\' : '/', + ss[plen] == '\n' && tlen != 0 ? '\\' : '/', linecount, plen, ss); } ss += plen; @@ -227,7 +232,7 @@ if (s1) { write_syslog(LOG_CRIT, s1); if (debug_file) debug_printf("%s\n", s1); - if (log_stderr != NULL && log_stderr != debug_file) + if (log_stderr && log_stderr != debug_file) fprintf(log_stderr, "%s\n", s1); } if (receive_call_bombout) receive_bomb_out(NULL, s2); /* does not return */ @@ -427,20 +432,19 @@ char afterwards if at the start, otherwise one before. */ else if (string_datestamp_offset >= 0) { - uschar *from = buffer + string_datestamp_offset; - uschar *to = from + string_datestamp_length; + uschar * from = buffer + string_datestamp_offset; + uschar * to = from + string_datestamp_length; + if (from == buffer || from[-1] == '/') { if (!isalnum(*to)) to++; } else - { if (!isalnum(from[-1])) from--; - } - /* This strcpy is ok, because we know that to is a substring of from. */ - - Ustrcpy(from, to); + /* This copy is ok, because we know that to is a substring of from. But + due to overlap we must use memmove() not Ustrcpy(). */ + memmove(from, to, Ustrlen(to)+1); } /* If the file name is too long, it is an unrecoverable disaster */ @@ -744,11 +748,11 @@ original log line that caused the problem. Afterwards, expire. */ if (panic_recurseflag) { - uschar *extra = (panic_save_buffer == NULL)? US"" : panic_save_buffer; - if (debug_file != NULL) debug_printf("%s%s", extra, log_buffer); - if (log_stderr != NULL && log_stderr != debug_file) + uschar *extra = panic_save_buffer ? panic_save_buffer : US""; + if (debug_file) debug_printf("%s%s", extra, log_buffer); + if (log_stderr && log_stderr != debug_file) fprintf(log_stderr, "%s%s", extra, log_buffer); - if (*extra != 0) write_syslog(LOG_CRIT, extra); + if (*extra) write_syslog(LOG_CRIT, extra); write_syslog(LOG_CRIT, log_buffer); die(US"exim: could not open panic log - aborting: see message(s) above", US"Unexpected log failure, please try later"); @@ -785,12 +789,14 @@ if (!path_inspected) int sep = ':'; /* Fixed separator - outside use */ uschar *s; const uschar *ss = log_file_path; + logging_mode = 0; while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE))) { if (Ustrcmp(s, "syslog") == 0) logging_mode |= LOG_MODE_SYSLOG; - else if ((logging_mode & LOG_MODE_FILE) != 0) multiple = TRUE; + else if (logging_mode & LOG_MODE_FILE) + multiple = TRUE; else { logging_mode |= LOG_MODE_FILE; @@ -820,7 +826,7 @@ if (!path_inspected) /* Set up the ultimate default if necessary. Then revert to the old store pool, and record that we've sorted out the path. */ - if ((logging_mode & LOG_MODE_FILE) != 0 && file_path[0] == 0) + if (logging_mode & LOG_MODE_FILE && !file_path[0]) file_path = string_sprintf("%s/log/%%slog", spool_directory); store_pool = old_pool; path_inspected = TRUE; @@ -858,12 +864,12 @@ DEBUG(D_any|D_v) } ptr += sprintf(CS ptr, "%s%s%s%s\n ", - ((flags & LOG_MAIN) != 0)? " MAIN" : "", - ((flags & LOG_PANIC) != 0)? " PANIC" : "", - ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE)? " DIE" : "", - ((flags & LOG_REJECT) != 0)? " REJECT" : ""); + flags & LOG_MAIN ? " MAIN" : "", + flags & LOG_PANIC ? " PANIC" : "", + (flags & LOG_PANIC_DIE) == LOG_PANIC_DIE ? " DIE" : "", + flags & LOG_REJECT ? " REJECT" : ""); - if ((flags & LOG_CONFIG) != 0) ptr = log_config_info(ptr, flags); + if (flags & LOG_CONFIG) ptr = log_config_info(ptr, flags); va_start(ap, format); if (!string_vformat(ptr, LOG_BUFFER_SIZE - (ptr-log_buffer)-1, format, ap)) @@ -877,7 +883,7 @@ DEBUG(D_any|D_v) /* If no log file is specified, we are in a mess. */ -if ((flags & (LOG_MAIN|LOG_PANIC|LOG_REJECT)) == 0) +if (!(flags & (LOG_MAIN|LOG_PANIC|LOG_REJECT))) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "log_write called with no log " "flags set"); @@ -909,7 +915,7 @@ if (LOGGING(pid)) if (really_exim && message_id[0] != 0) ptr += sprintf(CS ptr, "%s ", message_id); -if ((flags & LOG_CONFIG) != 0) ptr = log_config_info(ptr, flags); +if (flags & LOG_CONFIG) ptr = log_config_info(ptr, flags); va_start(ap, format); if (!string_vformat(ptr, LOG_BUFFER_SIZE - (ptr-log_buffer)-1, format, ap)) @@ -920,16 +926,17 @@ va_end(ap); /* Add the raw, unrewritten, sender to the message if required. This is done this way because it kind of fits with LOG_RECIPIENTS. */ -if ((flags & LOG_SENDER) != 0 && - ptr < log_buffer + LOG_BUFFER_SIZE - 10 - Ustrlen(raw_sender)) +if ( flags & LOG_SENDER + && ptr < log_buffer + LOG_BUFFER_SIZE - 10 - Ustrlen(raw_sender)) ptr += sprintf(CS ptr, " from <%s>", raw_sender); /* Add list of recipients to the message if required; the raw list, before rewriting, was saved in raw_recipients. There may be none, if an ACL discarded them all. */ -if ((flags & LOG_RECIPIENTS) != 0 && ptr < log_buffer + LOG_BUFFER_SIZE - 6 && - raw_recipients_count > 0) +if ( flags & LOG_RECIPIENTS + && ptr < log_buffer + LOG_BUFFER_SIZE - 6 + && raw_recipients_count > 0) { int i; ptr += sprintf(CS ptr, " for"); @@ -950,14 +957,15 @@ or unless there is no log_stderr (expn called from daemon, for example). */ if (!really_exim || log_testing_mode) { - if (debug_selector == 0 && log_stderr != NULL && - (selector == 0 || (selector & log_selector[0]) != 0)) - { + if ( !debug_selector + && log_stderr + && (selector == 0 || (selector & log_selector[0]) != 0) + ) if (host_checking) fprintf(log_stderr, "LOG: %s", CS(log_buffer + 20)); /* no timestamp */ else fprintf(log_stderr, "%s", CS log_buffer); - } + if ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE) exim_exit(EXIT_FAILURE, US""); return; } @@ -1028,11 +1036,11 @@ which case the flags are altered above. If there are any header lines (i.e. if the rejection is happening after the DATA phase), log the recipients and the headers. */ -if ((flags & LOG_REJECT) != 0) +if (flags & LOG_REJECT) { header_line *h; - if (header_list != NULL && LOGGING(rejected_header)) + if (header_list && LOGGING(rejected_header)) { if (recipients_count > 0) { @@ -1087,15 +1095,15 @@ if ((flags & LOG_REJECT) != 0) /* Write to syslog or to a log file */ - if ((logging_mode & LOG_MODE_SYSLOG) != 0 && - (syslog_duplication || (flags & LOG_PANIC) == 0)) + if ( logging_mode & LOG_MODE_SYSLOG + && (syslog_duplication || !(flags & LOG_PANIC))) write_syslog(LOG_NOTICE, log_buffer); /* Check for a change to the rejectlog file name when datestamping is in operation. This happens at midnight, at which point we want to roll over the file. Closing it has the desired effect. */ - if ((logging_mode & LOG_MODE_FILE) != 0) + if (logging_mode & LOG_MODE_FILE) { struct stat statbuf; @@ -1117,7 +1125,6 @@ if ((flags & LOG_REJECT) != 0) happening. */ if (rejectlogfd >= 0) - { if (Ustat(rejectlog_name, &statbuf) < 0 || statbuf.st_ino != rejectlog_inode) { @@ -1125,7 +1132,6 @@ if ((flags & LOG_REJECT) != 0) rejectlogfd = -1; rejectlog_inode = 0; } - } /* Open the file if necessary, and write the data */ @@ -1150,24 +1156,24 @@ open, there will be a recursive call to log_write(). We detect this above and attempt to write to the system log as a last-ditch try at telling somebody. In all cases except mua_wrapper, try to write to log_stderr. */ -if ((flags & LOG_PANIC) != 0) +if (flags & LOG_PANIC) { - if (log_stderr != NULL && log_stderr != debug_file && !mua_wrapper) + if (log_stderr && log_stderr != debug_file && !mua_wrapper) fprintf(log_stderr, "%s", CS log_buffer); - if ((logging_mode & LOG_MODE_SYSLOG) != 0) + if (logging_mode & LOG_MODE_SYSLOG) write_syslog(LOG_ALERT, log_buffer); /* If this panic logging was caused by a failure to open the main log, the original log line is in panic_save_buffer. Make an attempt to write it. */ - if ((logging_mode & LOG_MODE_FILE) != 0) + if (logging_mode & LOG_MODE_FILE) { panic_recurseflag = TRUE; open_log(&paniclogfd, lt_panic, NULL); /* Won't return on failure */ panic_recurseflag = FALSE; - if (panic_save_buffer != NULL) + if (panic_save_buffer) { int i = write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer)); i = i; /* compiler quietening */ -- cgit v1.2.3