Viewing File: /usr/local/cpanel/whostmgr/docroot/cgi/hostaccess.cgi
#!/usr/local/cpanel/3rdparty/bin/perl
# cpanel - whostmgr/docroot/cgi/hostaccess.cgi Copyright 2022 cPanel, L.L.C.
# All rights reserved.
# copyright@cpanel.net http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
use strict;
use warnings;
use Cpanel::Form ();
use Cpanel::OS ();
use Whostmgr::ACLS ();
use Whostmgr::HTMLInterface ();
if ( !check_acls('all') ) {
html_error( 403, "Forbidden" );
require Cpanel::Exit;
Cpanel::Exit::exit_with_stdout_closed_first();
}
my %FORM = Cpanel::Form::parseform();
if ( $FORM{'add_nftables_rule'} ) {
eval {
require Cpanel::XTables;
my $obj = Cpanel::XTables->new(
'chain' => 'cPanel-HostAccessControl',
);
if ( !$obj->table_exists( 'name' => 'filter', 'family' => 'inet' ) ) {
my $create_line = [ [qw'add table inet filter'] ];
$obj->exec_checked_calls($create_line);
}
$obj->init_chain() if !$obj->chain_exists();
$obj->add_rule(
'port' => $FORM{'port'},
'ip' => $FORM{'ip'},
'protocol' => $FORM{'protocol'},
'action' => $FORM{'action'},
);
};
if ($@) {
html_error( 500, $@ );
require Cpanel::Exit;
Cpanel::Exit::exit_with_stdout_closed_first();
}
$FORM{'no_cache'} = 1;
}
elsif ( $FORM{'delete_nftables_rule'} ) {
require Cpanel::XTables;
Cpanel::XTables->new(
'chain' => 'cPanel-HostAccessControl',
)->delete_rule(
'handle' => $FORM{'delete_nftables_rule'},
);
$FORM{'no_cache'} = 1;
}
if ( $FORM{'fetch_nftables_rules'} ) {
my $rules = [];
eval {
require Cpanel::JSON;
require Cpanel::XTables;
my $obj = Cpanel::XTables->new( 'chain' => 'cPanel-HostAccessControl' );
$obj->clear_ruleset_cache();
$rules = $obj->get_rules;
};
if ($@) {
push @$rules, { 'error' => $@ };
print "Status: 500\r\nContent-type: application/json\r\n\r\n";
}
else {
print "Status: 200\r\nContent-type: application/json\r\n\r\n";
}
print Cpanel::JSON::pretty_dump($rules);
require Cpanel::Exit;
Cpanel::Exit::exit_with_stdout_closed_first();
}
print "Content-type: text/html\r\n\r\n";
do_main();
sub do_main {
require Cpanel::Template;
my $saved;
if ( exists $FORM{'save_accesslist'} ) {
$saved = savehostaccesslist();
}
if ( Cpanel::OS::supports_hostaccess() ) {
require Cpanel::HostAccessLib;
my $hostaccesslib = Cpanel::HostAccessLib->new;
Cpanel::Template::process_template(
'whostmgr',
{
'template_file' => 'host_access/hostaccess.tmpl',
'data' => {
'action' => q{},
'saved' => $saved,
'services' => $hostaccesslib->fetch_services(),
'actions' => $hostaccesslib->fetch_actions(),
'wildcards' => $hostaccesslib->fetch_wildcards(),
'rules' => $hostaccesslib->{'DB'},
'emptyrule' => {
'daemon_list' => [],
'client_list' => [],
'action_list' => [],
'comment' => '',
'type' => 'empty_action',
},
},
},
);
}
else {
# Host Access Controls not supported on CentOS 8+, so we
# have a different implementation based on nftables.
Cpanel::Template::process_template(
'whostmgr',
{
'template_file' => 'host_access/nftables_access.tmpl',
'data' => {
'no_cache' => $FORM{'no_cache'} || 0,
},
},
);
}
return;
}
sub savehostaccesslist {
require Cpanel::HostAccessLib;
my $hostaccesslib = Cpanel::HostAccessLib->new;
for ( my $i = 0; $i <= $#{ $hostaccesslib->{'DB'} }; $i++ ) {
${ $hostaccesslib->{'DB'} }[$i]->{'linenum'} = ( $i + 1 );
foreach my $list ( 'daemon_list', 'action_list', 'client_list' ) {
if ( defined ${ $hostaccesslib->{'DB'} }[$i]->{$list} ) {
${ $hostaccesslib->{'DB'} }[$i]->{$list} = [];
}
}
}
foreach my $key ( keys %FORM ) {
my $evalue = $FORM{$key};
my ( $slinenum, $element ) = split( /-/, $key, 2 );
next if ( !defined $slinenum || $slinenum !~ /^\d+$/ || !defined $element );
my $linenum = int $slinenum;
$linenum--;
my ( $keyname, $keynum ) = split( /_/, $element, 2 );
if ( $keyname eq 'daemon' ) {
${ $hostaccesslib->{'DB'} }[$linenum]->{'daemon_list'} = Cpanel::HostAccessLib::daemon_parse($evalue);
}
elsif ( $keyname eq 'client' ) {
${ $hostaccesslib->{'DB'} }[$linenum]->{'client_list'} = Cpanel::HostAccessLib::client_parse($evalue);
}
elsif ( $keyname eq 'action' ) {
my $newval = Cpanel::HostAccessLib::ptrim($evalue);
next if ( $newval eq '' );
${ ${ $hostaccesslib->{'DB'} }[$linenum]->{'action_list'} }[$keynum] = $newval;
}
elsif ( $keyname eq 'comment' ) {
${ $hostaccesslib->{'DB'} }[$linenum]->{'comment'} = $evalue;
}
}
foreach my $line ( split( /:/, $FORM{'eventlist'} ) ) {
my ( $linenum, $offset ) = split( /,/, $line );
foreach ( my $i = 0; $i <= $#{ $hostaccesslib->{'DB'} }; $i++ ) {
if ( ${ $hostaccesslib->{'DB'} }[$i]->{'linenum'} == $linenum ) {
my $newpt = ( $i + $offset );
my @nl = splice( @{ $hostaccesslib->{'DB'} }, $i, 1 );
splice( @{ $hostaccesslib->{'DB'} }, $newpt, 0, @nl );
last;
}
}
}
for ( my $i = 0; $i <= $#{ $hostaccesslib->{'DB'} }; $i++ ) {
foreach my $list ( 'daemon_list', 'action_list', 'client_list' ) {
if ( !defined ${ $hostaccesslib->{'DB'} }[$i]->{$list} ) {
${ $hostaccesslib->{'DB'} }[$i]->{$list} = [];
}
}
if ( !defined ${ $hostaccesslib->{'DB'} }[$i]->{'type'} ) {
${ $hostaccesslib->{'DB'} }[$i]->{'type'} = 'access_list';
}
}
$hostaccesslib->reserialize();
$hostaccesslib->commit();
return 1;
}
sub check_acls {
my @acls = @_;
Whostmgr::ACLS::init_acls();
return scalar( grep { Whostmgr::ACLS::checkacl($_) } @acls ) == scalar(@acls);
}
sub html_error {
my ( $code, $msg ) = @_;
print "Status: $code\r\nContent-type: text/html\r\n\r\n";
Whostmgr::HTMLInterface::defheader();
print "<h1>$msg</h1>";
Whostmgr::HTMLInterface::sendfooter();
return;
}
Back to Directory
File Manager