plugin_dir = 'really-simple-ssl-pro-multisite'; $this->plugin_filename = 'really-simple-ssl-pro-multisite.php'; } else { $this->plugin_dir = 'really-simple-ssl-pro'; $this->plugin_filename = 'really-simple-ssl-pro.php'; } } self::$_this = $this; $this->abs_path = $this->getabs_path(); register_deactivation_hook( __DIR__ . '/' . $this->plugin_filename, array( $this, 'deactivate' ) ); add_action( 'admin_init', array( $this, 'add_privacy_info' ) ); add_action( 'admin_init', array( $this, 'maybe_dismiss_review_notice' ) ); add_action( 'rsssl_daily_cron', array( $this, 'clear_admin_notices_cache' ) ); //add the settings page for the plugin add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); add_action( 'admin_init', array( $this, 'listen_for_deactivation' ), 40 ); add_action( 'plugins_loaded', array( $this, 'maybe_redirect_old_settings_url' ), 10 ); $plugin = rsssl_plugin; add_filter( "plugin_action_links_$plugin", array( $this, 'plugin_settings_link' ) ); //Add update notification to Settings admin menu add_action( 'admin_menu', array( $this, 'add_plus_ones' ) ); //callbacks for the ajax dismiss buttons add_action( 'wp_ajax_rsssl_dismiss_review_notice', array( $this, 'dismiss_review_notice_callback' ) ); //handle notices add_action( 'admin_notices', array( $this, 'show_notices' ) ); //show review notice, only to free users if ( ! defined( 'rsssl_pro' ) && ! is_multisite() ) { add_action( 'admin_notices', array( $this, 'show_leave_review_notice' ) ); } //hooks only needed on settings page if ( $this->is_settings_page() ) { /** * Htaccess redirect handling */ add_action( 'rsssl_after_save_field', array( $this, 'maybe_flush_wprocket_htaccess' ), 100, 4 ); add_action( 'admin_init', array( $this, 'insert_secure_cookie_settings' ), 70 ); add_action( 'admin_init', array( $this, 'recheck_certificate' ) ); } add_filter( 'rsssl_htaccess_security_rules', array( $this, 'add_htaccess_redirect' ) ); add_filter( 'before_rocket_htaccess_rules', array( $this, 'add_htaccess_redirect_before_wp_rocket' ) ); add_filter( 'admin_init', array( $this, 'handle_activation' ) ); add_action( 'rocket_activation', 'rsssl_wrap_htaccess' ); add_action( 'rocket_deactivation', 'rsssl_wrap_htaccess' ); $plugin = rsssl_plugin; add_filter( "plugin_action_links_$plugin", array($this,'plugin_settings_link' ) ); add_filter( "network_admin_plugin_action_links_$plugin", array($this,'plugin_settings_link' ) ); add_action( 'upgrader_process_complete', array( $this, 'run_table_init_hook'), 10, 1); add_action( 'wp_initialize_site', array( $this, 'run_table_init_hook'), 10, 1); } public static function this() { return self::$_this; } /** * On Multisite site creation, run table init hook as well. * @return void */ public function run_table_init_hook(){ //only load on front-end if it's a cron job if ( !is_admin() && !wp_doing_cron() ) { return; } if (!wp_doing_cron() && !rsssl_user_can_manage() ) { return; } do_action( 'rsssl_install_tables' ); //we need to run table creation across subsites as well. if ( is_multisite() ) { $sites = get_sites(); if (count($sites)>0) { foreach ($sites as $site) { switch_to_blog($site->blog_id); do_action( 'rsssl_install_tables' ); restore_current_blog(); } } } } public function handle_activation(){ if ( !rsssl_admin_logged_in() ) { return; } if ( get_option('rsssl_activation') ) { if ( !class_exists('rsssl_le_hosts')) { require_once( rsssl_path . 'lets-encrypt/config/class-hosts.php'); } ( new rsssl_le_hosts() )->detect_host_on_activation(); $this->run_table_init_hook(); do_action('rsssl_activation'); delete_option('rsssl_activation'); } } /** * Add settings link on plugins overview page * @param array $links * * @return array */ public function plugin_settings_link($links) { //free version if ( ! rsssl_user_can_manage() || ( is_multisite() && ! is_network_admin() ) ) { return $links; } $settings_link = ''; $url = add_query_arg( array( 'page' => 'really-simple-security' ), rsssl_admin_url() ); //settings only on network wide activated, or no multisite at all. if ( is_multisite() && rsssl_is_networkwide_active() && is_super_admin() ) { $settings_link = '' . __( 'Settings', 'really-simple-ssl' ) . ''; } elseif ( ! is_multisite() ) { $settings_link = '' . __( 'Settings', 'really-simple-ssl' ) . ''; } array_unshift( $links, $settings_link ); //support $support = apply_filters( 'rsssl_support_link', '' . __( 'Support', 'really-simple-ssl' ) . '' ); array_unshift( $links, $support ); if ( ! defined( 'rsssl_pro' ) ) { $upgrade_link = '' . __( 'Improve security - Upgrade', 'really-simple-ssl' ) . ''; array_unshift( $links, $upgrade_link ); } return $links; } /** * Redirect to the new settings page * * @return void */ public function maybe_redirect_old_settings_url() { if ( ! rsssl_user_can_manage() || is_multisite() ) { return; } if ( isset( $_GET['page'] ) && 'rlrsssl_really_simple_ssl' === $_GET['page'] ) { wp_redirect( add_query_arg( [ 'page' => 'really-simple-security' ], rsssl_admin_url() ) ); exit; } } /** * Add some privacy info, telling our users we aren't tracking them */ public function add_privacy_info() { if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) { return; } $content = sprintf( // translators: %s is replaced with the hyperlink __( 'Really Simple SSL and Really Simple SSL add-ons do not process any personal identifiable information, so the GDPR does not apply to these plugins or usage of these plugins on your website. You can find our privacy policy here.', 'really-simple-ssl' ), 'https://really-simple-ssl.com/privacy-statement/' ); wp_add_privacy_policy_content( 'Really Simple SSL', wp_kses_post( wpautop( $content, false ) ) ); } /** * Check if current day falls within required date range. * * @return bool */ public function is_bf() { if ( defined( 'rsssl_pro' ) ) { return false; } $start_day = 20; $end_day = 27; $current_year = gmdate( 'Y' );//e.g. 2021 $current_month = gmdate( 'n' );//e.g. 3 $current_day = gmdate( 'j' );//e.g. 4 if ( 2023 === $current_year && 11 === $current_month && $current_day >= $start_day && $current_day <= $end_day ) { return true; } return false; } /** * Initializes the admin class * * @since 2.2 * * @access public * */ public function init() { if ( ! rsssl_user_can_manage() ) { return; } if ( defined( 'RSSSL_FORCE_ACTIVATE' ) && RSSSL_FORCE_ACTIVATE ) { rsssl_update_option( 'ssl_enabled', true ); } /* * check if we're one minute past the activation. Then flush rewrite rules * this way we lower the memory impact on activation * Flush should happen on shutdown, not on init, as often happens in other plugins * https://codex.wordpress.org/Function_Reference/flush_rewrite_rules * */ $activation_time = get_option( 'rsssl_flush_rewrite_rules' ); $more_than_one_minute_ago = $activation_time < strtotime( '-1 minute' ); $less_than_2_minutes_ago = $activation_time > strtotime( '-2 minute' ); if ( $more_than_one_minute_ago && $less_than_2_minutes_ago && get_option( 'rsssl_flush_rewrite_rules' ) ) { delete_option( 'rsssl_flush_rewrite_rules' ); add_action( 'shutdown', 'flush_rewrite_rules' ); } $more_than_2_minute_ago = get_option( 'rsssl_flush_caches' ) < strtotime( '-2 minute' ); $less_than_5_minutes_ago = get_option( 'rsssl_flush_caches' ) > strtotime( '-5 minute' ); if ( $more_than_2_minute_ago && $less_than_5_minutes_ago && get_option( 'rsssl_flush_caches' ) ) { delete_option( 'rsssl_flush_caches' ); add_action( 'shutdown', array( RSSSL()->cache, 'flush' ) ); } /* Detect configuration when: - on settings page - SSL not enabled */ //when configuration detection should run again if ( ! rsssl_get_option( 'ssl_enabled' ) || $this->is_settings_page() || defined( 'RSSSL_DOING_SYSTEM_STATUS' ) ) { $this->detect_configuration(); if ( ! $this->wpconfig_ok() ) { rsssl_update_option( 'ssl_enabled', false ); } else { //when one of the used server variables was found, test if the redirect works if ( RSSSL()->server->uses_htaccess() && 'NA' !== $this->ssl_type ) { $this->htaccess_test_success(); } } } } /** * Add htaccess redirect * @hooked * @param array $rules * @return [] */ public function add_htaccess_redirect( $rules ) { //we don't want these rules added by rsssl if wp rocket active. //if it's deactivating, start adding them again. if ( $this->is_deactivating_wprocket() || ! function_exists( 'rocket_clean_domain' ) ) { $rule = $this->get_redirect_rules(); if ( ! empty( $rule ) ) { $rules[] = [ 'rules' => $rule, 'identifier' => 'RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1', ]; } } return $rules; } /** * Check if we're in the middle of wp rocket deactivation * * @return bool */ public function is_deactivating_wprocket() { //default deactivating $is_deactivating = isset( $_GET['action'] ) && 'deactivate' === $_GET['action'] && isset( $_GET['plugin'] ) && strpos( $_GET['plugin'], 'wp-rocket.php' ) !== false; //deactivating with modal return $is_deactivating || ( isset( $_GET['action'] ) && 'rocket_deactivation' === $_GET['action'] ); } /** * Deactivate the plugin while keeping SSL * Activated when the 'uninstall_keep_ssl' button is clicked in the settings tab * */ public function listen_for_deactivation() { if ( ! rsssl_user_can_manage() ) { return; } if ( ! isset( $_GET['token'] ) || ( ! wp_verify_nonce( $_GET['token'], 'rsssl_deactivate_plugin' ) ) ) { return; } if ( isset( $_GET['action'] ) && 'uninstall_keep_ssl' === $_GET['action'] ) { //deactivate plugin, but don't revert to http. $plugin = $this->get_current_rsssl_dirname() . '/' . $this->plugin_filename; $plugin = plugin_basename( trim( $plugin ) ); if ( is_multisite() ) { $network_current = get_site_option( 'active_sitewide_plugins', array() ); if ( is_plugin_active_for_network( $plugin ) ) { unset( $network_current[ $plugin ] ); } update_site_option( 'active_sitewide_plugins', $network_current ); //remove plugin one by one on each site $sites = get_sites(); foreach ( $sites as $site ) { switch_to_blog( $site->blog_id ); $current = get_option( 'active_plugins', array() ); $current = $this->remove_plugin_from_array( $plugin, $current ); update_option( 'active_plugins', $current ); restore_current_blog(); //switches back to previous blog, not current, so we have to do it each loop } } else { $current = get_option( 'active_plugins', array() ); $current = $this->remove_plugin_from_array( $plugin, $current ); update_option( 'active_plugins', $current ); } do_action( 'rsssl_deactivate' ); wp_redirect( admin_url( 'plugins.php' ) ); exit; } } /** * Remove the plugin from the active plugins array when called from listen_for_deactivation * * */ public function remove_plugin_from_array( $plugin, $current ) { $key = array_search( $plugin, $current, true ); if ( false !== $key ) { unset( $current[ $key ] ); } return $current; } /** * @return bool * * Check if this site is a Bitnami site */ public function uses_bitnami(): bool { if ( isset( $_SERVER['DOCUMENT_ROOT'] ) && $_SERVER['DOCUMENT_ROOT'] === '/opt/bitnami/wordpress' ) { return true; } return false; } /** * Check if site uses an htaccess.conf file, used in bitnami installations * * @Since 3.1 */ public function uses_htaccess_conf() { $htaccess_conf_file = dirname( ABSPATH ) . '/conf/htaccess.conf'; //conf/htaccess.conf can be outside of open basedir, return false if so $open_basedir = ini_get( 'open_basedir' ); if ( ! empty( $open_basedir ) ) { return false; } return is_file( $htaccess_conf_file ); } /** * If the user has clicked "recheck certificate, clear the cache for the certificate check. * Used in a form in the dashboard notices. * @return void */ public function recheck_certificate() { if ( ! rsssl_user_can_manage() ) { return; } if ( isset( $_POST['rsssl_recheck_certificate'] ) ) { delete_transient( 'rsssl_certinfo' ); } } /** * Activate the SSL for this site */ public function activate_ssl($data) { //skip activation if safe mode if ( defined( 'RSSSL_SAFE_MODE' ) && RSSSL_SAFE_MODE ) { return [ 'success' => true, 'site_url_changed' => false, ]; } if ( !rsssl_user_can_manage() ) { return [ 'success' => false, 'site_url_changed' => false, ]; } $safe_mode = defined( 'RSSSL_SAFE_MODE' ) && RSSSL_SAFE_MODE; $error = false; $is_rest_request = isset( $data['is_rest_request'] ); $site_url_changed = false; $wpcli = defined( 'WP_CLI' ) && WP_CLI; if ( rsssl_get_option( 'site_has_ssl' ) || get_option( 'rsssl_ssl_detection_overridden' ) || $wpcli ) { //in a configuration reverse proxy without a set server variable https, add code to wpconfig if ( $this->do_wpconfig_loadbalancer_fix || $this->no_server_variable ) { $this->wpconfig_loadbalancer_fix(); } if ( ! $safe_mode && $this->wpconfig_siteurl_not_fixed && ! $this->uses_bitnami() ) { $this->fix_siteurl_defines_in_wpconfig(); } $this->insert_secure_cookie_settings(); if ( ! $safe_mode ) { rsssl_update_option( 'redirect', 'wp_redirect' ); rsssl_update_option( 'mixed_content_fixer', true ); //flush caches when just activated ssl //flush the permalinks update_option( 'rsssl_activation_timestamp', time(), false ); if ( ! defined( 'RSSSL_NO_FLUSH' ) || ! RSSSL_NO_FLUSH ) { update_option( 'rsssl_flush_rewrite_rules', time(), false ); } update_option( 'rsssl_flush_caches', time(), false ); } rsssl_update_option( 'ssl_enabled', true ); $site_url_changed = $this->set_siteurl_to_ssl(); delete_option( 'rsssl_admin_notices' ); } else { $error = true; } //if this is true, this is a request from the network admin. We save an option to ensure we know that this part is completed if ( is_multisite() && rsssl_is_networkwide_active() ) { update_site_option( 'rsssl_network_activation_status', 'main_site_activated' ); } if ( $is_rest_request ) { return [ 'success' => ! $error, 'site_url_changed' => $site_url_changed, 'request_success' => true, ]; } return ! $error; } /** * Check if the wp config configuration is ok for SSL activation * * @return bool */ public function wpconfig_ok() { //return false; if ( ( $this->do_wpconfig_loadbalancer_fix || $this->no_server_variable || $this->wpconfig_siteurl_not_fixed ) && ! $this->wpconfig_is_writable() && ! $this->uses_bitnami() ) { $result = false; } else { $result = true; } return apply_filters( 'rsssl_wpconfig_ok_check', $result ); } /** * @param string $class * @param string $content * @param string|bool $more_info * @param string|bool $dismiss_id * * @return false|string * * @since 4.0 * Return the notice HTML * */ public function notice_html( string $css_class, string $content, $more_info = false, $dismiss_id = false ) { if ( ! rsssl_user_can_manage() ) { return ''; } $css_class .= ' notice '; $is_internal_link = strpos( $more_info, 'really-simple-ssl.com' ) === false; $target = ! $is_internal_link ? 'target="_blank"' : ''; $url = is_ssl() ? 'https://' : 'http://'; $url .= $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; $url = wp_validate_redirect( $url, apply_filters( 'wp_safe_redirect_fallback', admin_url(), 302 ) ); $url = esc_url_raw( $url ); ob_start();?>
find_wp_config_path(); if ( empty( $wpconfig_path ) ) { return false; } if ( is_writable( $wpconfig_path ) ) { return true; } return false; } /** * Check if the uninstall file is renamed to .php * * @return string */ public function check_for_uninstall_file() { if ( file_exists( __DIR__ . '/force-deactivate.php' ) ) { return 'fail'; } return 'success'; } /** * Check to see if we are on the settings page, action hook independent * * @since 2.1 * * @access public * */ public function is_settings_page() { if ( rsssl_is_logged_in_rest() ) { return true; } if ( ! isset( $_SERVER['QUERY_STRING'] ) ) { return false; } if ( isset( $_GET['action'] ) && 'rsssl_rest_api_fallback' === $_GET['action'] ) { return true; } parse_str( $_SERVER['QUERY_STRING'], $params ); return array_key_exists( 'page', $params ) && 'really-simple-security' === $params['page']; } /** * Find the path to wp-config * * @since 2.1 * * @access public * @return string|false * */ public function find_wp_config_path() { $location_of_wp_config = ABSPATH; if ( ! file_exists( ABSPATH . 'wp-config.php' ) && file_exists( dirname( ABSPATH ) . '/wp-config.php' ) ) { $location_of_wp_config = dirname( ABSPATH ); } $location_of_wp_config = trailingslashit( $location_of_wp_config ); $wpconfig_path = $location_of_wp_config . 'wp-config.php'; if ( file_exists( $wpconfig_path ) ) { return $wpconfig_path; } return false; } /** * remove https from defined siteurl and homeurl in the wpconfig, if present * * @since 2.1 * * @access public * * @return void */ public function remove_ssl_from_siteurl_in_wpconfig() { if ( ! rsssl_user_can_manage() ) { return; } $wpconfig_path = $this->find_wp_config_path(); if ( ! empty( $wpconfig_path ) ) { $wpconfig = file_get_contents( $wpconfig_path ); $homeurl_pos = strpos( $wpconfig, "define('WP_HOME','https://" ); $siteurl_pos = strpos( $wpconfig, "define('WP_SITEURL','https://" ); if ( false !== $homeurl_pos || false !== $siteurl_pos ) { if ( is_writable( $wpconfig_path ) ) { $search_array = array( "define('WP_HOME','https://", "define('WP_SITEURL','https://" ); $ssl_array = array( "define('WP_HOME','http://", "define('WP_SITEURL','http://" ); //now replace these urls $wpconfig = str_replace( $search_array, $ssl_array, $wpconfig ); file_put_contents( $wpconfig_path, $wpconfig ); } } } } /** * Checks if the wp config contains any defined siteurl and homeurl * * @return void */ private function check_for_siteurl_in_wpconfig() { if ( ! rsssl_user_can_manage() ) { return; } $wpconfig_path = $this->find_wp_config_path(); if ( empty( $wpconfig_path ) ) { return; } $wpconfig = file_get_contents( $wpconfig_path ); $homeurl_pattern = '/(define\(\s*\'WP_HOME\'\s*,\s*\'http\:\/\/)/'; $siteurl_pattern = '/(define\(\s*\'WP_SITEURL\'\s*,\s*\'http\:\/\/)/'; $this->wpconfig_siteurl_not_fixed = false; if ( preg_match( $homeurl_pattern, $wpconfig ) || preg_match( $siteurl_pattern, $wpconfig ) ) { $this->wpconfig_siteurl_not_fixed = true; } } /** * Runs only when siteurl or homeurl define was found in the wpconfig, with the check_for_siteurl_in_wpconfig function * and only when wpconfig is writable. * * @since 2.1 * * @access public * */ private function fix_siteurl_defines_in_wpconfig() { if ( ! rsssl_user_can_manage() ) { return; } $wpconfig_path = $this->find_wp_config_path(); if ( empty( $wpconfig_path ) ) { return; } $wpconfig = file_get_contents( $wpconfig_path ); $homeurl_pattern = '/(define\(\s*\'WP_HOME\'\s*,\s*\'http\:\/\/)/'; $siteurl_pattern = '/(define\(\s*\'WP_SITEURL\'\s*,\s*\'http\:\/\/)/'; if ( preg_match( $homeurl_pattern, $wpconfig ) || preg_match( $siteurl_pattern, $wpconfig ) ) { if ( is_writable( $wpconfig_path ) ) { $wpconfig = preg_replace( $homeurl_pattern, "define('WP_HOME','https://", $wpconfig ); $wpconfig = preg_replace( $siteurl_pattern, "define('WP_SITEURL','https://", $wpconfig ); file_put_contents( $wpconfig_path, $wpconfig ); } else { //only when siteurl or homeurl is defined in wpconfig, and wpconfig is not writable is there a possible issue because we cannot edit the defined urls. $this->wpconfig_siteurl_not_fixed = true; } } } /** * Check if the wpconfig is already fixed * * @since 2.2 * * @access public * */ public function wpconfig_has_fixes() { $wpconfig_path = $this->find_wp_config_path(); if ( empty( $wpconfig_path ) ) { return false; } $wpconfig = file_get_contents( $wpconfig_path ); //only one of two fixes possible. if ( strpos( $wpconfig, '//Begin Really Simple SSL Load balancing fix' ) !== false ) { return true; } if ( strpos( $wpconfig, '//Begin Really Simple SSL Server variable fix' ) !== false ) { return true; } return false; } /** * In case of load balancer without server https on, add fix in wp-config * * @since 2.1 * * @access public * */ public function wpconfig_loadbalancer_fix() { if ( ! rsssl_user_can_manage() ) { return; } $wpconfig_path = $this->find_wp_config_path(); if ( empty( $wpconfig_path ) ) { return; } $wpconfig = file_get_contents( $wpconfig_path ); if ( strpos( $wpconfig, '//Begin Really Simple SSL Server variable fix' ) !== false ) { return; } if ( strpos( $wpconfig, '//Begin Really Simple SSL Load balancing fix' ) !== false ) { return; } if ( is_writable( $wpconfig_path ) ) { $rule = "\n" . '//Begin Really Simple SSL Server variable fix' . "\n"; $rule .= '$_SERVER["HTTPS"] = "on";' . "\n"; $rule .= '//END Really Simple SSL Server variable fix' . "\n"; $insert_after = 'find_wp_config_path(); if ( empty( $wpconfig_path ) ) { return; } //check for permissions $wpconfig = file_get_contents( $wpconfig_path ); if ( ! is_writable( $wpconfig_path ) ) { return; } //remove edits $wpconfig = preg_replace( '/\/\/Begin\s?Really\s?Simple\s?SSL\s?Server\s?variable\s?fix.*?\/\/END\s?Really\s?Simple\s?SSL\s?Server\s?variable\s?fix/s', '', $wpconfig ); $wpconfig = preg_replace( "/\n+/", "\n", $wpconfig ); file_put_contents( $wpconfig_path, $wpconfig ); } /** * Changes the siteurl and homeurl to https * * @since 2.0 * * @access public * @return bool */ public function set_siteurl_to_ssl() { $site_url_changed = false; $site_url = get_option( 'siteurl' ); $home_url = get_option( 'home' ); if ( strpos( $site_url, 'https://' ) === false || strpos( $home_url, 'https://' ) === false ) { update_option( 'siteurl', str_replace( 'http://', 'https://', $site_url ) ); update_option( 'home', str_replace( 'http://', 'https://', $home_url ) ); $site_url_changed = true; } //RSSSL has it's own, more extensive mixed content fixer. update_option( 'https_migration_required', false ); return $site_url_changed; } /** * On de-activation, siteurl and homeurl are reset to http * * @since 2.0 * * @access public * */ public function remove_ssl_from_siteurl() { if ( ! rsssl_user_can_manage() ) { return; } $siteurl_no_ssl = str_replace( 'https://', 'http://', get_option( 'siteurl' ) ); $homeurl_no_ssl = str_replace( 'https://', 'http://', get_option( 'home' ) ); update_option( 'siteurl', $siteurl_no_ssl ); update_option( 'home', $homeurl_no_ssl ); } /** * Handles deactivation of this plugin * * @since 2.0 * * @access public * */ public function deactivate() { if ( ! rsssl_user_can_manage() ) { return; } if ( is_multisite() ) { RSSSL()->multisite->deactivate(); } else { $ssl_was_enabled = rsssl_get_option( 'ssl_enabled' ); $this->deactivate_site( $ssl_was_enabled ); } } /**] * Deactivate SSL for the currently loaded site * * @param bool $ssl_was_enabled * * @return void */ public function deactivate_site( bool $ssl_was_enabled ) { if ( ! rsssl_user_can_manage() ) { return; } $this->remove_secure_cookie_settings(); if ( $ssl_was_enabled ) { $this->remove_ssl_from_siteurl(); if ( ! is_multisite() || is_main_site() ) { $this->remove_ssl_from_siteurl_in_wpconfig(); $this->remove_wpconfig_edit(); rsssl_remove_htaccess_security_edits(); } } do_action( 'rsssl_deactivate' ); rsssl_update_option( 'ssl_enabled', false ); } /** * remove secure cookie settings * * @since 4.0.10 * * @access public * */ public function remove_secure_cookie_settings() { if ( ! rsssl_user_can_manage() ) { return; } if ( $this->secure_cookie_settings_status() !== 'set' ) { return; } $wpconfig_path = $this->find_wp_config_path(); if ( empty( $wpconfig_path ) ) { return; } if ( ! is_writable( $wpconfig_path ) ) { return; } if ( ! empty( $wpconfig_path ) ) { $wpconfig = file_get_contents( $wpconfig_path ); $wpconfig = preg_replace( '/\/\/Begin\s?Really\s?Simple\s?SSL\s?session\s?cookie\s?settings.*?\/\/END\s?Really\s?Simple\s?SSL\s?cookie\s?settings/s', '', $wpconfig ); $wpconfig = preg_replace( "/\n+/", "\n", $wpconfig ); file_put_contents( $wpconfig_path, $wpconfig ); } } /** * Checks if we are currently on SSL protocol, but extends standard wp with loadbalancer check. * * @since 2.0 * * @access public * */ public function is_ssl_extended() { $server_var = false; if ( ( isset( $_ENV['HTTPS'] ) && ( 'on' === $_ENV['HTTPS'] ) ) || ( isset( $_SERVER['HTTP_X_FORWARDED_SSL'] ) && ( strpos( $_SERVER['HTTP_X_FORWARDED_SSL'], '1' ) !== false ) ) || ( isset( $_SERVER['HTTP_X_FORWARDED_SSL'] ) && ( strpos( $_SERVER['HTTP_X_FORWARDED_SSL'], 'on' ) !== false ) ) || ( isset( $_SERVER['HTTP_CF_VISITOR'] ) && ( strpos( $_SERVER['HTTP_CF_VISITOR'], 'https' ) !== false ) ) || ( isset( $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] ) && ( strpos( $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'], 'https' ) !== false ) ) || ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && ( strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) !== false ) ) || ( isset( $_SERVER['HTTP_X_PROTO'] ) && ( strpos( $_SERVER['HTTP_X_PROTO'], 'SSL' ) !== false ) ) ) { $server_var = true; } return is_ssl() || $server_var; } /** * Checks for SSL by opening a test page in the plugin directory * * @since 2.0 * * @access public * */ public function detect_configuration() { $this->configuration_loaded = true; //if current page is on SSL, we can assume SSL is available, even when an errormsg was returned if ( $this->is_ssl_extended() ) { $site_has_ssl = true; } else { //if certificate is valid $site_has_ssl = RSSSL()->certificate->is_valid(); } if ( $site_has_ssl ) { $filecontents = $this->get_test_page_contents(); //get filecontents to check .htaccess redirection method and wpconfig fix //check the type of SSL, either by parsing the returned string, or by reading the server vars. if ( ( false !== strpos( $filecontents, '#CLOUDFRONT#' ) ) || ( isset( $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] ) && ( 'https' === $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] ) ) ) { $this->ssl_type = 'CLOUDFRONT'; } elseif ( ( false !== strpos( $filecontents, '#CLOUDFLARE#' ) ) || ( isset( $_SERVER['HTTP_CF_VISITOR'] ) && ( false !== strpos( $_SERVER['HTTP_CF_VISITOR'], 'https' ) ) ) ) { $this->ssl_type = 'CLOUDFLARE'; } elseif ( ( false !== strpos( $filecontents, '#LOADBALANCER#' ) ) || ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && ( 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) ) { $this->ssl_type = 'LOADBALANCER'; } elseif ( ( false !== strpos( $filecontents, '#HTTP_X_PROTO#' ) ) || ( isset( $_SERVER['HTTP_X_PROTO'] ) && ( 'SSL' === $_SERVER['HTTP_X_PROTO'] ) ) ) { $this->ssl_type = 'HTTP_X_PROTO'; } elseif ( ( false !== strpos( $filecontents, '#HTTP_X_FORWARDED_SSL_ON#' ) ) || ( isset( $_SERVER['HTTP_X_FORWARDED_SSL'] ) && 'on' === $_SERVER['HTTP_X_FORWARDED_SSL'] ) ) { $this->ssl_type = 'HTTP_X_FORWARDED_SSL_ON'; } elseif ( ( false !== strpos( $filecontents, '#HTTP_X_FORWARDED_SSL_1#' ) ) || ( isset( $_SERVER['HTTP_X_FORWARDED_SSL'] ) && '1' === $_SERVER['HTTP_X_FORWARDED_SSL'] ) ) { $this->ssl_type = 'HTTP_X_FORWARDED_SSL_1'; } elseif ( ( false !== strpos( $filecontents, '#SERVER-HTTPS-ON#' ) ) || ( isset( $_SERVER['HTTPS'] ) && 'on' === strtolower( $_SERVER['HTTPS'] ) ) ) { $this->ssl_type = 'SERVER-HTTPS-ON'; } elseif ( ( false !== strpos( $filecontents, '#SERVER-HTTPS-1#' ) ) || ( isset( $_SERVER['HTTPS'] ) && '1' === strtolower( $_SERVER['HTTPS'] ) ) ) { $this->ssl_type = 'SERVER-HTTPS-1'; } elseif ( ( false !== strpos( $filecontents, '#SERVERPORT443#' ) ) || ( isset( $_SERVER['SERVER_PORT'] ) && ( '443' === $_SERVER['SERVER_PORT'] ) ) ) { $this->ssl_type = 'SERVERPORT443'; } elseif ( ( false !== strpos( $filecontents, '#ENVHTTPS#' ) ) || ( isset( $_ENV['HTTPS'] ) && ( 'on' === $_ENV['HTTPS'] ) ) ) { $this->ssl_type = 'ENVHTTPS'; } elseif ( ( false !== strpos( $filecontents, '#NO KNOWN SSL CONFIGURATION DETECTED#' ) ) ) { //if we are here, SSL was detected, but without any known server variables set. //So we can use this info to set a server variable ourselves. if ( ! $this->wpconfig_has_fixes() ) { $this->no_server_variable = true; } $this->ssl_type = 'NA'; } else { //no valid response, so set to NA $this->ssl_type = 'NA'; } //check for is_ssl() if ( ( ! $this->is_ssl_extended() && ( strpos( $filecontents, '#SERVER-HTTPS-ON#' ) === false ) && ( strpos( $filecontents, '#SERVER-HTTPS-1#' ) === false ) && ( strpos( $filecontents, '#SERVERPORT443#' ) === false ) ) || ( ! is_ssl() && $this->is_ssl_extended() ) ) { //when is_ssl would return false, we should add some code to wp-config.php if ( ! $this->wpconfig_has_fixes() ) { $this->do_wpconfig_loadbalancer_fix = true; } } } $this->check_for_siteurl_in_wpconfig(); rsssl_update_option( 'site_has_ssl', $site_has_ssl ); } /** * Test if the htaccess redirect will work * This way, no redirect loops should occur. * * @since 2.1 * * @access public * */ public function htaccess_test_success() { $test = get_transient( 'rsssl_htaccess_test_success' ); if ( ! $test ) { $filecontents = ''; $testpage_url = trailingslashit( $this->test_url() ) . 'testssl/'; switch ( $this->ssl_type ) { case 'CLOUDFRONT': $testpage_url .= 'cloudfront'; break; case 'CLOUDFLARE': $testpage_url .= 'cloudflare'; break; case 'LOADBALANCER': $testpage_url .= 'loadbalancer'; break; case 'HTTP_X_PROTO': $testpage_url .= 'serverhttpxproto'; break; case 'HTTP_X_FORWARDED_SSL_ON': $testpage_url .= 'serverhttpxforwardedsslon'; break; case 'HTTP_X_FORWARDED_SSL_1': $testpage_url .= 'serverhttpxforwardedssl1'; break; case 'SERVER-HTTPS-ON': $testpage_url .= 'serverhttpson'; break; case 'SERVER-HTTPS-1': $testpage_url .= 'serverhttps1'; break; case 'SERVERPORT443': $testpage_url .= 'serverport443'; break; case 'ENVHTTPS': $testpage_url .= 'envhttps'; break; default: $testpage_url .= 'serverhttpson'; } $testpage_url .= ( '/ssl-test-page.html' ); $response = wp_remote_get( $testpage_url ); if ( is_array( $response ) ) { $filecontents = wp_remote_retrieve_body( $response ); } if ( ! is_wp_error( $response ) && ( strpos( $filecontents, '#SSL TEST PAGE#' ) !== false ) ) { $test = 'success'; } else { //.htaccess rewrite rule seems to be giving problems. $test = 'error'; } if ( empty( $filecontents ) ) { $test = 'no-response'; } set_transient( 'rsssl_htaccess_test_success', $test, 600 ); } if ( 'no-response' === $test || 'error' === $test ) { return false; } if ( 'success' === $test ) { return true; } } /** * Get an url with which we can test the SSL connection and htaccess redirect rules. * * @since 2.0 * * @access public * */ public function test_url() { $plugin_url = str_replace( 'http://', 'https://', trailingslashit( rsssl_url ) ); $https_home_url = str_replace( 'http://', 'https://', home_url() ); //in some case we get a relative url here, so we check that. //we compare to urls replaced to https, in case one of them is still on http. if ( ( strpos( $plugin_url, 'https://' ) === false ) && ( strpos( $plugin_url, $https_home_url ) === false ) ) { //make sure we do not have a slash at the start $plugin_url = ltrim( $plugin_url, '/' ); $plugin_url = trailingslashit( home_url() ) . $plugin_url; } //for subdomains or domain mapping situations, we have to convert the plugin_url from main site to the subdomain url. if ( is_multisite() && ! is_main_site( get_current_blog_id() ) && ! RSSSL()->multisite->is_multisite_subfolder_install() ) { $mainsiteurl = trailingslashit( str_replace( 'http://', 'https://', network_site_url() ) ); $home = trailingslashit( $https_home_url ); $plugin_url = str_replace( $mainsiteurl, $home, $plugin_url ); } return $plugin_url; } /** * @return bool * * Check if the .htaccess redirect is allowed on this setup * * @since 2.0 * */ public function htaccess_redirect_allowed() { if ( is_multisite() && ! $this->can_apply_networkwide() ) { return false; } if ( RSSSL()->server->uses_htaccess() ) { return true; } return false; } /** * @return bool * * Checks if the htaccess contains redirect rules, either actual redirect or a rsssl marker. * * @since 2.0 * */ public function htaccess_contains_redirect_rules() { if ( ! file_exists( $this->htaccess_file() ) ) { return false; } $pattern = '/RewriteRule \^\(\.\*\)\$ https:\/\/%{HTTP_HOST}(\/\$1|%{REQUEST_URI}) (\[R=301,.*L\]|\[L,.*R=301\])/i'; $htaccess = file_get_contents( $this->htaccess_file() ); return preg_match( $pattern, $htaccess ); } /** * Checks if the htaccess contains the Really Simple SSL comment. * */ public function contains_rsssl_rules() { if ( ! file_exists( $this->htaccess_file() ) ) { return false; } $htaccess = file_get_contents( $this->htaccess_file() ); if ( preg_match( '/BEGIN rlrssslReallySimpleSSL/', $htaccess, $matches ) || preg_match( '/BEGIN Really Simple SSL Redirect/', $htaccess, $matches ) || preg_match( '/Begin Really Simple Security/', $htaccess, $matches ) ) { return false; } return true; } /** * @return bool * * Checks if a 301 redirect is set * this is the case if either the wp_redirect is set, or the htaccess redirect is set. * */ public function has_301_redirect() { if ( 'htaccess' === rsssl_get_option( 'redirect' ) || 'wp_redirect' === rsssl_get_option( 'redirect' ) ) { return true; } if ( RSSSL()->server->uses_htaccess() && $this->htaccess_contains_redirect_rules() ) { return true; } return false; } /** * returns list of recommended, but not active security headers for this site * returns empty array if no .htacces file exists * Uses cURL, fallback to .htaccess check upon cURL failure * @return array * * @since 4.0 * * @access public * */ public function get_recommended_security_headers() { $used_headers = array(); $not_used_headers = array(); $check_headers = apply_filters( 'rsssl_recommended_security_headers', array( array( 'name' => 'Upgrade Insecure Requests', 'pattern' => 'upgrade-insecure-requests', ), array( 'name' => 'X-XSS protection', 'pattern' => 'X-XSS-Protection', ), array( 'name' => 'X-Content Type Options', 'pattern' => 'X-Content-Type-Options', ), array( 'name' => 'Referrer-Policy', 'pattern' => 'Referrer-Policy', ), array( 'name' => 'X-Frame-Options', 'pattern' => 'X-Frame-Options', ), array( 'name' => 'Permissions-Policy', 'pattern' => 'Permissions-Policy', ), array( 'name' => 'HTTP Strict Transport Security', 'pattern' => 'Strict-Transport-Security', ), ) ); // cURL check. $curl_check_done = get_transient( 'rsssl_can_use_curl_headers_check' );//no, yes or false if ( ! $curl_check_done ) { //set a default set_transient( 'rsssl_can_use_curl_headers_check', 'no', WEEK_IN_SECONDS ); if ( function_exists( 'curl_init' ) ) { $url = get_site_url(); $ch = curl_init(); $headers = []; curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_TIMEOUT, 3 ); //timeout in seconds curl_setopt( $ch, CURLOPT_HEADERFUNCTION, function ( $curl, $header ) use ( &$headers ) { $len = strlen( $header ); $header = explode( ':', $header, 2 ); if ( count( $header ) < 2 ) { return $len; } $headers[ strtolower( trim( $header[0] ) ) ][] = trim( $header[1] ); return $len; } ); curl_exec( $ch ); // Check if any headers have been found if ( ! empty( $headers ) && is_array( $headers ) ) { // Loop through each header and check if it's one of the recommended security headers. If so, add to used_headers array. foreach ( $headers as $name => $value ) { foreach ( $check_headers as $check_header ) { // If the pattern occurs in either the header name or value, it's a security header. if ( stripos( $name, $check_header['pattern'] ) !== false || stripos( $value[0], $check_header['pattern'] ) !== false ) { // Prevent duplicate entries if ( ! in_array( $check_header['name'], $used_headers, true ) ) { $used_headers[] = $check_header['name']; } } } } // Now check which headers are unused. Compare the used headers against the $check_headers array. foreach ( $check_headers as $header ) { if ( in_array( $header['name'], $used_headers, true ) ) { // Header is used, do not add to unused array continue; } else { // Header is not used. Add to not used array $not_used_headers[] = $header['name']; } } $curl_check_done = $not_used_headers; } else { $curl_check_done = 'no'; } } else { $curl_check_done = 'no'; } set_transient( 'rsssl_can_use_curl_headers_check', $curl_check_done, WEEK_IN_SECONDS ); } if ( 'no' === $curl_check_done ) { if ( RSSSL()->server->uses_htaccess() && file_exists( $this->htaccess_file() ) ) { $htaccess = file_get_contents( $this->htaccess_file() ); foreach ( $check_headers as $check_header ) { if ( ! preg_match( '/' . $check_header['pattern'] . '/', $htaccess, $check ) ) { $not_used_headers[] = $check_header['name']; } } } } else { $not_used_headers = $curl_check_done; } return $not_used_headers; } /** * Check if the recommended headers are enabled * * @return bool */ public function recommended_headers_enabled() { $unused_headers = $this->get_recommended_security_headers(); if ( empty( $unused_headers ) ) { return true; } return false; } /** * Regenerate the wp rocket .htaccess rules */ public function maybe_flush_wprocket_htaccess( $field_id, $field_value, $prev_value, $field_type ) { if ( 'redirect' === $field_id && $field_value !== $prev_value && rsssl_user_can_manage() ) { if ( function_exists( 'flush_rocket_htaccess' ) ) { flush_rocket_htaccess(); } if ( function_exists( 'rocket_generate_config_file' ) ) { rocket_generate_config_file(); } } } /** * Return .htaccess redirect when using WP Rocket * @return string */ public function add_htaccess_redirect_before_wp_rocket() { $rules = $this->get_redirect_rules(); if ( ! empty( $rules ) ) { $start = "\n" . '#Begin Really Simple SSL Redirect'; $end = "\n" . '#End Really Simple SSL Redirect' . "\n"; $rules = $start . $rules . $end; } return $rules; } /** * Check if the mixed content fixer is functioning on the front end, by scanning the source of the homepage for the fixer comment. * @since 2.2 * @access public * @return string */ public function mixed_content_fixer_detected() { //no need to check for the mixed content fixer if it's not enabled yet. if ( ! rsssl_get_option( 'mixed_content_fixer' ) ) { return 'not-enabled'; } //it's enabled, so check if we can find it on the front-end. $status = 0; $result = get_transient( 'rsssl_mixed_content_fixer_detected' ); if ( ! $result ) { $web_source = ''; //check if the mixed content fixer is active $response = wp_remote_get( home_url() ); if ( ! is_wp_error( $response ) ) { if ( is_array( $response ) ) { $status = wp_remote_retrieve_response_code( $response ); $web_source = wp_remote_retrieve_body( $response ); } if ( 200 !== $status ) { //Could not connect to website $result = 'no-response'; } elseif ( strpos( $web_source, 'data-rsssl=' ) === false ) { //Mixed content fixer marker not found in the websource $result = 'not-found'; } else { $result = 'found'; } } if ( is_wp_error( $response ) ) { //Fallback since most errors will be cURL errors, Error encountered while retrieving the webpage. $result = 'error'; $error = $response->get_error_message(); set_transient( 'rsssl_curl_error', $error, DAY_IN_SECONDS ); if ( ! empty( $error ) && ( strpos( $error, 'cURL error' ) !== false ) ) { $result = 'curl-error'; } } set_transient( 'rsssl_mixed_content_fixer_detected', $result, 600 ); } return 'found' === $result; } /** * Create redirect rules for the .htaccess. * @since 2.1 * * @access public * * @param bool $manual * * @return string */ public function get_redirect_rules( $manual = false ) { //ensure the configuration check has run always. if ( ! $this->configuration_loaded ) { $this->detect_configuration(); } //only add the redirect rules when a known type of SSL was detected. Otherwise, we use https. $rule = ''; //if the htaccess test was successfull, and we know the redirect type, edit if ( rsssl_get_option( 'ssl_enabled' ) && 'htaccess' === rsssl_get_option( 'redirect' ) && ( $manual || $this->htaccess_test_success() ) && 'NA' !== $this->ssl_type ) { $rule .= "\n" . '', '' ); ?>
', '' ); ?>
- Rogier' . $rules . '
//Begin Really Simple SSL Server variable fix
$_SERVER["HTTPS"] = "on";
//END Really Simple SSL
//Begin Really Simple SSL session cookie settings
@ini_set('session.cookie_httponly', true);
@ini_set('session.cookie_secure', true);
@ini_set('session.use_only_cookies', true);
//END Really Simple SSL cookie settings