BackupPC_Admin_SCGI (BackupPC-4.3.2) | : | BackupPC_Admin_SCGI (BackupPC-4.4.0) | ||
---|---|---|---|---|
skipping to change at line 51 | skipping to change at line 51 | |||
# This program is distributed in the hope that it will be useful, | # This program is distributed in the hope that it will be useful, | |||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
# GNU General Public License for more details. | # GNU General Public License for more details. | |||
# | # | |||
# You should have received a copy of the GNU General Public License | # You should have received a copy of the GNU General Public License | |||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
# | # | |||
#======================================================================== | #======================================================================== | |||
# | # | |||
# Version 4.3.2, released 17 Feb 2020. | # Version 4.4.0, released 20 Jun 2020. | |||
# | # | |||
# See http://backuppc.sourceforge.net. | # See http://backuppc.sourceforge.net. | |||
# | # | |||
#======================================================================== | #======================================================================== | |||
use strict; | use strict; | |||
no utf8; | no utf8; | |||
use lib "__INSTALLDIR__/lib"; | use lib "__INSTALLDIR__/lib"; | |||
use IO::Socket; | use IO::Socket; | |||
use Data::Dumper; | use Data::Dumper; | |||
use POSIX ":sys_wait_h"; | use POSIX ":sys_wait_h"; | |||
use CGI; | use CGI; | |||
use BackupPC::Lib; | use BackupPC::Lib; | |||
use BackupPC::XS; | use BackupPC::XS; | |||
use BackupPC::CGI::Lib qw(:all); | use BackupPC::CGI::Lib qw(:all); | |||
skipping to change at line 80 | skipping to change at line 81 | |||
use BackupPC::CGI::Archive; | use BackupPC::CGI::Archive; | |||
use BackupPC::CGI::ArchiveInfo; | use BackupPC::CGI::ArchiveInfo; | |||
use BackupPC::CGI::Browse; | use BackupPC::CGI::Browse; | |||
use BackupPC::CGI::DeleteBackup; | use BackupPC::CGI::DeleteBackup; | |||
use BackupPC::CGI::DirHistory; | use BackupPC::CGI::DirHistory; | |||
use BackupPC::CGI::EditConfig; | use BackupPC::CGI::EditConfig; | |||
use BackupPC::CGI::EmailSummary; | use BackupPC::CGI::EmailSummary; | |||
use BackupPC::CGI::GeneralInfo; | use BackupPC::CGI::GeneralInfo; | |||
use BackupPC::CGI::HostInfo; | use BackupPC::CGI::HostInfo; | |||
use BackupPC::CGI::LOGlist; | use BackupPC::CGI::LOGlist; | |||
use BackupPC::CGI::Metrics; | ||||
use BackupPC::CGI::Queue; | use BackupPC::CGI::Queue; | |||
use BackupPC::CGI::ReloadServer; | use BackupPC::CGI::ReloadServer; | |||
use BackupPC::CGI::Restore; | use BackupPC::CGI::Restore; | |||
use BackupPC::CGI::RestoreFile; | use BackupPC::CGI::RestoreFile; | |||
use BackupPC::CGI::RestoreInfo; | use BackupPC::CGI::RestoreInfo; | |||
use BackupPC::CGI::StartServer; | use BackupPC::CGI::StartServer; | |||
use BackupPC::CGI::StartStopBackup; | use BackupPC::CGI::StartStopBackup; | |||
use BackupPC::CGI::StopServer; | use BackupPC::CGI::StopServer; | |||
use BackupPC::CGI::Summary; | use BackupPC::CGI::Summary; | |||
use BackupPC::CGI::View; | use BackupPC::CGI::View; | |||
my %ActionDispatch = ( | my %ActionDispatch = ( | |||
"deleteBackup" => "DeleteBackup", | "summary" => "Summary", | |||
"summary" => "Summary", | "Start_Incr_Backup" => "StartStopBackup", | |||
"Start_Incr_Backup" => "StartStopBackup", | "Start_Full_Backup" => "StartStopBackup", | |||
"Start_Full_Backup" => "StartStopBackup", | "Stop_Dequeue_Backup" => "StartStopBackup", | |||
"Stop_Dequeue_Backup" => "StartStopBackup", | "Stop_Dequeue_Archive" => "StartStopBackup", | |||
"Stop_Dequeue_Archive" => "StartStopBackup", | "queue" => "Queue", | |||
"queue" => "Queue", | "view" => "View", | |||
"view" => "View", | "LOGlist" => "LOGlist", | |||
"LOGlist" => "LOGlist", | "emailSummary" => "EmailSummary", | |||
"emailSummary" => "EmailSummary", | "browse" => "Browse", | |||
"browse" => "Browse", | "dirHistory" => "DirHistory", | |||
"dirHistory" => "DirHistory", | "Restore" => "Restore", | |||
"Restore" => "Restore", | "RestoreFile" => "RestoreFile", | |||
"RestoreFile" => "RestoreFile", | "hostInfo" => "HostInfo", | |||
"hostInfo" => "HostInfo", | "generalInfo" => "GeneralInfo", | |||
"generalInfo" => "GeneralInfo", | "restoreInfo" => "RestoreInfo", | |||
"restoreInfo" => "RestoreInfo", | "archiveInfo" => "ArchiveInfo", | |||
"archiveInfo" => "ArchiveInfo", | "Start_Archive" => "Archive", | |||
"Start_Archive" => "Archive", | "Archive" => "Archive", | |||
"Archive" => "Archive", | "Reload" => "ReloadServer", | |||
"Reload" => "ReloadServer", | "startServer" => "StartServer", | |||
"startServer" => "StartServer", | "Stop" => "StopServer", | |||
"Stop" => "StopServer", | "adminOpts" => "AdminOptions", | |||
"adminOpts" => "AdminOptions", | "editConfig" => "EditConfig", | |||
"editConfig" => "EditConfig", | "deleteBackup" => "DeleteBackup", | |||
"keepBackup" => "HostInfo", | ||||
"rss" => "Metrics", | ||||
"metrics" => "Metrics", | ||||
); | ); | |||
my %ChildPid2Num; | my %ChildPid2Num; | |||
BEGIN { | BEGIN { | |||
eval "use SCGI;"; | eval "use SCGI;"; | |||
if ( $@ ) { | if ( $@ ) { | |||
print("BackupPC_Admin_SCGI: can't load perl SCGI module - install via CP AN; exiting in 60 seconds\n"); | print("BackupPC_Admin_SCGI: can't load perl SCGI module - install via CP AN; exiting in 60 seconds\n"); | |||
# | # | |||
# if we exit immediately, BackupPC will restart us immediately | # if we exit immediately, BackupPC will restart us immediately | |||
# | # | |||
sleep(60); | sleep(60); | |||
exit(1); | exit(1); | |||
} | } | |||
eval "use BackupPC::CGI::RSS;"; | ||||
if ( !$@ ) { | ||||
$ActionDispatch{rss} = "RSS"; | ||||
} | ||||
} | } | |||
# | # | |||
# Edit this if you want to get more information about each request | # Edit this if you want to get more information about each request | |||
# | # | |||
my $LogLevel = 0; | my $LogLevel = 0; | |||
$Cgi = new CGI; | $Cgi = new CGI; | |||
die("BackupPC::Lib->new failed\n") if ( !($bpc = BackupPC::Lib->new) ); | die("BackupPC::Lib->new failed\n") if ( !($bpc = BackupPC::Lib->new) ); | |||
$TopDir = $bpc->TopDir(); | $TopDir = $bpc->TopDir(); | |||
$LogDir = $bpc->LogDir(); | $LogDir = $bpc->LogDir(); | |||
$BinDir = $bpc->BinDir(); | $BinDir = $bpc->BinDir(); | |||
%Conf = $bpc->Conf(); | %Conf = $bpc->Conf(); | |||
$Lang = $bpc->Lang(); | $Lang = $bpc->Lang(); | |||
$ConfigMTime = $bpc->ConfigMTime(); | $ConfigMTime = $bpc->ConfigMTime(); | |||
umask($Conf{UmaskMode}); | umask($Conf{UmaskMode}); | |||
my $LockFile = "$LogDir/scgi_lock"; | my $LockFile = "$LogDir/scgi_lock"; | |||
my $LockFileSz = 2048; | my $LockFileSz = 2048; | |||
my $ChildExited = 0; | my $ChildExited = 0; | |||
$SIG{INT} = \&childKill; | $SIG{INT} = \&childKill; | |||
$SIG{CHLD} = \&childCleanup; | $SIG{CHLD} = \&childCleanup; | |||
my $socket = IO::Socket::INET->new(Listen => 5, ReuseAddr => 1, | my $socket = IO::Socket::INET->new( | |||
LocalAddr => 'localhost', | Listen => 5, | |||
LocalPort => $Conf{SCGIServerPort} || 8199) | ReuseAddr => 1, | |||
or die "cannot bind to port $Conf{SCGIServerPort}: $!"; | LocalAddr => 'localhost', | |||
LocalPort => $Conf{SCGIServerPort} || 8199 | ||||
) or die "cannot bind to port $Conf{SCGIServerPort}: $!"; | ||||
my $scgi = SCGI->new($socket, blocking => 1); | my $scgi = SCGI->new($socket, blocking => 1); | |||
# | # | |||
# Clean up %ENV for taint checking | # Clean up %ENV for taint checking | |||
# | # | |||
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; | delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; | |||
$ENV{PATH} = $Conf{MyPath}; | $ENV{PATH} = $Conf{MyPath}; | |||
# | # | |||
skipping to change at line 223 | skipping to change at line 226 | |||
sleep(60); | sleep(60); | |||
exit(1); | exit(1); | |||
} | } | |||
my $LockFdNum = fileno($LockFd); | my $LockFdNum = fileno($LockFd); | |||
while ( 1 ) { | while ( 1 ) { | |||
if ( BackupPC::XS::DirOps::lockRangeFd($LockFdNum, 1, $MaxChild, 1) ) { | if ( BackupPC::XS::DirOps::lockRangeFd($LockFdNum, 1, $MaxChild, 1) ) { | |||
if ( $ChildExited ) { | if ( $ChildExited ) { | |||
$ChildExited = 0; | $ChildExited = 0; | |||
# | # | |||
# If a second child dies while in the signal handler caused by the | # If a second child dies while in the signal handler caused by the | |||
# first death, we won’t get another signal. So we must do a non-bloc king | # first death, we won't get another signal. So we must do a non-bloc king | |||
# loop here else we will leave the unreaped child as a zombie. And | # loop here else we will leave the unreaped child as a zombie. And | |||
# the next time two children die we get another zombie. And so on. | # the next time two children die we get another zombie. And so on. | |||
# | # | |||
# As we reap each child, we start another one in the same slot. | # As we reap each child, we start another one in the same slot. | |||
# | # | |||
while ( (my $child = waitpid(-1, WNOHANG)) > 0 ) { | while ( (my $child = waitpid(-1, WNOHANG)) > 0 ) { | |||
print("BackupPC_Admin_SCGI: child $child exited ($!)\n") | print("BackupPC_Admin_SCGI: child $child exited ($!)\n") | |||
if ( $LogLevel >= 3 ); | if ( $LogLevel >= 3 ); | |||
if ( defined($ChildPid2Num{$child}) ) { | if ( defined($ChildPid2Num{$child}) ) { | |||
childRun($ChildPid2Num{$child}); | childRun($ChildPid2Num{$child}); | |||
} | } | |||
} | } | |||
next; | next; | |||
} | } | |||
print("BackupPC_Admin_SCGI: parent lock failed ($!)... continuing\n") | print("BackupPC_Admin_SCGI: parent lock failed ($!)... continuing\n") | |||
if ( $LogLevel >= 3 ); | if ( $LogLevel >= 3 ); | |||
sleep(1); | sleep(1); | |||
next; | next; | |||
} | } | |||
BackupPC::XS::DirOps::unlockRangeFd($LockFdNum, 1, $MaxChild); | BackupPC::XS::DirOps::unlockRangeFd($LockFdNum, 1, $MaxChild); | |||
print("BackupPC_Admin_SCGI: all children busy... starting a new child $MaxCh ild\n") | print("BackupPC_Admin_SCGI: all children busy... starting a new child $MaxCh ild\n") | |||
if ( $LogLevel >= 5 ); | if ( $LogLevel >= 5 ); | |||
if ( $MaxChild >= $LockFileSz - 2 ) { | if ( $MaxChild >= $LockFileSz - 2 ) { | |||
# | # | |||
# Need to extend the lock file size, since we need a lock byte for | # Need to extend the lock file size, since we need a lock byte for | |||
# every child, plus one. | # every child, plus one. | |||
# | # | |||
$LockFileSz *= 2; | $LockFileSz *= 2; | |||
print("BackupPC_Admin_SCGI: extending $LockFile to length $LockFileSz\n" ); | print("BackupPC_Admin_SCGI: extending $LockFile to length $LockFileSz\n" ); | |||
sysseek($LockFd, 0, 0); | sysseek($LockFd, 0, 0); | |||
if ( syswrite($LockFd, chr(0) x $LockFileSz) != $LockFileSz ) { | if ( syswrite($LockFd, chr(0) x $LockFileSz) != $LockFileSz ) { | |||
print("BackupPC_Admin_SCGI: can't write $LockFileSz bytes to $LockFi | print( | |||
le; terminating children and exiting...\n"); | "BackupPC_Admin_SCGI: can't write $LockFileSz bytes to $LockFile | |||
; terminating children and exiting...\n" | ||||
); | ||||
kill 2, keys(%ChildPid2Num); | kill 2, keys(%ChildPid2Num); | |||
sleep(1); | sleep(1); | |||
kill 9, keys(%ChildPid2Num); | kill 9, keys(%ChildPid2Num); | |||
exit(1); | exit(1); | |||
} | } | |||
sysseek($LockFd, 0, 0); | sysseek($LockFd, 0, 0); | |||
} | } | |||
childRun($MaxChild++); | childRun($MaxChild++); | |||
} | } | |||
skipping to change at line 315 | skipping to change at line 320 | |||
print("BackupPC_Admin_SCGI: child $childNum can't open $LockFile; exitin g\n"); | print("BackupPC_Admin_SCGI: child $childNum can't open $LockFile; exitin g\n"); | |||
exit(1); | exit(1); | |||
} | } | |||
$LockFdNum = fileno($LockFd); | $LockFdNum = fileno($LockFd); | |||
while ( 1 ) { | while ( 1 ) { | |||
# | # | |||
# Grab a lock on byte #$childNum to indicate we are idle. | # Grab a lock on byte #$childNum to indicate we are idle. | |||
# | # | |||
if ( BackupPC::XS::DirOps::lockRangeFd($LockFdNum, 1 + $childNum, 1, 1) ) { | if ( BackupPC::XS::DirOps::lockRangeFd($LockFdNum, 1 + $childNum, 1, 1) ) { | |||
print("BackupPC_Admin_SCGI: child $childNum failed to get idle lock ($!)\n") | print("BackupPC_Admin_SCGI: child $childNum failed to get idle lock ($!)\n") | |||
if ( $LogLevel >= 3 ) ; | if ( $LogLevel >= 3 ); | |||
sleep(1); | sleep(1); | |||
next; | next; | |||
} | } | |||
print("BackupPC_Admin_SCGI: child $childNum got idle lock\n") | print("BackupPC_Admin_SCGI: child $childNum got idle lock\n") | |||
if ( $LogLevel >= 5 ); | if ( $LogLevel >= 5 ); | |||
if ( defined($fhWrite) ) { | if ( defined($fhWrite) ) { | |||
# | # | |||
# Now close the pipe write side, so the parent can safely continue. | # Now close the pipe write side, so the parent can safely continue. | |||
# | # | |||
close($fhWrite); | close($fhWrite); | |||
$fhWrite = undef; | $fhWrite = undef; | |||
} | } | |||
# | # | |||
# We use an exclusive lock on byte 0 of the lock file to make sure | # We use an exclusive lock on byte 0 of the lock file to make sure | |||
# only one child does an accept at a time. As we process the | # only one child does an accept at a time. As we process the | |||
# request, another child will get the lock on byte 0 and will accept | # request, another child will get the lock on byte 0 and will accept | |||
# the next request. | # the next request. | |||
# | # | |||
if ( BackupPC::XS::DirOps::lockRangeFd($LockFdNum, 0, 1, 1) ) { | if ( BackupPC::XS::DirOps::lockRangeFd($LockFdNum, 0, 1, 1) ) { | |||
print("BackupPC_Admin_SCGI: child $childNum lock failed ($!)... cont inuing\n") | print("BackupPC_Admin_SCGI: child $childNum lock failed ($!)... cont inuing\n") | |||
if ( $LogLevel >= 3 ); | if ( $LogLevel >= 3 ); | |||
sleep(1); | sleep(1); | |||
next; | next; | |||
} | } | |||
print("BackupPC_Admin_SCGI: child $childNum got accept lock\n") | print("BackupPC_Admin_SCGI: child $childNum got accept lock\n") | |||
if ( $LogLevel >= 5 ); | if ( $LogLevel >= 5 ); | |||
my $request = $scgi->accept; | my $request = $scgi->accept; | |||
BackupPC::XS::DirOps::unlockRangeFd($LockFdNum, 0, 1); | BackupPC::XS::DirOps::unlockRangeFd($LockFdNum, 0, 1); | |||
BackupPC::XS::DirOps::unlockRangeFd($LockFdNum, 1 + $childNum, 1); | BackupPC::XS::DirOps::unlockRangeFd($LockFdNum, 1 + $childNum, 1); | |||
my $iaddr = $request->connection->peeraddr(); | my $iaddr = $request->connection->peeraddr(); | |||
if ( ord($iaddr) != 127 ) { | if ( ord($iaddr) != 127 ) { | |||
# | # | |||
# peer is not a localhost address (ie: 127.0.0.1/8); ignore it | # peer is not a localhost address (ie: 127.0.0.1/8); ignore it | |||
# | # | |||
my $addrStr = join(".", unpack("C*", $iaddr)); | my $addrStr = join(".", unpack("C*", $iaddr)); | |||
printf("BackupPC_Admin_SCGI: unexpected connection from $addrStr (%s ) ignored\n", | printf("BackupPC_Admin_SCGI: unexpected connection from $addrStr (%s ) ignored\n", | |||
gethostbyaddr($iaddr, AF_INET)); | gethostbyaddr($iaddr, AF_INET)); | |||
$request = undef; | $request = undef; | |||
next; | next; | |||
} | } | |||
print("BackupPC_Admin_SCGI: child $childNum processing request\n") | print("BackupPC_Admin_SCGI: child $childNum processing request\n") | |||
if ( $LogLevel >= 5 ); | if ( $LogLevel >= 5 ); | |||
handleRequest($request); | handleRequest($request); | |||
$request = undef; | $request = undef; | |||
select(STDOUT); | select(STDOUT); | |||
print("BackupPC_Admin_SCGI: child $childNum finished request\n") | print("BackupPC_Admin_SCGI: child $childNum finished request\n") | |||
if ( $LogLevel >= 5 ); | if ( $LogLevel >= 5 ); | |||
} | } | |||
} | } | |||
sub handleRequest | sub handleRequest | |||
{ | { | |||
my($request) = @_; | my($request) = @_; | |||
$request->read_env; | $request->read_env; | |||
my $con = $request->connection; | my $con = $request->connection; | |||
read($con, my $body, $request->env->{CONTENT_LENGTH}); | read($con, my $body, $request->env->{CONTENT_LENGTH}); | |||
select($con); | select($con); | |||
NewRequest($request, $body); | NewRequest($request, $body); | |||
if ( $LogLevel >= 4 ) { | if ( $LogLevel >= 4 ) { | |||
my $fdDebug; | my $fdDebug; | |||
open($fdDebug, ">", "$LogDir/request.txt"); | open($fdDebug, ">", "$LogDir/request.txt"); | |||
print $fdDebug "Environment: ", Dumper($request->env), "\n\n"; | print $fdDebug "Environment: ", Dumper($request->env), "\n\n"; | |||
print $fdDebug "Body: ", $body, "\n\n"; | print $fdDebug "Body: ", $body, "\n\n"; | |||
print $fdDebug "Other: ", "User = $User, MyURL = $MyURL, PID = $$, In = | print $fdDebug "Other: ", "User = $User, MyURL = $MyURL, PID = $$, In = | |||
", Dumper(\%In), "Conf = ", Dumper(\%Conf), "\n\n"; | ", Dumper(\%In), "Conf = ", | |||
Dumper(\%Conf), "\n\n"; | ||||
close($fdDebug); | close($fdDebug); | |||
} | } | |||
if ( !defined($ActionDispatch{$In{action}}) ) { | if ( !defined($ActionDispatch{$In{action}}) ) { | |||
$In{action} = defined($In{host}) ? "hostInfo" : "generalInfo"; | $In{action} = defined($In{host}) ? "hostInfo" : "generalInfo"; | |||
} | } | |||
my $action = $ActionDispatch{$In{action}}; | my $action = $ActionDispatch{$In{action}}; | |||
$BackupPC::CGI::{"${action}::"}{action}(); | $BackupPC::CGI::{"${action}::"}{action}(); | |||
} | } | |||
sub NewRequest | sub NewRequest | |||
skipping to change at line 419 | skipping to change at line 425 | |||
$In{$name} = $2; | $In{$name} = $2; | |||
$In{$name} =~ s/\+/ /g; | $In{$name} =~ s/\+/ /g; | |||
$In{$name} =~ s{%(..)}{chr(hex($1))}eg; | $In{$name} =~ s{%(..)}{chr(hex($1))}eg; | |||
} | } | |||
$ENV{SCRIPT_NAME} = $request->env->{SCRIPT_NAME}; | $ENV{SCRIPT_NAME} = $request->env->{SCRIPT_NAME}; | |||
$ENV{REMOTE_USER} = $request->env->{REMOTE_USER}; | $ENV{REMOTE_USER} = $request->env->{REMOTE_USER}; | |||
$ENV{REQUEST_URI} = $request->env->{REQUEST_URI}; | $ENV{REQUEST_URI} = $request->env->{REQUEST_URI}; | |||
if ( $bpc->ConfigMTime() != $ConfigMTime ) { | if ( $bpc->ConfigMTime() != $ConfigMTime ) { | |||
$bpc->ConfigRead(); | $bpc->ConfigRead(); | |||
$TopDir = $bpc->TopDir(); | $TopDir = $bpc->TopDir(); | |||
$LogDir = $bpc->LogDir(); | $LogDir = $bpc->LogDir(); | |||
$BinDir = $bpc->BinDir(); | $BinDir = $bpc->BinDir(); | |||
%Conf = $bpc->Conf(); | %Conf = $bpc->Conf(); | |||
$Lang = $bpc->Lang(); | $Lang = $bpc->Lang(); | |||
$ConfigMTime = $bpc->ConfigMTime(); | $ConfigMTime = $bpc->ConfigMTime(); | |||
umask($Conf{UmaskMode}); | umask($Conf{UmaskMode}); | |||
} | } | |||
# | # | |||
# Default REMOTE_USER so in a miminal installation the user | # Default REMOTE_USER so in a miminal installation the user | |||
# has a sensible default. | # has a sensible default. | |||
# | # | |||
$ENV{REMOTE_USER} = $Conf{BackupPCUser} if ( $ENV{REMOTE_USER} eq "" ); | $ENV{REMOTE_USER} = $Conf{BackupPCUser} if ( $ENV{REMOTE_USER} eq "" ); | |||
# | # | |||
# We require that Apache pass in $ENV{SCRIPT_NAME} and $ENV{REMOTE_USER}. | # We require that Apache pass in $ENV{SCRIPT_NAME} and $ENV{REMOTE_USER}. | |||
# The latter requires .ht_access style authentication. Replace this | # The latter requires .ht_access style authentication. Replace this | |||
# code if you are using some other type of authentication, and have | # code if you are using some other type of authentication, and have | |||
# a different way of getting the user name. | # a different way of getting the user name. | |||
# | # | |||
$MyURL = $ENV{SCRIPT_NAME}; | $MyURL = $ENV{SCRIPT_NAME}; | |||
$User = $ENV{REMOTE_USER}; | $User = $ENV{REMOTE_USER}; | |||
# | # | |||
# Handle LDAP uid=user when using mod_authz_ldap and otherwise untaint | # Handle LDAP uid=user when using mod_authz_ldap and otherwise untaint | |||
# | # | |||
$User = $1 if ( $User =~ /uid=([^,]+)/i || $User =~ /(.*)/ ); | $User = $1 if ( $User =~ /uid=([^,]+)/i || $User =~ /(.*)/ ); | |||
if ( !defined($Hosts) || $bpc->HostsMTime() != $HostsMTime ) { | if ( !defined($Hosts) || $bpc->HostsMTime() != $HostsMTime ) { | |||
$HostsMTime = $bpc->HostsMTime(); | $HostsMTime = $bpc->HostsMTime(); | |||
$Hosts = $bpc->HostInfoRead(); | $Hosts = $bpc->HostInfoRead(); | |||
# turn moreUsers list into a hash for quick lookups | # turn moreUsers list into a hash for quick lookups | |||
foreach my $host (keys %$Hosts) { | foreach my $host ( keys %$Hosts ) { | |||
$Hosts->{$host}{moreUsers} = | $Hosts->{$host}{moreUsers} = | |||
{map {$_, 1} split(",", $Hosts->{$host}{moreUsers}) } | {map { $_, 1 } split(",", $Hosts->{$host}{moreUsers})}; | |||
} | } | |||
} | } | |||
# | # | |||
# Untaint the host name | # Untaint the host name | |||
# | # | |||
if ( $In{host} =~ /^([\w.\s-]+)$/ ) { | if ( $In{host} =~ /^([\w.\s-]+)$/ ) { | |||
$In{host} = $1; | $In{host} = $1; | |||
} else { | } else { | |||
delete($In{host}); | delete($In{host}); | |||
} | } | |||
} | } | |||
sub childCleanup | sub childCleanup | |||
{ | { | |||
$ChildExited = 1; | $ChildExited = 1; | |||
$SIG{CHLD} = \&childCleanup; | $SIG{CHLD} = \&childCleanup; | |||
} | } | |||
sub childKill | sub childKill | |||
End of changes. 28 change blocks. | ||||
77 lines changed or deleted | 83 lines changed or added |