-
-
Notifications
You must be signed in to change notification settings - Fork 117
/
Copy pathremote.cgi
executable file
·130 lines (118 loc) · 3.47 KB
/
remote.cgi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/local/bin/perl
# This program is designed to be called via HTTP requests from programs, and
# simply passes on parameters to a specified command-line program
package virtual_server;
use POSIX;
use Socket;
$trust_unknown_referers = 1;
require './virtual-server-lib.pl';
&ReadParse();
&can_remote($in{'program'}) || &api_error($text{'remote_ecannot'});
if (!$in{'program'}) {
# Tell the user what needs to be done
print "Content-type: text/plain\n\n";
print "This CGI is designed to be invoked by other programs wanting\n";
print "to perform some Virtualmin action programatically, such as\n";
print "creating or modifying domains and users.\n\n";
print "You must supply at least the CGI parameter 'program', which\n";
print "specifies which of the Virtualmin command-line scripts to\n";
print "run. You must also supply appropriate parameters to the\n";
print "program, similar to those that it accepts on the Unix command\n";
print "line. For example, the change the password for a server, you\n";
print "would request a URL like :\n\n";
print "http://yourserver:10000/virtual-server/remote.cgi?program=modify-domain&domain=foo.com&pass=somenewpassword\n\n";
print "All output from the command will be returned to the caller.\n";
exit;
}
# Get output format
$format = exists($in{'json'}) ? 'json' :
exists($in{'xml'}) ? 'xml' :
exists($in{'perl'}) ? 'perl' :
undef;
# Build the arg list
$main::virtualmin_remote_api = 1;
$ENV{'VIRTUALMIN_REMOTE_API'} = 1;
$in{'program'} =~ /^[a-z0-9\.\-]+$/i || &api_error($text{'remote_eprogram'});
$cmd = $dir = undef;
foreach $m ($module_name, "$module_name/pro", @plugins) {
$mdir = &module_root_directory($m);
$mcmd = "$mdir/$in{'program'}.pl";
if (-x $mcmd) {
$cmd = $mcmd;
$dir = $mdir;
}
}
$cmd || &api_error(&text('remote_eprogram2', $in{'program'}));
if ($format && !defined($in{'simple-multiline'})) {
# Always force multiline format, as JSON output makes no sense
# without it
$in{'multiline'} = '';
}
# Build list of command-line args
@args = ( );
foreach $iv (@in) {
($i, $v) = split(/=/, $iv, 2);
$i =~ tr/\+/ /;
$v =~ tr/\+/ /;
$i =~ s/%(..)/pack("c",hex($1))/ge;
$v =~ s/%(..)/pack("c",hex($1))/ge;
next if ($i eq "program" || $i eq $format);
if ($v eq "") {
push(@args, "--$i");
}
else {
push(@args, "--$i", split(/\n/, $v));
}
}
# Print correct MIME type for output format
if ($format eq "xml") {
print "Content-type: application/xml\n\n";
}
elsif ($format eq "json") {
print "Content-type: application/json\n\n";
}
else {
print "Content-type: text/plain\n\n";
}
# Execute the command within the same perl interpreter
socketpair(SUBr, SUBw, AF_UNIX, SOCK_STREAM, PF_UNSPEC);
$pid = &execute_webmin_script($cmd, $mod, \@args, SUBw);
if ($format) {
# Capture and convert to selected format
$err = &check_remote_format($format);
if ($err) {
print "Invalid format $format : $err\n";
exit(0);
}
my $out;
while(<SUBr>) {
$out .= $_;
}
waitpid($pid, 0);
print &convert_remote_format($out, $?, $in{'program'},
\%in, $format, \%config);
}
else {
# Stream output
while(<SUBr>) {
print $_;
}
close(SUBr);
waitpid($pid, 0);
print "\n";
print "Exit status: $?\n";
}
sub api_error
{
print "Content-type: text/plain\n\n";
if ($format) {
$data = { 'status' => 'error',
'error' => join("", @_) };
$ffunc = "create_".$format."_format";
print &$ffunc($data);
}
else {
print "ERROR: ",@_,"\n";
}
CORE::exit(0);
}