Skip to content
Permalink
ab5e00e41e
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
executable file 174 lines (167 sloc) 4.14 KB
#!/usr/local/bin/perl
# rpc.cgi
# Handles remote_foreign_require and remote_foreign_call requests from
# other webmin servers. State is preserved by starting a process for each
# session that listens for requests on a named pipe (and dies after a few
# seconds of inactivity)
# access{'rpc'} 0=not allowed 1=allowed 2=allowed if root or admin
BEGIN { push(@INC, "."); };
use WebminCore;
use POSIX;
&init_config();
if ($ENV{'REQUEST_METHOD'} eq 'POST') {
local $got;
local $left = $ENV{'CONTENT_LENGTH'} - length($rawarg);
while($left > 0) {
read(STDIN, $got, $left) > 0 || last;
$rawarg .= $got;
$left = $ENV{'CONTENT_LENGTH'} - length($rawarg);
}
}
else {
$rawarg = $ENV{'QUERY_STRING'};
}
$arg = &unserialise_variable($rawarg);
$| = 1;
print "Content-type: text/plain\n\n";
# Can this user make remote calls?
%access = &get_module_acl();
if ($access{'rpc'} == 0 || $access{'rpc'} == 2 &&
$base_remote_user ne 'admin' && $base_remote_user ne 'root' &&
$base_remote_user ne 'sysadm') {
print &serialise_variable( { 'status' => 0 } );
exit;
}
if ($arg->{'newsession'}) {
# Need to fork a new session-handler process
$fifo1 = &tempname();
$fifo2 = &tempname();
mkfifo($fifo1, 0700);
mkfifo($fifo2, 0700);
if (!fork()) {
# This is the subprocess where execution really happens
$SIG{'ALRM'} = "fifo_timeout";
untie(*STDIN);
untie(*STDOUT);
close(STDIN);
close(STDOUT);
close(miniserv::SOCK);
local $stime = time();
local $rcount = 0;
while(1) {
local ($rawcmd, $cmd, @rv);
alarm($rcount ? 360 : 60);
open(FIFO, $fifo1) || last;
while(<FIFO>) {
$rawcmd .= $_;
}
close(FIFO);
alarm(0);
$cmd = &unserialise_variable($rawcmd);
if ($cmd->{'action'} eq 'quit') {
# time to end this session (after the reply)
@rv = ( { 'time' => time() - $stime } );
}
elsif ($cmd->{'action'} eq 'require') {
# require a library
&foreign_require($cmd->{'module'},
$cmd->{'file'});
@rv = ( { 'session' => [ $fifo1, $fifo2 ] } );
}
elsif ($cmd->{'action'} eq 'call') {
# execute a function
@rv = &foreign_call($cmd->{'module'},
$cmd->{'func'},
@{$cmd->{'args'}});
}
elsif ($cmd->{'action'} eq 'eval') {
# eval some perl code
if ($cmd->{'module'}) {
@rv = eval <<EOF;
package $cmd->{'module'};
$cmd->{'code'}
EOF
}
else {
@rv = eval $cmd->{'code'};
}
}
open(FIFO, ">$fifo2");
if (@rv == 1) {
print FIFO &serialise_variable(
{ 'status' => 1, 'rv' => $rv[0] } );
}
else {
print FIFO &serialise_variable(
{ 'status' => 1, 'arv' => \@rv } );
}
close(FIFO);
last if ($cmd->{'action'} eq 'quit');
$rcount++;
}
unlink($fifo1);
unlink($fifo2);
exit;
}
$session = [ $fifo1, $fifo2 ];
}
else {
# Use the provided session id
$session = $arg->{'session'};
}
if ($arg->{'action'} eq 'ping') {
# Just respond with an OK
print &serialise_variable( { 'status' => 1 } );
}
elsif ($arg->{'action'} eq 'check') {
# Check if some module is supported
print &serialise_variable(
{ 'status' => 1,
'rv' => &foreign_check($arg->{'module'}, undef, undef,
$arg->{'api'}) } );
}
elsif ($arg->{'action'} eq 'config') {
# Get the config for some module
local %config = &foreign_config($arg->{'module'});
print &serialise_variable(
{ 'status' => 1, 'rv' => \%config } );
}
elsif ($arg->{'action'} eq 'write') {
# Transfer data to a local temp file
local $file = $arg->{'file'} ? $arg->{'file'} :
$arg->{'name'} ? &tempname($arg->{'name'}) :
&tempname();
open(FILE, ">$file");
print FILE $arg->{'data'};
close(FILE);
print &serialise_variable(
{ 'status' => 1, 'rv' => $file } );
}
elsif ($arg->{'action'} eq 'read') {
# Transfer data from a file
local ($data, $got);
open(FILE, $arg->{'file'});
while(read(FILE, $got, 1024) > 0) {
$data .= $got;
}
close(FILE);
print &serialise_variable(
{ 'status' => 1, 'rv' => $data } );
}
else {
# Pass the request on to the subprocess
open(FIFO, ">$session->[0]");
print FIFO $rawarg;
close(FIFO);
open(FIFO, $session->[1]);
while(<FIFO>) {
print;
}
close(FIFO);
}
sub fifo_timeout
{
unlink($fifo1);
unlink($fifo2);
exit;
}