1
|
#!/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
|
`/usr/bin/mkfifo -m666 /tmp/$account~$session.tasks`;# unless (-e "/tmp/$account~$session.tasks");
|
108
|
$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
|
}
|