3 # Handles remote_foreign_require and remote_foreign_call requests from
4 # other webmin servers. State is preserved by starting a process for each
5 # session that listens for requests on a named pipe (and dies after a few
6 # seconds of inactivity)
7 # access{'rpc'} 0=not allowed 1=allowed 2=allowed if root or admin
12 if ($ENV{'REQUEST_METHOD'} eq 'POST') {
14 while(length($rawarg) < $ENV{'CONTENT_LENGTH'}) {
15 read(STDIN, $got, $ENV{'CONTENT_LENGTH'}) > 0 || last;
20 $rawarg = $ENV{'QUERY_STRING'};
22 $arg = &unserialise_variable($rawarg);
24 print "Content-type: text/plain\n\n";
26 # Can this user make remote calls?
27 %access = &get_module_acl();
28 if ($access{'rpc'} == 0 || $access{'rpc'} == 2 &&
29 $base_remote_user ne 'admin' && $base_remote_user ne 'root' &&
30 $base_remote_user ne 'sysadm') {
31 print &serialise_variable( { 'status' => 0 } );
35 if ($arg->{'newsession'}) {
36 # Need to fork a new session-handler process
42 # This is the subprocess where execution really happens
43 $SIG{'ALRM'} = "fifo_timeout";
48 close(miniserv::SOCK);
49 local $stime = time();
51 local ($rawcmd, $cmd, @rv);
53 open(FIFO, $fifo1) || last;
59 $cmd = &unserialise_variable($rawcmd);
60 if ($cmd->{'action'} eq 'quit') {
61 # time to end this session (after the reply)
62 @rv = ( { 'time' => time() - $stime } );
64 elsif ($cmd->{'action'} eq 'require') {
66 &foreign_require($cmd->{'module'},
68 @rv = ( { 'session' => [ $fifo1, $fifo2 ] } );
70 elsif ($cmd->{'action'} eq 'call') {
72 @rv = &foreign_call($cmd->{'module'},
76 elsif ($cmd->{'action'} eq 'eval') {
78 if ($cmd->{'module'}) {
80 package $cmd->{'module'};
85 @rv = eval $cmd->{'code'};
88 open(FIFO, ">$fifo2");
90 print FIFO &serialise_variable(
91 { 'status' => 1, 'rv' => $rv[0] } );
94 print FIFO &serialise_variable(
95 { 'status' => 1, 'arv' => \@rv } );
98 last if ($cmd->{'action'} eq 'quit');
104 $session = [ $fifo1, $fifo2 ];
107 # Use the provided session id
108 $session = $arg->{'session'};
111 if ($arg->{'action'} eq 'ping') {
112 # Just respond with an OK
113 print &serialise_variable( { 'status' => 1 } );
115 elsif ($arg->{'action'} eq 'check') {
116 # Check if some module is supported
117 print &serialise_variable(
119 'rv' => &foreign_check($arg->{'module'}, undef, undef,
122 elsif ($arg->{'action'} eq 'config') {
123 # Get the config for some module
124 local %config = &foreign_config($arg->{'module'});
125 print &serialise_variable(
126 { 'status' => 1, 'rv' => \%config } );
128 elsif ($arg->{'action'} eq 'write') {
129 # Transfer data to a local temp file
130 local $file = $arg->{'file'} ? $arg->{'file'} :
131 $arg->{'name'} ? &tempname($arg->{'name'}) :
133 open(FILE, ">$file");
134 print FILE $arg->{'data'};
136 print &serialise_variable(
137 { 'status' => 1, 'rv' => $file } );
139 elsif ($arg->{'action'} eq 'read') {
140 # Transfer data from a file
142 open(FILE, $arg->{'file'});
143 while(read(FILE, $got, 1024) > 0) {
147 print &serialise_variable(
148 { 'status' => 1, 'rv' => $data } );
151 # Pass the request on to the subprocess
152 open(FIFO, ">$session->[0]");
155 open(FIFO, $session->[1]);