Project

General

Profile

Download (6.27 KB) Statistics
| Branch: | Revision:
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
    #    `/usr/bin/mkfifo -m666 /tmp/$account~$session.tasks` unless (-e "/tmp/$account~$session.tasks");
85
        my $tasks = qq|{"type": "session", "session": "$session", "url": "/stabile/ui_update/$account~ui_update?s=$session"}|;
86
        print "[$tasks]\n";
87
    } else {
88
        sleep $naptime;
89
    }
90
} else { # Wait and read input from operations
91
    print header('application/json; charset=UTF8');
92

    
93
    $session = $params{'s'};
94
    $session =~ /(.+)/; $session = $1; #untaint
95
#    if (-e "/tmp/$account~$session.tasks") {
96
    my $r = substr rand(),2,4;
97
    my $update = qq|{"type": "serial", "serial": "$r"}|;
98
    my $tasks;
99
    if (-e "/tmp/$account.tasks") {
100
        $update = qq|{"type": "serial", "serial": "$r", "orphan": true}|;
101
        # Orphaned tasks found - read them
102
        $tasks = `/bin/cat < /tmp/$account.tasks`; # Read session tasks from pipe
103
        # unlink ("/tmp/$account.tasks");
104
        `rm "/tmp/$account.tasks"`;
105
    } else {
106
        $update = qq|{"type": "serial", "serial": "$r"}|;
107
        # This is where we block and wait for news...
108
        `/usr/bin/mkfifo -m666 /tmp/$account~$session.tasks` unless (-e "/tmp/$account~$session.tasks");
109
        $tasks = `/bin/cat < /tmp/$account~$session.tasks`; # Read session tasks from pipe
110
    }
111
    chomp $tasks;
112
    $tasks = substr($tasks, 0, -2) if ($tasks =~ /(, )$/); # Remove last comma and space
113
    if ($tasks && $tasks ne "--") {
114
        $update .= qq|, $tasks|;
115
    }
116
    print "[$update]\n";
117
    unlink "/tmp/$account~$session.tasks";
118
#    } else {
119
#        my $tasks = qq|{"type":"logout", "message":"Logged out"}| ;
120
#        print "[$tasks]\n";
121
#    }
122
}
123

    
124
sub handle_signal {
125
    my $sig = shift;
126
    return 0 if ($sig eq 'PIPE');
127
#    unlink "/tmp/$account~$session.tasks"; # unless ($hupped);
128
#    `/bin/rm /tmp/$account~$session.tasks`; # unless ($hupped);
129
#    `/usr/bin/touch /tmp/$account~$session.tasks` if (-e "/tmp/$account~$session.tasks");
130
    # Remove old session files
131
#    `/usr/bin/find /tmp/* -maxdepth 0 -name "*.tasks" ! -name "$account~$session.tasks" -mmin +1 -exec rm '{}' \\;`;
132
#    print header('application/json; charset=UTF8');
133
    print qq|{"signal":"$sig"}\n|;
134
    my $t = time;
135
    unlink "/tmp/$account~$session.tasks";
136
    `pkill -f "/bin/cat < /tmp/$account~$session.tasks"`;
137
    exit 0;
138
#    die;
139
}
140

    
141
sub is_user {
142
    # $0 contains the name of the script e.g. jakob@cabo.dk~ui_update.cgi
143
    $0 =~ /.+\/(.+)~+.+/;
144
    if ($1 eq $user || $1 eq $account) {return 1;}
145
    else {return 0;}
146
}
147

    
148
sub getPrivileges {
149
    my $u = shift;
150
    unless (tie %userreg,'Tie::DBI', {
151
        db=>'mysql:steamregister',
152
        table=>'users',
153
        key=>'username',
154
        autocommit=>0,
155
        CLOBBER=>1,
156
        user=>$dbiuser,
157
        password=>$dbipasswd}) {return ""};
158
    my $privs = $userreg{$u}->{'privileges'};
159
    untie %userreg;
160
    return $privs;
161
}
162

    
163
sub checkAccount {
164
    my ($user, $account) = @_;
165
    unless (tie %userreg,'Tie::DBI', {
166
        db=>'mysql:steamregister',
167
        table=>'users',
168
        key=>'username',
169
        autocommit=>0,
170
        CLOBBER=>1,
171
        user=>$dbiuser,
172
        password=>$dbipasswd}) {return 0};
173

    
174
    my %ahash;
175
    my @accounts = split(',', $userreg{$user}->{'accounts'});
176
    my @accountsprivs = split(',', $userreg{$user}->{'accountsprivileges'});
177
    for my $i (0 .. $#accounts)
178
        { $ahash{$accounts[$i]} = $accountsprivs[$i] || 'r'; }
179

    
180
    if ($ahash{$account}) {
181
        $user = $account;
182
        $privileges = $ahash{$account};
183
        unless ($userreg{$user}->{'username'}) {
184
            return 0;
185
        };
186
        if (index($privileges,"d")!=-1) {
187
            return 0;
188
        };
189
    }
190
    untie %userreg;
191
    return $user;
192
}
(8-8/9)