Update Apache config test to keep old behavior when ServerName is set

This commit is contained in:
Ilia Ross
2026-10-02 16:35:15 +02:00
parent aeee5edd15
commit 22c580aea1
2 changed files with 65 additions and 20 deletions

View File

@@ -1994,12 +1994,6 @@ sub test_config
return undef if ($httpd_modules{'core'} < 1.301);
my $okre = qr/(syntax|Checking).*\s+ok/i;
# Without a global ServerName, Apache looks up the system hostname in DNS
# while loading the config, which stalls the test when DNS is slow. Apache
# applies -C directives before reading the config files, so this placeholder
# never overrides a ServerName set in the config.
my $noname = "-C \"ServerName localhost\"";
# Build the httpd command from the configured paths
my $httpd = &find_httpd();
my $httpdcmd = "\"$httpd\" -d \"$config{'httpd_dir'}\"";
@@ -2010,33 +2004,41 @@ foreach my $d (&get_httpd_defines()) {
$httpdcmd .= " -D$d";
}
# Pick the standard test command, and the same test without the DNS lookup
my ($cmd, $fastcmd, $apachectl);
# Pick the standard test command
my ($cmd, $apachectl);
if ($config{'test_apachectl'} &&
-x &translate_filename($config{'apachectl_path'})) {
# Test with apachectl, which may set up environment the config needs
$apachectl = "\"$config{'apachectl_path'}\"";
$cmd = "$apachectl configtest";
$fastcmd = "$apachectl $noname -t";
}
else {
# Test with httpd
$cmd = "$httpdcmd -t";
$fastcmd = "$httpdcmd $noname -t";
}
# Try the test without the DNS lookup first
my $out = &backquote_command("$fastcmd 2>&1");
if ($apachectl && $httpd && $out =~ /no\s+longer\s+supported/i) {
# Red Hat's apachectl refuses extra arguments, and its configtest
# just runs httpd -t, so test with httpd instead
$out = &backquote_command("$httpdcmd $noname -t 2>&1");
# Without a global ServerName, Apache looks up the system hostname in DNS
# while loading the config, which stalls the test when DNS is slow. So first
# try the test with a placeholder ServerName. Apache applies -C directives
# before reading the config files, so a ServerName that this check misses,
# such as one inside an IfModule section, still takes effect.
my $conf = &get_config();
if ($conf && !&find_directive("ServerName", $conf)) {
my $noname = "-C \"ServerName localhost\"";
my $out = &backquote_command(
($apachectl ? "$apachectl $noname -t" : "$httpdcmd $noname -t").
" 2>&1");
if ($apachectl && $httpd && $out =~ /no\s+longer\s+supported/i) {
# Red Hat's apachectl refuses extra arguments, and its
# configtest just runs httpd -t, so test with httpd instead
$out = &backquote_command("$httpdcmd $noname -t 2>&1");
}
return undef if ($out =~ $okre);
}
return undef if ($out =~ $okre);
# The quick test failed, so run the standard test in case the extra
# arguments, rather than the config, caused the failure
$out = &backquote_command("$cmd 2>&1");
# Run the standard test. This also runs when the quick test failed, in case
# the extra arguments, rather than the config, caused the failure.
my $out = &backquote_command("$cmd 2>&1");
if ($out && $out !~ $okre) {
return $out;
}

View File

@@ -120,6 +120,23 @@ require File::Spec->catfile($root, 'apache', 'apache-lib.pl');
$main::httpd_modules{'core'} = 2.4;
}
# set_apache_conf(text)
# Writes the main Apache config file and clears the cached copy
sub set_apache_conf
{
my ($text) = @_;
write_text($apache_conf, $text);
main::flush_config_cache();
}
# A ServerName inside a virtual host is not global, so Apache still looks up
# the system hostname
my $no_global_name = "Listen 80\n".
"<VirtualHost *:80>\n".
" ServerName vhost.example\n".
"</VirtualHost>\n";
set_apache_conf($no_global_name);
# Expected log lines for the fake commands
my $noname = 'ServerName localhost';
my $direct_fast = join('|', 'httpd', '-d', $apache_root, '-f', $apache_conf,
@@ -202,6 +219,32 @@ subtest 'unknown apachectl falls back to configtest' => sub {
'standard test runs when apachectl rejects the arguments');
};
subtest 'global ServerName uses only the standard test' => sub {
set_apache_conf("ServerName www.example.com\n".$no_global_name);
my ($err, $cmds) = run_test(0, undef, 'ok');
is($err, undef, 'valid config passes');
is_deeply($cmds, [ $direct_std ], 'httpd runs without a placeholder');
($err, $cmds) = run_test(1, $redhat_ctl, 'error');
like($err, qr/Syntax error on line 2/, 'error output is returned');
is_deeply($cmds, [ $ctl_std, $httpd_std ],
'apachectl configtest runs as before');
set_apache_conf($no_global_name);
};
subtest 'global ServerName in an included file is found' => sub {
# Webmin expands includes with glob(), which splits paths on spaces
my $inc = File::Spec->catfile($tmp, 'servername.conf');
write_text($inc, "ServerName www.example.com\n");
set_apache_conf("Include $inc\n".$no_global_name);
my ($err, $cmds) = run_test(1, $debian_ctl, 'ok');
is($err, undef, 'valid config passes');
is_deeply($cmds, [ $ctl_std, $httpd_std ],
'apachectl configtest runs as before');
unlink($inc);
set_apache_conf($no_global_name);
};
subtest 'old Apache versions are not tested' => sub {
no warnings 'once';
local $main::httpd_modules{'core'} = 1.3;