mirror of
https://github.com/webmin/webmin.git
synced 2026-02-03 22:23:28 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70c7ddf3bb | ||
|
|
17764483dc | ||
|
|
cdc1c82e83 | ||
|
|
d29e5aea99 | ||
|
|
c3a2396986 | ||
|
|
da37f364dd | ||
|
|
0342f06fc8 | ||
|
|
ef05252413 | ||
|
|
74f879dc2b | ||
|
|
94cbabea9e | ||
|
|
2634afb859 | ||
|
|
4bf296447e | ||
|
|
cf458db765 | ||
|
|
af7cb99298 |
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,5 +1,19 @@
|
||||
## Changelog
|
||||
|
||||
#### 2.610 (November 23, 2025)
|
||||
* Fix to drop dependency on `IO::Pty` Perl module
|
||||
* Fix `virtual-server` module server-side search to work correctly
|
||||
* Update the Authentic theme to the latest version with various improvements and fixes:
|
||||
- Add a range slider to adjust content page margins more precisely
|
||||
- Add an option to enable rounded corners for content page
|
||||
- Add more customization options for pie charts
|
||||
- Fix to increase clickable area for checkboxes in File Manager
|
||||
- Fix to correct rotation of pin and unpin button for right side slider
|
||||
- Fix color of selected items in the multiselect dropdown
|
||||
- Fix to improve the visibility of disabled checkboxes
|
||||
- Fix to send saved params in the post body when saving theme configuration
|
||||
[More details...](https://github.com/webmin/authentic-theme/releases/tag/26.20)
|
||||
|
||||
#### 2.600 (November 9, 2025)
|
||||
* Add an options to enable the slow query log in the MySQL/MariaDB module [#2560](https://github.com/webmin/webmin/issues/2560)
|
||||
* Add ability to install multiple PHP extensions at once in the PHP Configuration module
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
**Webmin** is a web-based system administration tool for Unix-like servers, and services with about _1,000,000_ yearly installations worldwide. Using it, it is possible to configure operating system internals, such as users, disk quotas, services or configuration files, as well as modify, and control open-source apps, such as BIND DNS Server, Apache HTTP Server, PHP, MySQL, and many more.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://webmin.com/screenshots/#gh-light-mode-only" target="_blank">
|
||||
<img width="1440" alt="Dashboard screenshot" src="https://user-images.githubusercontent.com/4426533/218264253-c08fb45a-8d75-44bf-93b3-37a2ecae3d20.png">
|
||||
<a href="https://webmin.com/screenshots/?theme=light#gh-light-mode-only" target="_blank">
|
||||
<img width="1440" alt="Dashboard screenshot" src="https://github.com/user-attachments/assets/a01d0a78-4130-4665-9284-814955ae1c97">
|
||||
</a>
|
||||
<a href="https://webmin.com/screenshots/#gh-dark-mode-only" target="_blank">
|
||||
<img width="1440" alt="Dashboard screenshot" src="https://user-images.githubusercontent.com/4426533/218265232-31140aa6-ada1-4019-bd75-04240aeabc83.png">
|
||||
<a href="https://webmin.com/screenshots/?theme=dark#gh-dark-mode-only" target="_blank">
|
||||
<img width="1440" alt="Dashboard screenshot" src="https://github.com/user-attachments/assets/da4b90a0-c002-4e10-8b34-5acb251bbec9">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
@@ -291,7 +291,13 @@ return &ui_checkbox("d", $user->{'name'}, "", 0).
|
||||
($ro ? "<b>" : "").
|
||||
&ui_link("$cgi?$param=".&urlize($user->{'name'}),
|
||||
$user->{'name'}).
|
||||
($user->{'twofactor_id'} ? "*" : "").
|
||||
($user->{'twofactor_id'}
|
||||
? &ui_tag('sup', '⚷',
|
||||
{ title => $text{'index_twofactor_enabled'},
|
||||
class => 'twofactor-enabled-icon',
|
||||
style => 'font-size: 11px; margin-left: 5px; cursor: default;'.
|
||||
'display: inline-block; transform: rotate(90deg);' } )
|
||||
: "").
|
||||
($ro ? "</b>" : "").
|
||||
($lck ? "</i>" : "");
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ index_screate=Create a new safe user.
|
||||
index_convert=Convert Unix To Webmin Users
|
||||
index_cert=Request an SSL Certificate
|
||||
index_twofactor=Two-Factor Authentication
|
||||
index_twofactor_enabled=Two-factor authentication is enabled for this user
|
||||
index_certmsg=Click this button to request an SSL certificate that will allow you to securely login to Webmin without having to enter a username and password.
|
||||
index_return=user list
|
||||
index_none=None
|
||||
|
||||
@@ -241,6 +241,7 @@ if ($< == 0) {
|
||||
system("cd $usr_dir && chown -R root:bin .");
|
||||
}
|
||||
system("find $usr_dir -name .git | xargs rm -rf");
|
||||
system("find $usr_dir -name .github | xargs rm -rf");
|
||||
system("find $usr_dir -name RELEASE | xargs rm -rf");
|
||||
system("find $usr_dir -name RELEASE.sh | xargs rm -rf");
|
||||
if (-r "$usr_dir/$mod/EXCLUDE") {
|
||||
|
||||
@@ -263,6 +263,7 @@ my $ucprog = ucfirst($prog);
|
||||
system("/bin/mkdir -p /tmp/makemodulerpm");
|
||||
system("cd $par && /bin/cp -rpL $source_mod /tmp/makemodulerpm/$mod");
|
||||
system("/usr/bin/find /tmp/makemodulerpm -name .git | xargs rm -rf");
|
||||
system("/usr/bin/find /tmp/makemodulerpm -name .github | xargs rm -rf");
|
||||
system("/usr/bin/find /tmp/makemodulerpm -name RELEASE | xargs rm -rf");
|
||||
system("/usr/bin/find /tmp/makemodulerpm -name RELEASE.sh | xargs rm -rf");
|
||||
system("/usr/bin/find /tmp/makemodulerpm -name t | xargs rm -rf");
|
||||
|
||||
60
miniserv.pl
60
miniserv.pl
@@ -227,15 +227,7 @@ if ($rand1 eq $rand2) {
|
||||
|
||||
# Check if we can call sudo
|
||||
if ($config{'sudo'} && &has_command("sudo")) {
|
||||
eval "use IO::Pty";
|
||||
if (!$@) {
|
||||
$use_sudo = 1;
|
||||
}
|
||||
else {
|
||||
push(@startup_msg,
|
||||
"Perl module IO::Pty needed for calling sudo is not ".
|
||||
"installed : $@");
|
||||
}
|
||||
$use_sudo = 1;
|
||||
}
|
||||
|
||||
# init days and months for http_date
|
||||
@@ -6042,7 +6034,7 @@ sub check_sudo_permissions
|
||||
{
|
||||
local ($user, $pass) = @_;
|
||||
|
||||
# First try the pipes
|
||||
# First try the cache stored by the main process
|
||||
if ($PASSINw) {
|
||||
print DEBUG "check_sudo_permissions: querying cache for $user\n";
|
||||
print $PASSINw "readsudo $user\n";
|
||||
@@ -6054,27 +6046,18 @@ if ($PASSINw) {
|
||||
}
|
||||
}
|
||||
|
||||
local $ptyfh = new IO::Pty;
|
||||
print DEBUG "check_sudo_permissions: ptyfh=$ptyfh\n";
|
||||
if (!$ptyfh) {
|
||||
&log_error("Failed to create new PTY with IO::Pty");
|
||||
return 0;
|
||||
}
|
||||
local @uinfo = getpwnam($user);
|
||||
# Setup pipes for communication with the sudo sub-process
|
||||
pipe(SUDOINr, SUDOINw);
|
||||
pipe(SUDOOUTr, SUDOOUTw);
|
||||
print DEBUG "check_sudo_permissions\n";
|
||||
|
||||
my @uinfo = getpwnam($user);
|
||||
if (!@uinfo) {
|
||||
&log_error("Unix user $user does not exist for sudo");
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Execute sudo in a sub-process, via a pty
|
||||
local $ttyfh = $ptyfh->slave();
|
||||
print DEBUG "check_sudo_permissions: ttyfh=$ttyfh\n";
|
||||
local $tty = $ptyfh->ttyname();
|
||||
print DEBUG "check_sudo_permissions: tty=$tty\n";
|
||||
chown($uinfo[2], $uinfo[3], $tty);
|
||||
pipe(SUDOr, SUDOw);
|
||||
print DEBUG "check_sudo_permissions: about to fork..\n";
|
||||
local $pid = fork();
|
||||
my $pid = fork();
|
||||
print DEBUG "check_sudo_permissions: fork=$pid pid=$$\n";
|
||||
if ($pid < 0) {
|
||||
&log_error("fork for sudo failed : $!");
|
||||
@@ -6089,40 +6072,37 @@ if (!$pid) {
|
||||
$ENV{'USER'} = $ENV{'LOGNAME'} = $user;
|
||||
$ENV{'HOME'} = $uinfo[7];
|
||||
|
||||
$ptyfh->make_slave_controlling_terminal();
|
||||
close(STDIN); close(STDOUT); close(STDERR);
|
||||
untie(*STDIN); untie(*STDOUT); untie(*STDERR);
|
||||
close($PASSINw); close($PASSOUTr);
|
||||
close(SUDOw);
|
||||
close(SUDOINw); close(SUDOOUTr);
|
||||
close(SOCK);
|
||||
close(MAIN);
|
||||
open(STDIN, "<&SUDOr");
|
||||
open(STDOUT, ">$tty");
|
||||
open(STDIN, "<&SUDOINr");
|
||||
open(STDOUT, ">&SUDOOUTw");
|
||||
open(STDERR, ">&STDOUT");
|
||||
close($ptyfh);
|
||||
exec("sudo -l -S");
|
||||
print "Exec failed : $!\n";
|
||||
exit 1;
|
||||
}
|
||||
print DEBUG "check_sudo_permissions: pid=$pid\n";
|
||||
close(SUDOr);
|
||||
$ptyfh->close_slave();
|
||||
close(SUDOINr);
|
||||
close(SUDOOUTw);
|
||||
|
||||
# Send password, and get back response
|
||||
local $oldfh = select(SUDOw);
|
||||
my $oldfh = select(SUDOINw);
|
||||
$| = 1;
|
||||
select($oldfh);
|
||||
print DEBUG "check_sudo_permissions: about to send pass\n";
|
||||
local $SIG{'PIPE'} = 'ignore'; # Sometimes sudo doesn't ask for a password
|
||||
print SUDOw $pass,"\n";
|
||||
print SUDOINw $pass,"\n";
|
||||
print DEBUG "check_sudo_permissions: sent pass=$pass\n";
|
||||
close(SUDOw);
|
||||
local $out;
|
||||
while(<$ptyfh>) {
|
||||
close(SUDOINw);
|
||||
my $out;
|
||||
while(<SUDOOUTr>) {
|
||||
print DEBUG "check_sudo_permissions: got $_";
|
||||
$out .= $_;
|
||||
}
|
||||
close($ptyfh);
|
||||
close(SUDOOUTr);
|
||||
kill('KILL', $pid);
|
||||
waitpid($pid, 0);
|
||||
local ($ok) = ($out =~ /\(ALL\)\s+ALL|\(ALL\)\s+NOPASSWD:\s+ALL|\(ALL\s*:\s*ALL\)\s+ALL|\(ALL\s*:\s*ALL\)\s+NOPASSWD:\s+ALL/ ? 1 : 0);
|
||||
|
||||
@@ -158,6 +158,51 @@ $out =~ s/^\s+//g; $out =~ s/\s+$//g;
|
||||
return split(/\s+/, $out);
|
||||
}
|
||||
|
||||
# linux_openpty()
|
||||
# Linux-only, pure-Perl openpty(3)-style helper.
|
||||
# Returns master fh, slave fh, slave path, and ioctl value on success
|
||||
sub linux_openpty
|
||||
{
|
||||
|
||||
require Fcntl; Fcntl->import(qw(O_RDWR));
|
||||
require POSIX; POSIX->import(qw(setsid));
|
||||
|
||||
# Linux ioctl values
|
||||
my $TIOCGPTN = 0x80045430; # get pty number
|
||||
my $TIOCSPTLCK = 0x40045431; # unlock slave
|
||||
my $TIOCSCTTY = 0x540E; # set controlling tty
|
||||
|
||||
my ($ptmx, $ttyfh);
|
||||
|
||||
# Open PTY master
|
||||
sysopen($ptmx, "/dev/ptmx", O_RDWR) || return;
|
||||
|
||||
# Unlock the slave
|
||||
my $lock = pack("i", 0);
|
||||
ioctl($ptmx, $TIOCSPTLCK, $lock) || do {
|
||||
close($ptmx);
|
||||
return;
|
||||
};
|
||||
|
||||
# Get slave number
|
||||
my $buf = pack("i", 0);
|
||||
ioctl($ptmx, $TIOCGPTN, $buf) || do {
|
||||
close($ptmx);
|
||||
return;
|
||||
};
|
||||
my $n = unpack("i", $buf);
|
||||
|
||||
# Open PTY slave
|
||||
my $tty = "/dev/pts/$n";
|
||||
open($ttyfh, "+<", $tty) || do {
|
||||
close($ptmx);
|
||||
return;
|
||||
};
|
||||
|
||||
# Return master fh, slave fh, slave path, ioctl value
|
||||
return ($ptmx, $ttyfh, $tty, $TIOCSCTTY);
|
||||
}
|
||||
|
||||
# get_new_pty()
|
||||
# Returns the filehandles and names for a pty and tty
|
||||
sub get_new_pty
|
||||
|
||||
@@ -261,17 +261,19 @@ if (&is_readonly_mode()) {
|
||||
&webmin_debug_log('CMD', "cmd=$cmd uid=$uid gid=$gid")
|
||||
if ($gconfig{'debug_what_cmd'});
|
||||
|
||||
my ($ptyfh, $ttyfh, $pty, $tty, $TIOCSCTTY);
|
||||
|
||||
eval "use IO::Pty";
|
||||
if (!$@) {
|
||||
# Use the IO::Pty perl module if installed
|
||||
local $ptyfh = new IO::Pty;
|
||||
$ptyfh = new IO::Pty;
|
||||
if (!$ptyfh) {
|
||||
&error("Failed to create new PTY with IO::Pty");
|
||||
}
|
||||
local $pid = fork();
|
||||
if (!$pid) {
|
||||
local $ttyfh = $ptyfh->slave();
|
||||
local $tty = $ptyfh->ttyname();
|
||||
$ttyfh = $ptyfh->slave();
|
||||
$tty = $ptyfh->ttyname();
|
||||
if (defined(&close_controlling_pty)) {
|
||||
&close_controlling_pty();
|
||||
}
|
||||
@@ -311,9 +313,57 @@ if (!$@) {
|
||||
$ptyfh->close_slave();
|
||||
return ($ptyfh, $pid);
|
||||
}
|
||||
elsif (defined &linux_openpty &&
|
||||
do { ($ptyfh, $ttyfh, $tty, $TIOCSCTTY) = linux_openpty(); $ptyfh }) {
|
||||
# Use pure-Perl Linux fallback
|
||||
my $pid = fork();
|
||||
if (!$pid) {
|
||||
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);
|
||||
|
||||
# Turn off echoing, if we can
|
||||
eval "use IO::Stty";
|
||||
if (!$@) {
|
||||
IO::Stty::stty($ttyfh, 'raw', '-echo');
|
||||
}
|
||||
|
||||
close(STDIN); close(STDOUT); close(STDERR);
|
||||
untie(*STDIN); untie(*STDOUT); untie(*STDERR);
|
||||
if ($uid) {
|
||||
my $username = getpwuid($uid);
|
||||
&switch_to_unix_user([ $username, undef, $uid, $gid ]);
|
||||
}
|
||||
|
||||
open(STDIN, "<&".fileno($ttyfh));
|
||||
open(STDOUT, ">&".fileno($ttyfh));
|
||||
open(STDERR, ">&".fileno($ttyfh));
|
||||
close($ttyfh);
|
||||
|
||||
if ($binary) {
|
||||
my @args = &split_quoted_string($cmd);
|
||||
my $args0 = $args[0];
|
||||
$args[0] = $binary;
|
||||
exec { $args0 } @args;
|
||||
}
|
||||
else {
|
||||
exec($cmd);
|
||||
}
|
||||
print STDERR "Exec failed : $!\n";
|
||||
exit 1;
|
||||
}
|
||||
close($ttyfh);
|
||||
return ($ptyfh, $pid);
|
||||
}
|
||||
else {
|
||||
# Need to create a PTY using built-in Webmin code
|
||||
local ($ptyfh, $ttyfh, $pty, $tty) = &get_new_pty();
|
||||
($ptyfh, $ttyfh, $pty, $tty) = &get_new_pty();
|
||||
$tty || &error("Failed to create new PTY - try installing the IO::Tty Perl module");
|
||||
local $pid = fork();
|
||||
if (!$pid) {
|
||||
|
||||
@@ -40,8 +40,8 @@ else {
|
||||
# All reasonable modules
|
||||
@mods = &get_available_module_infos();
|
||||
}
|
||||
@mods = grep { !$_->{'clone'} && !$_->{'hidden'} }
|
||||
grep { !$_->{'noui'} && !$_->{$pn.'_noui'} } @mods;
|
||||
@mods = grep { !($_->{clone} || $_->{noui} || ($pn && $_->{"${pn}_noui"})) &&
|
||||
(($_->{hidden} // 0) != 1) } @mods;
|
||||
@mods = sort { $b->{'longdesc'} cmp $a->{'longdesc'} } @mods;
|
||||
foreach my $m (@mods) {
|
||||
if ($m->{'desc'} =~ /\Q$re\E/i) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
xterm=xterm-256color
|
||||
fontsize=15
|
||||
fontsize=14
|
||||
base_port=555
|
||||
rcfile=0
|
||||
locale=0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
xterm=Set <tt>TERM</tt> environmental variable to,4,xterm+256color-xterm-256color,xterm+16color-xterm-16color,xterm-xterm,vt102-vt102,vt100-vt100,vt52-vt52,rxvt-rxvt,nsterm-nsterm,dtterm-dtterm,ansi-ansi
|
||||
size=Terminal width and height in characters,3,Automatic,5,,,Static (80x24)
|
||||
fontsize=Adjust font size,4,0-Auto,12-Small,15-Normal,18-Large,21-Huge
|
||||
fontsize=Adjust font size,4,0-Auto,12-Small,14-Normal,16-Large,18-Huge
|
||||
locale=Set shell character encoding,10,0-Shell default,1-<tt>en_US.UTF-8</tt>,Custom
|
||||
rcfile=Execute initialization commands from file,10,0-Shell default,1-Module default,Custom
|
||||
screen_reader=Enable screen reader mode,1,true-Yes,false-No
|
||||
|
||||
@@ -6,7 +6,7 @@ require './xterm-lib.pl';
|
||||
$ENV{'HTTP_WEBMIN_PATH'} && &error($text{'index_eproxy'});
|
||||
|
||||
# Check for needed modules
|
||||
my @modnames = ("Digest::SHA", "Digest::MD5", "IO::Pty",
|
||||
my @modnames = ("Digest::SHA", "Digest::MD5",
|
||||
"IO::Select", "Time::HiRes",
|
||||
"Net::WebSocket::Server");
|
||||
foreach my $modname (@modnames) {
|
||||
@@ -55,7 +55,7 @@ my $def_cols_n = 80;
|
||||
my $def_rows_n = 24;
|
||||
my $xmlhr = $ENV{'HTTP_X_REQUESTED_WITH'} eq "XMLHttpRequest";
|
||||
my %term_opts;
|
||||
my $font_size = $config{'fontsize'} || 15;
|
||||
my $font_size = $config{'fontsize'} || 14;
|
||||
|
||||
# Parse module config
|
||||
my ($conf_cols_n, $conf_rows_n) = ($conf_size_str =~ /([\d]+)X([\d]+)/i);
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user