configs/utils/auth-save-downloader.pl

96 lines
2.1 KiB
Perl
Executable File

#! /usr/bin/perl
#
# Allows DGL admin users to download saves from CSZO's save dump directory.
#
use CGI qw/:standard/;
use MIME::Base64;
use DBI;
my $DB = "%%LOGIN_DB%%";
my $CONTENT_DIR = '%%SAVE_DUMPDIR%%/';
my $AUTH_REALM = 'CSZO developer account';
sub request_auth() {
print(header(-type => 'text/html',
-status => '401 Authorization Required',
-WWW_Authenticate => "Basic realm=\"$AUTH_REALM\""),
start_html('CSZO save dumps'),
p('Must authenticate to access saves'),
end_html);
return undef;
}
sub match_password($$) {
my ($plain, $crypt) = @_;
my $cc = crypt($plain, $crypt);
return crypt($plain, $crypt) eq $crypt;
}
sub valid_user($$) {
my ($user, $password) = @_;
my $db = DBI->connect("dbi:SQLite:dbname=$DB", '', '')
or die "Can't open auth db: $DB\n";
my $st = $db->prepare(<<QUERY);
SELECT username, password FROM dglusers
WHERE username=? AND (flags & 1) = 1;
QUERY
$st->execute($user);
my $row = $st->fetchrow_arrayref;
# Should have at least one row.
return defined($row) && match_password($password, $row->[1]);
}
sub valid_auth($) {
my $header = shift;
return unless $header =~ s/^Basic //;
my $decoded = decode_base64($header);
my ($user, $password) = $decoded =~ /(.*?):(.*)/;
valid_user($user, $password)
}
sub authenticate() {
my $auth_header = http('Authorization');
return request_auth() unless $auth_header && valid_auth($auth_header);
1
}
sub file_bytes($) {
my $file = shift;
open my $inf, '<', $file;
binmode $inf;
my $content = do { local $/; <$inf> };
close $inf;
$content
}
sub serve_file() {
my ($file) = param('file');
my $absfile = "$CONTENT_DIR/$file";
if ($file =~ /[.]{2}/ ||
$file !~ /^[a-zA-Z0-9._-]+$/ ||
$file !~ /\.(?:tar\.bz2|cs|core)$/ ||
!-r $absfile)
{
print(header(-status => '404 Not Found'),
start_html,
p("Could not find $absfile"),
end_html);
return;
}
print(header(-type => 'application/octet-stream'),
file_bytes($absfile));
}
sub main() {
return unless authenticate();
serve_file();
}
main();