#
# Authentic Theme (https://github.com/authentic-theme/authentic-theme)
# Copyright Ilia Rostovtsev <ilia@virtualmin.com>
# Licensed under MIT (https://github.com/authentic-theme/authentic-theme/blob/master/LICENSE)
#
use strict;
use Fcntl qw( :flock );
our (%gconfig, %in, $get_user_level, $current_theme, $config_directory, $theme_webprefix, %theme_text, %theme_config);
&webmin_user_is_admin() || &error($theme_text{'theme_error_access_dir_not_allowed'});
my $csf_conf = "/etc/csf";
my $csf_lib = "/var/lib/csf";
my $header = "csf.header";
my $body = "csf.body";
my $footer = "csf.footer";
my $htmltag = "csf.htmltag";
my $bodytag = "csf.bodytag";
my $csf_header = "$csf_conf/$header";
my $csf_body = "$csf_conf/$body";
my $csf_footer = "$csf_conf/$footer";
my $csf_html_tag = "$csf_conf/$htmltag";
my $csf_body_tag = "$csf_conf/$bodytag";
my $csf_ui_patch = "$config_directory/$current_theme/csf.ui";
sub csf_clear
{
unlink_file($csf_header);
unlink_file($csf_body);
unlink_file($csf_footer);
unlink_file($csf_html_tag);
unlink_file($csf_body_tag);
unlink_file($csf_ui_patch);
}
sub csf_strings
{
# Define CSF installed version
my $error;
my $csf_update_required;
my $csf_title;
my $csf_data;
my $csf_remote_version;
my $csf_installed_version = read_file_lines("$csf_conf/version.txt", 1);
$csf_installed_version = $csf_installed_version->[0];
# Define CSF actual version if allowed
if ($theme_config{'settings_sysinfo_csf_updates'} eq 'true' &&
&webmin_user_is_admin() &&
$in{'xhr-info'} eq '1')
{
$csf_remote_version = theme_cached('version-csf-stable');
if (!$csf_remote_version) {
http_download('download.configserver.com', '80', '/csf/version.txt', \$csf_remote_version, \$error,
undef, undef, undef, undef, 30);
theme_cached('version-csf-stable', $csf_remote_version, $error);
}
# Trim versions' number
$csf_installed_version =~ s/^\s+|\s+$//g;
$csf_remote_version =~ s/^\s+|\s+$//g;
} else {
$csf_remote_version = '0';
}
if ($csf_remote_version <= $csf_installed_version) {
$csf_update_required = '0';
} else {
$csf_update_required = '1';
}
$csf_title = $theme_text{'body_firewall'} . ' '
.
( `pgrep lfd` ? '' :
' <a class="label label-danger csf-submit" data-id="csf_lfdstatus" class="label label-danger">Stopped</a> '
);
$csf_data = (
'<a href=\'' . $theme_webprefix . '/csf/index.cgi\' data-id="csf_link_open">' .
$theme_text{'theme_xhred_csf'} . '</a> ' . product_version_update($csf_installed_version, 'f') . ''
. ($csf_update_required eq '1' ?
'. ' . $theme_text{'theme_update_available'} . ' ' . $csf_remote_version . ' ' :
' '
) .
'
<form action="/csf/index.cgi" method="post" class="hidden" id="csf_lfdstatus">
<input type="hidden" name="action" value="lfdstatus">
</form>
<form action="/csf/index.cgi" method="post" class="hidden" id="csf_upgrade">
<input type="hidden" name="action" value="upgrade">
</form>
<form action="/csf/index.cgi" method="post" class="hidden" id="csf_temporary_ip_entries">
<input type="hidden" name="action" value="temp">
</form>
<form action="/csf/index.cgi" method="post" class="hidden" id="csf_search_system_log">
<input type="hidden" name="action" value="loggrep">
</form>
<form action="/csf/index.cgi" method="post" class="hidden" id="csf_denyf">
<input type="hidden" name="action" value="denyf">
</form>
'
. (
$csf_update_required eq '1' ?
'<div class="btn-group">
<a class="btn btn-xxs btn-success csf csf-submit" data-id="csf_upgrade"><i class="fa fa-fw fa-refresh"> </i>'
. $theme_text{'theme_update'} . '</a>
<a class="btn btn-xxs btn-info csf" target="_blank" href="https://download.configserver.com/csf/changelog.txt"><i class="fa fa-fw fa-pencil-square-o"> </i>'
. $theme_text{'theme_changelog'} . '</a>
<a class="btn btn-xxs btn-warning csf" target="_blank" href="https://download.configserver.com/csf.tgz"><i class="fa fa-fw fa-download"> </i>'
. $theme_text{'theme_download'} . '</a>
</div>'
:
'<div class="btn-group" data-no-update>
<a class="btn btn-default btn-xxs btn-hidden hidden csf csf-submit" data-toggle="tooltip" data-placement="auto top" data-container="body" data-title="Search system logs" data-id="csf_search_system_log"><i class="fa fa-fw fa-filter"></i></a>
<a class="btn btn-default btn-xxs btn-hidden hidden csf csf-submit" data-toggle="tooltip" data-placement="auto top" data-container="body" data-title="Temporary IP entries" data-id="csf_temporary_ip_entries"><i class="fa fa-fw fa-ban"></i></a>
<a class="btn btn-default btn-xxs btn-hidden hidden csf csf-submit" data-id="csf_denyf"><i class="fa fa-fw fa-trash-o"></i> Flush all blocks</a>
</div>'
) .
'');
return ($csf_title, $csf_data, $csf_remote_version);
}
sub csf_mod
{
my $ext = (theme_debug_mode() ? 'src' : 'min');
my $csf_header_mod = "$config_directory/$current_theme/$header";
my $csf_body_mod = "$config_directory/$current_theme/$body";
my $csf_footer_mod = "$config_directory/$current_theme/$footer";
my $csf_htmltag_mod = "$config_directory/$current_theme/$htmltag";
my $csf_bodytag_mod = "$config_directory/$current_theme/$bodytag";
open(my $fh, '>', $csf_header_mod) or die $!;
print $fh '<link data-hostname="' . &get_display_hostname() . '" data-version="' .
(theme_version('timestamped')) . '" rel="shortcut icon" href="' . $theme_webprefix . '/images/favicons/webmin/favicon.ico">' . "\n";
print $fh '<link href="' .
$theme_webprefix . '/unauthenticated/css/bundle.min.css?' . theme_version('timestamped') . '" rel="stylesheet">' . "\n";
print $fh '<link href="' . $theme_webprefix .
'/unauthenticated/css/palettes/nightrider.' . $ext . '.css?' . theme_version('timestamped') . '" rel="stylesheet">' . "\n";
print $fh '<link href="' . $theme_webprefix .
'/unauthenticated/css/fonts-roboto.' . $ext . '.css?' . theme_version('timestamped') . '" rel="stylesheet">' . "\n";
# Print default options
print $fh " <script src=\"$theme_webprefix/unauthenticated/js/defaults.js?" . theme_version('timestamped') . "\"></script>\n";
# Print object with language strings
print $fh ' <script>';
print $fh 'var v___theme_language = ' . get_theme_language();
print $fh "</script>\n";
print $fh '<script src="' .
$theme_webprefix . '/unauthenticated/js/bundle.min.js?' . theme_version('timestamped') . '"></script>' . "\n";
print $fh '<link href="' .
$theme_webprefix . '/extensions/csf/csf.' . $ext . '.css?' . theme_version('timestamped') . '" rel="stylesheet">' . "\n";
print $fh '<script src="' .
$theme_webprefix . '/extensions/csf/csf.' . $ext . '.js?' . theme_version('timestamped') . '"></script>' . "\n";
close $fh;
open(my $fh2, '>', $csf_body_mod) or die $!;
print $fh2 '<div class="container-fluid col-lg-10 col-lg-offset-1 csf-container" data-dcontainer="1">' . "\n";
close $fh2;
open(my $fh3, '>', $csf_footer_mod) or die $!;
print $fh3 '</div><script>!$.support.spa && csf_init()</script>' . "\n";
close $fh3;
open(my $fh4, '>', $csf_htmltag_mod) or die $!;
print $fh4 ' '
.
replace("\"", "'",
header_html_data('csf', '1', ($theme_text{'theme_xhred_csf'} . " — " . get_html_framed_title(), 0, 0, '1')))
.
'';
close $fh4;
open(my $fh5, '>', $csf_bodytag_mod) or die $!;
print $fh5 ' ' . replace("\"", "'", header_body_data('csf')) . '';
close $fh5;
if (-e $csf_conf && -d $csf_conf) {
copy_source_dest($csf_header_mod, $csf_conf);
copy_source_dest($csf_body_mod, $csf_conf);
copy_source_dest($csf_footer_mod, $csf_conf);
copy_source_dest($csf_htmltag_mod, $csf_conf);
copy_source_dest($csf_bodytag_mod, $csf_conf);
}
my $csf_ui = uc('style' . '_' . 'custom');
my $csf_conf = ("$csf_conf/csf.conf");
if (-f $csf_conf && !-f $csf_ui_patch) {
(my $fc = read_file_contents($csf_conf)) =~ s/$csf_ui = "0"/$csf_ui = "1"/g;
write_file_contents($csf_conf, $fc);
write_file_contents($csf_ui_patch, "\n");
}
}
sub csf_temporary_list
{
my $let = "$csf_conf/csf.allow";
my $ban = "$csf_conf/csf.deny";
my $cnf = "$csf_conf/csf.conf";
my $tmp = "$csf_lib/csf.tempban";
my $log = "$csf_lib/stats/iptables_log";
my @p;
my @t;
my @l;
if (-e $cnf && !-z $cnf) {
my @q;
my $x = read_file_contents($let) . read_file_contents($ban);
my $z = read_file_contents($cnf);
(@p) = $z =~
/(?:TCP_IN|UDP_IN|TCP6_IN|UDP6_IN|PORTS_TCP|PORTS_UDP|CT_PORTS|CLUSTER_PORT|PORTS_webmin|PORTS_sshd).*=\s*"([\d+,]+)"/g;
(@q) = $x =~ /^(?:(?!#).).*\|(?:d|s)=([\d+,]+)\|/gm;
if (@p || @q) {
@p = array_unique(split(",", join(",", (@p, @q))));
}
}
if (-e $tmp && !-z $tmp) {
open(my $IN, "<", $tmp) or die $!;
@t = <$IN>;
chomp @t;
close($IN);
}
if (@t && -e $log) {
open(my $IN, "<", $log) or die $!;
flock($IN, LOCK_SH);
my @i = <$IN>;
close($IN);
chomp @i;
@i = reverse @i;
my $c = 0;
my $s = scalar @i;
my @g;
foreach my $h (reverse @t) {
if ($h) {
my ($a, $b, $d, $e, $f, $g) = split(/\|/, $h);
my ($ll, $dl) = (undef, '|');
for (my $x = 0; $x < $s; $x++) {
$c++;
my $u = $i[$x];
my ($o, $l) = split(/\|/, $u);
my ($r, $w, $k);
if ($l =~ /SRC=(\S+)/) {$r = $1}
if ($l =~ /DST=(\S+)/) {$w = $1}
if ($l =~ /DPT=(\d+)/) {$k = $1}
if (($r eq $b && array_contains(\@p, $k)) || $d =~ /\d/g || $g =~ /failed|\(CT\)/gi) {
$ll = ($a . $dl . $b . $dl . $w . $dl . $k . $dl . $d . $dl . $e . $dl . $f . $dl . $g);
if (!array_contains(\@g, $g) && !array_contains(\@l, $ll)) {
push @g, $g;
push @l, $ll;
}
}
}
}
}
}
convert_to_json(\@l);
}
1;