Merge branch 'master' of github.com:webmin/webmin

This commit is contained in:
Jamie Cameron
2025-07-30 16:59:39 -07:00
12 changed files with 182 additions and 14 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,5 @@
firewall_cmd=firewall-cmd
init_name=firewalld
config_dir=/etc/firewalld
packet_handling=drop
packet_handling=0
timeout=0

View File

@@ -2,3 +2,4 @@ firewall_cmd=Full path to firewall-cmd program,0
init_name=FirewallD init script name,0
config_dir=FirewallD configuration directory,0
packet_handling=Default packet handling action,1,0-<tt>drop</tt>,1-<tt>reject</tt>
timeout=Timeout for temporary rules,15,timeout_data

48
firewalld/config_info.pl Executable file
View File

@@ -0,0 +1,48 @@
require './firewalld-lib.pl';
# show_timeout_data(value, config-option-name)
# Returns a radio button and a select box for timeout values
sub show_timeout_data
{
my ($value, $name) = @_;
$name = &format_option_name($name);
my $radio = &ui_radio(
"${name}_def", !$value ? 1 : 0,
[ [ 1, $text{'config_timeout_none'} ],
[ 0, ' ' ] ] );
my @list = &get_timeouts();
my @opts = map { [ $_, $text{"config_timeout_$_"} ] } @list;
my $select = &ui_select($name, !$value ? $list[3] : $value, \@opts);
return $radio . '&nbsp;' . $select;
}
# parse_timeout_data(old-value, config-option-name)
# Parses the timeout value from the form input
sub parse_timeout_data
{
my ($oldval, $name) = @_;
$name = &format_option_name($name);
my $val = $in{$name} // '';
return 0 if ($in{"${name}_def"});
my %valid = map { $_ => 1 } &get_timeouts();
&error(&text('config_timeout_err', $val)) unless($valid{$val});
return $val;
}
# get_timeouts
# Returns a list of valid timeout values for the select box
sub get_timeouts
{
return qw(1m 5m 15m 30m 1h 3h 6h 12h 1d 3d 7d 30d);
}
# format_option_name(name)
# Formats the option name for use in HTML element names
sub format_option_name
{
my ($name) = @_;
$name =~ s/\s+/_/g;
$name =~ s/[^\x00-\x7F]/_/g;
$name = lc($name);
return $name;
}

View File

@@ -540,6 +540,14 @@ if (!$zone) {
$zone = $zone->{'name'};
}
# Timeout
my $timeout = $opts->{'timeout'};
if ($timeout) {
# Validate timeout format
&error(&text('config_timeout_err', $timeout))
if ($timeout !~ /^(\d+)([smhd]?)$/);
}
# Permanent rule
my $permanent = $opts->{'permanent'};
@@ -548,7 +556,8 @@ my $get_cmd = sub {
my ($rtype) = @_;
my $type = $rtype ? " --permanent" : "";
return "$config{'firewall_cmd'} --zone=\"".quotemeta($zone)."\"".
"$type --".quotemeta($action)."-rich-rule='$opts->{'rule'}'";
"$type --".quotemeta($action)."-rich-rule='$opts->{'rule'}'".
($timeout ? " --timeout=".quotemeta($timeout) : "");
};
for my $type (0..1) {

View File

@@ -50,6 +50,21 @@ index_dependent=Failed to restart $1 dependent service
index_manual=Edit Config Files.
index_downrules=FirewallD rules cannot be created or edited and are not enforced unless the server is running.
config_timeout_none=None
config_timeout_1m=1 minute
config_timeout_5m=5 minutes
config_timeout_15m=15 minutes
config_timeout_30m=30 minutes
config_timeout_1h=1 hour
config_timeout_3h=3 hours
config_timeout_6h=6 hours
config_timeout_12h=12 hours
config_timeout_1d=1 day
config_timeout_3d=3 days
config_timeout_7d=7 days
config_timeout_30d=30 days
config_timeout_err=Invalid timeout value <tt>$1</tt>
manual_title=Edit Config Files
manual_editsel=Edit FirewallD configuration file
manual_err=Failed to save config file

View File

@@ -6,7 +6,7 @@ use warnings;
no warnings 'redefine';
no warnings 'uninitialized';
require './firewalld-lib.pl';
our (%in, %text);
our (%in, %text, %config);
&ReadParse();
# Setup error messages
@@ -31,6 +31,7 @@ $ip =~ s/\Q$mask\E// if ($mask);
# Block the IP
my $perm = $in{'permanent'} ? 'perm' : '';
my $timeout = $config{'timeout'} unless ($perm && $config{'timeout'});
my ($out, $rs) = &rich_rule('add',
{ 'rule' =>
&construct_rich_rule(
@@ -38,7 +39,8 @@ my ($out, $rs) = &rich_rule('add',
'action' => $allow ? 'accept' : undef,
'priority' => $allow ? -32767 : -32766,
),
'zone' => $zone->{'name'}, 'permanent' => $perm });
'zone' => $zone->{'name'}, 'permanent' => $perm,
'timeout' => $timeout });
&error($out) if ($rs);
&apply_firewalld() if ($perm);

