Fix cluster software remote eval escaping and target validation (#11)

This commit is contained in:
Ilia Ross
2026-03-10 17:29:18 +02:00
parent 2de16faafc
commit 5862cde30f
3 changed files with 35 additions and 4 deletions

View File

@@ -10,6 +10,24 @@ use WebminCore;
$parallel_max = 20;
%access = &get_module_acl();
# validate_remote_download_target()
# Validates URL-derived download target fields in %in
sub validate_remote_download_target
{
$in{'host'} =~ /^\S+$/ || &error("Invalid download host");
my @ips = &to_ipaddress($in{'host'});
push(@ips, &to_ip6address($in{'host'}));
@ips || &error("Invalid download host");
if ($in{'ftpfile'}) {
$in{'ftpfile'} =~ /^\/\S+$/ || &error("Invalid FTP path");
}
else {
$in{'port'} =~ /^\d+$/ && $in{'port'} >= 1 && $in{'port'} <= 65535 ||
&error("Invalid HTTP port");
$in{'page'} =~ /^\/\S*$/ || &error("Invalid HTTP path");
}
}
# list_software_hosts()
# Returns a list of all hosts whose software is being managed by this module
sub list_software_hosts

View File

@@ -24,6 +24,9 @@ else {
}
$in{'source'} == 3 || -r $in{'file'} || &error($text{'do_edeleted'});
if ($in{'source'} == 2 && $in{'down'}) {
&validate_remote_download_target();
}
&ui_print_header(undef, $text{'do_title'}, "");
# Setup error handler for down hosts
@@ -75,8 +78,9 @@ foreach $h (@hosts) {
elsif ($in{'source'} == 0) {
# Is the file the same on remote (like if we have NFS)
local @st = stat($in{'file'});
local $qfile = &quote_literal_escape($in{'file'});
local $rst = &remote_eval($s->{'host'}, "software",
"[ stat('$in{'file'}') ]");
"[ stat('$qfile') ]");
local @rst = @$rst;
if (@st && @rst && $st[7] == $rst[7] &&
$st[9] == $rst[9]) {
@@ -170,8 +174,11 @@ foreach $h (@hosts) {
}
}
}
&remote_eval($s->{'host'}, "software", "unlink('$rfile')")
if ($need_unlink);
if ($need_unlink) {
local $qfile = &quote_literal_escape($rfile);
&remote_eval($s->{'host'}, "software",
"unlink('$qfile')");
}
print $wh &serialise_variable(\@rv);
close($wh);

View File

@@ -12,6 +12,9 @@ foreach $p (@packages) {
push(@names, $n); push(@descs, $d);
}
-r $in{'file'} || &error($text{'do_edeleted'});
if ($in{'source'} == 2 && $in{'down'}) {
&validate_remote_download_target();
}
&ui_print_header(undef, $text{'do_title'}, "");
print "<b>",&text('do_header', join(" ", @names)),"</b><p>\n";
@@ -78,7 +81,10 @@ foreach $h (@hosts) {
}
}
}
&remote_eval($s->{'host'}, "software", "unlink('$rfile')") if ($need_unlink);
if ($need_unlink) {
local $qfile = &quote_literal_escape($rfile);
&remote_eval($s->{'host'}, "software", "unlink('$qfile')");
}
}
unlink($in{'file'}) if ($in{'need_unlink'});
print "<p><b>$text{'do_done'}</b><p>\n";