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
9 BEGIN { push(@INC, ".."); };
14 if ($ENV{'REQUEST_METHOD'} eq 'POST') {
16 local $left = $ENV{'CONTENT_LENGTH'} - length($rawarg);
18 read(STDIN, $got, $left) > 0 || last;
20 $left = $ENV{'CONTENT_LENGTH'} - length($rawarg);
24 $rawarg = $ENV{'QUERY_STRING'};
26 $arg = &unserialise_variable($rawarg);
28 print "Content-type: text/plain\n\n";
30 # Can this user make remote calls?
31 %access = &get_module_acl();
32 if ($access{'rpc'} == 0 || $access{'rpc'} == 2 &&
33 $base_remote_user ne 'admin' && $base_remote_user ne 'root' &&
34 $base_remote_user ne 'sysadm') {
35 print &serialise_variable( { 'status' => 0 } );
39 if ($arg->{'newsession'}) {
40 # Need to fork a new session-handler process
46 # This is the subprocess where execution really happens
47 $SIG{'ALRM'} = "fifo_timeout";
52 close(miniserv::SOCK);
53 local $stime = time();
56 local ($rawcmd, $cmd, @rv);
57 alarm($rcount ? 360 : 60);
58 open(FIFO, $fifo1) || last;
64 $cmd = &unserialise_variable($rawcmd);
65 if ($cmd->{'action'} eq 'quit') {
66 # time to end this session (after the reply)
67 @rv = ( { 'time' => time() - $stime } );
69 elsif ($cmd->{'action'} eq 'require') {
71 &foreign_require($cmd->{'module'},
73 @rv = ( { 'session' => [ $fifo1, $fifo2 ] } );
75 elsif ($cmd->{'action'} eq 'call') {
77 @rv = &foreign_call($cmd->{'module'},
81 elsif ($cmd->{'action'} eq 'eval') {
83 if ($cmd->{'module'}) {
85 package $cmd->{'module'};
90 @rv = eval $cmd->{'code'};
93 open(FIFO, ">$fifo2");
95 print FIFO &serialise_variable(
96 { 'status' => 1, 'rv' => $rv[0] } );
99 print FIFO &serialise_variable(
100 { 'status' => 1, 'arv' => \@rv } );
103 last if ($cmd->{'action'} eq 'quit');
110 $session = [ $fifo1, $fifo2 ];
113 # Use the provided session id
114 $session = $arg->{'session'};
117 if ($arg->{'action'} eq 'ping') {
118 # Just respond with an OK
119 print &serialise_variable( { 'status' => 1 } );
121 elsif ($arg->{'action'} eq 'check') {
122 # Check if some module is supported
123 print &serialise_variable(
125 'rv' => &foreign_check($arg->{'module'}, undef, undef,
128 elsif ($arg->{'action'} eq 'config') {
129 # Get the config for some module
130 local %config = &foreign_config($arg->{'module'});
131 print &serialise_variable(
132 { 'status' => 1, 'rv' => \%config } );
134 elsif ($arg->{'action'} eq 'write') {
135 # Transfer data to a local temp file
136 local $file = $arg->{'file'} ? $arg->{'file'} :
137 $arg->{'name'} ? &tempname($arg->{'name'}) :
139 open(FILE, ">$file");
140 print FILE $arg->{'data'};
142 print &serialise_variable(
143 { 'status' => 1, 'rv' => $file } );
145 elsif ($arg->{'action'} eq 'read') {
146 # Transfer data from a file
148 open(FILE, $arg->{'file'});
149 while(read(FILE, $got, 1024) > 0) {
153 print &serialise_variable(
154 { 'status' => 1, 'rv' => $data } );
157 # Pass the request on to the subprocess
158 open(FIFO, ">$session->[0]");
161 open(FIFO, $session->[1]);