X-Git-Url: https://git.exim.org/users/jgh/exim.git/blobdiff_plain/efc8902f16c92a74d06870f2556cb36c84dd4d93..4ed67f68df666fe38076e3bfd2183db71e742c7a:/test/runtest diff --git a/test/runtest b/test/runtest index d52facc7a..fea40845c 100755 --- a/test/runtest +++ b/test/runtest @@ -112,7 +112,7 @@ $ENV{LC_ALL} = 'C'; $ENV{USER} = getpwuid($>) if not exists $ENV{USER}; my ($parm_configure_owner, $parm_configure_group); -my ($parm_ipv4, $parm_ipv6); +my ($parm_ipv4, $parm_ipv6, $parm_ipv6_stripped); my $parm_hostname; ############################################################################### @@ -492,10 +492,10 @@ RESET_AFTER_EXTRA_LINE_READ: # time used was fixed when I first started running automatic Exim tests. # Date/time in header lines and SMTP responses - s/[A-Z][a-z]{2},\s\d\d?\s[A-Z][a-z]{2}\s\d\d\d\d\s\d\d\:\d\d:\d\d\s[-+]\d{4} + s/[A-Z][a-z]{2},\s\d\d?\s[A-Z][a-z]{2}\s\d{4}\s\d\d\:\d\d:\d\d\s[-+]\d{4} /Tue, 2 Mar 1999 09:44:33 +0000/gx; # and in a French locale - s/\S{4},\s\d\d?\s[^,]+\s\d\d\d\d\s\d\d\:\d\d:\d\d\s[-+]\d{4} + s/\S{4},\s\d\d?\s[^,]+\s\d{4}\s\d\d\:\d\d:\d\d\s[-+]\d{4} /dim., 10 f\xE9vr 2019 20:05:49 +0000/gx; # Date/time in logs and in one instance of a filter test @@ -553,7 +553,7 @@ RESET_AFTER_EXTRA_LINE_READ: # (discarding kex, cipher, mac). For TLS 1.3 there is no kex # element (and no _WITH); insert a spurious "RSA". - s/^\s+by .+ with .+ \K tls TLS_.*?([^_]+)_WITH.+$/(TLS1.x:ke-\1-AES256-SHAnnn:xxx)/; + s/^\s+by .+ with .+ \K tls TLS_.*?([^_]+)_WITH.+$/(TLS1.x:ke-$1-AES256-SHAnnn:xxx)/; s/^\s+by .+ with .+ \K tls TLS_.+$/(TLS1.x:ke-RSA-AES256-SHAnnn:xxx)/; # Test machines might have various different TLS library versions supporting @@ -604,27 +604,52 @@ RESET_AFTER_EXTRA_LINE_READ: # GnuTLS have seen: # TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256 + # TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM__AEAD:256 + # TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256 + # TLS1.3:ECDHE_PSK_SECP256R1__AES_256_GCM__AEAD:256 # # TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 # TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128 # TLS1.2:RSA_AES_256_CBC_SHA1:256 (canonical) # TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128 + # TLS1.2:ECDHE_SECP256R1__RSA_SHA256__AES_256_GCM:256 + # TLS1.2:ECDHE_SECP256R1__RSA_SHA256__AES_128_CBC__SHA256:128 + # TLS1.2:ECDHE_SECP256R1__ECDSA_SHA512__AES_256_GCM:256 + # TLS1.2:ECDHE_SECP256R1__AES_256_GCM:256 (3.6.7 resumption) + # TLS1.2:ECDHE_RSA_SECP256R1__AES_256_GCM:256 (! 3.5.18 !) + # TLS1.2:RSA__CAMELLIA_256_GCM:256 (leave the cipher name) + # TLS1.2-PKIX:RSA__AES_128_GCM__AEAD:128 (the -PKIX seems to be a 3.1.20 thing) + # TLS1.2-PKIX:ECDHE_RSA_SECP521R1__AES_256_GCM__AEAD:256 # # X=TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256 # X=TLS1.2:RSA_AES_256_CBC_SHA1:256 # X=TLS1.1:RSA_AES_256_CBC_SHA1:256 + # X=TLS1.0:RSA_AES_256_CBC_SHA1:256 # X=TLS1.0:DHE_RSA_AES_256_CBC_SHA1:256 + # X=TLS1.0-PKIX:RSA__AES_256_CBC__SHA1:256 # and as stand-alone cipher: # ECDHE-RSA-AES256-SHA # DHE-RSA-AES256-SHA256 # DHE-RSA-AES256-SHA # picking latter as canonical simply because regex easier that way. s/\bDHE_RSA_AES_128_CBC_SHA1:128/RSA-AES256-SHA1:256/g; - s/TLS1.[0123]:((EC)?DHE_)?(RSA|ECDSA)_AES_(256|128)_(CBC|GCM)_SHA(1|256|384):(256|128)/TLS1.x:ke-$3-AES256-SHAnnn:xxx/g; + s/TLS1.[0123](-PKIX)?: # TLS version + ((EC)?DHE(_((?PSK)_)?((?RSA|ECDSA)_)? + (SECP(256|521)R1|X25519))?__?)? # key-exchange + ((?RSA|ECDSA)((_PSS_RSAE)?_SHA(512|256))?__?)? # authentication + AES_(256|128)_(CBC|GCM) # cipher + (__?AEAD)? # pseudo-MAC + (__?SHA(1|256|384))? # PRF + :(256|128) # cipher strength + /"TLS1.x:ke-" + . (defined($+{psk}) ? $+{psk} : "") + . (defined($+{auth}) ? $+{auth} : "") + . "-AES256-SHAnnn:xxx"/gex; + s/TLS1.2:RSA__CAMELLIA_256_GCM(_SHA384)?:256/TLS1.2:RSA_CAMELLIA_256_GCM-SHAnnn:256/g; s/\b(ECDHE-(RSA|ECDSA)-AES256-SHA|DHE-RSA-AES256-SHA256)\b/ke-$2-AES256-SHAnnn/g; # GnuTLS library error message changes - s/No certificate was found/The peer did not send any certificate/g; + s/(No certificate was found|Certificate is required)/The peer did not send any certificate/g; #(dodgy test?) s/\(certificate verification failed\): invalid/\(gnutls_handshake\): The peer did not send any certificate./g; s/\(gnutls_priority_set\): No or insufficient priorities were set/\(gnutls_handshake\): Could not negotiate a supported cipher suite/g; s/\(gnutls_handshake\): \KNo supported cipher suites have been found.$/Could not negotiate a supported cipher suite./; @@ -733,9 +758,6 @@ RESET_AFTER_EXTRA_LINE_READ: s/waiting for children of \d+/waiting for children of pppp/; s/waiting for (\S+) \(\d+\)/waiting for $1 (pppp)/; - # The spool header file name varies with PID - s%^(Writing spool header file: .*/hdr).[0-9]{1,5}%$1.pppp%; - # ======== Port numbers ======== # Incoming port numbers may vary, but not in daemon startup line. @@ -750,7 +772,7 @@ RESET_AFTER_EXTRA_LINE_READ: } # Port in host address in spool file output from -Mvh - s/^-host_address (.*)\.\d+/-host_address $1.9999/; + s/^(--?host_address) (.*)\.\d+/$1 $2.9999/; if ($dynamic_socket and $dynamic_socket->opened and my $port = $dynamic_socket->sockport) { s/^Connecting to 127\.0\.0\.1 port \K$port//; @@ -772,6 +794,7 @@ RESET_AFTER_EXTRA_LINE_READ: s/host\s\Q$parm_ipv6\E\s\[\Q$parm_ipv6\E\]/host ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6 [ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6]/; s/\b\Q$parm_ipv4\E\b/ip4.ip4.ip4.ip4/g; s/(^|\W)\K\Q$parm_ipv6\E/ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6/g; + s/(^|\W)\K\Q$parm_ipv6_stripped\E/ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6/g; s/\b\Q$parm_ipv4r\E\b/ip4-reverse/g; s/(^|\W)\K\Q$parm_ipv6r\E/ip6-reverse/g; s/^(\s+host\s\S+\s+\[\S+\]) +$/$1 /; @@ -974,8 +997,15 @@ RESET_AFTER_EXTRA_LINE_READ: s/^waiting for server to shut down\.+ done$/waiting for server to shut down.... done/; s/^\/.*postgres /POSTGRES /; + # DMARC is not always supported by the build + next if /^dmarc_tld_file =/; + # ARC is not always supported by the build next if /^arc_sign =/; + + # TLS resumption is not always supported by the build + next if /^tls_resumption_hosts =/; + next if /^-tls_resumption/; } # ======== stderr ======== @@ -1056,7 +1086,7 @@ RESET_AFTER_EXTRA_LINE_READ: next if /name=localhost address=::1/; # drop pdkim debugging header - next if /^PDKIM( <<<<<<<<<<<<<<<<<<<<<<<<<<<<<+|: no signatures)$/; + next if /^DKIM( <<<<<<<<<<<<<<<<<<<<<<<<<<<<<+|: no signatures)$/; # Various other IPv6 lines must be omitted too @@ -1064,6 +1094,7 @@ RESET_AFTER_EXTRA_LINE_READ: next if /get\[host\|ipnode\]byname\[2\]\(af=inet6\)/; next if /DNS lookup of \S+ \(AAAA\) using fakens/; next if / in dns_ipv4_lookup?/; + next if / writing neg-cache entry for .*AAAA/; if (/DNS lookup of \S+ \(AAAA\) gave NO_DATA/) { @@ -1071,6 +1102,17 @@ RESET_AFTER_EXTRA_LINE_READ: next; } + # Non-TLS bulds have a different Recieved: header expansion + s/^((.*)\t}}}}by \$primary_hostname \${if def:received_protocol {with \$received_protocol }})\(Exim \$version_number\)$/$1\${if def:tls_in_cipher_std { tls \$tls_in_cipher_std\n$2\t}}(Exim \$version_number)/; + s/^((\s*).*considering: with \$received_protocol }})\(Exim \$version_number\)$/$1\${if def:tls_in_cipher_std { tls \$tls_in_cipher_std\n$2\t}}(Exim \$version_number)/; + if (/condition: def:tls_in_cipher_std$/) + { + $_= ; $_= ; $_= ; $_= ; + $_= ; $_= ; $_= ; $_= ; + $_= ; $_= ; $_= ; next; + } + + # Skip tls_advertise_hosts and hosts_require_tls checks when the options # are unset, because tls ain't always there. @@ -1125,16 +1167,28 @@ RESET_AFTER_EXTRA_LINE_READ: # remote port numbers vary s/(Connection request from 127.0.0.1 port) \d{1,5}/$1 sssss/; + # Platform-dependent error strings + s/Operation timed out/Connection timed out/; + + # Platform-dependent resolver option bits + s/^ (?:writing|update) neg-cache entry for [^,]+-\K[0-9a-f]+, ttl/xxxx, ttl/; + + # timing variance, run-to-run + s/^time on queue = \K1s/0s/; + # Skip hosts_require_dane checks when the options # are unset, because dane ain't always there. next if /in\shosts_require_dane\?\sno\s\(option\sunset\)/x; - # DISABLE_OCSP + # DISABLE_OCSP next if /in hosts_requ(est|ire)_ocsp\? (no|yes)/; # SUPPORT_PROXY next if /host in hosts_proxy\?/; + # PIPE_CONNECT + next if / in (pipelining_connect_advertise_hosts|hosts_pipe_connect)?\? no /; + # Experimental_International next if / in smtputf8_advertise_hosts\? no \(option unset\)/; @@ -1144,9 +1198,6 @@ RESET_AFTER_EXTRA_LINE_READ: # TCP Fast Open next if /^(ppppp )?setsockopt FASTOPEN: Network Error/; - # Experimental_PIPE_CONNECT - next if / in (pipelining_connect_advertise_hosts|hosts_pipe_connect)?\? no /; - # Environment cleaning next if /\w+ in keep_environment\? (yes|no)/; @@ -1169,26 +1220,57 @@ RESET_AFTER_EXTRA_LINE_READ: } # Not all platforms build with DKIM enabled - next if /^PDKIM >> Body data for hash, canonicalized/; + next if /^DKIM >> Body data for hash, canonicalized/; + + # Not all platforms build with SPF enabled + next if /^(spf_conn_init|SPF_dns_exim_new|spf_compile\.c)/; # Not all platforms have sendfile support next if /^cannot use sendfile for body: no support$/; # Parts of DKIM-specific debug output depend on the time/date next if /^date:\w+,\{SP\}/; - next if /^PDKIM \[[^[]+\] (Header hash|b) computed:/; + next if /^DKIM \[[^[]+\] (Header hash|b) computed:/; # Not all platforms support TCP Fast Open, and the compile omits the check - if (s/\S+ in hosts_try_fastopen\? no \(option unset\)\n$//) + if (s/\S+ in hosts_try_fastopen\? (no \(option unset\)|yes \(matched "\*"\))\n$//) { $_ .= ; s/ \.\.\. >>> / ... /; + if (s/ non-TFO mode connection attempt to 224.0.0.0, 0 data\b$//) { $_ .= ; } s/Address family not supported by protocol family/Network Error/; s/Network is unreachable/Network Error/; } next if /^(ppppp )?setsockopt FASTOPEN: Protocol not available$/; s/^(Connecting to .* \.\.\. sending) \d+ (nonTFO early-data)$/$1 dd $2/; + if (/^([0-9: ]* # possible timestamp + Connecting\ to\ [^ ]+\ [^ ]+(\ from\ [^ ]+)?)\ \.\.\. + \ .*TFO\ mode\x20 + (sendto,\ no\ data:\ EINPROGRESS # Linux + |connection\ attempt\ to\ [^,]+,\ 0\ data) # MacOS & no-support + $/x) + { + $_ = $1 . " ... " . ; + s/^(.* \.\.\.) [0-9: ]*connected$/$1 connected/; + + if (/^Connecting to .* \.\.\. connected$/) + { + $_ .= ; + if (/^(Connecting to .* \.\.\. )connected\n\s+SMTP(\(close\)>>|\(Connection refused\)<<)$/) + { + $_ = $1 . "failed: Connection refused\n" . ; + s/^(Connecting .*)\n\s+SMTP\(close\)>>$/$1/; + } + elsif (/^(Connecting to .* \.\.\. connected\n)read response data: size=/) + { $_ = $1; } + + # Date/time in SMTP banner + s/[A-Z][a-z]{2},\s\d\d?\s[A-Z][a-z]{2}\s\d{4}\s\d\d\:\d\d:\d\d\s[-+]\d{4} + /Tue, 2 Mar 1999 09:44:33 +0000/gx; + } + } + # Specific pointer values reported for DB operations change from run to run s/^(\s*returned from EXIM_DBOPEN: )(0x)?[0-9a-f]+/${1}0xAAAAAAAA/; s/^(\s*EXIM_DBCLOSE.)(0x)?[0-9a-f]+/${1}0xAAAAAAAA/; @@ -1201,6 +1283,16 @@ RESET_AFTER_EXTRA_LINE_READ: # Not all builds include DMARC next if /^DMARC: no (dmarc_tld_file|sender_host_address)$/ ; + # TLS resumption is not always supported by the build + next if /in tls_resumption_hosts\?/; + + # Most builds are without HAVE_LOCAL_SCAN + next if /^calling local_scan\(\); timeout=300$/; + next if /^local_scan\(\) returned 0 NULL$/; + + # Platform differences in errno strings + s/ SMTP\(Operation timed out\)<; + if (/error on first read/) + { + s/TLS session: \Kerror on first read:/(gnutls_handshake): A TLS fatal alert has been received.:/; + goto RESET_AFTER_EXTRA_LINE_READ; + } + else + { $_ = $prev; } + } + # translate gnutls error into the openssl one + s/ARC: AMS signing: privkey PEM-block import: \KThe requested data were not available.$/error:0906D06C:PEM routines:PEM_read_bio:no start line/; # DKIM timestamps if ( /(DKIM: d=.*) t=([0-9]*) x=([0-9]*) / ) @@ -1268,6 +1377,16 @@ RESET_AFTER_EXTRA_LINE_READ: my ($prefix, $t_diff) = ($1, $3 - $2); s/DKIM: d=.* t=[0-9]* x=[0-9]* /${prefix} t=T x=T+${t_diff} /; } + + # port numbers + s/(?:\[[^\]]*\]:|port )\K$parm_port_d/PORT_D/; + s/(?:\[[^\]]*\]:|port )\K$parm_port_d2/PORT_D2/; + s/(?:\[[^\]]*\]:|port )\K$parm_port_d3/PORT_D3/; + s/(?:\[[^\]]*\]:|port )\K$parm_port_d4/PORT_D4/; + s/(?:\[[^\]]*\]:|port )\K$parm_port_s/PORT_S/; + s/(?:\[[^\]]*\]:|port )\K$parm_port_n/PORT_N/; + s/I=\[[^\]]*\]:\K\d+/ppppp/; + } # ======== mail ======== @@ -2803,7 +2922,6 @@ foreach (@eximinfo) my $git = `git describe --dirty=-XX --match 'exim-4*'`; if (defined $git and $? == 0) { chomp $git; - $version =~ s/^\d+\K\./_/; $git =~ s/^exim-//i; $git =~ s/.*-\Kg([[:xdigit:]]+(?:-XX)?)/$1/; print <<___ @@ -2880,7 +2998,7 @@ die "CONFIGURE_GROUP ($parm_configure_group) does not match the group invoking $ if 0020 & (stat "$parm_cwd/test-config")[2] and $parm_configure_group != $); -die "aux-fixed file is world-writeable; best to strip them all, recursively\n" +die "aux-fixed file is group-writeable; best to strip them all, recursively\n" if 0020 & (stat "aux-fixed/0037.f-1")[2]; @@ -3297,21 +3415,28 @@ else # Find this host's IP addresses - there may be many, of course, but we keep # one of each type (IPv4 and IPv6). +#XXX it would be good to avoid non-UP interfaces open(IFCONFIG, '-|', (grep { -x "$_/ip" } split /:/, $ENV{PATH}) ? 'ip address' : 'ifconfig -a') or die "** Cannot run 'ip address' or 'ifconfig -a'\n"; while (not ($parm_ipv4 and $parm_ipv6) and defined($_ = )) { + if (/^(?:[0-9]+: )?([a-z0-9]+): /) { $ifname = $1; } + if (not $parm_ipv4 and /^\s*inet(?:\saddr)?:?\s?(\d+\.\d+\.\d+\.\d+)(?:\/\d+)?\s/i) { - next if $1 =~ /^(?:127|10)\./; + # It would be nice to be able to vary the /16 used for manyhome; we could take + # an option to runtest used here - but we'd also have to pass it on to fakens. + # Possibly an environment variable? + next if $1 eq '0.0.0.0' or $1 =~ /^(?:127|10\.250)\./; $parm_ipv4 = $1; } - if (not $parm_ipv6 and /^\s*inet6(?:\saddr)?:?\s?([abcdef\d:]+)(?:\/\d+)/i) + if (not $parm_ipv6 and /^\s*inet6(?:\saddr)?:?\s?([abcdef\d:]+)(?:%[^ \/]+)?(?:\/\d+)?/i) { - next if $1 eq '::1' or $1 =~ /^fe80/i; + next if $1 eq '::' or $1 eq '::1' or $1 =~ /^ff00/i or $1 =~ /^fe80::1/i; $parm_ipv6 = $1; + if ($1 =~ /^fe80/i) { $parm_ipv6 .= '%' . $ifname; } } } close(IFCONFIG); @@ -3368,6 +3493,9 @@ else print "IPv4 address is $parm_ipv4\n"; print "IPv6 address is $parm_ipv6\n"; +$parm_ipv6 =~ /^[^%\/]*/; +# drop any %scope from the ipv6, for some uses +($parm_ipv6_stripped = $parm_ipv6) =~ s/%.*//g; # For munging test output, we need the reversed IP addresses. @@ -3377,7 +3505,7 @@ $parm_ipv4r = ($parm_ipv4 !~ /^\d/)? '' : $parm_ipv6r = $parm_ipv6; # Appropriate if not in use if ($parm_ipv6 =~ /^[\da-f]/) { - my(@comps) = split /:/, $parm_ipv6; + my(@comps) = split /:/, $parm_ipv6_stripped; my(@nibbles); foreach $comp (@comps) { @@ -3798,7 +3926,7 @@ if ($have_ipv4 || $have_ipv6) "; for queries that it cannot answer\n\n" . "PASS ON NOT FOUND\n\n"; print OUT "$shortname A $parm_ipv4\n" if $have_ipv4; - print OUT "$shortname AAAA $parm_ipv6\n" if $have_ipv6; + print OUT "$shortname AAAA $parm_ipv6_stripped\n" if $have_ipv6; print OUT "\n; End\n"; close(OUT); } @@ -3806,28 +3934,39 @@ if ($have_ipv4 || $have_ipv6) if ($have_ipv4 && $parm_ipv4 ne "127.0.0.1") { my(@components) = $parm_ipv4 =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/; - open(OUT, ">$parm_cwd/dnszones/db.ip4.$components[0]") || - tests_exit(-1, - "Failed to open $parm_cwd/dnszones/db.ip4.$components[0]: $!"); - print OUT "; This is a dynamically constructed fake zone file.\n" . - "; The zone is $components[0].in-addr.arpa.\n\n" . - "$components[3].$components[2].$components[1] PTR $parm_hostname.\n\n" . - "; End\n"; - close(OUT); + + if ($components[0]=='10') + { + open(OUT, ">>$parm_cwd/dnszones/db.ip4.$components[0]") || + tests_exit(-1, "Failed to open $parm_cwd/dnszones/db.ip4.$components[0]: $!"); + print OUT "$components[3].$components[2].$components[1] PTR $parm_hostname.\n\n"; + close(OUT); + } + else + { + open(OUT, ">$parm_cwd/dnszones/db.ip4.$components[0]") || + tests_exit(-1, + "Failed to open $parm_cwd/dnszones/db.ip4.$components[0]: $!"); + print OUT "; This is a dynamically constructed fake zone file.\n" . + "; The zone is $components[0].in-addr.arpa.\n\n" . + "$components[3].$components[2].$components[1] PTR $parm_hostname.\n\n" . + "; End\n"; + close(OUT); + } } -if ($have_ipv6 && $parm_ipv6 ne "::1") +if ($have_ipv6 && $parm_ipv6_stripped ne "::1") { - my($exp_v6) = $parm_ipv6; + my($exp_v6) = $parm_ipv6_stripped; $exp_v6 =~ s/[^:]//g; - if ( $parm_ipv6 =~ /^([^:].+)::$/ ) { + if ( $parm_ipv6_stripped =~ /^([^:].+)::$/ ) { $exp_v6 = $1 . ':0' x (9-length($exp_v6)); - } elsif ( $parm_ipv6 =~ /^(.+)::(.+)$/ ) { + } elsif ( $parm_ipv6_stripped =~ /^(.+)::(.+)$/ ) { $exp_v6 = $1 . ':0' x (8-length($exp_v6)) . ':' . $2; - } elsif ( $parm_ipv6 =~ /^::(.+[^:])$/ ) { + } elsif ( $parm_ipv6_stripped =~ /^::(.+[^:])$/ ) { $exp_v6 = '0:' x (9-length($exp_v6)) . $1; } else { - $exp_v6 = $parm_ipv6; + $exp_v6 = $parm_ipv6_stripped; } my(@components) = split /:/, $exp_v6; my(@nibbles) = reverse (split /\s*/, shift @components); @@ -4132,10 +4271,22 @@ foreach $test (@test_list) print "==================>\n"; system("tail -20 test-stdout"); print "===================\n"; + print "stderr tail:\n"; print "==================>\n"; - system("tail -20 test-stderr"); + system("tail -30 test-stderr"); print "===================\n"; + + print "stdout-server tail:\n"; + print "==================>\n"; + system("tail -20 test-stdout-server"); + print "===================\n"; + + print "stderr-server tail:\n"; + print "==================>\n"; + system("tail -30 test-stderr-server"); + print "===================\n"; + print "... continue forced\n"; }