Compare commits

..

79 Commits
2.610 ... 2.620

Author SHA1 Message Date
Ilia Ross
5f1bbc4ac2 Fix to mention if user is missing in error message 2026-01-09 01:06:47 +02:00
Jamie Cameron
124147205f We don't use const anywhere else in Webmin, so don't use it here 2026-01-08 13:02:18 -08:00
Ilia Ross
e9b3ed9624 Fix incorrectly resolved conflict 2026-01-08 22:12:42 +02:00
Jamie Cameron
ccde77c0e2 Merge branch 'master' of github.com:webmin/webmin
Conflicts:
	fastrpc.cgi
2026-01-08 10:50:22 -08:00
Jamie Cameron
ffd8171e18 Fork can fail if there are no more processes left 2026-01-08 10:45:39 -08:00
Ilia Ross
65ab502176 Add an option to configure RPC timeout 2026-01-08 18:30:41 +02:00
Ilia Ross
013aa5a5c6 Fix to make timeout cleanly configurable 2026-01-08 18:28:43 +02:00
Ilia Ross
12dca80535 Fix to improve fork handling and zombie reaping
*Note: Even though the current code generally works, it's better to properly reap child processes with waitpid to avoid infinite timeouts and also clean up inherited FDs.
2026-01-08 16:40:44 +02:00
Ilia Ross
89ee635de3 Fix key order 2026-01-08 14:37:57 +02:00
Jamie Cameron
af3ddd652f Merge branch 'master' of github.com:webmin/webmin 2026-01-07 21:39:48 -08:00
Jamie Cameron
e6d214b776 Keep track of sub-processes doing reads or writes, and don't timeout connections while they are in progress
https://forum.virtualmin.com/t/problem-with-backup-of-large-virtual-servers-to-a-remote-webmin-server/136186
2026-01-07 21:39:27 -08:00
Ilia Ross
45521e9c30 Fix inessential semicolon 2026-01-07 23:13:08 +02:00
Jamie Cameron
123beb03d8 Add a config option to increase the RPC timeout 2026-01-07 11:08:40 -08:00
Jamie Cameron
72b122dbce Merge branch 'master' of github.com:webmin/webmin 2026-01-07 11:07:20 -08:00
Jamie Cameron
e9be9b1d53 Use my instead of local 2026-01-07 11:06:53 -08:00
Ilia Ross
7beeea2106 Fix to remove extra line
[no-build]
2026-01-07 19:13:17 +02:00
Jamie Cameron
27c5ad998e Merge branch 'master' of github.com:webmin/webmin 2026-01-07 07:48:28 -08:00
Jamie Cameron
474ca81d4a Fix parsing of attributes
https://sourceforge.net/p/webadmin/bugs/5659/
2026-01-07 07:48:21 -08:00
Ilia Ross
a63c92f77c Webmin version bump (use master workflow fixes)
*Note: The problem was that we didn't check the commit message correctly and didn't add the right flag to rebuild all non-core Webmin modules. Now it should work.
2026-01-07 14:40:52 +02:00
Jamie Cameron
db96a9fd09 Don't read output one byte at a time, especially when not needed 2026-01-06 21:58:25 -08:00
Jamie Cameron
198cc1c4d8 Clearing a hash while iterating over it seems unreliable 2026-01-05 21:35:47 -08:00
Jamie Cameron
4f681a2db0 Webmin version bump 2026-01-05 16:56:21 -08:00
Ilia Ross
ab46ec806f Fix action log clearing not to purge the previous logs on each save if the time option is not set 2026-01-05 19:29:54 +02:00
Jamie Cameron
b1fe988f57 Add an extra check for a manual config change that breaks the index 2026-01-04 13:35:24 -08:00
Jamie Cameron
94c0826499 Merge branch 'master' of github.com:webmin/webmin 2026-01-04 13:34:12 -08:00
Jamie Cameron
191d8a255c Add support for EC SSL cert and key file directives
https://github.com/webmin/webmin/issues/2597
2026-01-04 13:33:51 -08:00
Ilia Ross
d4ab826097 Add support for Ubuntu 26.04 2026-01-04 15:21:32 +02:00
Ilia Ross
a84c2af1d8 Merge pull request #2612 from hayden-t/patch-2
incorrect ssl_enforce setting for HSTS
2025-12-31 13:55:29 +02:00
Ilia Ross
476915850a Fix displaying correct IP version label
https://github.com/webmin/webmin/issues/2613
2025-12-31 12:46:07 +02:00
hayden-t
2510b985b1 incorrect ssl_enforce setting for HSTS
https://github.com/webmin/webmin/issues/2611
2025-12-30 13:54:39 +11:00
Ilia Ross
db4f5b5e9c Fix to skip uninstall when package is replaced by rename
*Note: This is to support clean upgrade and replacement of wbm-* → webmin-* modules
2025-12-28 19:39:52 +02:00
Jamie Cameron
f3dda46138 Merge branch 'master' of github.com:webmin/webmin 2025-12-28 08:02:42 -08:00
Jamie Cameron
7a278ad894 Add ed25519 as a key type
https://github.com/webmin/webmin/pull/2609
2025-12-28 08:02:34 -08:00
Jamie Cameron
179d36859a Merge pull request #2609 from hayden-t/patch-1
id_ed25519.pub support for authorized_keys update
2025-12-26 20:55:07 -08:00
hayden-t
eec14b6c1f id_ed25519.pub support for authorized_keys update 2025-12-27 09:05:17 +11:00
Ilia Ross
bc44562637 Add a new secret 2025-12-24 01:33:33 +02:00
Jamie Cameron
a55a9e142b Merge branch 'master' of github.com:webmin/webmin 2025-12-19 21:53:29 -08:00
Jamie Cameron
7911eaeae1 TLS options must be at the root level, not in the global block
https://github.com/webmin/webmin/issues/2597
2025-12-19 21:53:23 -08:00
Ilia Ross
a2cb8daaee Fix not to hide download errors 2025-12-20 04:10:29 +02:00
Jamie Cameron
c4dc034da7 Don't save allowed modules if fetching them fails 2025-12-18 17:47:58 -08:00
Jamie Cameron
8a8d1bc12f use has to be inside a string eval 2025-12-17 21:47:58 -08:00
Jamie Cameron
025ab50ecb Merge branch 'master' of github.com:webmin/webmin 2025-12-17 21:47:11 -08:00
Jamie Cameron
1f71aebe49 Don't run entropy generator if not needed
00~https://github.com/webmin/webmin/issues/260401~
2025-12-17 21:46:22 -08:00
Ilia Ross
03379b0052 Add ability to use correct driver depending on the database 2025-12-16 13:56:27 +02:00
Jamie Cameron
86a27eff18 Check for and use DBD::MariaBB as well
https://forum.virtualmin.com/t/webmin-2-6-not-available-yet/135883/45
2025-12-15 17:10:27 -08:00
Jamie Cameron
b338875039 Merge branch 'master' of github.com:webmin/webmin 2025-12-14 19:48:03 -08:00
Jamie Cameron
e88d16a888 UI for setting real name for from address
https://github.com/webmin/webmin/issues/2600
2025-12-14 15:13:56 -08:00
Ilia Ross
f0486443ae Fix to just recommend MariaDB Perl package 2025-12-14 19:58:56 +02:00
Ilia Ross
f55515fdb0 Revert "Fix to support installing missing Perl modules using package manager"
This reverts commit 9bce05f48a.
2025-12-14 19:53:42 +02:00
Ilia Ross
ebefe283fd Revert "Add FreeBSD package names"
This reverts commit f4e573278d.
2025-12-14 19:53:33 +02:00
Ilia Ross
d7c49a51c7 Fix to drop obsolete secret 2025-12-14 01:18:19 +02:00
Jamie Cameron
018ad0062b Add config option for real name part of from address
https://github.com/webmin/webmin/issues/2600
2025-12-13 10:17:49 -08:00
Ilia Ross
50075dd71d Fix pre-release repo label 2025-12-12 20:03:15 +02:00
Ilia Ross
f4e573278d Add FreeBSD package names 2025-12-11 09:44:35 +02:00
Ilia Ross
9bce05f48a Fix to support installing missing Perl modules using package manager 2025-12-10 18:57:14 +02:00
Ilia Ross
238756902b Fix to remove empty extra line 2025-12-09 02:43:42 +02:00
Ilia Ross
b597bfb0bd Fix stable name 2025-12-09 01:19:27 +02:00
Ilia Ross
00adb84d69 Revert "Fix to explicitly set no auto-reconnect"
This reverts commit 9ba627e461.
2025-12-09 00:53:48 +02:00
Ilia Ross
0cf0af85cd Update workflow 2025-12-07 20:50:36 +02:00
Ilia Ross
ae89844754 Fix repo name 2025-12-07 15:38:57 +02:00
Ilia Ross
9ba627e461 Fix to explicitly set no auto-reconnect
https://forum.virtualmin.com/t/webmin-2-6-not-available-yet/135883/10?u=ilia
2025-12-07 15:04:42 +02:00
Ilia Ross
bae6e39889 Fix to pad multiple keys with new line 2025-12-03 20:55:26 +02:00
Ilia Ross
5377098de3 Add support for installing multiple keys 2025-12-03 19:07:33 +02:00
Ilia Ross
48291845b4 Add support to set different key download server 2025-12-03 15:37:05 +02:00
Ilia Ross
36194ade8e Fix description consistency 2025-12-02 23:25:32 +02:00
Ilia Ross
d8e9ad116a Fix colors 2025-12-02 22:57:39 +02:00
Ilia Ross
4c5911887c Add support to configure repo pathname 2025-12-02 22:34:08 +02:00
Ilia Ross
392d3aceff Fix comments 2025-12-02 22:33:05 +02:00
Ilia Ross
15a3c91f9d Fix to keep repo name consistent 2025-12-02 22:31:17 +02:00
Ilia Ross
58c6d41295 Fix to correctly print downloaded and installed key name 2025-12-02 20:46:50 +02:00
Jamie Cameron
7b9bca5b67 Fix param for field being saved 2025-12-02 06:17:30 -08:00
Jamie Cameron
ba47e2a0d0 Fix selection of TLS cert/key fields 2025-12-02 05:35:08 -08:00
Jamie Cameron
3b06c4dccb Revert "Fux subs to use local variable for parameters #2597"
This reverts commit 1e6611ade5.
2025-12-02 05:32:33 -08:00
Ilia Ross
1e6611ade5 Fux subs to use local variable for parameters #2597 2025-12-01 14:45:24 +02:00
Jamie Cameron
dfa5ac8b21 Use more efficient code for if-undefined 2025-11-29 14:28:34 -08:00
Jamie Cameron
d7cf050d71 Merge branch 'master' of github.com:webmin/webmin 2025-11-29 14:26:59 -08:00
Jamie Cameron
7945a9f0e6 Don't globally change PGPASSFILE
https://github.com/webmin/webmin/issues/2592
2025-11-29 14:22:52 -08:00
Ilia Ross
6cd04c131c Fix to steal if needed and don't fail unless term wanted #2595 2025-11-29 22:19:02 +02:00
Jamie Cameron
9f4a4fadf7 Add tool tip about where to setup notifcation methods
https://github.com/webmin/webmin/issues/2594
2025-11-28 20:56:48 -08:00
37 changed files with 464 additions and 166 deletions

