?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/multi_pkgs.zip
???????
PK :�[K[� � 1 pre_transaction/ea-__WILDCARD__/001-ensure-nobodynu ȯ�� #!/usr/bin/perl use strict; use warnings; system("touch /etc/systemd/dont-synthesize-nobody") if -d "/etc/systemd"; my $uid = getpwnam("nobody"); my $gid = getgrnam("nobody"); my @ids = ( 65534, 99 ); my $user_needs_informed = 0; if ( !defined $gid ) { $user_needs_informed = 1; my $addgroup = -x '/usr/sbin/groupadd' ? "groupadd" : "addgroup"; for my $id (@ids) { system("$addgroup --system --gid $id nobody"); $gid = getgrnam("nobody"); last if defined $gid; } if ( !defined $gid ) { system("$addgroup --system nobody"); } $gid = getgrnam("nobody"); die "Could not ensure `nobody` group\n" if !defined $gid; } if ( !defined $uid ) { $user_needs_informed = 1; my $flags = -x '/usr/sbin/groupadd' ? "" : "--disabled-password --disabled-login"; for my $id (@ids) { system("adduser --system --uid $id --gid $gid --home / --no-create-home --shell /sbin/nologin $flags nobody"); $uid = getpwnam("nobody"); last if defined $uid; } if ( !defined $uid ) { system("adduser --system --gid $gid --home / --no-create-home --shell /sbin/nologin $flags nobody"); } $uid = getpwnam("nobody"); die "Could not ensure `nobody` user\n" if !defined $uid; } # if already done, its a noop. adduser’s --gid does not make this happen system("usermod -g $gid nobody"); my $home = ( getpwnam("nobody") )[7]; if ( !-d $home ) { # We do not want to create it for them in case there are other implications in /nonexistent existing. # We can’t `usermod --home / nobody` for them because we’d have to hard stop all nobody processes first. my $sep = "#" x 42; print <<"END_HOMEDIR"; $sep [WARN] Detected non-existent home directory for `nobody`. This situation can result in some harmless STDERR going to your web server’s error log as errors. If you experience this your options are: 1. Ignore the log entries 2. Create the directory “$home” if it is safe to do so. 3. Change the `nobody` user’s home directory to one that exists. e.g. `usermod --home / nobody` $sep END_HOMEDIR } print "[INFO] `nobody` user created with UID $uid and GID $gid\n" if $user_needs_informed; PK :�[��� - transaction/ea-__WILDCARD__/300-fixmailman.plnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # cpanel - SOURCES/300-fixmailman.pl Copyright(c) 2016 cPanel, Inc. # All Rights Reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited package ea_apache24_config_runtime::SOURCES::300_fixmailman; use strict; use warnings; use Cpanel::Mailman::Perms (); use Cpanel::SafeRun::Simple (); use Cpanel::Daemonizer::Tiny (); our @Steps = ( { name => 'Fix mailman package directories', code => \&fix_pkg_dirs, }, { name => 'Fix mailing list perms', code => \&fix_list_dirs, }, ); # Fixes the mailing list archive directories based on Apache environment sub fix_list_dirs { my $script = '/usr/local/cpanel/scripts/fixmailman'; Cpanel::SafeRun::Simple::saferun($script) if -x $script; return 1; # it doesn't return a proper exit code on success, so we ignore it } # Fixes the permissions of the core mailman directories... # because this used to installed without a package on systems < 11.57 sub fix_pkg_dirs { my $perm = Cpanel::Mailman::Perms->new(); $perm->set_perms(); # this always assumes success, so no point in checking retval return 1; } sub main { my $argv = shift; for my $step (@Steps) { print "$step->{name} …\n"; my $pid = Cpanel::Daemonizer::Tiny::run_as_daemon( sub { $0 = $step->{name}; $step->{code}->($argv); return; # nobody is listening } ); print " … PID $pid\n"; } return 0; } exit( __PACKAGE__->main( \@ARGV ) ) unless caller(); 1; __END__ PK :�[�ǁь � , transaction/ea-__WILDCARD__/010-suphpconf.plnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # cpanel - 010-suphpconf.pl Copyright 2017 cPanel, Inc. # All rights Reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited package suphpconf; use strict; use warnings; use Cpanel::SysPkgs::SCL (); our $suphpconf = '/etc/suphp.conf'; run() unless caller; sub run { if ( -e $suphpconf ) { if ( !-e "/usr/local/bin/ea_convert_php_ini" ) { # This madness will go away with EA-5696 warn "Unable to update /etc/suphp.conf without the ea-cpanel-tools package installed.\n"; } else { require "/usr/local/bin/ea_convert_php_ini"; ##no critic (RequireBarewordIncludes) This madness will go away with EA-5696 my $parser = Parse::PHP::Ini->new; my $tree = $parser->parse( path => $suphpconf ); my $handlers = $parser->get_matching_section( $tree, 'handlers' ); if ( !$handlers ) { $handlers = $parser->make_section_node( 'handlers', -1 ); $tree->add_daughter($handlers); } my %packages; @packages{ @{ Cpanel::SysPkgs::SCL::get_scl_versions(qr/\w+-php/) } } = (); # update/cleanout existing entries for my $daughter ( @{ $handlers->{daughters} } ) { if ( $daughter->{name} =~ m{application/x-httpd-(.*)} ) { my $pkg = $1; if ( exists $packages{$pkg} ) { my $cgi_path = _get_cgi_path($pkg); my $count = $daughter->{attributes}{line}; # TODO: make this something else? my $tmp = $parser->make_setting_node( "application/x-httpd-$pkg", qq{"php:$cgi_path"}, $count ); my $attr = $tmp->attribute(); $parser->update_node( $daughter, $attr ); print "Ensuring current entry for “$pkg” is correct …\n"; $packages{$pkg} = "update"; } else { print "Ignoring current entry for “$pkg” …\n"; $packages{$pkg} = "ignore"; } } } # add entries reflecting the actual state for my $pkg ( keys %packages ) { if ( !$packages{$pkg} ) { my $cgi_path = _get_cgi_path($pkg); my $count = 0; # TODO: make this something else? my $setting = $parser->make_setting_node( "application/x-httpd-$pkg", qq{"php:$cgi_path"}, $count ); $handlers->add_daughter($setting); print "Adding entry for “$pkg” …\n"; $packages{$pkg} = "add"; } } # write $suphpconf _write_suphpconf($tree); } } else { print "Nothing to do ($suphpconf does not exist)\n"; } return; } ############### #### helpers ## ############### sub _get_cgi_path { my ($pkg) = @_; my $cgi_path = Cpanel::SysPkgs::SCL::get_scl_prefix($pkg) . "/root/usr/bin/php-cgi"; if ( !-x $cgi_path ) { warn "$cgi_path is not executable, please rectify (e.g. a symlink …/root to the right spot should do the trick)\n"; } return $cgi_path; } sub _write_suphpconf { my ($tree) = @_; # Encapsualte the madness here, NS use noted in /usr/local/bin/ea_convert_php_ini no warnings "once"; local $ea_convert_php_ini_file::Cfg{force} = 1; ea_convert_php_ini_file::write_php_ini( $tree, $suphpconf ); } PK :�[=�p�] ] 7 transaction/ea-__WILDCARD__/011-modsec_cpanel_conf_initnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl exec '/usr/local/cpanel/bin/modsec_cpanel_conf_init'; PK :�[?�,�Z Z 1 transaction/ea-__WILDCARD__/020-rebuild-httpdconfnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl exec '/usr/local/cpanel/scripts/rebuildhttpdconf'; PK :�[�٤Z Z 0 transaction/ea-__WILDCARD__/030-update-apachectlnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl exec '/usr/local/cpanel/scripts/update_apachectl'; PK :�[��N� � 0 transaction/ea-__WILDCARD__/500-restartsrv_httpdnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # Copyright (c) 2023, cPanel, L.L.C. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package ea_apache24_config_runtime::SOURCES::restartsrv_httpd; use strict; use warnings; our $disable_flag_file = '/var/cpanel/ea4-disable-500-restartsrv_httpd-for-glibc'; run(@ARGV) unless caller(); sub run { my @args = @_; my ($path) = map( { m/^--pkg_list=(.*)$/ ? ($1) : () } @args ); my $hard_restart = 0; if ( defined $path && -e $path ) { if ( open( my $fh, '<', $path ) ) { my @lines = <$fh>; close($fh); if ( grep { m/^ea-apache24$/ || m/^ea-apache24-mod[_\-]/ } @lines ) { $hard_restart = 1; } } else { warn "Failed to open “$path”: $!\n"; $hard_restart = 1; # err on the side of caution } } if( $0 =~ m{glibc-restartsrv_httpd$} ) { return 0 if -e $disable_flag_file; $hard_restart = 1 } if ($hard_restart) { system('/usr/local/cpanel/scripts/restartsrv_httpd --stop'); system('/usr/local/cpanel/scripts/restartsrv_httpd'); } else { system('/usr/local/cpanel/scripts/restartsrv_httpd'); } } 1; PK :�[K[� � - transaction/ea-__WILDCARD__/001-ensure-nobodynu ȯ�� #!/usr/bin/perl use strict; use warnings; system("touch /etc/systemd/dont-synthesize-nobody") if -d "/etc/systemd"; my $uid = getpwnam("nobody"); my $gid = getgrnam("nobody"); my @ids = ( 65534, 99 ); my $user_needs_informed = 0; if ( !defined $gid ) { $user_needs_informed = 1; my $addgroup = -x '/usr/sbin/groupadd' ? "groupadd" : "addgroup"; for my $id (@ids) { system("$addgroup --system --gid $id nobody"); $gid = getgrnam("nobody"); last if defined $gid; } if ( !defined $gid ) { system("$addgroup --system nobody"); } $gid = getgrnam("nobody"); die "Could not ensure `nobody` group\n" if !defined $gid; } if ( !defined $uid ) { $user_needs_informed = 1; my $flags = -x '/usr/sbin/groupadd' ? "" : "--disabled-password --disabled-login"; for my $id (@ids) { system("adduser --system --uid $id --gid $gid --home / --no-create-home --shell /sbin/nologin $flags nobody"); $uid = getpwnam("nobody"); last if defined $uid; } if ( !defined $uid ) { system("adduser --system --gid $gid --home / --no-create-home --shell /sbin/nologin $flags nobody"); } $uid = getpwnam("nobody"); die "Could not ensure `nobody` user\n" if !defined $uid; } # if already done, its a noop. adduser’s --gid does not make this happen system("usermod -g $gid nobody"); my $home = ( getpwnam("nobody") )[7]; if ( !-d $home ) { # We do not want to create it for them in case there are other implications in /nonexistent existing. # We can’t `usermod --home / nobody` for them because we’d have to hard stop all nobody processes first. my $sep = "#" x 42; print <<"END_HOMEDIR"; $sep [WARN] Detected non-existent home directory for `nobody`. This situation can result in some harmless STDERR going to your web server’s error log as errors. If you experience this your options are: 1. Ignore the log entries 2. Create the directory “$home” if it is safe to do so. 3. Change the `nobody` user’s home directory to one that exists. e.g. `usermod --home / nobody` $sep END_HOMEDIR } print "[INFO] `nobody` user created with UID $uid and GID $gid\n" if $user_needs_informed; PK :�[��wL wL * transaction/ea-__WILDCARD__/009-phpconf.plnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # Copyright (c) 2015, cPanel, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package ea_apache2_config::phpconf; use strict; use Cpanel::Imports; use Cpanel::PackMan (); use Try::Tiny; use Cpanel::ConfigFiles::Apache (); use Cpanel::Config::LoadUserDomains (); use Cpanel::Config::LoadCpUserFile (); use Cpanel::Exception (); use Cpanel::WebServer::Userdata (); use Cpanel::DataStore (); use Cpanel::EA4::Util (); use Cpanel::Notify (); use Cpanel::ProgLang (); use Cpanel::WebServer (); use Getopt::Long (); use POSIX qw( :sys_wait_h ); our @PreferredHandlers = qw( suphp dso cgi ); our $cpanel_default_php_pkg = "ea-php" . Cpanel::EA4::Util::get_default_php_version(); $cpanel_default_php_pkg =~ s/\.//g; my ( $php, $server ); sub debug { my $cfg = shift; my $t = localtime; print "[$t] DEBUG: @_\n" if $cfg->{args}->{debug}; } sub is_handler_supported { my ( $handler, $package ) = @_; $php ||= Cpanel::ProgLang->new( type => 'php' ); $server ||= Cpanel::WebServer->new()->get_server( type => 'apache' ); my $ref = $server->get_available_handlers( lang => $php, package => $package ); return 1 if $ref->{$handler}; return 0; } sub send_notification { my ( $package, $language, $webserver, $missing_handler, $replacement_handler ) = @_; my %args = ( class => q{EasyApache::EA4_LangHandlerMissing}, application => q{universal_hook_phpconf}, constructor_args => [ package => $package, language => $language, webserver => $webserver, missing_handler => $missing_handler || 'UNDEFINED', replacement_handler => $replacement_handler ], ); # No point in catching the failure since we can't do anything # about here anyways. try { my $class = Cpanel::Notify::notification_class(%args); waitpid( $class->{'_icontact_pid'}, WNOHANG ); }; return 1; } sub get_preferred_handler { my $package = shift; my $cfg = shift; my $old_handler = $cfg->{$package} || $PreferredHandlers[0]; my $new_handler; if ( is_handler_supported( $old_handler, $package ) ) { $new_handler = $old_handler; } else { for my $handler (@PreferredHandlers) { last if $new_handler; $new_handler = $handler if is_handler_supported( $handler, $package ); } } if ( !$new_handler ) { my $def = Cpanel::EA4::Util::get_default_php_handler(); logger->info("Could not find a handler for $package. Defaulting to “$def” so that, at worst case, we get an error instead of source code."); $new_handler = $def; } return $new_handler; } # EA-3819: The cpanel api calls depend on php.conf having all known packages # to be in php.conf. This will update php.conf with some temporary # values just in case they're missing. This will also remove entries # if they no longer installed. sub sanitize_php_config { my $cfg = shift; my $prog = shift; return 1 unless scalar @{ $cfg->{packages} }; # The %save hash is used to ensure cpanel has a basic php.conf that will # not break the MultiPHP EA4 code if a package or handler is removed # from the system while it's configured. It will iterate over all # possible handler attempting to find a suitable (and supported) # handler. It will resort to the Cpanel::EA4::Util::get_default_php_handler() handler if nothing else # is supported. # # Finally, the cfg_ref hash is what this applications uses to update # packages/handlers to a "preferred" one if the current is missing or # no longer installed. my %save = %{ $cfg->{cfg_ref} }; my $default = delete $cfg->{cfg_ref}{default}; # remove packages which are no longer installed for my $pkg ( keys %{ $cfg->{cfg_ref} } ) { unless ( grep( /\A\Q$pkg\E\z/, @{ $cfg->{packages} } ) ) { delete $cfg->{cfg_ref}->{$pkg}; delete $save{$pkg}; } } # add packages which are newly installed and at least make sure it's a valid handler for my $pkg ( @{ $cfg->{packages} } ) { $save{$pkg} = get_preferred_handler( $pkg, \%save ); } # make sure the default package has been assigned if ( !defined $default ) { my @packages = sort @{ $cfg->{packages} }; # if we have $cpanel_default_php_pkg use that, otherwise use the latest that is installed $default = grep( { $_ eq $cpanel_default_php_pkg } @packages ) ? $cpanel_default_php_pkg : $packages[-1]; } $save{default} = $default; # and only allow a single dso handler, set the rest to Cpanel::EA4::Util::get_default_php_handler() !$cfg->{args}{dryrun} && $prog->set_conf( conf => \%save ); return 1; } # Retrieves current PHP sub get_php_config { my $argv = shift || []; my %cfg = ( packages => [], args => { dryrun => 0, debug => 0 } ); Getopt::Long::Configure(qw( pass_through )); # not sure if we're passed any args by the universal hooks plugin Getopt::Long::GetOptionsFromArray( $argv, dryrun => \$cfg{args}{dryrun}, debug => \$cfg{args}{debug}, ); my $apacheconf = Cpanel::ConfigFiles::Apache->new(); eval { require Cpanel::ProgLang; require Cpanel::ProgLang::Conf; }; # Need to use the old API, not new one if ($@) { $cfg{api} = 'old'; $cfg{apache_path} = $apacheconf->file_conf_php_conf(); $cfg{cfg_path} = $cfg{apache_path} . '.yaml'; try { require Cpanel::Lang::PHP::Settings; my $php = Cpanel::Lang::PHP::Settings->new(); $cfg{php} = $php; $cfg{packages} = $php->php_get_installed_versions(); $cfg{cfg_ref} = Cpanel::DataStore::fetch_ref( $cfg{cfg_path} ); }; } else { # get basic information in %cfg in case php isn't installed my $prog = Cpanel::ProgLang::Conf->new( type => 'php' ); $cfg{api} = 'new'; $cfg{apache_path} = $apacheconf->file_conf_php_conf(); # hack until we can add this API to Cpanel::WebServer $cfg{cfg_path} = $prog->get_file_path(); try { my $php = Cpanel::ProgLang->new( type => 'php' ); # this will die if PHP isn't installed $cfg{php} = $php; $cfg{packages} = $php->get_installed_packages(); $cfg{cfg_ref} = $prog->get_conf(); }; sanitize_php_config( \%cfg, $prog ); } return \%cfg; } sub get_rebuild_settings { my $cfg = shift; my $ref = $cfg->{cfg_ref}; my %settings; return {} unless @{ $cfg->{packages} }; my $php = $cfg->{php}; # We can't assume that suphp will always be available for each package. # This will iterate over each package and verify that the handler is # installed. If it's not, then revert to the Cpanel::EA4::Util::get_default_php_handler() handler, # which should be installed (if it is 'cgi' then it is available by default). for my $package ( @{ $cfg->{packages} } ) { my $old_handler = $ref->{$package} || ''; my $new_handler = get_preferred_handler( $package, $ref ); if ( $old_handler ne '' && $old_handler ne $new_handler ) { print locale->maketext(q{WARNING: You removed a configured [asis,Apache] handler.}), "\n"; print locale->maketext( q{The “[_1]” package will revert to the “[_2]”[comment,the web server handler that will be used in its place (e.g. cgi)] “[_3]” handler.}, $package, 'Apache', $new_handler ), "\n"; $cfg->{args}->{dryrun} && send_notification( $package, 'PHP', 'Apache', $old_handler, $new_handler ); } $settings{$package} = $new_handler; } if ( $cfg->{api} eq 'old' ) { my $cur_sys_default = eval { $php->php_get_system_default_version() }; $settings{phpversion} = _ensure_default_key_is_valid( $cur_sys_default => $cfg ); } else { my $cur_sys_default = $php->get_system_default_package(); $settings{default} = _ensure_default_key_is_valid( $cur_sys_default => $cfg ); } return \%settings; } sub _ensure_default_key_is_valid { my ( $cur_sys_default, $cfg ) = @_; $cur_sys_default = undef if !$cur_sys_default || !grep { $cur_sys_default eq $_ } @{ $cfg->{packages} }; my $def = $cur_sys_default || Cpanel::EA4::Util::get_default_php_version(); if ( $def =~ m/\./ ) { $def = "ea-php$def"; $def =~ s/\.//g; } my $def_hr = Cpanel::PackMan->instance->pkg_hr($def) || {}; $def = $cfg->{packages}[-1] if !$def_hr->{version_installed}; return $def; } sub apply_rebuild_settings { my $cfg = shift; my $settings = shift; if ( $#{ $cfg->{packages} } == -1 ) { debug( $cfg, "No PHP packages installed. Removing configuration files." ); logger->info("!!!! No PHPs installed! !!\nUsers’ PHP settings will be left as is. That way PHP requests will get an error instead of serving source code and potentially sensitive data like database credentials."); !$cfg->{args}->{dryrun} && unlink( $cfg->{apache_path}, $cfg->{cfg_path} ); return 1; } try { if ( $cfg->{api} eq 'old' ) { my %rebuild = %$settings; $rebuild{restart} = 0; $rebuild{dryrun} = 0; $rebuild{version} = $settings->{phpversion}; debug( $cfg, "Updating PHP using old API" ); !$cfg->{args}->{dryrun} && $cfg->{php}->php_set_system_default_version(%rebuild); } else { my %pkginfo = %$settings; my $default = delete $pkginfo{default}; debug( $cfg, "Setting the system default PHP package to the '$default' handler" ); !$cfg->{args}->{dryrun} && $cfg->{php}->set_system_default_package( package => $default ); debug( $cfg, "Successfully updated the system default PHP package" ); require Cpanel::WebServer; my $apache = Cpanel::WebServer->new->get_server( type => "apache" ); my $disable_flag_file = "/var/cpanel/ea4-disable_009-phpconf.pl_user_setting_validation_and_risk_breaking_PHP_based_sites_and_exposing_sensitive_data_in_PHP_source_code"; while ( my ( $pkg, $handler ) = each(%pkginfo) ) { debug( $cfg, "Setting the '$pkg' package to the '$handler' handler" ); if ( !$cfg->{args}->{dryrun} ) { $apache->set_package_handler( type => $handler, lang => $cfg->{php}, package => $pkg, ); try { if ( -e $disable_flag_file ) { die "Ensuring that user settings are still valid is disabled via the existence of $disable_flag_file:\n\t!!!! your PHP based sites may be broken and exposing sensitive data in the source code !!\n"; } $apache->update_user_package_handlers( type => $handler, lang => $cfg->{php}, package => $pkg ); } catch { logger->info("Error updating user package handlers for $pkg: $_"); }; } debug( $cfg, "Successfully updated the '$pkg' package" ); } # now that existing packages are ship shape, let’s handle users still set to non-existent version if ( -e $disable_flag_file ) { logger->info("Ensuring that user settings are still valid is disabled via the existence of $disable_flag_file:\n\t!!!! your PHP based sites may be broken and exposing sensitive data in the source code !!"); } else { update_users_set_to_non_existant_phps( $apache, $cfg->{php}, "inherit" ); } } } catch { logger->die("$_"); # copy $_ since it can be magical }; return 1; } sub update_users_set_to_non_existant_phps { my ( $apache, $lang, $default ) = @_; my ( %users, @error ); Cpanel::Config::LoadUserDomains::loadtrueuserdomains( \%users, 1 ); my %installed; @installed{ @{ $lang->get_installed_packages() } } = (); # this should not be possible *but* just in case if ( !keys %installed ) { logger->info("!!!! No PHPs installed! !!\nUsers’ PHP settings will be left as is. That way PHP requests will get an error instead of serving source code and potentially sensitive data like database credentials."); return; } for my $user ( keys %users ) { next unless $users{$user}; # some accounts are invalid and don't contain a domain in the /etc/trueusersdomain configuration file my $cfg = try { Cpanel::Config::LoadCpUserFile::load_or_die($user) }; next unless $cfg; next if $cfg->{PLAN} =~ /Cpanel\s+Ticket\s+System/i; # Accounts like this are created by the autofixer2 create_temp_reseller_for_ticket_access script when cpanel support logs in my $userdata = Cpanel::WebServer::Userdata->new( user => $user ); for my $vhost ( @{ $userdata->get_vhost_list() } ) { try { my $pkg = $userdata->get_vhost_lang_package( lang => $lang, vhost => $vhost ); if ( $pkg ne "inherit" && !exists $installed{$pkg} ) { # This PHP is no longer installed so set them to the default (their code may break but at least we ensure their source code is not served) logger->info("User $user’s vhost “$vhost” is set to PHP “$pkg” which is no longer installed. Setting them to inherit …"); $apache->set_vhost_lang_package( userdata => $userdata, vhost => $vhost, lang => $lang, package => $default ); $userdata->set_vhost_lang_package( vhost => $vhost, lang => $lang, package => $default ); } } catch { push @error, $_; }; } } die Cpanel::Exception::create( 'Collection', [ exceptions => \@error ] ) if @error > 1; die $error[0] if @error == 1; return 1; } sub setup_session_save_path { require Cpanel::ProgLang::Supported::php::Ini; if ( Cpanel::ProgLang::Supported::php::Ini->can('setup_session_save_path') ) { my $rv = eval { Cpanel::ProgLang::Supported::php::Ini::setup_session_save_path() }; return 2 if ref($@) eq "Cpanel::Exception::FeatureNotEnabled"; # ignore failures from PHP not being installed return $rv; } return; } unless ( caller() ) { my $cfg = get_php_config( \@ARGV ); my $settings = get_rebuild_settings($cfg); apply_rebuild_settings( $cfg, $settings ); setup_session_save_path(); } 1; __END__ =encoding utf8 =head1 NAME 009-phpconf.pl -- package manager universal hook =head1 SYNOPSIS Executed by various package managers via this package: https://github.com/CpanelInc/yum-plugin-universal-hooks =head1 DESCRIPTION This scripts updates the cPanel and Apache MultiPHP configurations. It's important for this script to run after packages have been added, removed, or updated via the package manager because the cPanel MultiPHP system depends on the configuration (default: /etc/cpanel/ea4/php.conf) always being correct. Some of the things it does are as follows: =over 2 =item * If no PHP packages are installed on the system, it will remove all cPanel and Apache configuration information related to PHP. It will leave users’ configurations as-is in case it was a temporary situation or a mistake. It also acts as a security benefit because they will get an error instead of the source code. =item * If a PHP package is removed using the package manager, configuration for that package is removed. Users assigned to it will be moved to the newest PHP installed. This uses userdata for efficiency and reliability. It will not traverse the file system looking for C<.htaccess> files that have PHP looking handlers. That would be an expensive and fragile operation. As long as they use MultiPHP Manager (or CL’s PHP selector/cagefs system?) they will be in ship shape. =item * If a PHP package is added using the package manager, a default configuration is applied. =item * If an Apache handler for PHP is removed using the package manager, a default Apache handler is used instead. =back =head1 DEFAULT SYSTEM PACKAGE If the default PHP package is removed, C<$cpanel_default_php_pkg> (AKA C<Cpanel::EA4::Util::get_default_php_version()>) is used if its installed. Otherwise the latest (according to PHP version number) is used. =head1 APACHE HANDLER FOR PHP If the Apache handler assigned to a PHP package is missing, the following checks are performed. If a check succeeds, no further checks are performed. =over 2 =item 1. Attempt to assign a package to the 'suphp' handler if the mod_suphp Apache module is installed. =item 2. Attempt to assign a package to the 'dso' handler if the correct package is installed. =over 2 =item * IMPORTANT NOTE: Only one 'dso' handler can be assigned at a time. =back =item 3. Attempt to assign a package to the Cpanel::EA4::Util::get_default_php_handler() (which if it is cgi, will work since the mod_cgi or mod_cgid Apache modules should be installed (and in the weird case it isn't then at leats they'll get errors instead of source code)). =back =head1 ADDITIONAL INFORMATION This script depends on the packages setting up the correct dependencies and conflicts. For example, this script doesn't check the Apache configuration for MPM ITK when assigning PHP to the SuPHP handler since it assumes the package should already have a conflict detected by the package manager during installation. PK :�[���� � 4 transaction/ea-__WILDCARD__/070-cloudlinux-cagefs.plnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # Copyright (c) 2015, cPanel, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use strict; use Cpanel::Imports; use Cpanel::CloudLinux (); if ( Cpanel::CloudLinux::installed() && _has_lines_matching( '/etc/cagefs/cagefs.mp', qr{^\s*[!@#]?/\w+} ) ) { print locale->maketext('Updating the [asis,CloudLinux CageFS] virtual filesystem …') . "\n"; system('/usr/sbin/cagefsctl --update --force-update') && logger->warn("/usr/sbin/cagefsctl exited non-zero: $?"); print "\n"; print locale->maketext(' … done.') . "\n"; } sub _has_lines_matching { my ( $file, $regexp ) = @_; return if !-s $file || !-f _; my $matches = 0; if ( open( my $fh, '<', $file ) ) { while ( my $line = <$fh> ) { if ( $line =~ $regexp ) { $matches = 1; last; } } close($fh); return 1 if $matches; } else { logger->warn("Could not read $file: $!"); } return; }PK :�[�Ț�� � 1 transaction/ea-__WILDCARD__/520-enablefileprotectnu ȯ�� #!/usr/bin/bash if [[ -e /var/cpanel/fileprotect ]] then /usr/local/cpanel/scripts/enablefileprotect else /usr/local/cpanel/scripts/disablefileprotect fi PK :�[x�F# # 6 transaction/ea-__WILDCARD__/400-patch_mod_security2.plnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # Copyright (c) 2016, cPanel, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use strict; use warnings; use Cpanel::FileUtils; use Cpanel::Version::Compare; use File::Copy; use Whostmgr::Version; use Whostmgr::ModSecurity; print "Aligning modsec config to Whostmgr\n"; my $whm_version = Whostmgr::Version::getversion(); print "- Whostmgr version $whm_version\n"; if ( !supports_new_location($whm_version) ) { print "- Whostmgr supports conf.d location only\n"; print "- Migrating modsec2 files to conf.d\n"; unmigrate_modsec2_config_move(); } else { print "- Whostmgr supports conf.d/modsec location\n"; print "- No change necessary\n"; } exit 0; sub supports_new_location { my $version = shift; # explicit returns because we will need to add more conditions as we backport # the WHM UI interface to each particular version. # # Future lines should look like: # return 1 if ( Cpanel::Version::Compare::compare....( $version, '>=', 'version guaranteed to have backport' ) ); return 1 if ( Cpanel::Version::Compare::compare_major_release( $version, '>=', '11.58' ) ); return 0; } sub unmigrate_modsec2_config_move { my $config_prefix = Whostmgr::ModSecurity::config_prefix(); print "- moving $config_prefix/modsec/modsec2.cpanel.conf $config_prefix/modsec2.cpanel.conf\n"; File::Copy::move( "$config_prefix/modsec/modsec2.cpanel.conf", "$config_prefix/modsec2.cpanel.conf" ); print "- moving $config_prefix/modsec/modsec2.cpanel.conf.PREVIOUS $config_prefix/modsec2.cpanel.conf.PREVIOUS\n"; File::Copy::move( "$config_prefix/modsec/modsec2.cpanel.conf.PREVIOUS", "$config_prefix/modsec2.cpanel.conf.PREVIOUS" ); print "- moving $config_prefix/modsec/modsec2.user.conf $config_prefix/modsec2.user.conf\n"; File::Copy::move( "$config_prefix/modsec/modsec2.user.conf", "$config_prefix/modsec2.user.conf" ); print "- moving $config_prefix/modsec/modsec2.user.conf.PREVIOUS $config_prefix/modsec2.user.conf.PREVIOUS\n"; File::Copy::move( "$config_prefix/modsec/modsec2.user.conf.PREVIOUS", "$config_prefix/modsec2.user.conf.PREVIOUS" ); print "- removing modsec2.cpanel.conf include in $config_prefix/modsec2.conf\n"; Cpanel::FileUtils::regex_rep_file( "$config_prefix/modsec2.conf", { qr{^\s*Include\s+.*/modsec/modsec2\.cpanel\.conf\s*} => "" } ); print "- removing modsec2.user.conf include in $config_prefix/modsec2.conf\n"; Cpanel::FileUtils::regex_rep_file( "$config_prefix/modsec2.conf", { qr{^\s*Include\s+.*/modsec/modsec2\.user\.conf\s*} => "" } ); return 1; } PK :�[c�n� � 8 transaction/ea-__WILDCARD__/060-setup_apache_symlinks.plnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # Copyright (c) 2015, cPanel, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use strict; use warnings; use Cpanel::ConfigFiles::Apache (); use Cpanel::FileUtils (); # Get the paths from the paths.conf file my $apacheconf = Cpanel::ConfigFiles::Apache->new(); # These are the old Easy Apache 3 paths my $ea3_basedir = '/usr/local/apache'; my $ea3_confdir = "$ea3_basedir/conf"; my $ea3_bindir = "$ea3_basedir/bin"; my %ea3_paths = ( dir_logs => "$ea3_basedir/logs", dir_domlogs => "$ea3_basedir/domlogs", dir_modules => "$ea3_basedir/modules", dir_conf_includes => "$ea3_confdir/includes", dir_conf_userdata => "$ea3_confdir/userdata", dir_docroot => "$ea3_basedir/htdocs", file_access_log => "$ea3_basedir/access_log", file_error_log => "$ea3_basedir/error_log", file_conf => "$ea3_confdir/httpd.conf", file_conf_mime_types => "$ea3_confdir/mime.types", file_conf_srm_conf => "$ea3_confdir/srm.conf", file_conf_php_conf => "$ea3_confdir/php.conf", bin_httpd => "$ea3_bindir/httpd", bin_apachectl => "$ea3_bindir/apachectl", bin_suexec => "$ea3_bindir/suexec", ); for my $dir ( $ea3_basedir, $ea3_bindir, $ea3_confdir ) { next if -d $dir; if ( !mkdir($dir) ) { die "Unable to create $dir: $!\n"; } } # Make a symlink from all the old ea3 paths to the new folders my $verbose = grep /^--verbose/, @ARGV; my $had_errors = 0; foreach my $key ( sort keys %ea3_paths ) { eval { # If the old and the new are the same, no symlink required if ( $apacheconf->{$key} eq $ea3_paths{$key} ) { print "Source and destination same, $ea3_paths{$key}, no need to link\n" if $verbose; return; } # No sense in trying to link to something that doesn't exist if ( !-e $apacheconf->{$key} ) { print "Target $apacheconf->{$key} doesn't exist, can't link to it\n" if $verbose; return; } # If a symlink already exists, it may be old/wrong, remake it if ( -l $ea3_paths{$key} ) { if ( readlink( $ea3_paths{$key} ) ne $apacheconf->{$key} ) { print "Previous symlink at $ea3_paths{$key}, unlinking\n" if $verbose; unlink( $ea3_paths{$key} ) or die("Unable to unlink $ea3_paths{$key}: $!\n"); } else { print "Link already exists: $ea3_paths{$key} -> $apacheconf->{$key}\n" if $verbose; return; } } # If we can see the item to be linked, it is possibly visible # due to its parent being linked. # If not, backup and move the EA3 file before creating the link if ( -e $ea3_paths{$key} ) { # Test if they are actually the same file by virtue of parent # directory linkage if ( Cpanel::FileUtils::equivalent_files( $ea3_paths{$key}, $apacheconf->{$key} ) ) { print "$ea3_paths{$key} already linked via parent directory, no need to link\n" if $verbose; return; } # Move the file out of the way so we can create the link # Passing "-fa" to safemv will cause it to uniquely rename # the destination file if it already exists print "Renaming $ea3_paths{$key} to $ea3_paths{$key}.ea3 to create link\n" if $verbose; Cpanel::FileUtils::safemv( "-fa", $ea3_paths{$key}, $ea3_paths{$key} . '.ea3' ) or die("Unable to rename $ea3_paths{$key}: $!\n"); } print "Linking $ea3_paths{$key} -> $apacheconf->{$key}\n" if $verbose; symlink( $apacheconf->{$key}, $ea3_paths{$key} ) or die("Unable to symlink $ea3_paths{$key} to $apacheconf->{$key}: $!\n"); }; if ($@) { warn "Error: $@"; $had_errors++; } } if ($had_errors) { exit 1; } PK :�[,��C C . transaction/ea-__WILDCARD__/010-purge_cache.plnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # Copyright (c) 2015, cPanel, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use strict; use warnings; use Cpanel::CachedCommand::Utils (); # # First purge all the CachedCommand caches # purge_cached_commands(); # # Rebuild the global cache # print "Rebuilding global cache\n"; system('/usr/local/cpanel/bin/build_global_cache'); sub purge_cached_commands { print "Purging all relevant cached command results\n"; # Get the directory where the CachedCommand cache files live my $cache_dir = Cpanel::CachedCommand::Utils::_get_datastore_dir(); if ( !defined $cache_dir or !$cache_dir ) { print STDERR "Unable to obtain the cached command datastore directory\n"; return; } # Guard against getting back something like "/", make sure it is a real cPanel cache dir if ( $cache_dir !~ /\.cpanel\/datastore$/ ) { print STDERR "Invalid cached command datastore directory: $cache_dir\n"; return; } if ( !-d $cache_dir ) { print STDERR "$cache_dir is not a directory\n"; return; } my $dh; if ( !opendir( $dh, $cache_dir ) ) { print STDERR "Unable to open $cache_dir: $!\n"; return; } while ( my $file = readdir($dh) ) { my $full_path = "$cache_dir/$file"; # Only actual files, no subdirs, no . or .. next unless -f $full_path; # Only actions run on apache next unless ( $file =~ /http/ ); print "Removing: $full_path\n"; unlink $full_path or print STDERR "Unable to delete $file: $!\n"; } closedir($dh); } PK :�[�ǁь � 9 transaction/__WILDCARD__-php__WILDCARD__/010-suphpconf.plnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # cpanel - 010-suphpconf.pl Copyright 2017 cPanel, Inc. # All rights Reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited package suphpconf; use strict; use warnings; use Cpanel::SysPkgs::SCL (); our $suphpconf = '/etc/suphp.conf'; run() unless caller; sub run { if ( -e $suphpconf ) { if ( !-e "/usr/local/bin/ea_convert_php_ini" ) { # This madness will go away with EA-5696 warn "Unable to update /etc/suphp.conf without the ea-cpanel-tools package installed.\n"; } else { require "/usr/local/bin/ea_convert_php_ini"; ##no critic (RequireBarewordIncludes) This madness will go away with EA-5696 my $parser = Parse::PHP::Ini->new; my $tree = $parser->parse( path => $suphpconf ); my $handlers = $parser->get_matching_section( $tree, 'handlers' ); if ( !$handlers ) { $handlers = $parser->make_section_node( 'handlers', -1 ); $tree->add_daughter($handlers); } my %packages; @packages{ @{ Cpanel::SysPkgs::SCL::get_scl_versions(qr/\w+-php/) } } = (); # update/cleanout existing entries for my $daughter ( @{ $handlers->{daughters} } ) { if ( $daughter->{name} =~ m{application/x-httpd-(.*)} ) { my $pkg = $1; if ( exists $packages{$pkg} ) { my $cgi_path = _get_cgi_path($pkg); my $count = $daughter->{attributes}{line}; # TODO: make this something else? my $tmp = $parser->make_setting_node( "application/x-httpd-$pkg", qq{"php:$cgi_path"}, $count ); my $attr = $tmp->attribute(); $parser->update_node( $daughter, $attr ); print "Ensuring current entry for “$pkg” is correct …\n"; $packages{$pkg} = "update"; } else { print "Ignoring current entry for “$pkg” …\n"; $packages{$pkg} = "ignore"; } } } # add entries reflecting the actual state for my $pkg ( keys %packages ) { if ( !$packages{$pkg} ) { my $cgi_path = _get_cgi_path($pkg); my $count = 0; # TODO: make this something else? my $setting = $parser->make_setting_node( "application/x-httpd-$pkg", qq{"php:$cgi_path"}, $count ); $handlers->add_daughter($setting); print "Adding entry for “$pkg” …\n"; $packages{$pkg} = "add"; } } # write $suphpconf _write_suphpconf($tree); } } else { print "Nothing to do ($suphpconf does not exist)\n"; } return; } ############### #### helpers ## ############### sub _get_cgi_path { my ($pkg) = @_; my $cgi_path = Cpanel::SysPkgs::SCL::get_scl_prefix($pkg) . "/root/usr/bin/php-cgi"; if ( !-x $cgi_path ) { warn "$cgi_path is not executable, please rectify (e.g. a symlink …/root to the right spot should do the trick)\n"; } return $cgi_path; } sub _write_suphpconf { my ($tree) = @_; # Encapsualte the madness here, NS use noted in /usr/local/bin/ea_convert_php_ini no warnings "once"; local $ea_convert_php_ini_file::Cfg{force} = 1; ea_convert_php_ini_file::write_php_ini( $tree, $suphpconf ); } PK :�[��wL wL 7 transaction/__WILDCARD__-php__WILDCARD__/009-phpconf.plnu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl # Copyright (c) 2015, cPanel, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package ea_apache2_config::phpconf; use strict; use Cpanel::Imports; use Cpanel::PackMan (); use Try::Tiny; use Cpanel::ConfigFiles::Apache (); use Cpanel::Config::LoadUserDomains (); use Cpanel::Config::LoadCpUserFile (); use Cpanel::Exception (); use Cpanel::WebServer::Userdata (); use Cpanel::DataStore (); use Cpanel::EA4::Util (); use Cpanel::Notify (); use Cpanel::ProgLang (); use Cpanel::WebServer (); use Getopt::Long (); use POSIX qw( :sys_wait_h ); our @PreferredHandlers = qw( suphp dso cgi ); our $cpanel_default_php_pkg = "ea-php" . Cpanel::EA4::Util::get_default_php_version(); $cpanel_default_php_pkg =~ s/\.//g; my ( $php, $server ); sub debug { my $cfg = shift; my $t = localtime; print "[$t] DEBUG: @_\n" if $cfg->{args}->{debug}; } sub is_handler_supported { my ( $handler, $package ) = @_; $php ||= Cpanel::ProgLang->new( type => 'php' ); $server ||= Cpanel::WebServer->new()->get_server( type => 'apache' ); my $ref = $server->get_available_handlers( lang => $php, package => $package ); return 1 if $ref->{$handler}; return 0; } sub send_notification { my ( $package, $language, $webserver, $missing_handler, $replacement_handler ) = @_; my %args = ( class => q{EasyApache::EA4_LangHandlerMissing}, application => q{universal_hook_phpconf}, constructor_args => [ package => $package, language => $language, webserver => $webserver, missing_handler => $missing_handler || 'UNDEFINED', replacement_handler => $replacement_handler ], ); # No point in catching the failure since we can't do anything # about here anyways. try { my $class = Cpanel::Notify::notification_class(%args); waitpid( $class->{'_icontact_pid'}, WNOHANG ); }; return 1; } sub get_preferred_handler { my $package = shift; my $cfg = shift; my $old_handler = $cfg->{$package} || $PreferredHandlers[0]; my $new_handler; if ( is_handler_supported( $old_handler, $package ) ) { $new_handler = $old_handler; } else { for my $handler (@PreferredHandlers) { last if $new_handler; $new_handler = $handler if is_handler_supported( $handler, $package ); } } if ( !$new_handler ) { my $def = Cpanel::EA4::Util::get_default_php_handler(); logger->info("Could not find a handler for $package. Defaulting to “$def” so that, at worst case, we get an error instead of source code."); $new_handler = $def; } return $new_handler; } # EA-3819: The cpanel api calls depend on php.conf having all known packages # to be in php.conf. This will update php.conf with some temporary # values just in case they're missing. This will also remove entries # if they no longer installed. sub sanitize_php_config { my $cfg = shift; my $prog = shift; return 1 unless scalar @{ $cfg->{packages} }; # The %save hash is used to ensure cpanel has a basic php.conf that will # not break the MultiPHP EA4 code if a package or handler is removed # from the system while it's configured. It will iterate over all # possible handler attempting to find a suitable (and supported) # handler. It will resort to the Cpanel::EA4::Util::get_default_php_handler() handler if nothing else # is supported. # # Finally, the cfg_ref hash is what this applications uses to update # packages/handlers to a "preferred" one if the current is missing or # no longer installed. my %save = %{ $cfg->{cfg_ref} }; my $default = delete $cfg->{cfg_ref}{default}; # remove packages which are no longer installed for my $pkg ( keys %{ $cfg->{cfg_ref} } ) { unless ( grep( /\A\Q$pkg\E\z/, @{ $cfg->{packages} } ) ) { delete $cfg->{cfg_ref}->{$pkg}; delete $save{$pkg}; } } # add packages which are newly installed and at least make sure it's a valid handler for my $pkg ( @{ $cfg->{packages} } ) { $save{$pkg} = get_preferred_handler( $pkg, \%save ); } # make sure the default package has been assigned if ( !defined $default ) { my @packages = sort @{ $cfg->{packages} }; # if we have $cpanel_default_php_pkg use that, otherwise use the latest that is installed $default = grep( { $_ eq $cpanel_default_php_pkg } @packages ) ? $cpanel_default_php_pkg : $packages[-1]; } $save{default} = $default; # and only allow a single dso handler, set the rest to Cpanel::EA4::Util::get_default_php_handler() !$cfg->{args}{dryrun} && $prog->set_conf( conf => \%save ); return 1; } # Retrieves current PHP sub get_php_config { my $argv = shift || []; my %cfg = ( packages => [], args => { dryrun => 0, debug => 0 } ); Getopt::Long::Configure(qw( pass_through )); # not sure if we're passed any args by the universal hooks plugin Getopt::Long::GetOptionsFromArray( $argv, dryrun => \$cfg{args}{dryrun}, debug => \$cfg{args}{debug}, ); my $apacheconf = Cpanel::ConfigFiles::Apache->new(); eval { require Cpanel::ProgLang; require Cpanel::ProgLang::Conf; }; # Need to use the old API, not new one if ($@) { $cfg{api} = 'old'; $cfg{apache_path} = $apacheconf->file_conf_php_conf(); $cfg{cfg_path} = $cfg{apache_path} . '.yaml'; try { require Cpanel::Lang::PHP::Settings; my $php = Cpanel::Lang::PHP::Settings->new(); $cfg{php} = $php; $cfg{packages} = $php->php_get_installed_versions(); $cfg{cfg_ref} = Cpanel::DataStore::fetch_ref( $cfg{cfg_path} ); }; } else { # get basic information in %cfg in case php isn't installed my $prog = Cpanel::ProgLang::Conf->new( type => 'php' ); $cfg{api} = 'new'; $cfg{apache_path} = $apacheconf->file_conf_php_conf(); # hack until we can add this API to Cpanel::WebServer $cfg{cfg_path} = $prog->get_file_path(); try { my $php = Cpanel::ProgLang->new( type => 'php' ); # this will die if PHP isn't installed $cfg{php} = $php; $cfg{packages} = $php->get_installed_packages(); $cfg{cfg_ref} = $prog->get_conf(); }; sanitize_php_config( \%cfg, $prog ); } return \%cfg; } sub get_rebuild_settings { my $cfg = shift; my $ref = $cfg->{cfg_ref}; my %settings; return {} unless @{ $cfg->{packages} }; my $php = $cfg->{php}; # We can't assume that suphp will always be available for each package. # This will iterate over each package and verify that the handler is # installed. If it's not, then revert to the Cpanel::EA4::Util::get_default_php_handler() handler, # which should be installed (if it is 'cgi' then it is available by default). for my $package ( @{ $cfg->{packages} } ) { my $old_handler = $ref->{$package} || ''; my $new_handler = get_preferred_handler( $package, $ref ); if ( $old_handler ne '' && $old_handler ne $new_handler ) { print locale->maketext(q{WARNING: You removed a configured [asis,Apache] handler.}), "\n"; print locale->maketext( q{The “[_1]” package will revert to the “[_2]”[comment,the web server handler that will be used in its place (e.g. cgi)] “[_3]” handler.}, $package, 'Apache', $new_handler ), "\n"; $cfg->{args}->{dryrun} && send_notification( $package, 'PHP', 'Apache', $old_handler, $new_handler ); } $settings{$package} = $new_handler; } if ( $cfg->{api} eq 'old' ) { my $cur_sys_default = eval { $php->php_get_system_default_version() }; $settings{phpversion} = _ensure_default_key_is_valid( $cur_sys_default => $cfg ); } else { my $cur_sys_default = $php->get_system_default_package(); $settings{default} = _ensure_default_key_is_valid( $cur_sys_default => $cfg ); } return \%settings; } sub _ensure_default_key_is_valid { my ( $cur_sys_default, $cfg ) = @_; $cur_sys_default = undef if !$cur_sys_default || !grep { $cur_sys_default eq $_ } @{ $cfg->{packages} }; my $def = $cur_sys_default || Cpanel::EA4::Util::get_default_php_version(); if ( $def =~ m/\./ ) { $def = "ea-php$def"; $def =~ s/\.//g; } my $def_hr = Cpanel::PackMan->instance->pkg_hr($def) || {}; $def = $cfg->{packages}[-1] if !$def_hr->{version_installed}; return $def; } sub apply_rebuild_settings { my $cfg = shift; my $settings = shift; if ( $#{ $cfg->{packages} } == -1 ) { debug( $cfg, "No PHP packages installed. Removing configuration files." ); logger->info("!!!! No PHPs installed! !!\nUsers’ PHP settings will be left as is. That way PHP requests will get an error instead of serving source code and potentially sensitive data like database credentials."); !$cfg->{args}->{dryrun} && unlink( $cfg->{apache_path}, $cfg->{cfg_path} ); return 1; } try { if ( $cfg->{api} eq 'old' ) { my %rebuild = %$settings; $rebuild{restart} = 0; $rebuild{dryrun} = 0; $rebuild{version} = $settings->{phpversion}; debug( $cfg, "Updating PHP using old API" ); !$cfg->{args}->{dryrun} && $cfg->{php}->php_set_system_default_version(%rebuild); } else { my %pkginfo = %$settings; my $default = delete $pkginfo{default}; debug( $cfg, "Setting the system default PHP package to the '$default' handler" ); !$cfg->{args}->{dryrun} && $cfg->{php}->set_system_default_package( package => $default ); debug( $cfg, "Successfully updated the system default PHP package" ); require Cpanel::WebServer; my $apache = Cpanel::WebServer->new->get_server( type => "apache" ); my $disable_flag_file = "/var/cpanel/ea4-disable_009-phpconf.pl_user_setting_validation_and_risk_breaking_PHP_based_sites_and_exposing_sensitive_data_in_PHP_source_code"; while ( my ( $pkg, $handler ) = each(%pkginfo) ) { debug( $cfg, "Setting the '$pkg' package to the '$handler' handler" ); if ( !$cfg->{args}->{dryrun} ) { $apache->set_package_handler( type => $handler, lang => $cfg->{php}, package => $pkg, ); try { if ( -e $disable_flag_file ) { die "Ensuring that user settings are still valid is disabled via the existence of $disable_flag_file:\n\t!!!! your PHP based sites may be broken and exposing sensitive data in the source code !!\n"; } $apache->update_user_package_handlers( type => $handler, lang => $cfg->{php}, package => $pkg ); } catch { logger->info("Error updating user package handlers for $pkg: $_"); }; } debug( $cfg, "Successfully updated the '$pkg' package" ); } # now that existing packages are ship shape, let’s handle users still set to non-existent version if ( -e $disable_flag_file ) { logger->info("Ensuring that user settings are still valid is disabled via the existence of $disable_flag_file:\n\t!!!! your PHP based sites may be broken and exposing sensitive data in the source code !!"); } else { update_users_set_to_non_existant_phps( $apache, $cfg->{php}, "inherit" ); } } } catch { logger->die("$_"); # copy $_ since it can be magical }; return 1; } sub update_users_set_to_non_existant_phps { my ( $apache, $lang, $default ) = @_; my ( %users, @error ); Cpanel::Config::LoadUserDomains::loadtrueuserdomains( \%users, 1 ); my %installed; @installed{ @{ $lang->get_installed_packages() } } = (); # this should not be possible *but* just in case if ( !keys %installed ) { logger->info("!!!! No PHPs installed! !!\nUsers’ PHP settings will be left as is. That way PHP requests will get an error instead of serving source code and potentially sensitive data like database credentials."); return; } for my $user ( keys %users ) { next unless $users{$user}; # some accounts are invalid and don't contain a domain in the /etc/trueusersdomain configuration file my $cfg = try { Cpanel::Config::LoadCpUserFile::load_or_die($user) }; next unless $cfg; next if $cfg->{PLAN} =~ /Cpanel\s+Ticket\s+System/i; # Accounts like this are created by the autofixer2 create_temp_reseller_for_ticket_access script when cpanel support logs in my $userdata = Cpanel::WebServer::Userdata->new( user => $user ); for my $vhost ( @{ $userdata->get_vhost_list() } ) { try { my $pkg = $userdata->get_vhost_lang_package( lang => $lang, vhost => $vhost ); if ( $pkg ne "inherit" && !exists $installed{$pkg} ) { # This PHP is no longer installed so set them to the default (their code may break but at least we ensure their source code is not served) logger->info("User $user’s vhost “$vhost” is set to PHP “$pkg” which is no longer installed. Setting them to inherit …"); $apache->set_vhost_lang_package( userdata => $userdata, vhost => $vhost, lang => $lang, package => $default ); $userdata->set_vhost_lang_package( vhost => $vhost, lang => $lang, package => $default ); } } catch { push @error, $_; }; } } die Cpanel::Exception::create( 'Collection', [ exceptions => \@error ] ) if @error > 1; die $error[0] if @error == 1; return 1; } sub setup_session_save_path { require Cpanel::ProgLang::Supported::php::Ini; if ( Cpanel::ProgLang::Supported::php::Ini->can('setup_session_save_path') ) { my $rv = eval { Cpanel::ProgLang::Supported::php::Ini::setup_session_save_path() }; return 2 if ref($@) eq "Cpanel::Exception::FeatureNotEnabled"; # ignore failures from PHP not being installed return $rv; } return; } unless ( caller() ) { my $cfg = get_php_config( \@ARGV ); my $settings = get_rebuild_settings($cfg); apply_rebuild_settings( $cfg, $settings ); setup_session_save_path(); } 1; __END__ =encoding utf8 =head1 NAME 009-phpconf.pl -- package manager universal hook =head1 SYNOPSIS Executed by various package managers via this package: https://github.com/CpanelInc/yum-plugin-universal-hooks =head1 DESCRIPTION This scripts updates the cPanel and Apache MultiPHP configurations. It's important for this script to run after packages have been added, removed, or updated via the package manager because the cPanel MultiPHP system depends on the configuration (default: /etc/cpanel/ea4/php.conf) always being correct. Some of the things it does are as follows: =over 2 =item * If no PHP packages are installed on the system, it will remove all cPanel and Apache configuration information related to PHP. It will leave users’ configurations as-is in case it was a temporary situation or a mistake. It also acts as a security benefit because they will get an error instead of the source code. =item * If a PHP package is removed using the package manager, configuration for that package is removed. Users assigned to it will be moved to the newest PHP installed. This uses userdata for efficiency and reliability. It will not traverse the file system looking for C<.htaccess> files that have PHP looking handlers. That would be an expensive and fragile operation. As long as they use MultiPHP Manager (or CL’s PHP selector/cagefs system?) they will be in ship shape. =item * If a PHP package is added using the package manager, a default configuration is applied. =item * If an Apache handler for PHP is removed using the package manager, a default Apache handler is used instead. =back =head1 DEFAULT SYSTEM PACKAGE If the default PHP package is removed, C<$cpanel_default_php_pkg> (AKA C<Cpanel::EA4::Util::get_default_php_version()>) is used if its installed. Otherwise the latest (according to PHP version number) is used. =head1 APACHE HANDLER FOR PHP If the Apache handler assigned to a PHP package is missing, the following checks are performed. If a check succeeds, no further checks are performed. =over 2 =item 1. Attempt to assign a package to the 'suphp' handler if the mod_suphp Apache module is installed. =item 2. Attempt to assign a package to the 'dso' handler if the correct package is installed. =over 2 =item * IMPORTANT NOTE: Only one 'dso' handler can be assigned at a time. =back =item 3. Attempt to assign a package to the Cpanel::EA4::Util::get_default_php_handler() (which if it is cgi, will work since the mod_cgi or mod_cgid Apache modules should be installed (and in the weird case it isn't then at leats they'll get errors instead of source code)). =back =head1 ADDITIONAL INFORMATION This script depends on the packages setting up the correct dependencies and conflicts. For example, this script doesn't check the Apache configuration for MPM ITK when assigning PHP to the SuPHP handler since it assumes the package should already have a conflict detected by the package manager during installation. PK :�[�L�Q Q @ transaction/ea-php__WILDCARD__/011-migrate_extension_to_pecl_ininu ȯ�� #!/usr/local/cpanel/3rdparty/bin/perl ############################################################################################## # # Copyright (c) 2017, cPanel, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ############################################################################################## use strict; use warnings; use Cpanel::Version::Tiny (); use Cpanel::Version::Compare (); use File::Slurp (); # because we are not sure if older versions all have the same Cpanel:: modules/functions/behavior # The libraries needed to run this script weren't introduced until this release. exit 0 unless Cpanel::Version::Compare::compare( $Cpanel::Version::Tiny::VERSION_BUILD, '>=', '11.66' ); require Cpanel::ProgLang; # oooold versions do not have this so require it after the version check my $php = Cpanel::ProgLang->new( type => 'php' ); my $installed_phps = $php->get_installed_packages(); # this always returns an array ref for my $php_pkg ( @{$installed_phps} ) { next if ($php_pkg =~ m/alt-php/); print "Processing $php_pkg …\n"; my $source = $php->get_ini( package => $php_pkg )->get_default_system_ini(); my $pecl = $source; $pecl =~ s{/php\.ini$}{/php.d/zzzzzzz-pecl.ini}; print "\t… moving zend_extension and extension directives from php.ini to php.d/zzzzzzz-pecl.ini …\n"; _migrate_extension_directives( $source, $pecl ); } ############### #### helpers ## ############### sub _migrate_extension_directives { my ( $from, $to ) = @_; # 1. grab all extension directives from $from my @from_cont = File::Slurp::read_file($from); $from_cont[-1] .= "\n" if substr( $from_cont[-1], -1, 1 ) ne "\n"; # ensure trailing newline on last line my @extensions = grep { m/^\s*(?:zend_)?extension\s*=/ } @from_cont; if (@extensions) { # 2. write them to $to my @to_cont = -e $to ? File::Slurp::read_file($to) : (); File::Slurp::write_file( $to, ( @extensions, @to_cont ) ); # 3. remove them from $from File::Slurp::write_file( $from, grep( !m/\s*(?:zend_)?extension\s*=/, @from_cont ) ); } return 1; } PK :�[���� � <