forked from wizzat/arsimto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharsimtoREST
executable file
·180 lines (153 loc) · 5.43 KB
/
arsimtoREST
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/perl
# vim: set noexpandtab sw=4 ts=4:
# --
# A recent battle with vim and a Go program finally settled this for me.
# Tabs for indent, spaces for formatting. If you change your shiftwidth and
# tabstop to different values and your code looks ugly, say aloud: tabs
# for indent, spaces for formatting.
# --
# arsimtoREST listens on --port=<whatever> and takes REST URLs and calls
# arsimto with the appropriate flags, then returns the result to the
# client.
# --
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# THIS SCRIPT IS NOT SECURE! It simply passes user input straight through to a
# Unix command run as the executing user. Do not expose this to a port where
# malicious attackers might be able to get to it! It will roll over and give
# them the keys to your kingdom. You have been warned.
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#
# license: gpl v2.
# author: Tim Ellis, CTO Fifth Sigma, Inc.
use strict;
use warnings;
use Socket;
use POSIX qw/strftime/;
# things passed in via arguments
my @extraArgs;
my $listenPort = 14321;
my $listenIP = '0.0.0.0';
my $verbose;
# no arguments passed in? short help.
unless (scalar @ARGV) {
doArgs('short');
exit 255;
}
# if they want an rcfile, must be first arg
my $rcFile = $ENV{"HOME"} . "/.arsimtorc";
if ($ARGV && $ARGV[0] =~ /^-+r(cfile)*=(.+)$/) { $rcFile = $2; }
# read in rcfile if it exists - it'll just be args
if (open (IFILE, "< $rcFile")) {
my $inLine;
while ($inLine = <IFILE>) {
chomp ($inLine);
# must put args from rcfile at start so options passed on the
# commandline will override them
if ($inLine =~ /^-+(\w+)/) {
unshift (@ARGV, $inLine);
}
}
}
# parse input arguments. put anything unparsed onto @extraArgs
foreach my $arg (@ARGV) {
if ($arg =~ /^-+h(elp)*$/) { doArgs('long'); exit 0; }
elsif ($arg =~ /^-+i(p)*=(.+)$/) { $listenIP = $2; }
elsif ($arg =~ /^-+p(ort)*=(.+)$/) { $listenPort = $2; }
elsif ($arg =~ /^-+v(erbose)*$/) { $verbose = 1; }
else { push (@extraArgs, $arg); }
}
# create a socket, make it reusable, bind to it, listen on it
my $sock;
my $queueLen = 10;
socket($sock, PF_INET, SOCK_STREAM, getprotobyname('tcp'))
or die "Can't open socket $!\n";
setsockopt($sock, SOL_SOCKET, SO_REUSEADDR, 1)
or die "Can't set socket option to SO_REUSEADDR $!\n";
bind($sock , sockaddr_in($listenPort, INADDR_ANY))
or die "bind failed : $!";
listen($sock , $queueLen);
print "Server is now listening with queue length $queueLen\n";
#accept incoming connections and talk to clients
while(1)
{
my $client;
my $addrInfo = accept($client , $sock);
my($port, $iaddr) = sockaddr_in($addrInfo);
#my $name = gethostbyaddr($iaddr, AF_INET);
my $sessionNum = int(rand(999999999));
doLog (" - sess=$sessionNum ; connection accepted");
# get from client, set to client!
my $input = <$client>;
my $arsimtoCmdLine = parseURLinput ($input);
doLog (" - sess=$sessionNum ; parsed input as [$arsimtoCmdLine]");
my $output = '';
if ($arsimtoCmdLine =~ /^ERR/) {
$output = $arsimtoCmdLine;
} else {
# prepend args passed to arsimtoREST to call to arsimto
$arsimtoCmdLine = join (" ", @extraArgs) . " $arsimtoCmdLine";
$output = `arsimto $arsimtoCmdLine 2>&1`;
}
# determine Content-Length
my $outLen = length($output);
doLog (" - sess=$sessionNum ; Content-Length:$outLen");
#send some message to the client
print $client
"HTTP/1.x 200 OK\015\012" .
"Accept-Ranges: bytes\015\012" .
"Connection: keep-alive\015\012" .
"Content-Length: $outLen\015\012" .
"Content-Type: application/json\015\012" .
"Server: arsimto/1.2 (Timeless)\015\012" .
"Access-Control-Allow-Origin: *\015\012" .
"\015\012" .
"$output";
;
}
#close the socket
close($sock);
exit(0);
# ----------------------------------------------------------------------------------------
# subroutines follow
# ----------------------------------------------------------------------------------------
# give help. either short and concise or long.
sub doArgs {
my $helpLength = shift;
if ($helpLength eq 'short') {
print "usage: $0 -p=|--port=<portNum> [-i=|--ip=<ipAddr>]\n";
print " [-h|--help] [-v|--verbose] [-r=|--rcfile=<rcFile>]\n";
print "\n";
}
if ($helpLength eq 'long') {
print "The daemon sents logging info to STDERR. Redirect to your preferred log file.\n";
print "\n";
print " -h Long version help. Run without arguments for short help.\n";
print " -i IP address to listen to. Default is 0.0.0.0.\n";
print " -p Or --port. The port to listen on for REST calls. Default 14321.\n";
print " -v Verbose/debugging output\n";
print "\n";
print "Example:\n";
print "\n";
print "$0 --port=14322 --ip=127.0.0.1 >/var/log/arsimtoREST.log 2>&1 &\n";
}
}
# parse the input URI and make it something arsimto can comprehend
sub parseURLinput {
my $inputLine = shift;
my $retVal = '';
# it's a REST call, so it'll be like GET /lipsum&ripsum&lor HTTP/1.1
# if they stick ".json" at the end, accept it but strip it away
if ($inputLine =~ /GET \/arsimto\/(.+?)(\.json)* HTTP/) {
$retVal = $1;
$retVal =~ s/\// /g;
} else {
return "ERRNOARSIMTO: This is Arsimto REST helper. URL must be /arsimto/arg/arg/arg - See the github Arsimto project for more details.";
}
return $retVal;
}
# output a log message
sub doLog {
my $message = shift;
my $currTime = strftime ('%Y-%m-%d %H:%M:%S', localtime);
print STDERR "$currTime $message\n";
}