1 |
95b003ff
|
Origo
|
#!/usr/bin/perl
|
2 |
|
|
|
3 |
|
|
# All rights reserved and Copyright (c) 2020 Origo Systems ApS.
|
4 |
|
|
# This file is provided with no warranty, and is subject to the terms and conditions defined in the license file LICENSE.md.
|
5 |
|
|
# The license file is part of this source code package and its content is also available at:
|
6 |
|
|
# https://www.origo.io/info/stabiledocs/licensing/stabile-open-source-license
|
7 |
|
|
|
8 |
|
|
use CGI ':standard';
|
9 |
|
|
use JSON;
|
10 |
|
|
use URI::Escape;
|
11 |
|
|
use Tie::DBI;
|
12 |
|
|
use Error qw(:try);
|
13 |
|
|
use Sys::Syslog qw( :DEFAULT setlogsock);
|
14 |
|
|
use ConfigReader::Simple;
|
15 |
|
|
use Data::Dumper;
|
16 |
|
|
use Time::HiRes qw(usleep);
|
17 |
|
|
|
18 |
|
|
$ENV{PATH} = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin';
|
19 |
|
|
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
|
20 |
|
|
|
21 |
|
|
$SIG{'INT'} = sub { handle_signal('INT'); };
|
22 |
|
|
$SIG{'PIPE'} = sub { handle_signal('PIPE'); };
|
23 |
|
|
$SIG{'HUP'} = sub { handle_signal('HUP'); };
|
24 |
|
|
$SIG{'TERM'} = sub { handle_signal('TERM'); };
|
25 |
|
|
|
26 |
|
|
$q = new CGI;
|
27 |
|
|
%params = $q->Vars;
|
28 |
|
|
|
29 |
|
|
$user = $ENV{'REMOTE_USER'};
|
30 |
|
|
$user = $1 if ($user =~ /(.+)/); #untaint
|
31 |
|
|
$account = $q->cookie('steamaccount'); # User is using another account
|
32 |
|
|
$account = $user unless ($account);
|
33 |
|
|
$account = $1 if ($account =~ /(.+)/); #untaint
|
34 |
|
|
|
35 |
|
|
|
36 |
|
|
$naptime = 2;
|
37 |
|
|
$tied;
|
38 |
|
|
$session;
|
39 |
|
|
$i = 0;
|
40 |
|
|
|
41 |
|
|
my $config = ConfigReader::Simple->new("/etc/stabile/config.cfg",
|
42 |
|
|
[qw(STORAGE_BACKUPDIR
|
43 |
|
|
DBI_USER DBI_PASSWD ENGINEID
|
44 |
|
|
)]);
|
45 |
|
|
my $dbiuser = $config->get('DBI_USER') || "irigo";
|
46 |
|
|
my $dbipasswd = $config->get('DBI_PASSWD') || "";
|
47 |
|
|
my $tktname = 'auth_tkt';
|
48 |
|
|
$tktname = ('auth_' . substr($config->get('ENGINEID'), 0, 8) ) if ($config->get('ENGINEID'));
|
49 |
|
|
|
50 |
|
|
if (!is_user()) { # User not authenticated
|
51 |
|
|
print header('text/html', '401 Unauthorized');
|
52 |
|
|
print "User: $0 : $user not allowed\n";
|
53 |
|
|
|
54 |
|
|
} elsif (!$params{'s'}) { # Set up a new session
|
55 |
|
|
|
56 |
|
|
$privileges = getPrivileges($user);
|
57 |
|
|
|
58 |
|
|
if ($account ne $user) { # Check privileges
|
59 |
|
|
$account = checkAccount($user, $account); # this also sets global $privileges
|
60 |
|
|
}
|
61 |
|
|
my $isadmin = index($privileges,"a")!=-1;
|
62 |
|
|
|
63 |
|
|
if (!$account || index($privileges,"d")!=-1) {
|
64 |
|
|
print header('text/html', '401 Unauthorized');
|
65 |
|
|
exit 0;
|
66 |
|
|
}
|
67 |
|
|
|
68 |
|
|
my $tkt = $q->cookie($tktname);
|
69 |
|
|
$session = substr($tkt, 0, 6);
|
70 |
|
|
$session = "A-" . $session if ($isadmin);
|
71 |
|
|
$session =~ /(.+)/; $session = $1; #untaint
|
72 |
|
|
my $i = 1;
|
73 |
|
|
while (-e "/tmp/$account~$session.$i.tasks") {$i++;};
|
74 |
|
|
$session = "$session.$i";
|
75 |
|
|
|
76 |
|
|
$account = $1 if ($account =~ /(.+)/);
|
77 |
|
|
|
78 |
|
|
print header('application/json; charset=UTF8');
|
79 |
|
|
|
80 |
|
|
# system(qq[/usr/bin/pkill -f "$account~ui_update" &]); # Remove lingering ui_update.cgi's if reloading or changing account
|
81 |
|
|
`pkill -f "$account~ui_update.cgi"`; # Remove lingering ui_update.cgi's if reloading or changing account
|
82 |
|
|
|
83 |
|
|
if ($session ) {
|
84 |
|
|
my $tasks = qq|{"type": "session", "session": "$session", "url": "/stabile/ui_update/$account~ui_update?s=$session"}|;
|
85 |
|
|
print "[$tasks]\n";
|
86 |
|
|
} else {
|
87 |
|
|
sleep $naptime;
|
88 |
|
|
}
|
89 |
|
|
} else { # Wait and read input from operations
|
90 |
|
|
print header('application/json; charset=UTF8');
|
91 |
|
|
|
92 |
|
|
$session = $params{'s'};
|
93 |
|
|
$session =~ /(.+)/; $session = $1; #untaint
|
94 |
|
|
# if (-e "/tmp/$account~$session.tasks") {
|
95 |
|
|
my $r = substr rand(),2,4;
|
96 |
|
|
my $update = qq|{"type": "serial", "serial": "$r"}|;
|
97 |
|
|
my $tasks;
|
98 |
|
|
if (-e "/tmp/$account.tasks") {
|
99 |
|
|
$update = qq|{"type": "serial", "serial": "$r", "orphan": true}|;
|
100 |
|
|
# Orphaned tasks found - read them
|
101 |
|
|
$tasks = `/bin/cat < /tmp/$account.tasks`; # Read session tasks from pipe
|
102 |
|
|
# unlink ("/tmp/$account.tasks");
|
103 |
|
|
`rm "/tmp/$account.tasks"`;
|
104 |
|
|
} else {
|
105 |
|
|
$update = qq|{"type": "serial", "serial": "$r"}|;
|
106 |
|
|
# This is where we block and wait for news...
|
107 |
04c16f26
|
hq
|
`/usr/bin/mkfifo -m666 /tmp/$account~$session.tasks`;# unless (-e "/tmp/$account~$session.tasks");
|
108 |
95b003ff
|
Origo
|
$tasks = `/bin/cat < /tmp/$account~$session.tasks`; # Read session tasks from pipe
|
109 |
|
|
}
|
110 |
|
|
chomp $tasks;
|
111 |
|
|
$tasks = substr($tasks, 0, -2) if ($tasks =~ /(, )$/); # Remove last comma and space
|
112 |
|
|
if ($tasks && $tasks ne "--") {
|
113 |
|
|
$update .= qq|, $tasks|;
|
114 |
|
|
}
|
115 |
|
|
print "[$update]\n";
|
116 |
|
|
unlink "/tmp/$account~$session.tasks";
|
117 |
|
|
# } else {
|
118 |
|
|
# my $tasks = qq|{"type":"logout", "message":"Logged out"}| ;
|
119 |
|
|
# print "[$tasks]\n";
|
120 |
|
|
# }
|
121 |
|
|
}
|
122 |
|
|
|
123 |
|
|
sub handle_signal {
|
124 |
|
|
my $sig = shift;
|
125 |
|
|
return 0 if ($sig eq 'PIPE');
|
126 |
|
|
# unlink "/tmp/$account~$session.tasks"; # unless ($hupped);
|
127 |
|
|
# `/bin/rm /tmp/$account~$session.tasks`; # unless ($hupped);
|
128 |
|
|
# `/usr/bin/touch /tmp/$account~$session.tasks` if (-e "/tmp/$account~$session.tasks");
|
129 |
|
|
# Remove old session files
|
130 |
|
|
# `/usr/bin/find /tmp/* -maxdepth 0 -name "*.tasks" ! -name "$account~$session.tasks" -mmin +1 -exec rm '{}' \\;`;
|
131 |
|
|
# print header('application/json; charset=UTF8');
|
132 |
|
|
print qq|{"signal":"$sig"}\n|;
|
133 |
|
|
my $t = time;
|
134 |
|
|
unlink "/tmp/$account~$session.tasks";
|
135 |
|
|
`pkill -f "/bin/cat < /tmp/$account~$session.tasks"`;
|
136 |
|
|
exit 0;
|
137 |
|
|
# die;
|
138 |
|
|
}
|
139 |
|
|
|
140 |
|
|
sub is_user {
|
141 |
|
|
# $0 contains the name of the script e.g. jakob@cabo.dk~ui_update.cgi
|
142 |
|
|
$0 =~ /.+\/(.+)~+.+/;
|
143 |
|
|
if ($1 eq $user || $1 eq $account) {return 1;}
|
144 |
|
|
else {return 0;}
|
145 |
|
|
}
|
146 |
|
|
|
147 |
|
|
sub getPrivileges {
|
148 |
|
|
my $u = shift;
|
149 |
|
|
unless (tie %userreg,'Tie::DBI', {
|
150 |
|
|
db=>'mysql:steamregister',
|
151 |
|
|
table=>'users',
|
152 |
|
|
key=>'username',
|
153 |
|
|
autocommit=>0,
|
154 |
|
|
CLOBBER=>1,
|
155 |
|
|
user=>$dbiuser,
|
156 |
|
|
password=>$dbipasswd}) {return ""};
|
157 |
|
|
my $privs = $userreg{$u}->{'privileges'};
|
158 |
|
|
untie %userreg;
|
159 |
|
|
return $privs;
|
160 |
|
|
}
|
161 |
|
|
|
162 |
|
|
sub checkAccount {
|
163 |
|
|
my ($user, $account) = @_;
|
164 |
|
|
unless (tie %userreg,'Tie::DBI', {
|
165 |
|
|
db=>'mysql:steamregister',
|
166 |
|
|
table=>'users',
|
167 |
|
|
key=>'username',
|
168 |
|
|
autocommit=>0,
|
169 |
|
|
CLOBBER=>1,
|
170 |
|
|
user=>$dbiuser,
|
171 |
|
|
password=>$dbipasswd}) {return 0};
|
172 |
|
|
|
173 |
|
|
my %ahash;
|
174 |
|
|
my @accounts = split(',', $userreg{$user}->{'accounts'});
|
175 |
|
|
my @accountsprivs = split(',', $userreg{$user}->{'accountsprivileges'});
|
176 |
|
|
for my $i (0 .. $#accounts)
|
177 |
|
|
{ $ahash{$accounts[$i]} = $accountsprivs[$i] || 'r'; }
|
178 |
|
|
|
179 |
|
|
if ($ahash{$account}) {
|
180 |
|
|
$user = $account;
|
181 |
|
|
$privileges = $ahash{$account};
|
182 |
|
|
unless ($userreg{$user}->{'username'}) {
|
183 |
|
|
return 0;
|
184 |
|
|
};
|
185 |
|
|
if (index($privileges,"d")!=-1) {
|
186 |
|
|
return 0;
|
187 |
|
|
};
|
188 |
|
|
}
|
189 |
|
|
untie %userreg;
|
190 |
|
|
return $user;
|
191 |
|
|
}
|