mirror of
https://github.com/webmin/webmin.git
synced 2026-02-03 06:03:28 +00:00
Remove dependency on IO::Pty for calling sudo
https://github.com/webmin/webmin/issues/2587
This commit is contained in:
60
miniserv.pl
60
miniserv.pl
@@ -227,15 +227,7 @@ if ($rand1 eq $rand2) {
|
|||||||
|
|
||||||
# Check if we can call sudo
|
# Check if we can call sudo
|
||||||
if ($config{'sudo'} && &has_command("sudo")) {
|
if ($config{'sudo'} && &has_command("sudo")) {
|
||||||
eval "use IO::Pty";
|
$use_sudo = 1;
|
||||||
if (!$@) {
|
|
||||||
$use_sudo = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
push(@startup_msg,
|
|
||||||
"Perl module IO::Pty needed for calling sudo is not ".
|
|
||||||
"installed : $@");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# init days and months for http_date
|
# init days and months for http_date
|
||||||
@@ -6042,7 +6034,7 @@ sub check_sudo_permissions
|
|||||||
{
|
{
|
||||||
local ($user, $pass) = @_;
|
local ($user, $pass) = @_;
|
||||||
|
|
||||||
# First try the pipes
|
# First try the cache stored by the main process
|
||||||
if ($PASSINw) {
|
if ($PASSINw) {
|
||||||
print DEBUG "check_sudo_permissions: querying cache for $user\n";
|
print DEBUG "check_sudo_permissions: querying cache for $user\n";
|
||||||
print $PASSINw "readsudo $user\n";
|
print $PASSINw "readsudo $user\n";
|
||||||
@@ -6054,27 +6046,18 @@ if ($PASSINw) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local $ptyfh = new IO::Pty;
|
# Setup pipes for communication with the sudo sub-process
|
||||||
print DEBUG "check_sudo_permissions: ptyfh=$ptyfh\n";
|
pipe(SUDOINr, SUDOINw);
|
||||||
if (!$ptyfh) {
|
pipe(SUDOOUTr, SUDOOUTw);
|
||||||
&log_error("Failed to create new PTY with IO::Pty");
|
print DEBUG "check_sudo_permissions\n";
|
||||||
return 0;
|
|
||||||
}
|
my @uinfo = getpwnam($user);
|
||||||
local @uinfo = getpwnam($user);
|
|
||||||
if (!@uinfo) {
|
if (!@uinfo) {
|
||||||
&log_error("Unix user $user does not exist for sudo");
|
&log_error("Unix user $user does not exist for sudo");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Execute sudo in a sub-process, via a pty
|
my $pid = fork();
|
||||||
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();
|
|
||||||
print DEBUG "check_sudo_permissions: fork=$pid pid=$$\n";
|
print DEBUG "check_sudo_permissions: fork=$pid pid=$$\n";
|
||||||
if ($pid < 0) {
|
if ($pid < 0) {
|
||||||
&log_error("fork for sudo failed : $!");
|
&log_error("fork for sudo failed : $!");
|
||||||
@@ -6089,40 +6072,37 @@ if (!$pid) {
|
|||||||
$ENV{'USER'} = $ENV{'LOGNAME'} = $user;
|
$ENV{'USER'} = $ENV{'LOGNAME'} = $user;
|
||||||
$ENV{'HOME'} = $uinfo[7];
|
$ENV{'HOME'} = $uinfo[7];
|
||||||
|
|
||||||
$ptyfh->make_slave_controlling_terminal();
|
|
||||||
close(STDIN); close(STDOUT); close(STDERR);
|
close(STDIN); close(STDOUT); close(STDERR);
|
||||||
untie(*STDIN); untie(*STDOUT); untie(*STDERR);
|
untie(*STDIN); untie(*STDOUT); untie(*STDERR);
|
||||||
close($PASSINw); close($PASSOUTr);
|
close(SUDOINw); close(SUDOOUTr);
|
||||||
close(SUDOw);
|
|
||||||
close(SOCK);
|
close(SOCK);
|
||||||
close(MAIN);
|
close(MAIN);
|
||||||
open(STDIN, "<&SUDOr");
|
open(STDIN, "<&SUDOINr");
|
||||||
open(STDOUT, ">$tty");
|
open(STDOUT, ">&SUDOOUTw");
|
||||||
open(STDERR, ">&STDOUT");
|
open(STDERR, ">&STDOUT");
|
||||||
close($ptyfh);
|
|
||||||
exec("sudo -l -S");
|
exec("sudo -l -S");
|
||||||
print "Exec failed : $!\n";
|
print "Exec failed : $!\n";
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
print DEBUG "check_sudo_permissions: pid=$pid\n";
|
print DEBUG "check_sudo_permissions: pid=$pid\n";
|
||||||
close(SUDOr);
|
close(SUDOINr);
|
||||||
$ptyfh->close_slave();
|
close(SUDOOUTw);
|
||||||
|
|
||||||
# Send password, and get back response
|
# Send password, and get back response
|
||||||
local $oldfh = select(SUDOw);
|
my $oldfh = select(SUDOINw);
|
||||||
$| = 1;
|
$| = 1;
|
||||||
select($oldfh);
|
select($oldfh);
|
||||||
print DEBUG "check_sudo_permissions: about to send pass\n";
|
print DEBUG "check_sudo_permissions: about to send pass\n";
|
||||||
local $SIG{'PIPE'} = 'ignore'; # Sometimes sudo doesn't ask for a password
|
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";
|
print DEBUG "check_sudo_permissions: sent pass=$pass\n";
|
||||||
close(SUDOw);
|
close(SUDOINw);
|
||||||
local $out;
|
my $out;
|
||||||
while(<$ptyfh>) {
|
while(<SUDOOUTr>) {
|
||||||
print DEBUG "check_sudo_permissions: got $_";
|
print DEBUG "check_sudo_permissions: got $_";
|
||||||
$out .= $_;
|
$out .= $_;
|
||||||
}
|
}
|
||||||
close($ptyfh);
|
close(SUDOOUTr);
|
||||||
kill('KILL', $pid);
|
kill('KILL', $pid);
|
||||||
waitpid($pid, 0);
|
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);
|
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user