View File

@@ -6,15 +6,17 @@ on:
- master
release:
types:
- published
- prereleased
- released
jobs:
build:
uses: webmin/webmin-ci-cd/.github/workflows/master-workflow.yml@main
with:
build-type: package
project-name: webmin
project-name: ${{ github.event.repository.name }}
is-release: ${{ github.event_name == 'release' }}
is-prerelease: ${{ github.event.release.prerelease || false }}
secrets:
DEV_IP_ADDR: ${{ secrets.DEV_IP_ADDR }}
DEV_IP_KNOWN_HOSTS: ${{ secrets.DEV_IP_KNOWN_HOSTS }}
@@ -22,4 +24,4 @@ jobs:
DEV_UPLOAD_SSH_DIR: ${{ secrets.DEV_UPLOAD_SSH_DIR }}
PRERELEASE_UPLOAD_SSH_DIR: ${{ secrets.PRERELEASE_UPLOAD_SSH_DIR }}
DEV_SSH_PRV_KEY: ${{ secrets.DEV_SSH_PRV_KEY }}
DEV_SIGN_BUILD_REPOS_CMD: ${{ secrets.DEV_SIGN_BUILD_REPOS_CMD }}
ALL_GPG_PH2: ${{ secrets.ALL_GPG_PH2 }}

View File

@@ -161,6 +161,7 @@ manual_efile=Invalid Apache config file
manual_etest=Configuration file error detected : $1
manual_editfile=Edit config file:
manual_switch=Edit
manual_evirt=Virtual host could not be found after manual changes - maybe the ServerName was changed?
dir_title=Per-Directory Options
dir_proxyall=All proxy requests

View File

@@ -73,6 +73,14 @@ if ($config{'test_manual'}) {
&error(&text('manual_etest',
"<pre>".&html_escape($err)."</pre>"));
}
if (defined($in{'virt'}) && !defined($in{'idx'})) {
undef(@get_config_cache);
($conf, $v) = &get_virtual_config($in{'virt'});
if (!$v) {
&copy_source_dest($temp, $file);
&error($text{'manual_evirt'});
}
}
}
unlink($temp);
&unlock_file($file);

View File