View File

@@ -31,7 +31,7 @@ show_count=Afficher le nombre de messages dans la boîte de réception?,1,1-Oui,
sort_mode=Trier les boîtes aux lettres par,1,2-Taille,1-Nom d'utilisateur,0-Commander dans le fichier de mot de passe
show_mail=Afficher uniquement les utilisateurs qui ont du courrier?,1,1-Oui,0-Non
size_mode=Inclure tous les dossiers dans la taille?,1,1-Oui,0-Non (premier dossier uniquement)
ignore_users=Ignorer ces noms d'utilisateur (ne pas afficher),15,Liste des utilisateurs ignorés
ignore_users=Ignorer ces noms d'utilisateur (ne pas afficher),15,userIgnoreList
ignore_users_enabled=Ignorer l'état de la liste,1,1-Activé,0-Désactivé
line0.5=Options de dossier,11

View File

@@ -31,11 +31,11 @@ if ($got) {
}
# Try to install them
&ui_print_header("<tt>".&html_escape($in{'file'})."</tt>",
&ui_print_unbuffered_header("<tt>".&html_escape($in{'file'})."</tt>",
$text{'imod_title'}, "");
print &text('imod_alldoing', "<tt>".&html_escape($in{'mod'})."</tt>",
$ver),"<p>\n";
$ver),"<br>\n";
my $ok = 0;
foreach my $pkg (@poss) {
@@ -57,13 +57,13 @@ foreach my $pkg (@poss) {
}
if ($ok) {
print &text('imod_alldone',
"<tt>".&html_escape($ok)."</tt>"),"<p>\n";
"<tt>".&html_escape($ok)."</tt>");
&graceful_apache_restart($in{'file'});
&webmin_log("imod", undef, $in{'file'}, { 'mod' => $in{'mod'} });
}
else {
print &text('imod_allfailed',
"<tt>".&html_escape(join(" ", @poss))."</tt>"),"<p>\n";
"<tt>".&html_escape(join(" ", @poss))."</tt>");
}
&ui_print_footer("edit_mods.cgi?file=".&urlize($in{'file'}),

View File

@@ -513,7 +513,12 @@ if (&has_command("sensors")) {
# CPU full output must have either voltage or fan data
my ($cpu_volt) = $_ =~ /(?|in[\d+]\s*:\s+([\+\-0-9\.]+)\s+V|cpu\s+core\s+voltage\s*:\s+([0-9\.]+)\s+V)/i;
my ($cpu_fan_num, $cpu_fan_rpm) = $_ =~ /(?|fan([\d+])\s*:\s*([0-9]+)\s*rpm|cpu(\s)fan\s*:\s*([0-9]+)\s*rpm|cpu\s+fan\s*:\s*([0-9]+)\s*rpm)/i;
# CPU fans should be always labeled as 'cpu fan' or 'cpu_fan' or 'cpufan'
# and/or 'cpu fan 1', 'cpu_fan1', 'cpufan1', 'cpu_fan 2', 'cpu_fan2',
# 'cpufan2' etc.
my ($cpu_fan_num, $cpu_fan_rpm) =
$_ =~ /(?|^\s*cpu[_ ]?fan(?:[_ ]?(\d+))?\s*:\s*(\d+)\s*rpm)/i;
$cpu_fan_num //= 1 if (defined($cpu_fan_rpm));
$cpu++ if ($cpu_volt || $cpu_fan_num);
# First just store fan data for any device if any

View File

@@ -1602,7 +1602,7 @@ return &theme_ui_buttons_end(@_) if (defined(&theme_ui_buttons_end));
return "</table>\n";
}
=head2 ui_buttons_row(script, button-label, description, [hiddens], [after-submit], [before-submit])
=head2 ui_buttons_row(script, button-label, description, [hiddens], [after-submit], [before-submit], [postmethod])
Returns HTML for a button with a description next to it, and perhaps other
inputs. The parameters are :
@@ -1619,15 +1619,18 @@ inputs. The parameters are :
=item before-submit - HTML for text or inputs to appear before the submit button.
=item postmethod - Defines the method used to submit the form. Defaults to 'post'.
=cut
sub ui_buttons_row
{
return &theme_ui_buttons_row(@_) if (defined(&theme_ui_buttons_row));
my ($script, $label, $desc, $hiddens, $after, $before) = @_;
my ($script, $label, $desc, $hiddens, $after, $before, $postmethod) = @_;
$postmethod ||= 'post';
if (ref($hiddens)) {
$hiddens = join("\n", map { &ui_hidden(@$_) } @$hiddens);
}
return "<form action='$script' class='ui_buttons_form' method='post'>\n".
return "<form action='$script' class='ui_buttons_form' method='$postmethod'>\n".
$hiddens.
"<tr class='ui_buttons_row'> ".
"<td nowrap width='20%' valign='top' class='ui_buttons_label'>".

View File

@@ -14004,6 +14004,90 @@ if (&read_env_file($wconfig, \%wconfig) &&
return '';
}
# encrypt_phrase(plain, passphrase, [run-as-user])
# Encrypts a phrase using OpenSSL and a passphrase
sub encrypt_phrase
{
my ($plain, $passphrase, $run_as) = @_;
my $openssl = &has_command('openssl');
# Check if parameters are defined
unless ($plain && $passphrase) {
return wantarray ? (undef, 'Missing parameters') : undef;
}
# Check if OpenSSL is available
unless ($openssl) {
return wantarray ? (undef, 'OpenSSL command not found') : undef;
}
# Temp file for plaintext
my $src = &transname();
&write_file_contents($src, $plain);
# Encrypt
$passphrase = quotemeta($passphrase);
my @args = (
$openssl, 'enc', '-aes-256-cbc', '-a', '-A', '-salt',
'-pbkdf2', '-iter', '100000',
'-pass', "pass:$passphrase",
'-in', $src,
);
my $cmd = &command_as_user($run_as || 'nobody', 0, @args) . ' 2>&1';
my $out = &backquote_logged($cmd);
# Return if error
return wantarray ? (undef, $out) : undef if ($?);
# Remove newlines
$out =~ s/\s+\z//;
# Check if result is valid
if (!&is_encrypt_phrase($out)) {
# Encryption failed
return wantarray
? (undef, "Encryption failed with invalid cipher result : $out")
: undef;
}
# Return successfully created ciphertext
return wantarray ? ($out, undef) : $out;
}
# decrypt_phrase(ciphertext, passphrase, [run-as-user])
# Decrypts a ciphertext using OpenSSL and a passphrase
sub decrypt_phrase
{
my ($cipher, $passphrase, $run_as) = @_;
my $openssl = &has_command('openssl');
# Check if OpenSSL is available
if (!$openssl) {
return wantarray ? (undef, 'OpenSSL command not found') : undef;
}
# Tempfile for ciphertext
my $src = &transname();
&write_file_contents($src, $cipher);
# Decrypt
$passphrase = quotemeta($passphrase);
my @args = (
$openssl, 'enc', '-d', '-aes-256-cbc', '-a', '-A',
'-pbkdf2', '-iter', '100000',
'-pass', "pass:$passphrase",
'-in', $src,
);
my $cmd = &command_as_user($run_as || 'nobody', 0, @args) . ' 2>&1';
my $out = &backquote_logged($cmd);
# Return if error
return wantarray ? (undef, $out) : undef if ($?);
# Return result
return wantarray ? ($out, undef) : $out;
}
# is_encrypt_phrase(ciphertext)
# Checks if a ciphertext is encrypted correctly
sub is_encrypt_phrase
{
my ($ct) = @_;
unless (defined($ct) && $ct =~ /^[A-Za-z0-9+\/]+=*$/ && length($ct) % 4 == 0) {
# Invalid ciphertext format
return 0;
}
# Check if is OpenSSL salt header
return &decode_base64($ct) =~ /^Salted__/ ? 1 : 0;
}
$done_web_lib_funcs = 1;
1;