diff --git a/cluster-software/cluster-software-lib.pl b/cluster-software/cluster-software-lib.pl index 1568829aa..72a988f57 100755 --- a/cluster-software/cluster-software-lib.pl +++ b/cluster-software/cluster-software-lib.pl @@ -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 diff --git a/cluster-software/do_install.cgi b/cluster-software/do_install.cgi index 27f356fce..dfa271289 100755 --- a/cluster-software/do_install.cgi +++ b/cluster-software/do_install.cgi @@ -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 = "e_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 = "e_literal_escape($rfile); + &remote_eval($s->{'host'}, "software", + "unlink('$qfile')"); + } print $wh &serialise_variable(\@rv); close($wh); diff --git a/cluster-software/do_install_serial.cgi b/cluster-software/do_install_serial.cgi index 73f6b7dbd..2fc6afd84 100755 --- a/cluster-software/do_install_serial.cgi +++ b/cluster-software/do_install_serial.cgi @@ -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 "",&text('do_header', join(" ", @names)),"

\n"; @@ -78,7 +81,10 @@ foreach $h (@hosts) { } } } - &remote_eval($s->{'host'}, "software", "unlink('$rfile')") if ($need_unlink); + if ($need_unlink) { + local $qfile = "e_literal_escape($rfile); + &remote_eval($s->{'host'}, "software", "unlink('$qfile')"); + } } unlink($in{'file'}) if ($in{'need_unlink'}); print "

$text{'do_done'}

\n";