@@ -70,12 +70,18 @@ sub get_rand_flag
if ($gconfig{'os_type'} =~ /-linux$/ &&
$config{'force_random'} eq '0' &&
-r "/dev/urandom" &&
&compare_version_numbers($bind_version, 9) >= 0 &&
&compare_version_numbers($bind_version, '9.14.2') < 0) {
# Version: 9.14.2 deprecated the use of -r option
# in favor of using /dev/random [bugs:#5370]
return "-r /dev/urandom";
&compare_version_numbers($bind_version, 9) >= 0) {
if (&compare_version_numbers($bind_version, '9.14.2') < 0) {
return "-r /dev/urandom";
}
else {
# Version: 9.14.2 deprecated the use of -r option
# in favor of using /dev/random [bugs:#5370]. So no
# entropy generation is needed.
return undef;
}
}
# No random flag, and entropy is needed
return "";
}
@@ -1118,7 +1124,7 @@ else {
@v = ( );
}
if ($type eq "A" || $type eq "AAAA") {
print &ui_table_row($text{'value_A1'},
print &ui_table_row($text{"value_${type}1"},
&ui_textbox("value0", $v[0], 20)." ".
(!defined($_[5]) && $type eq "A" ?
&free_address_button("value0") : ""), 3);
@@ -3458,7 +3464,8 @@ closedir(ZONEDIR);
# Fork a background job to do lots of IO, to generate entropy
my $pid;
if (!&get_rand_flag()) {
my $flag = &get_rand_flag();
if (defined($flag) && !$flag) {
$pid = fork();
if (!$pid) {
exec("find / -type f >/dev/null 2>&1");
@@ -3507,7 +3514,7 @@ else {
"cd ".quotemeta($fn)." && ".
"$config{'keygen'} -a ".quotemeta($alg).
" -b ".quotemeta($zonesize).
" -n ZONE ".&get_rand_flag()." $dom 2>&1");
" -n ZONE ".($flag || "")." $dom 2>&1");
if ($?) {
kill('KILL', $pid) if ($pid);
return $out;
@@ -3519,7 +3526,7 @@ else {
"cd ".quotemeta($fn)." && ".
"$config{'keygen'} -a ".quotemeta($alg).
" -b ".quotemeta($size).
" -n ZONE -f KSK ".&get_rand_flag()." $dom 2>&1");
" -n ZONE -f KSK ".($flag || "")." $dom 2>&1");
kill('KILL', $pid) if ($pid);
if ($?) {
return $out;
@@ -3589,7 +3596,8 @@ $zonekey || return "Could not find DNSSEC zone key";
# Fork a background job to do lots of IO, to generate entropy
my $pid;
if (!&get_rand_flag()) {
my $flag = &get_rand_flag();
if (defined($flag) && !$flag) {
$pid = fork();
if (!$pid) {
exec("find / -type f >/dev/null 2>&1");
@@ -3606,7 +3614,7 @@ my $alg = $zonekey->{'algorithm'};
my $out = &backquote_logged(
"cd ".quotemeta($dir)." && ".
"$config{'keygen'} -a ".quotemeta($alg)." -b ".quotemeta($zonesize).
" -n ZONE ".&get_rand_flag()." $dom 2>&1");
" -n ZONE ".($flag || "")." $dom 2>&1");
kill('KILL', $pid) if ($pid);
if ($?) {
return "Failed to generate new zone key : $out";

View File

@@ -10,6 +10,10 @@ use POSIX;
use Socket;
$force_lang = $default_lang;
&init_config();
my $DEFAULT_RPC_TIMEOUT = 60;
my $DEFAULT_RPC_IDLE_FACTOR = 6;
print "Content-type: text/plain\n\n";
# Can this user make remote calls?
@@ -34,7 +38,7 @@ if ($aerr) {
exit;
}
if (open(RANDOM, "/dev/urandom")) {
local $tmpsid;
my $tmpsid;
read(RANDOM, $tmpsid, 16);
$sid = lc(unpack('h*', $tmpsid));
close RANDOM;
@@ -45,6 +49,16 @@ else {
$version = &get_webmin_version();
print "1 $port $sid $version\n";
# Timeout
my $rpc_idle_factor = $gconfig{'rpc_idle_factor'} || $DEFAULT_RPC_IDLE_FACTOR;
if ($rpc_idle_factor !~ /^\d+$/ || $rpc_idle_factor < 1) {
$rpc_idle_factor = $DEFAULT_RPC_IDLE_FACTOR;
}
my $config_rpc_timeout = $gconfig{'rpc_timeout'} || $DEFAULT_RPC_TIMEOUT;
if ($config_rpc_timeout !~ /^\d+$/ || $config_rpc_timeout < 1) {
$config_rpc_timeout = $DEFAULT_RPC_TIMEOUT;
}
# Fork and listen for calls ..
$pid = fork();
if ($pid < 0) {
@@ -57,12 +71,12 @@ untie(*STDIN);
untie(*STDOUT);
# Accept the TCP connection
local $rmask;
my $rmask;
vec($rmask, fileno(MAIN), 1) = 1;
if ($use_ipv6) {
vec($rmask, fileno(MAIN6), 1) = 1;
}
$sel = select($rmask, undef, undef, 60);
$sel = select($rmask, undef, undef, $config_rpc_timeout);
if ($sel <= 0) {
print STDERR "fastrpc: accept timed out\n"
if ($gconfig{'rpcdebug'});
@@ -78,39 +92,52 @@ else {
die "No connection on any socket!";
}
die "accept failed : $!" if (!$acptaddr);
$oldsel = select(SOCK);
my $oldsel = select(SOCK);
$| = 1;
select($oldsel);
$rcount = 0;
my $rcount = 0;
my %xfer_kids;
while(1) {
# Clean up the list of waiting sub-processes
foreach my $p (keys %xfer_kids) {
my $waited_pid = waitpid($p, POSIX::WNOHANG());
delete($xfer_kids{$p}) if ($waited_pid > 0 || $waited_pid == -1);
}
# Wait for the request. Wait longer if this isn't the first one
local $rmask;
my $rmask;
vec($rmask, fileno(SOCK), 1) = 1;
local $sel = select($rmask, undef, undef, $rcount ? 360 : 60);
my $timeout = $rcount
? $config_rpc_timeout * $rpc_idle_factor
: $config_rpc_timeout;
my $sel = select($rmask, undef, undef, $timeout);
if ($sel <= 0) {
# Don't kill the control session while a tcpwrite/tcpread is
# running
next if (keys %xfer_kids);
print STDERR "fastrpc: session timed out\n"
if ($gconfig{'rpcdebug'});
last;
}
local $line = <SOCK>;
my $line = <SOCK>;
last if (!$line);
local ($len, $auth) = split(/\s+/, $line);
my ($len, $auth) = split(/\s+/, $line);
die "Invalid session ID" if ($auth ne $sid);
local $rawarg;
my $rawarg;
while(length($rawarg) < $len) {
local $got;
local $rv = read(SOCK, $got, $len - length($rawarg));
my $got;
my $rv = read(SOCK, $got, $len - length($rawarg));
exit if ($rv <= 0);
$rawarg .= $got;
}
print STDERR "fastrpc: raw $rawarg\n" if ($gconfig{'rpcdebug'});
local $dumper = substr($rawarg, 0, 5) eq '$VAR1' ? 1 : 0;
local $arg = &unserialise_variable($rawarg);
my $dumper = substr($rawarg, 0, 5) eq '$VAR1' ? 1 : 0;
my $arg = &unserialise_variable($rawarg);
# Process it
local $rv;
my $rv;
if ($arg->{'action'} eq 'ping') {
# Just respond with an OK
print STDERR "fastrpc: ping\n" if ($gconfig{'rpcdebug'});
@@ -126,12 +153,12 @@ while(1) {
elsif ($arg->{'action'} eq 'config') {
# Get the config for some module
print STDERR "fastrpc: config $arg->{'module'}\n" if ($gconfig{'rpcdebug'});
local %config = &foreign_config($arg->{'module'});
my %config = &foreign_config($arg->{'module'});
$rv = { 'status' => 1, 'rv' => \%config };
}
elsif ($arg->{'action'} eq 'write') {
# Transfer data to a local temp file
local $file = $arg->{'file'} ? $arg->{'file'} :
# Transfer data to a my temp file
my $file = $arg->{'file'} ? $arg->{'file'} :
$arg->{'name'} ? &tempname($arg->{'name'}) :
&tempname();
print STDERR "fastrpc: write $file\n" if ($gconfig{'rpcdebug'});
@@ -142,24 +169,32 @@ while(1) {
$rv = { 'status' => 1, 'rv' => $file };
}
elsif ($arg->{'action'} eq 'tcpwrite') {
# Transfer data to a local temp file over TCP connection
local $file = $arg->{'file'} ? $arg->{'file'} :
# Transfer data to a my temp file over TCP connection
my $file = $arg->{'file'} ? $arg->{'file'} :
$arg->{'name'} ? &tempname($arg->{'name'}) :
&tempname();
print STDERR "fastrpc: tcpwrite $file\n" if ($gconfig{'rpcdebug'});
local $tsock = time().$$;
local $tsock6 = $use_ipv6 ? time().$$."v6" : undef;
local $tport = $port + 1;
my $tsock = time().$$;
my $tsock6 = $use_ipv6 ? time().$$."v6" : undef;
my $tport = $port + 1;
&allocate_socket($tsock, $tsock6, \$tport);
if (!fork()) {
my $cpid = fork();
if (!defined($cpid)) {
$rv = { 'status' => 0, 'rv' => "fork() failed : $!" };
}
elsif ($cpid == 0) {
close(SOCK);
close(MAIN);
close(MAIN6) if ($use_ipv6);
# Accept connection in separate process
print STDERR "fastrpc: tcpwrite $file port $tport\n" if ($gconfig{'rpcdebug'});
local $rmask;
print STDERR "fastrpc: tcpwrite $file port $tport\n"
if ($gconfig{'rpcdebug'});
my $rmask;
vec($rmask, fileno($tsock), 1) = 1;
if ($use_ipv6) {
vec($rmask, fileno($tsock6), 1) = 1;
}
local $sel = select($rmask, undef, undef, 30);
my $sel = select($rmask, undef, undef, 30);
exit if ($sel <= 0);
if (vec($rmask, fileno($tsock), 1)) {
accept(TRANS, $tsock) || exit;
@@ -168,14 +203,14 @@ while(1) {
accept(TRANS, $tsock6) || exit;
}
print STDERR "fastrpc: tcpwrite $file accepted\n" if ($gconfig{'rpcdebug'});
local $buf;
local $err;
my $buf;
my $err;
if (open(FILE, ">$file")) {
binmode(FILE);
print STDERR "fastrpc: tcpwrite $file writing\n" if ($gconfig{'rpcdebug'});
my $bs = &get_buffer_size();
while(read(TRANS, $buf, $bs) > 0) {
local $ok = (print FILE $buf);
my $ok = (print FILE $buf);
if (!$ok) {
$err = "Write to $file failed : $!";
last;
@@ -192,15 +227,19 @@ while(1) {
close(TRANS);
exit;
}
else {
$xfer_kids{$cpid} = 1;
print STDERR "fastrpc: tcpwrite $file started\n"
if ($gconfig{'rpcdebug'});
$rv = { 'status' => 1, 'rv' => [ $file, $tport ] };
}
close($tsock);
close($tsock6);
print STDERR "fastrpc: tcpwrite $file done\n" if ($gconfig{'rpcdebug'});
$rv = { 'status' => 1, 'rv' => [ $file, $tport ] };
close($tsock6) if ($use_ipv6);
}
elsif ($arg->{'action'} eq 'read') {
# Transfer data from a file
print STDERR "fastrpc: read $arg->{'file'}\n" if ($gconfig{'rpcdebug'});
local ($data, $got);
my ($data, $got);
open(FILE, "<$arg->{'file'}");
binmode(FILE);
my $bs = &get_buffer_size();
@@ -221,18 +260,25 @@ while(1) {
}
else {
binmode(FILE);
local $tsock = time().$$;
local $tsock6 = $use_ipv6 ? time().$$."v6" : undef;
local $tport = $port + 1;
my $tsock = time().$$;
my $tsock6 = $use_ipv6 ? time().$$."v6" : undef;
my $tport = $port + 1;
&allocate_socket($tsock, $tsock6, \$tport);
if (!fork()) {
my $cpid = fork();
if (!defined($cpid)) {
$rv = { 'status' => 0, 'rv' => "fork() failed : $!" };
}
elsif ($cpid == 0) {
close(SOCK);
close(MAIN);
close(MAIN6) if ($use_ipv6);
# Accept connection in separate process
local $rmask;
my $rmask;
vec($rmask, fileno($tsock), 1) = 1;
if ($use_ipv6) {
vec($rmask, fileno($tsock6), 1) = 1;
}
local $sel = select($rmask, undef, undef, 30);
my $sel = select($rmask, undef, undef, 30);
exit if ($sel <= 0);
if (vec($rmask, fileno($tsock), 1)) {
accept(TRANS, $tsock) || exit;
@@ -240,7 +286,7 @@ while(1) {
elsif (vec($rmask, fileno($tsock6), 1)) {
accept(TRANS, $tsock6) || exit;
}
local $buf;
my $buf;
while(read(FILE, $buf, 1024) > 0) {
print TRANS $buf;
}
@@ -248,11 +294,17 @@ while(1) {
close(TRANS);
exit;
}
else {
$xfer_kids{$cpid} = 1;
print STDERR "fastrpc: tcpread $arg->{'file'} ".
"started\n"
if ($gconfig{'rpcdebug'});
$rv = { 'status' => 1,
'rv' => [ $arg->{'file'}, $tport ] };
}
close(FILE);
close($tsock);
close($tsock6);
print STDERR "fastrpc: tcpread $arg->{'file'} done\n" if ($gconfig{'rpcdebug'});
$rv = { 'status' => 1, 'rv' => [ $arg->{'file'}, $tport ] };
close($tsock6) if ($use_ipv6);
}
}
elsif ($arg->{'action'} eq 'require') {
@@ -274,7 +326,7 @@ while(1) {
elsif ($arg->{'action'} eq 'call') {
# execute a function
print STDERR "fastrpc: call $arg->{'module'}::$arg->{'func'}(",join(",", @{$arg->{'args'}}),")\n" if ($gconfig{'rpcdebug'});
local @rv;
my @rv;
eval {
local $main::error_must_die = 1;
@rv = &foreign_call($arg->{'module'},
@@ -296,9 +348,9 @@ while(1) {
elsif ($arg->{'action'} eq 'eval') {
# eval some perl code
print STDERR "fastrpc: eval $arg->{'module'} $arg->{'code'}\n" if ($gconfig{'rpcdebug'});
local $erv;
my $erv;
if ($arg->{'module'}) {
local $pkg = $arg->{'module'};
my $pkg = $arg->{'module'};
$pkg =~ s/[^A-Za-z0-9]/_/g;
$erv = eval "package $pkg;\n".
$arg->{'code'}."\n";
@@ -334,8 +386,8 @@ while(1) {
# allocate_socket(handle, ipv6-handle, &port)
sub allocate_socket
{
local ($fh, $fh6, $port) = @_;
local $proto = getprotobyname('tcp');
my ($fh, $fh6, $port) = @_;
my $proto = getprotobyname('tcp');
if (!socket($fh, PF_INET, SOCK_STREAM, $proto)) {
return "socket failed : $!";
}

View File

@@ -475,6 +475,14 @@ time_in_mins=In $1 minutes
time_in_sec=In $1 second
time_in_secs=In $1 seconds
time_now=Just now
time_second=second
time_seconds=seconds
time_minute=minute
time_minutes=minutes
time_hour=hour
time_hours=hours
time_day=day
time_days=days
defcert_error=Default $1 bundled SSL certificate is being used. It is highly advised to update default <tt>$2</tt> certificate before proceeding with login.

View File

@@ -51,6 +51,7 @@ spam_report=Report spam using,1,sa_learn-<tt>sa&#45;learn --spam</tt>,spamassass
line3.5=From address options,11
from_addr=<tt>From:</tt> address to use when sending email manually,3,From mailbox username
webmin_from=<tt>From:</tt> address to use when Webmin sends email,3,Default (<tt>webmin-noreply@<i>yourhost</i></tt>)
webmin_from_name=Real name to use in From: address,3,None
from_virtualmin=Get <tt>From:</tt> address from Virtualmin?,1,1-Yes,0-No
from_dom=Domain to use in <tt>From:</tt> address,3,System hostname
no_orig_ip=Include browser IP in <tt>X-Originating</tt>-IP header?,1,0-Yes,1-No

View File

@@ -600,16 +600,21 @@ return &ui_link("list_mail.cgi?user=$_[0]&folder=$_[1]->{'index'}",$text{'mail_r
# Returns the address to use when sending email from a script
sub get_from_address
{
local $host = &get_from_domain();
my $host = &get_from_domain();
my $rv;
if ($config{'webmin_from'} =~ /\@/) {
return $config{'webmin_from'};
$rv = $config{'webmin_from'};
}
elsif (!$config{'webmin_from'}) {
return "webmin-noreply\@$host";
$rv = "webmin-noreply\@$host";
}
else {
return "$config{'webmin_from'}\@$host";
$rv = "$config{'webmin_from'}\@$host";
}
if ($config{'webmin_from_name'}) {
$rv = "\"$config{'webmin_from_name'}\" <$rv>";
}
return $rv;
}
# get_from_domain()

View File

@@ -109,7 +109,7 @@ if ($product eq "webmin") {
$size = int(`du -sk $tmp_dir`);
@deps = ( "perl", "libnet-ssleay-perl", "openssl", "libauthen-pam-perl", "libpam-runtime", "libio-pty-perl", "unzip", "shared-mime-info", "tar", "libdigest-sha-perl", "libdigest-md5-perl", "gzip" );
$deps = join(", ", @deps);
@recommends = ( "libdatetime-perl", "libdatetime-timezone-perl", "libdatetime-locale-perl", "libtime-piece-perl", "libencode-detect-perl", "libtime-hires-perl", "libsocket6-perl", "html2text", "qrencode", "libdbi-perl", "libdbd-mysql-perl", "libjson-xs-perl", "libsys-syslog-perl" );
@recommends = ( "libdatetime-perl", "libdatetime-timezone-perl", "libdatetime-locale-perl", "libtime-piece-perl", "libencode-detect-perl", "libtime-hires-perl", "libsocket6-perl", "html2text", "qrencode", "libdbi-perl", "libdbd-mysql-perl", "libdbd-mariadb-perl", "libjson-xs-perl", "libsys-syslog-perl" );
$recommends = join(", ", @recommends);
open(CONTROL, ">$control_file");
print CONTROL <<EOF;

View File

@@ -287,4 +287,3 @@ sub usage
{
die "Usage: $0 [--minimal] [--mod-list type] <version>\n";
}

View File

@@ -551,6 +551,9 @@ if [ "$istheme" = "1" -a "\$1" = "0" ]; then
fi
# Run the pre-uninstall script, if we are not upgrading
if [ "$prog" = "webmin" -a "\$1" = "0" -a -r "/usr/libexec/$prog/$mod/uninstall.pl" ]; then
# Skip if replaced by a different package (wbm-foo - webmin-foo)
owner=\$(rpm -qf --qf '%%{NAME}\\n' "/usr/libexec/$prog/$mod/uninstall.pl" 2>/dev/null || true)
[ -n "\$owner" -a "\$owner" != "%{name}" ] && exit 0
cd /usr/libexec/$prog
WEBMIN_CONFIG=/etc/$prog WEBMIN_VAR=/var/$prog /usr/libexec/$prog/run-uninstalls.pl $mod
fi

View File

@@ -88,7 +88,7 @@ Release: $rel
Provides: %{name}-%{version} perl(WebminCore)
Requires(pre): /usr/bin/perl
Requires: /bin/sh /usr/bin/perl perl(lib) perl(open) perl(Net::SSLeay) perl(Time::Local) perl(Data::Dumper) perl(File::Path) perl(File::Basename) perl(Digest::SHA) perl(Digest::MD5) openssl unzip tar gzip
Recommends: perl(DateTime) perl(DateTime::TimeZone) perl(DateTime::Locale) perl(Time::Piece) perl(Encode::Detect) perl(Time::HiRes) perl(Socket6) perl(Sys::Syslog) html2text shared-mime-info lsof perl-File-Basename perl-File-Path perl-JSON-XS qrencode perl(DBI) perl(DBD::mysql)
Recommends: perl(DateTime) perl(DateTime::TimeZone) perl(DateTime::Locale) perl(Time::Piece) perl(Encode::Detect) perl(Time::HiRes) perl(Socket6) perl(Sys::Syslog) html2text shared-mime-info lsof perl-File-Basename perl-File-Path perl-JSON-XS qrencode perl(DBI) perl(DBD::mysql) perl(DBD::MariaDB)
AutoReq: 0
License: BSD-3-Clause
Group: System/Tools

View File

@@ -3,6 +3,5 @@ require 'mysql-lib.pl';
sub cpan_recommended
{
return ( "DBI", "DBD::mysql" );
return ( "DBI", $mysql_version =~ /mariadb/i ? "DBD::MariaDB" : "DBD::mysql" );
}

View File

@@ -320,14 +320,26 @@ else {
if (foreign_available("cpan")) {
eval "use DBI";
push(@needs, "DBI") if ($@);
$nodbi++ if ($@);
eval "use DBD::mysql";
push(@needs, "DBD::mysql") if ($@);
push(@needs, $driver_info->{prefer}) if (!$driver_info->{avail});
if (@needs) {
$needs = &urlize(join(" ", @needs));
print &ui_alert_box(&text(@needs == 2 ? 'index_nomods' : 'index_nomod', @needs,
"../cpan/download.cgi?source=3&cpan=$needs&mode=2&return=/$module_name/&returndesc=".
&urlize($text{'index_return'})), 'warn');
&urlize($text{'index_return'})), 'warn',
undef, undef, "");
}
}
# No CPAN module, just check for the driver
else {
eval "use DBI";
push(@needs, "DBI") if ($@);
push(@needs, $driver_info->{prefer}) if (!$driver_info->{avail});
if (@needs) {
print &ui_alert_box(
&text(@needs == 2
? 'index_nomods_manual'
: 'index_nomod_manual', @needs), 'warn',
undef, undef, "");
}
}
}

View File

@@ -30,6 +30,8 @@ index_version=$2 version $1
index_version2=$3 version $1 on $2
index_nomod=The Perl module <tt>$1</tt> is not installed on your system, so Webmin will not be able to reliably access your MySQL database. <a href='$2'>Click here</a> to install it now.
index_nomods=The Perl modules <tt>$1</tt> and <tt>$2</tt> are not installed on your system, so Webmin will not be able to reliably access your MySQL database. <a href='$3'>Click here</a> to install them now.
index_nomod_manual=The Perl module <tt>$1</tt> is not installed on your system, so Webmin will not be able to reliably access your MySQL database. Install it manually using your package manager.
index_nomods_manual=The Perl modules <tt>$1</tt> and <tt>$2</tt> are not installed on your system, so Webmin will not be able to reliably access your MySQL database. Install them manually using your package manager.
index_mysqlver=The command <tt>$1</tt> returned :
index_eenvpass=The MySQL client program $1 does not accept passwords passed using the <tt>MYSQL_PWD</tt> environment variable. To ensure that Webmin is able to fully communicate with MySQL, this option should be turned off on the <a href='$2'>module configuration</a> page. Alternately, you can remove any password set in the <tt>root</tt> user's <tt>.my.cnf</tt> file.
index_ecnf=The MySQL config file $1 was not found on your system. Use the <a href='$2'>module configuration</a> page to set the correct path.

View File

@@ -67,13 +67,44 @@ $password_func = $config{'passwd_mode'} ? "old_password" : "password";
'enum', 'set');
@priv_cols = ('Host', 'User', 'Password', 'Select_priv', 'Insert_priv', 'Update_priv', 'Delete_priv', 'Create_priv', 'Drop_priv', 'Reload_priv', 'Shutdown_priv', 'Process_priv', 'File_priv', 'Grant_priv', 'References_priv', 'Index_priv', 'Alter_priv', 'Show_db_priv', 'Super_priv', 'Create_tmp_table_priv', 'Lock_tables_priv', 'Execute_priv', 'Repl_slave_priv', 'Repl_client_priv', 'Create_view_priv', 'Show_view_priv', 'Create_routine_priv', 'Alter_routine_priv', 'Create_user_priv');
$driver_info = &dbi_driver_info();
if (!$config{'nodbi'}) {
# Check if we have DBI::mysql
eval <<EOF;
use DBI;
\$driver_handle = DBI->install_driver("mysql");
EOF
# Check if we have DBI::mysql or DBI::MariaDB
eval "require DBI;
\$driver_handle = DBI->install_driver(\$driver_info->{'drv'});";
}
# dbi_driver_info()
# Based on the current database variant, returns info about the DBI driver.
# Falls back to MySQL if the preferred driver is not available.
sub dbi_driver_info
{
my %dbmap = (
'mysql' => { drv => 'mysql', opt => 'mysql', mod => 'DBD::mysql' },
'mariadb' => { drv => 'MariaDB', opt => 'mariadb', mod => 'DBD::MariaDB' }
);
my $want = ($mysql_version && $mysql_version =~ /mariadb/i)
? 'mariadb'
: 'mysql';
# Try preferred driver
my $m = $dbmap{$want}->{'mod'};
my $ok = eval "require $m; 1;";
$dbmap{$want}->{'avail'} = $ok ? 1 : 0;
$dbmap{$want}->{'prefer'} = $dbmap{$want}->{'mod'};
return $dbmap{$want} if $ok;
# If MariaDB preferred but unavailable, fallback to MySQL
if ($want eq 'mariadb') {
$m = $dbmap{'mysql'}->{'mod'};
$ok = eval "require $m; 1;";
$dbmap{'mysql'}->{'avail'} = $ok ? 1 : 0;
$dbmap{'mysql'}->{'prefer'} = $dbmap{$want}->{'mod'};
return $dbmap{'mysql'};
}
# Preferred driver unavailable, no fallback
return $dbmap{$want};
}
# Fix text if we're running MariaDB
@@ -324,15 +355,16 @@ $sql = &escape_backslashes_in_quotes($sql);
if ($driver_handle && !$config{'nodbi'}) {
# Use the DBI interface
local $cstr = "database=$_[0]";
local $drv = $driver_info->{opt};
$cstr .= ";host=$config{'host'}" if ($config{'host'});
$cstr .= ";port=$config{'port'}" if ($config{'port'});
$cstr .= ";mysql_socket=$config{'sock'}" if ($config{'sock'});
$cstr .= ";mysql_read_default_file=$config{'my_cnf'}"
$cstr .= ";${drv}_socket=$config{'sock'}" if ($config{'sock'});
$cstr .= ";${drv}_read_default_file=$config{'my_cnf'}"
if (-r $config{'my_cnf'});
if ($config{'ssl'}) {
$cstr .= ";mysql_ssl=1";
$cstr .= ";${drv}_ssl=1";
if ($DBD::mysql::VERSION >= 4.043) {
$cstr .= ";mysql_ssl_optional=1";
$cstr .= ";${drv}_ssl_optional=1";
}
}
local $dbh = $driver_handle->connect($cstr, $mysql_login, $mysql_pass,

View File

@@ -128,6 +128,7 @@ Ubuntu Linux $1 debian-linux 11.0 $os_release =~ /Ubuntu\s+(20\.[0-9\.]+)/ ||
Ubuntu Linux $1 debian-linux 12.0 $os_release =~ /Ubuntu\s+(21\.[0-9\.]+)/ || $etc_issue =~ /Ubuntu.*\s(21\.[0-9\.]+)\s/i || $etc_issue =~ /Ubuntu\s+(hirsute|impish)/i
Ubuntu Linux $1 debian-linux 13.0 $os_release =~ /Ubuntu\s+(22\.[0-9\.]+)/ || $etc_issue =~ /Ubuntu.*\s(22\.[0-9\.]+)\s/i || $etc_issue =~ /Ubuntu\s+jammy/i
Ubuntu Linux $1 debian-linux 14.0 $os_release =~ /Ubuntu\s+(24\.[0-9\.]+)/ || $etc_issue =~ /Ubuntu.*\s(24\.[0-9\.]+)\s/i || $etc_issue =~ /Ubuntu\s+noble/i
Ubuntu Linux $1 debian-linux 15.0 $os_release =~ /Ubuntu\s+(26\.[0-9\.]+)/ || $etc_issue =~ /Ubuntu.*\s(26\.[0-9\.]+)\s/i || $etc_issue =~ /Ubuntu\s+resolute/i
Ubuntu Linux $1 debian-linux 3.1 $etc_issue =~ /Ubuntu.*\s([0-9\.]+)\s/i
Mepis Linux $1 debian-linux $1 $etc_issue =~ /MEPIS/ && `cat /etc/debian_version 2>/dev/null` =~ /([0-9\.]+)/
Mepis Linux $1 debian-linux 4.0 $etc_issue =~ /MEPIS/ && `cat /etc/debian_version 2>/dev/null` =~ /(stable)/

View File

@@ -1234,7 +1234,7 @@ if (&supports_pgpass()) {
push(@main::temporary_files, $pgpass);
$cmd = "HOME=$temphome $cmd";
}
$ENV{'PGPASSFILE'} = $pgpass;
$cmd = "PGPASSFILE=$pgpass $cmd";
open(PGPASS, ">$pgpass");
print PGPASS "*:*:*:$user:$pass\n";
close(PGPASS);

View File

@@ -321,12 +321,25 @@ elsif (defined &linux_openpty &&
if (defined(&close_controlling_pty)) {
&close_controlling_pty();
}
setsid(); # create new session group
my $ctty_arg = 0; # must be writable scalar
ioctl($ttyfh, $TIOCSCTTY, $ctty_arg) # controlling tty
or &error("TIOCSCTTY failed: $!");
# Child must not hold the master end
close($ptyfh);
my $need_ctty = $ENV{'TERM'} ? 1 : 0;
setsid() # create new session group
or do {
# don't fail, just log it if we have a terminal
&error_stderr("setsid failed: $!")
if ($need_ctty);
};
close($ptyfh); # child must not hold master
my $ctty_arg = 0; # try normal attach
ioctl($ttyfh, $TIOCSCTTY, $ctty_arg) or do {
$ctty_arg = 1; # try force attach
ioctl($ttyfh, $TIOCSCTTY, $ctty_arg)
or do {
# don't fail, just log it if we have a
# terminal
&error_stderr("TIOCSCTTY failed: $!")
if ($need_ctty);
}
};
# Turn off echoing, if we can
eval "use IO::Stty";

View File

@@ -388,13 +388,17 @@ mod_tls_required=SSL required?
mod_tls_ctrl=For control channel
mod_tls_auth=For authentication
mod_tls_authdata=For authentication and data
mod_tls_file=SSL certificate file
mod_tls_efile=SSL certificate file does not exist!
mod_tls_key=SSL key file
mod_tls_ekey=SSL key file does not exist!
mod_tls_file=RSA SSL certificate file
mod_tls_efile=RSA SSL certificate file does not exist!
mod_tls_key=RSA SSL key file
mod_tls_ekey=RSA SSL key file does not exist!
mod_tls_ca=SSL CA certificate file
mod_tls_eca=SSL CA certificate file does not exist!
mod_tls_none=None set
mod_tls_ecfile=EC SSL certificate file
mod_tls_eecfile=EC SSL certificate file does not exist!
mod_tls_eckey=EC SSL key file
mod_tls_eeckey=EC SSL key file does not exist!
start_err=Failed to start FTP server
start_einetd=You cannot start the server daemon when in inetd mode.

View File

@@ -2,11 +2,13 @@
sub mod_tls_directives
{
local $rv = [
[ 'TLSEngine', 0, 7, 'virtual global', 1.27, 10 ],
[ 'TLSRequired', 0, 7, 'virtual global', 1.27, 1 ],
[ 'TLSRSACertificateFile', 0, 7, 'virtual global', 1.27, 8 ],
[ 'TLSRSACertificateKeyFile', 0, 7, 'virtual global', 1.27, 7 ],
[ 'TLSCACertificateFile', 0, 7, 'virtual global', 1.27, 6 ],
[ 'TLSEngine', 0, 7, 'virtual root', 1.27, 10 ],
[ 'TLSRequired', 0, 7, 'virtual root', 1.27, 9 ],
[ 'TLSRSACertificateFile', 0, 7, 'virtual root', 1.27, 8 ],
[ 'TLSRSACertificateKeyFile', 0, 7, 'virtual root', 1.27, 7 ],
[ 'TLSCACertificateFile', 0, 7, 'virtual root', 1.27, 5 ],
[ 'TLSECCertificateFile', 0, 7, 'virtual root', 1.35, 4 ],
[ 'TLSECCertificateKeyFile', 0, 7, 'virtual root', 1.35, 3 ],
];
return &make_directives($rv, $_[0], "mod_tls");
}
@@ -40,7 +42,7 @@ return &parse_choice("TLSRequired", "");
sub edit_TLSRSACertificateFile
{
my $n = $_[0]->{'name'};
my $n = $_[1]->{'name'};
return (2, $text{'mod_tls_file'},
&ui_opt_textbox($n, $_[0]->{'value'}, 60, $text{'mod_tls_none'})." ".
&file_chooser_button($n));
@@ -59,7 +61,7 @@ else {
sub edit_TLSRSACertificateKeyFile
{
my $n = $_[0]->{'name'};
my $n = $_[1]->{'name'};
return (2, $text{'mod_tls_key'},
&ui_opt_textbox($n, $_[0]->{'value'}, 60, $text{'mod_tls_none'})." ".
&file_chooser_button($n));
@@ -78,7 +80,7 @@ else {
sub edit_TLSCACertificateFile
{
my $n = $_[0]->{'name'};
my $n = $_[1]->{'name'};
return (2, $text{'mod_tls_ca'},
&ui_opt_textbox($n, $_[0]->{'value'}, 60, $text{'mod_tls_none'})." ".
&file_chooser_button($n));
@@ -95,4 +97,42 @@ else {
}
}
sub edit_TLSECCertificateFile
{
my $n = $_[1]->{'name'};
return (2, $text{'mod_tls_ecfile'},
&ui_opt_textbox($n, $_[0]->{'value'}, 60, $text{'mod_tls_none'})." ".
&file_chooser_button($n));
}
sub save_TLSECCertificateFile
{
my $n = $_[0]->{'name'};
if ($in{$n."_def"}) {
return ( [ ] );
}
else {
-r $in{$n} || &error($text{'mod_tls_eecfile'});
return ( [ $in{$n} ] );
}
}
sub edit_TLSECCertificateKeyFile
{
my $n = $_[1]->{'name'};
return (2, $text{'mod_tls_eckey'},
&ui_opt_textbox($n, $_[0]->{'value'}, 60, $text{'mod_tls_none'})." ".
&file_chooser_button($n));
}
sub save_TLSECCertificateKeyFile
{
my $n = $_[0]->{'name'};
if ($in{$n."_def"}) {
return ( [ ] );
}
else {
-r $in{$n} || &error($text{'mod_tls_eeckey'});
return ( [ $in{$n} ] );
}
}
1;

View File

@@ -34,8 +34,10 @@ if ($oldsite{'size'} != $st[7] ||
}
}
close(MODS);
$site{'modules'} = join(" ", @mods);
&write_file("$module_config_directory/site", \%site);
if (!$? || !-r "$module_config_directory/site") {
$site{'modules'} = join(" ", @mods);
&write_file("$module_config_directory/site", \%site);
}
}
}

View File

@@ -839,8 +839,8 @@ if [ "$upgrading" != 1 ]; then
# Enable HSTS by default
echo "ssl_hsts=1" >> $config_dir/miniserv.conf
# Enable force redirect to SSL by default
echo "ssl_enforce=1" >> $config_dir/miniserv.conf
# Enable force redirect to SSL with HSTS by default
echo "ssl_enforce=2" >> $config_dir/miniserv.conf
# Disallow unknown referers by default
echo "referers_none=1" >>$config_dir/config
@@ -851,10 +851,10 @@ else
echo "ssl_hsts=1" >> $config_dir/miniserv.conf
fi
# Enable force redirect to SSL if not set
# Enable force redirect to SSL with HSTS if not set
grep ssl_enforce= $config_dir/miniserv.conf >/dev/null
if [ "$?" != "0" ]; then
echo "ssl_enforce=1" >> $config_dir/miniserv.conf
echo "ssl_enforce=2" >> $config_dir/miniserv.conf
fi
# Disallow unknown referers if not set

View File

@@ -406,18 +406,25 @@ if ($config{'attribs'}) {
push(@attribs, [ $2, $7 ]);
}
elsif (/^\s*(\d+)\s+(\S+)\s+(0x\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/) {
# A new-style vendor attribute
# A new-style vendor attribute, like :
# 1 Raw_Read_Error_Rate 0x000f 130 130 039 Pre-fail Always - 4294967295
$doneknown = 1;
push(@attribs, [ $2, $10, undef, $4 ]);
$attribs[$#attribs]->[0] =~ s/_/ /g;
}
elsif (/^((\w+.*):\s+([0-9]+(,[0-9]+)+)|(\w+.*):\s+(\d+x\d+)|(\w+.*):\s+(\d+%)|^(\w+.*):\s+(\d+))/) {
# NVME style
elsif (/^((\w+.*):\s+([0-9]+(,[0-9]+)+)|(\w+.*):\s+(\d+x\d+)|(\w+.*):\s+(\d+%)|^(\w+.*):\s+(\d+))$/) {
# NVME style (what is this like??)
$doneknown = 1;
push(@attribs, [ $5 || $7 || $9 || $2, $6 || $8 || $10 || $3, undef, undef ]);
}
elsif (/^([A-Z][^:]+):\s+(\S.*)$/) {
# Some other attribute like :
# Form Factor: 2.5 inches
push(@attribs, [ $1, $2 ]);
}
elsif (/^(\S.*\S):\s+\(\s*(\S+)\)\s*(.*)/ && !$doneknown) {
# A known attribute
# A known attribute, like :
# Offline data collection status: (0x02) Offline data collection activity
local $attrib = [ $1, $2, $3 ];
if ($lastline =~ /^\S/ && $lastline !~ /:/) {
$attrib->[0] = $lastline." ".$attrib->[0];
@@ -425,7 +432,8 @@ if ($config{'attribs'}) {
push(@attribs, $attrib);
}
elsif (/^\s+(\S.*)/ && @attribs && !$doneknown) {
# Continuation of a known attribute description
# Continuation of a known attribute description, like :
# was completed without error.
local $cont = $1;
local $ls = $attribs[$#attribs];
if ($ls->[2] =~ /\.\s*$/) {

View File

@@ -25,7 +25,7 @@ print &ui_table_row($text{'sync_pass'},
print &ui_table_row($text{'sync_type'},
&ui_select("type", $config{'sync_type'},
[ [ "", $text{'sync_auto'} ],
[ "rsa" ], [ "dsa" ], [ "rsa1" ] ]));
[ "ed25519" ], [ "rsa" ], [ "dsa" ], [ "rsa1" ] ]));
print &ui_table_end();
print &ui_form_end([ [ undef, $text{'save'} ] ]);

View File

@@ -26,6 +26,9 @@ if ($config{'sync_create'} && &has_command($config{'keygen_path'}) &&
if (-r "$uinfo->{'home'}/.ssh/identity.pub") {
&copy_source_dest("$uinfo->{'home'}/.ssh/identity.pub", $akeys);
}
elsif (-r "$uinfo->{'home'}/.ssh/id_ed25519.pub") {
&copy_source_dest("$uinfo->{'home'}/.ssh/id_ed25519.pub", $akeys);
}
elsif (-r "$uinfo->{'home'}/.ssh/id_rsa.pub") {
&copy_source_dest("$uinfo->{'home'}/.ssh/id_rsa.pub", $akeys);
}

View File

@@ -167,7 +167,7 @@ foreach $n (keys %notify) {
# Don't clear set but un-usable modes
print &ui_hidden("notify", $n);
}
print &ui_table_row($text{'mon_notify'}, $notify,
print &ui_table_row(&hlink($text{'mon_notify'}, "notify"), $notify,
undef, \@tds);
# Show extra address to email

6
status/help/notify.html Normal file
View File

@@ -0,0 +1,6 @@
<header>Notification methods</header>
Available notification methods for this monitor can be configured on the
Scheduled Monitoring page. <p>
<footer>

View File

@@ -1 +1 @@
2.610
2.620

View File

@@ -7214,8 +7214,9 @@ if ($gconfig{'logclear'}) {
# check if it is time to clear the log
my @st = stat("$webmin_logfile.time");
my $write_logtime = 0;
my $log_time = $gconfig{'logtime'} || 168;
if (@st) {
if ($st[9]+$gconfig{'logtime'}*60*60 < time()) {
if ($st[9]+$log_time*60*60 < time()) {
# clear logfile and all diff files
&unlink_file("$ENV{'WEBMIN_VAR'}/diffs");
&unlink_file("$ENV{'WEBMIN_VAR'}/files");
@@ -7778,6 +7779,7 @@ my $pid = &open_execute_command(OUT, "($realcmd) <".quotemeta($null_file), 1, $_
my $start = time();
my $timed_out = 0;
my $linecount = 0;
my $bufsize = $_[3] ? 80 : &get_buffer_size();
while(1) {
my $elapsed = time() - $start;
last if ($elapsed > $_[1]);
@@ -7786,7 +7788,7 @@ while(1) {
my $sel = select($rmask, undef, undef, $_[1] - $elapsed);
last if (!$sel || $sel < 0);
my $line;
my $got = read(OUT, $line, 1);
my $got = read(OUT, $line, $bufsize);
last if (!$got);
$out .= $line;
$linecount += scalar(() = $out =~ /\n/g);
@@ -8605,13 +8607,13 @@ foreach my $sn (keys %remote_session) {
my $server = $remote_session_server{$sn};
&remote_rpc_call($server, { 'action' => 'quit',
'session' => $remote_session{$sn} } );
delete($remote_session{$sn});
delete($remote_session_server{$sn});
}
%remote_session = ( );
%remote_session_server = ( );
foreach my $fh (keys %fast_fh_cache) {
close($fh);
delete($fast_fh_cache{$fh});
}
%fast_fh_cache = ( );
}
=head2 remote_error_setup(&function)
@@ -8705,7 +8707,9 @@ if ($serv->{'fast'} || !$sn) {
my $line = &read_http_connection($con);
$line =~ tr/\r\n//d;
if ($line =~ /^HTTP\/1\..\s+40[13]\s+/) {
return &$main::remote_error_handler("Login to RPC server as $user rejected");
my $username = $user;
$username ||= 'unknown';
return &$main::remote_error_handler("Login to RPC server as user \"$username\" rejected");
}
$line || return &$main::remote_error_handler("HTTP error : No status line");
$line =~ /^HTTP\/1\..\s+200\s+/ ||
@@ -8810,7 +8814,7 @@ if ($serv->{'fast'} || !$sn) {
my $rstr = <$fh>;
if ($rstr eq '') {
return &$main::remote_error_handler(
"Error reading response length from fastrpc.cgi : $!")
"Error reading response length from fastrpc.cgi : $!");
}
my $rlen = int($rstr);
my ($fromstr, $got);
@@ -12626,8 +12630,7 @@ my @rv;
my %miniserv;
&get_miniserv_config(\%miniserv);
if (!$miniserv{'userdb_nocache'} && $main::connect_userdb_cache{$str}) {
my $timeout = defined($miniserv{'userdb_cache_timeout'}) ?
$miniserv{'userdb_cache_timeout'} : 60;
my $timeout = $miniserv{'userdb_cache_timeout'} // 60;
@rv = @{$main::connect_userdb_cache{$str}};
if (time() - $main::connect_userdb_cache_time{$str} > $timeout) {
# Yes, but it's already timed out. Force close it, and make a new

View File

@@ -10,16 +10,19 @@ repo_download="https://$repo_host"
repo_download_prerelease="https://rc.download.webmin.dev"
repo_download_unstable="https://download.webmin.dev"
repo_key="developers-key.asc"
repo_key_download="$repo_download/$repo_key"
repo_key_server="$repo_download"
repo_key_suffix="webmin-developers"
repo_key_name="Webmin Developers"
repo_name="webmin-stable"
repo_name_prerelease="webmin-prerelease"
repo_name_unstable="webmin-unstable"
repo_rpm_pathname="/download/newkey/yum"
repo_deb_pathname="/download/newkey/repository"
repo_component="main"
repo_dist="stable"
repo_section="contrib"
repo_description="Webmin Releases"
repo_description_prerelease="Webmin Prerelease"
repo_description="Webmin Stable"
repo_description_prerelease="Webmin Pre-release"
repo_description_unstable="Webmin Unstable"
install_check_binary="/usr/bin/webmin"
install_message="Webmin and Usermin can be installed with:"
@@ -31,7 +34,7 @@ repo_auth_pass=""
repo_mode="stable"
download_curl="/usr/bin/curl"
download="$download_curl -f -s -L -O"
download="$download_curl -q -f -sS -L -O"
force_setup=0
# Colors
@@ -55,14 +58,18 @@ General options:
Repository types:
--stable Set up the stable repo, built with extra testing
--prerelease Set up the prerelease repo built from latest tag
--prerelease Set up the pre-release repo built from latest tag
--unstable Set up unstable repo built from the latest commit
Repository configuration:
--host=<host> Main repository host
--prerelease-host=<host> Prerelease repository host
--repo-rpm-path=<path> Repository path for RPM-based systems
--repo-deb-path=<path> Repository path for DEB-based systems
--prerelease-host=<host> Pre-release repository host
--unstable-host=<host> Unstable repository host
--key=<key> Repository signing key file
--key-server=<url> Repository signing key download server
--key-name=<name> Repository key name for display
--key-suffix=<suffix> Repository key suffix for file naming
--auth-user=<user> Repository authentication username
--auth-pass=<pass> Repository authentication password
@@ -104,14 +111,24 @@ process_args() {
for arg in "$@"; do
case "$arg" in
--stable) repo_mode="stable" ;;
--prerelease|--rc) repo_mode="prerelease" ;;
--prerelease|--pre-release|--rc) repo_mode="prerelease" ;;
--unstable|--testing|-t) repo_mode="unstable" ;;
-f|--force) force_setup=1 ;;
-h|--help) usage ;;
--host=*)
repo_host="${arg#*=}"
repo_download="https://$repo_host"
repo_key_download="$repo_download/$repo_key"
repo_key_server="$repo_download"
;;
--repo-rpm-path=*)
repo_rpm_pathname="${arg#*=}"
[ "$repo_rpm_pathname" = "/" ] && repo_rpm_pathname=""
repo_rpm_pathname_set=1
;;
--repo-deb-path=*)
repo_deb_pathname="${arg#*=}"
[ "$repo_deb_pathname" = "/" ] && repo_deb_pathname=""
repo_deb_pathname_set=1
;;
--prerelease-host=*)
repo_download_prerelease="https://${arg#*=}"
@@ -121,7 +138,14 @@ process_args() {
;;
--key=*)
repo_key="${arg#*=}"
repo_key_download="$repo_download/$repo_key"
;;
--key-server=*)
key_server="${arg#*=}"
key_server="${key_server%/}"
repo_key_server="$key_server"
;;
--key-name=*)
repo_key_name="${arg#*=}"
;;
--key-suffix=*)
repo_key_suffix="${arg#*=}"
@@ -140,14 +164,14 @@ process_args() {
;;
--name=*)
base_name="${arg#*=}"
repo_name="$base_name"
repo_name="${base_name}-stable"
repo_name_prerelease="${base_name}-prerelease"
repo_name_unstable="${base_name}-unstable"
;;
--description=*)
base_description="${arg#*=}"
repo_description="$base_description Releases"
repo_description_prerelease="${base_description} Prerelease"
repo_description="$base_description Stable"
repo_description_prerelease="${base_description} Pre-release"
repo_description_unstable="${base_description} Unstable"
;;
--component=*)
@@ -286,18 +310,22 @@ set_os_variables() {
}
ask_confirmation() {
repo_desc_formatted=$(echo "$active_repo_description" | \
sed 's/\([^ ]*\)\(.*\)/\1\L\2/')
# Format description so only the first word keeps its case and the rest is
# lowercased
repo_desc_formatted=$(echo "$active_repo_description" | \
sed 's/\([^ ]*\)\(.*\)/\1\L\2/')
# Show special messages for prerelease and unstable repos
case "$repo_mode" in
prerelease)
printf \
"\e[47;1;31;82mPrerelease builds are automated from the latest tagged release\e[0m\n"
"\e[48;5;236;38;5;208;1mPre-release builds are automated from the latest tagged release\e[0m\n"
;;
unstable)
printf \
"\e[47;1;31;82mUnstable builds are automated experimental versions designed for\e[0m\n"
printf \
"\e[47;1;31;82mdevelopment, often containing critical bugs and breaking changes\e[0m\n"
"\e[48;5;236;38;5;160;1mUnstable builds are automated experimental versions designed for\e[0m\n"
printf \
"\e[48;5;236;38;5;160;1mdevelopment, often containing critical bugs and breaking changes\e[0m\n"
;;
esac
if [ "$force_setup" != "1" ]; then
@@ -378,10 +406,16 @@ enforce_package_priority() {
}
download_key() {
rm -f "/tmp/$repo_key"
echo " Downloading Webmin developers key .."
download_out=$($download "$repo_key_download" 2>&1)
post_status $? "$(echo "$download_out" | tr '\n' ' ')"
echo " Downloading $repo_key_name key .."
for key in $repo_key; do
rm -f "/tmp/$key"
download_out=$($download "$repo_key_server/$key" 2>&1)
if [ $? -ne 0 ]; then
post_status 1 "$(printf '%s : %s' "$repo_key_server/$key" "$download_out" | tr '\n' ' ')"
fi
done
post_status 0 ""
}
rpm_repo_prefs() {
@@ -394,8 +428,24 @@ rpm_repo_prefs() {
}
setup_repos() {
# Format description so only the first word keeps its case and the rest is
# lowercased
repo_desc_formatted=$(echo "$active_repo_description" | \
sed 's/\([^ ]*\)\(.*\)/\1\L\2/')
# Defaults for unstable and prerelease repos when no custom paths are set
case "$repo_mode" in
prerelease|unstable)
if [ -z "$repo_rpm_pathname_set" ]; then
repo_rpm_pathname=""
repo_rpm_pathname_set=1
fi
if [ -z "$repo_deb_pathname_set" ]; then
repo_deb_pathname=""
repo_deb_pathname_set=1
fi
;;
esac
# Construct auth URL if credentials provided
repo_auth_url="$active_repo_download"
@@ -407,11 +457,18 @@ setup_repos() {
case "$package_type" in
rpm)
echo " Installing Webmin developers key .."
rpm --import "$repo_key"
echo " Installing $repo_key_name key .."
mkdir -p "/etc/pki/rpm-gpg"
cp -f "$repo_key" \
"/etc/pki/rpm-gpg/RPM-GPG-KEY-$repo_key_suffix"
combined_key="/etc/pki/rpm-gpg/RPM-GPG-KEY-$repo_key_suffix"
# Build a single keyring file from all the key files, making sure each key
# ends with a newline so armor blocks stay separated
{
for key in $repo_key; do
cat "$key"
printf '\n'
done
} > "$combined_key"
rpm --import "$combined_key"
echo " .. done"
# Configure packages extra preferences if given
if [ -n "$repo_pkg_prefs" ]; then
@@ -441,14 +498,14 @@ setup_repos() {
fi
# Configure the repository
echo " Setting up ${repo_desc_formatted} repository .."
if [ "$repo_mode" = "stable" ]; then
repo_url="$active_repo_download/download/newkey/yum"
if [ -z "$repo_rpm_pathname_set" ]; then
repo_url="$active_repo_download$repo_rpm_pathname"
else
repo_url="$repo_auth_url"
repo_url="$repo_auth_url$repo_rpm_pathname"
fi
repo_extra_opts_caller=$(rpm_repo_prefs)
cat << EOF > "$rpm_repo_file"
[$active_repo_name-noarch]
[$active_repo_name]
name=$active_repo_description
baseurl=$repo_url
enabled=1
@@ -469,10 +526,16 @@ EOF
rm -f \
"/usr/share/keyrings/debian-$repo_key_suffix.gpg" \
"/usr/share/keyrings/$repoid_debian_like-$repo_key_suffix.gpg"
echo " Installing Webmin developers key .."
gpg --import "$repo_key" 1>/dev/null 2>&1
gpg --dearmor < "$repo_key" \
> "/usr/share/keyrings/$repoid_debian_like-$repo_key_suffix.gpg"
echo " Installing $repo_key_name key .."
combined_keyring="/usr/share/keyrings/$repoid_debian_like-$repo_key_suffix.gpg"
# Build a single keyring file from all the key files, making sure each key
# ends with a newline so armor blocks stay separated
{
for key in $repo_key; do
cat "$key"
printf '\n'
done
} | gpg --dearmor > "$combined_keyring"
post_status $?
# Set correct permissions on the repo key in case the system uses a restrictive umask
chmod 644 "/usr/share/keyrings/$repoid_debian_like-$repo_key_suffix.gpg"
@@ -522,12 +585,12 @@ EOF
fi
# Configure the repository
echo " Setting up ${repo_desc_formatted} repository .."
if [ "$repo_mode" = "stable" ]; then
if [ -z "$repo_deb_pathname_set" ]; then
repo_line="deb [signed-by=/usr/share/keyrings/$repoid_debian_like-$repo_key_suffix.gpg] \
$active_repo_download/download/newkey/repository $repo_dist $repo_section"
$active_repo_download$repo_deb_pathname $repo_dist $repo_section"
else
repo_line="deb [signed-by=/usr/share/keyrings/$repoid_debian_like-$repo_key_suffix.gpg] \
$active_repo_download $repo_dist $repo_component"
$active_repo_download$repo_deb_pathname $repo_dist $repo_component"
fi
echo "$repo_line" > "$debian_repo_file"

View File

@@ -180,6 +180,12 @@ $in{'passreset_timeout'} =~ /^\d+$/ && $in{'passreset_timeout'} > 0 ||
&error($text{'session_epassreset_timeout'});
$gconfig{'passreset_timeout'} = $in{'passreset_timeout'};
# RPC timeout
my $rpc_timeout = $in{'rpc_timeout'};
$rpc_timeout =~ /^\d+$/ && $rpc_timeout > 0 ||
&error($text{'session_erpc_timeout'});
$gconfig{'rpc_timeout'} = $rpc_timeout;
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");

View File

@@ -64,7 +64,9 @@ $fromdef = "webmin-noreply\@".&mailboxes::get_from_domain();
print &ui_table_row($text{'sendmail_from'},
&ui_opt_textbox("from", $from, 40,
&text('sendmail_fromdef', $fromdef)."<br>",
$text{'sendmail_fromaddr'}));
$text{'sendmail_fromaddr'})." ".
$text{'sendmail_name'}." ".
&ui_textbox("from_name", $mconfig{'webmin_from_name'}, 30), 3);
# Default to address for notifications
$to = $gconfig{'webmin_email_to'};

View File

@@ -174,6 +174,11 @@ print &ui_table_row($text{'session_md5'},
[ 2, $text{'session_sha512'}."<br>" ],
[ 3, $text{'session_yescrypt'} ] ]));
# RPC timeout
print &ui_table_row(&hlink($text{'session_rpc_timeout'}, 'rpc_timeout'),
&ui_textbox("rpc_timeout", $gconfig{'rpc_timeout'} || 60, 3).
" ".$text{'time_seconds'});
print ui_table_end();
print ui_form_end([ [ "save", $text{'save'} ] ]);

View File

@@ -0,0 +1,6 @@
<header>RPC session timeout</header>
Sets how many seconds Webmin keeps an RPC session open while it is waiting with
no activity.
<footer>

View File

@@ -664,6 +664,8 @@ session_pmode0=Always deny users with expired passwords
session_pmode1=Always allow users with expired passwords
session_pmode2=Prompt users with expired passwords to enter a new one
session_md5=Webmin password hashing format
session_rpc_timeout=RPC session timeout
session_erpc_timeout=RPC session timeout is missing or must be a number greater than 0
session_md5off=Determine automatically
session_md5on=Use <tt>MD5</tt> hashing format
session_sha512=Use <tt>SHA512</tt> hashing format
@@ -1105,6 +1107,7 @@ sendmail_authdef=Default (currently Cram-MD5)
sendmail_from=From address for email from Webmin
sendmail_fromdef=Default ($1)
sendmail_fromaddr=Address
sendmail_name=Display name
sendmail_toaddr=Default destination address for notifications
sendmail_to_def=None set
sendmail_etoaddr=Missing or incorrectly formatted destination address

View File

@@ -63,6 +63,7 @@ else {
$in{'from'} =~ /^\S+$/ || &error($text{'sendmail_efrom'});
$mconfig{'webmin_from'} = $in{'from'};
}
$mconfig{'webmin_from_name'} = $in{'from_name'};
# Save to address
if ($in{'to_def'}) {