diff --git a/cron/CHANGELOG b/cron/CHANGELOG
index b91623dd1..bb13a2336 100644
--- a/cron/CHANGELOG
+++ b/cron/CHANGELOG
@@ -28,3 +28,5 @@ Handle the daily / monthly / weekly Cron specification used on Ubuntu 7.
---- Changes since 1.400 ----
Fixed a bug that prevented new cron jobs from being created unless the 'Date range to execute' setting was changed.
Added a check for a valid module configuration, especially the cron jobs directory, to prevent accidental deletion of jobs.
+---- Changes since 1.410 ----
+Added an access control option to prevent individual Webmin users from creating cron jobs that run more often than hourly.
diff --git a/cron/acl_security.pl b/cron/acl_security.pl
index 4ddaa7de6..acfb8d894 100644
--- a/cron/acl_security.pl
+++ b/cron/acl_security.pl
@@ -6,63 +6,56 @@ do '../ui-lib.pl';
# Output HTML for editing security options for the cron module
sub acl_security_form
{
-print "
$text{'acl_users'} \n";
-printf " $text{'acl_all'} \n",
- $_[0]->{'mode'} == 0 ? "checked" : "";
+local $m = $_[0]->{'mode'};
+print &ui_table_row($text{'acl_users'},
+ &ui_radio("mode", $m,
+ [ [ 0, "$text{'acl_all'} " ],
+ [ 3, "$text{'acl_this'} " ],
+ [ 1, $text{'acl_only'}." ".
+ &ui_textbox("userscan",
+ $m == 1 ? $_[0]->{'users'} : "", 40)." ".
+ &user_chooser_button("userscan", 1)." " ],
+ [ 2, $text{'acl_except'}." ".
+ &ui_textbox("userscannot",
+ $m == 2 ? $_[0]->{'users'} : "", 40)." ".
+ &user_chooser_button("userscannot", 1)." " ],
+ [ 5, $text{'acl_gid'}." ".
+ &ui_textbox("gid",
+ $m == 5 ? scalar(getgrgid($_[0]->{'users'})) : "", 13)." ".
+ &group_chooser_button("gid", 0)." " ],
+ [ 4, $text{'acl_uid'}." ".
+ &ui_textbox("uidmin", $_[0]->{'uidmin'}, 6)." - ".
+ &ui_textbox("uidmax", $_[0]->{'uidmax'}, 6)." " ],
+ ]), 3);
-printf " $text{'acl_this'} \n",
- $_[0]->{'mode'} == 3 ? "checked" : "";
+print &ui_table_row($text{'acl_control'},
+ &ui_radio("allow", $_[0]->{'allow'},
+ [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ]));
-printf " $text{'acl_only'}\n",
- $_[0]->{'mode'} == 1 ? "checked" : "";
-printf " %s \n",
- $_[0]->{'mode'} == 1 ? $_[0]->{'users'} : "",
- &user_chooser_button("userscan", 1);
+print &ui_table_row($text{'acl_command'},
+ &ui_radio("command", $_[0]->{'command'},
+ [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ]));
-printf " $text{'acl_except'}\n",
- $_[0]->{'mode'} == 2 ? "checked" : "";
-printf " %s \n",
- $_[0]->{'mode'} == 2 ? $_[0]->{'users'} : "",
- &user_chooser_button("userscannot", 1);
+print &ui_table_row($text{'acl_create'},
+ &ui_radio("create", $_[0]->{'create'},
+ [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ]));
-printf " $text{'acl_gid'}\n",
- $_[0]->{'mode'} == 5 ? "checked" : "";
-printf " %s \n",
- $_[0]->{'mode'} == 5 ? scalar(getgrgid($_[0]->{'users'})) : "",
- &group_chooser_button("gid", 0);
+print &ui_table_row($text{'acl_delete'},
+ &ui_radio("delete", $_[0]->{'delete'},
+ [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ]));
-printf " $text{'acl_uid'}\n",
- $_[0]->{'mode'} == 4 ? "checked" : "";
-printf " -\n",
- $_[0]->{'mode'} == 4 ? $_[0]->{'uidmin'} : "";
-printf " \n",
- $_[0]->{'mode'} == 4 ? $_[0]->{'uidmax'} : "";
+print &ui_table_row($text{'acl_move'},
+ &ui_radio("move", $_[0]->{'move'},
+ [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ]));
-print " $text{'acl_control'} \n";
-print "",&ui_radio("allow", $_[0]->{'allow'},
- [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ])," \n";
+print &ui_table_row($text{'acl_kill'},
+ &ui_radio("kill", $_[0]->{'kill'},
+ [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ]));
-print "$text{'acl_command'} \n";
-print "",&ui_radio("command", $_[0]->{'command'},
- [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ])," \n";
-
-print " $text{'acl_create'} \n";
-print "",&ui_radio("create", $_[0]->{'create'},
- [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ])," \n";
-
-print "$text{'acl_delete'} \n";
-print "",&ui_radio("delete", $_[0]->{'delete'},
- [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ])," \n";
-
-print " $text{'acl_move'} \n";
-print "",&ui_radio("move", $_[0]->{'move'},
- [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ])," \n";
-
-print "$text{'acl_kill'} \n";
-print "",&ui_radio("kill", $_[0]->{'kill'},
- [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ])," \n";
-
-print "\n";
+print &ui_table_row($text{'acl_hourly'},
+ &ui_radio("hourly", $_[0]->{'hourly'},
+ [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ],
+ [ 2, $text{'acl_hourlydef'} ] ]), 3);
}
# acl_security_save(&options)
@@ -83,5 +76,6 @@ $_[0]->{'create'} = $in{'create'};
$_[0]->{'delete'} = $in{'delete'};
$_[0]->{'move'} = $in{'move'};
$_[0]->{'kill'} = $in{'kill'};
+$_[0]->{'hourly'} = $in{'hourly'};
}
diff --git a/cron/cron-lib.pl b/cron/cron-lib.pl
index a5b73b42b..d394b30a1 100644
--- a/cron/cron-lib.pl
+++ b/cron/cron-lib.pl
@@ -12,9 +12,13 @@ if ($module_info{'usermin'}) {
&switch_to_remote_user();
&create_user_config_dirs();
$range_cmd = "$user_module_config_directory/range.pl";
+ $hourly_only = 0;
}
else {
$range_cmd = "$module_config_directory/range.pl";
+ $hourly_only = $access{'hourly'} == 0 ? 0 :
+ $access{'hourly'} == 1 ? 1 :
+ $config{'hourly_only'};
}
$temp_delete_cmd = "$module_config_directory/tempdelete.pl";
$cron_temp_file = &transname();
@@ -691,18 +695,18 @@ foreach $arr ("mins", "hours", "days", "months", "weekdays") {
# Output selection list
print "\n";
printf " $text{'edit_all'} \n",
- $arr eq "mins" && $config{'hourly_only'} ? "disabled" : "",
+ $arr eq "mins" && $hourly_only ? "disabled" : "",
$job->{$arr} eq "*" ? "checked" : "";
printf " $text{'edit_selected'} \n",
$job->{$arr} ne "*" ? "checked" : "";
print " \n";
- for($j=0; $j<@$arr; $j+=($arr eq "mins" && $config{'hourly_only'} ? 60 : 12)) {
- $jj = $j+($arr eq "mins" && $config{'hourly_only'} ? 59 : 11);
+ for($j=0; $j<@$arr; $j+=($arr eq "mins" && $hourly_only ? 60 : 12)) {
+ $jj = $j+($arr eq "mins" && $hourly_only ? 59 : 11);
if ($jj >= @$arr) { $jj = @$arr - 1; }
@sec = @$arr[$j .. $jj];
printf "\n",
- $arr eq "mins" && $config{'hourly_only'} ? "" : "multiple",
- @sec > 12 ? ($arr eq "mins" && $config{'hourly_only'} ? 1 : 12) : scalar(@sec);
+ $arr eq "mins" && $hourly_only ? "" : "multiple",
+ @sec > 12 ? ($arr eq "mins" && $hourly_only ? 1 : 12) : scalar(@sec);
foreach $v (@sec) {
if ($v =~ /^(.*)=(.*)$/) { $disp = $1; $code = $2; }
else { $disp = $code = $v; }
diff --git a/cron/defaultacl b/cron/defaultacl
index fcabff677..2104b66a0 100644
--- a/cron/defaultacl
+++ b/cron/defaultacl
@@ -7,3 +7,4 @@ create=1
delete=1
move=1
kill=1
+hourly=2
diff --git a/cron/lang/en b/cron/lang/en
index 2f76e3f03..5ef27f082 100644
--- a/cron/lang/en
+++ b/cron/lang/en
@@ -118,6 +118,8 @@ acl_create=Can create Cron jobs?
acl_delete=Can delete Cron jobs?
acl_move=Can move Cron jobs?
acl_kill=Can terminate Cron jobs?
+acl_hourly=Limit jobs to at most hourly?
+acl_hourlydef=As set in Module Config
log_modify=Modified Cron job for $1
log_modify_l=Modified Cron job "$2" for $1