Stop doing scheduled module upgrades, as this is a rarely used feature and a potential security risk

This commit is contained in:
Jamie Cameron
2021-07-25 13:37:08 -07:00
parent 3c27fe3a0a
commit e8cd1ca5a7
6 changed files with 11 additions and 279 deletions
+1 -64
View File
@@ -31,7 +31,7 @@ elsif ($mode eq "portage") {
# Show tabs
@tabs = map { [ $_, $text{'upgrade_tab'.$_}, "edit_upgrade.cgi?mode=$_" ] }
( $skip_upgrade ? ( ) : ( "upgrade" ),
"grants", "update", "sched" );
"grants", "update" );
print ui_tabs_start(\@tabs, "mode", $in{'mode'} || $tabs[0]->[0], 1);
if (!$skip_upgrade) {
@@ -138,69 +138,6 @@ print ui_table_end();
print ui_form_end([ [ undef, $text{'update_ok'} ] ]);
print ui_tabs_end_tab();
# Display scheduled update form
print ui_tabs_start_tab("mode", "sched");
print "$text{'update_desc2'}<p>\n";
print ui_form_start("update_sched.cgi", "post");
print ui_table_start($text{'update_header2'}, undef, 2);
print &ui_table_row($text{'update_enabled'},
&ui_yesno_radio("enabled", $config{'update'}));
print &ui_table_row($text{'update_src'},
&ui_radio("source", $config{'upsource'} ? 1 : 0,
[ [ 0, $text{'update_webmin'}."<br>" ],
[ 1, $text{'update_other'} ] ])."<br>\n".
&ui_textarea("other", join("\n", split(/\t+/, $config{'upsource'})),
2, 50));
if ($config{'cron_mode'} == 0) {
$upmins = sprintf "%2.2d", $config{'upmins'};
print &ui_table_row("",
&text('update_sched2',
&ui_textbox("hour", $config{'uphour'}, 2),
&ui_textbox("mins", $upmins, 2),
&ui_textbox("days", $config{'updays'}, 3)));
}
else {
&foreign_require("cron", "cron-lib.pl");
@jobs = &cron::list_cron_jobs();
$job = &find_cron_job(\@jobs);
$job ||= { 'mins' => 0,
'hours' => $config{'uphour'},
'days' => "*/$config{'updays'}",
'months' => '*',
'weekdays' => '*' };
print &cron::get_times_input($job, 1);
}
print &ui_table_row($text{'update_opts'},
&ui_checkbox("show", 1, $text{'update_show'},
$config{'upshow'}).
"<br>\n".
&ui_checkbox("missing", 1, $text{'update_missing'},
$config{'upmissing'}).
"<br>\n".
&ui_checkbox("third", 1, $text{'update_third'},
$config{'upthird'}).
"<br>\n".
&ui_checkbox("quiet", 1, $text{'update_quiet'},
$config{'upquiet'}).
"<br>\n".
&ui_checkbox("checksig", 1, $text{'update_checksig'},
$config{'upchecksig'}));
print &ui_table_row($text{'update_email'},
&ui_textbox("upemail", $config{'upemail'}, 30));
print &ui_table_row($text{'update_user'},
&ui_textbox("upuser", $config{'upuser'}, 30));
print &ui_table_row($text{'update_pass'},
&ui_password("uppass", $config{'uppass'}, 30));
print ui_table_end();
print ui_form_end([ [ undef, $text{'update_apply'} ] ]);
print ui_tabs_end_tab();
print &ui_tabs_end(1);
&ui_print_footer("", $text{'index_return'});
+7 -7
View File
@@ -6,13 +6,13 @@ sub module_install
# Update cache of which module's underlying servers are installed
&build_installed_modules();
# Pick a random update time
if (!defined($config{'uphour'}) ||
$config{'uphour'} == 3 && $config{'upmins'} == 0 && !$config{'update'}) {
&seed_random();
$config{'uphour'} = int(rand()*24);
$config{'upmins'} = int(rand()*60);
&save_module_config();
# Remove the scheduled module update cron, which is now obsolete
&foreign_require("cron");
my @jobs = &cron::list_cron_jobs();
my $job = &find_cron_job(\@jobs);
if ($job) {
&cron::delete_cron_job($job);
&unlink_logged($cron_cmd);
}
# Figure out the preferred cipher mode
-12
View File
@@ -5,18 +5,6 @@ require 'webmin-lib.pl';
sub module_uninstall
{
# Remove the update cron job, if enabled
if ($config{'update'}) {
&foreign_require("cron");
$cron_cmd = "$module_config_directory/update.pl";
foreach $j (&cron::list_cron_jobs()) {
if ($j->{'user'} eq 'root' &&
$j->{'command'} eq $cron_cmd) {
&cron::delete_cron_job($j);
}
}
}
# Remove the link from /usr/sbin/webmin
my $bindir = "/usr/sbin";
my $lnk = $bindir."/webmin";
-107
View File
@@ -1,107 +0,0 @@
#!/usr/local/bin/perl
# update.pl
# Find and install updated modules, and email out the result
$no_acl_check++;
require './webmin-lib.pl';
# Fetch the updates
@urls = $config{'upsource'} ? split(/\t+/, $config{'upsource'})
: ( $update_url );
foreach $url (@urls) {
# Get updates from this URL, and filter to those for this system
$checksig = $config{'upchecksig'} ? 2 : $url eq $update_url ? 2 : 1;
eval {
$main::error_must_die = 1;
($updates, $host, $port, $page, $ssl) =
&fetch_updates($url, $config{'upuser'}, $config{'uppass'},
$checksig);
};
if ($@) {
print STDERR "Failed to fetch updates : $@\n";
exit(0);
}
$updates = &filter_updates($updates, undef, $config{'upthird'},
$config{'upmissing'});
# Go through the results
foreach $u (@$updates) {
# Get module or theme's details
my %minfo = &get_module_info($u->[0]);
my %tinfo = &get_theme_info($u->[0]);
my %info = %minfo ? %minfo : %tinfo;
# Skip if we already have the version, perhaps from an earlier
# update in this run
my $nver = $u->[1];
$nver =~ s/^(\d+\.\d+)\..*$/$1/;
next if (%info && $info{'version'} &&
$info{'version'} >= $nver);
if ($config{'upshow'}) {
# Just tell the user what would be done
$rv .= &text('update_mshow', $u->[0], $u->[1])."\n".
($info{'longdesc'} ? "$text{'update_fixes'} : " : "").
$u->[4]."\n\n";
}
else {
# Actually do the update ..
my (@mdescs, @mdirs, @msizes);
$rv .= &text('update_mok', $u->[0], $u->[1])."\n".
($info{'longdesc'} ? "$text{'update_fixes'} : " : "").
$u->[4]."\n\n";
($mhost, $mport, $mpage, $mssl) =
&parse_http_url($u->[2], $host, $port, $page, $ssl);
($mfile = $mpage) =~ s/^(.*)\///;
$mtemp = &transname($mfile);
&retry_http_download($mhost, $mport, $mpage, $mtemp, \$error,
undef, $mssl,
$config{'upuser'}, $config{'uppass'});
if ($error) {
$rv .= "$error\n\n";
last;
}
else {
$irv = &check_update_signature(
$mhost, $mport, $mpage,
$mssl, $config{'upuser'}, $config{'uppass'},
$mtemp, $checksig);
$irv ||= &install_webmin_module($mtemp, 1, 0,
[ "admin", "root" ]);
if (!ref($irv)) {
$irv =~ s/<[^>]*>//g;
$rv .= &text('update_failed', $irv)."\n\n";
}
else {
$rv .= &text('update_mdesc', $irv->[0]->[0],
$irv->[2]->[0])."\n\n";
}
}
}
}
}
# Check if a new version of webmin itself is available
$version = &get_latest_webmin_version();
if ($version > &get_webmin_version()) {
$rv .= &text('update_version', $version)."\n";
}
# Send off a results email
if ($config{'upemail'} && $rv && &foreign_check("mailboxes")) {
# Construct and send the email
&foreign_require("mailboxes", "mailboxes-lib.pl");
my $data;
my $type = $gconfig{'real_os_type'} || $gconfig{'os_type'};
my $version = $gconfig{'real_os_version'} || $gconfig{'os_version'};
my $myhost = &get_system_hostname();
$data .= "$myhost ($type $version)\n\n";
$data .= &text('update_rv', "http://$host:$port$page")."\n\n";
$data .= $rv;
&mailboxes::send_text_mail(&mailboxes::get_from_address(),
$config{'upemail'},
undef,
$text{'update_subject'},
$data);
}
-88
View File
@@ -1,88 +0,0 @@
#!/usr/local/bin/perl
# update_sched.cgi
# Schedule the auto-updating of webmin modules
require './webmin-lib.pl';
&foreign_require("cron", "cron-lib.pl");
&ReadParse();
&error_setup($text{'update_err'});
# Validate inputs
&lock_file("$module_config_directory/config");
if ($in{'source'} == 0) {
$config{'upsource'} = undef;
}
else {
@urls = ( );
foreach $url (split(/\r?\n/, $in{'other'})) {
$url =~ /^http:\/\/([^:\/]+)(:(\d+))?(\/\S*)$/ ||
&error($text{'update_eurl'});
push(@urls, $url);
}
@urls || &error($text{'update_eurl'});
$config{'upsource'} = join("\t", @urls);
}
$config{'update'} = $in{'enabled'};
if ($config{'cron_mode'} == 0) {
$in{'hour'} =~ /^\d+$/ && $in{'hour'} < 24 ||
&error($text{'update_ehour'});
$config{'uphour'} = $in{'hour'};
$in{'mins'} =~ /^\d+$/ && $in{'mins'} < 60 ||
&error($text{'update_emins'});
$config{'upmins'} = $in{'mins'};
$in{'days'} =~ /^\d+$/ ||
&error($text{'update_edays'});
$config{'updays'} = $in{'days'};
}
$config{'upshow'} = $in{'show'};
$config{'upmissing'} = $in{'missing'};
$config{'upthird'} = $in{'third'};
$config{'upquiet'} = $in{'quiet'};
$config{'upchecksig'} = $in{'checksig'};
$config{'upemail'} = $in{'upemail'};
$config{'upuser'} = $in{'upuser'};
$config{'uppass'} = $in{'uppass'};
!$in{'show'} || $in{'upemail'} || &error($text{'update_eemail'});
&write_file("$module_config_directory/config", \%config);
&unlock_file("$module_config_directory/config");
# Setup the cron job
@jobs = &cron::list_cron_jobs();
$job = &find_cron_job(\@jobs);
&lock_file($cron_cmd);
if ($job) {
&cron::delete_cron_job($job);
unlink($cron_cmd);
}
if ($in{'enabled'}) {
# Create the program that cron calls
&cron::create_wrapper($cron_cmd, $module_name, "update.pl");
$njob = { 'user' => 'root', 'active' => 1,
'command' => $cron_cmd };
if ($config{'cron_mode'} == 0) {
# Setup the actual cron job, simply
if ($in{'days'} == 1) {
@days = ( "*" );
}
else {
for($i=1; $i<=31; $i+=$in{'days'}) {
push(@days, $i);
}
}
$njob->{'mins'} = $in{'mins'};
$njob->{'hours'} = $in{'hour'};
$njob->{'days'} = join(",",@days);
$njob->{'months'} = '*';
$njob->{'weekdays'} = '*';
}
else {
# Create complex cron job
&cron::parse_times_input($njob, \%in);
}
&foreign_call("cron", "create_cron_job", $njob);
}
&unlock_file($cron_cmd);
&redirect("");
+3 -1
View File
@@ -58,6 +58,7 @@ our $third_ssl = 0;
our $default_key_size = "2048";
# Obsolete, but still defined so it can be deleted
our $cron_cmd = "$module_config_directory/update.pl";
our $os_info_address = "os\@webmin.com";
@@ -983,8 +984,9 @@ as returned by cron::list_cron_jobs
=cut
sub find_cron_job
{
my ($jobs) = @_;
my ($job) = grep { $_->{'user'} eq 'root' &&
$_->{'command'} eq $cron_cmd } @{$_[0]};
$_->{'command'} eq $cron_cmd } @$jobs;
return $job;
}