PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-waf/src/class-compatibility.php +331 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,331 @@
1 +<?php
2 +/**
3 + * Class used to manage backwards-compatibility of the package.
4 + *
5 + * @since 0.8.0
6 + *
7 + * @package automattic/jetpack-waf
8 + */
9 +
10 +namespace Automattic\Jetpack\Waf;
11 +
12 +use Jetpack_Options;
13 +
14 +/**
15 + * Defines methods for ensuring backwards compatibility.
16 + */
17 +class Waf_Compatibility {
18 +
19 + /**
20 + * Returns the name for the IP allow list enabled/disabled option.
21 + *
22 + * @since 0.22.0
23 + *
24 + * @return string
25 + */
26 + private static function get_ip_allow_list_enabled_option_name() {
27 + /**
28 + * Patch: bootstrap script generated prior to 0.17.0 may have autoloaded Waf_Rules_Manager class during standalone mode execution.
29 + *
30 + * @see peb6dq-2HL-p2
31 + */
32 + if ( ! defined( 'Waf_Rules_Manager::IP_ALLOW_LIST_ENABLED_OPTION_NAME' ) ) {
33 + return 'jetpack_waf_ip_allow_list_enabled';
34 + }
35 +
36 + return Waf_Rules_Manager::IP_ALLOW_LIST_ENABLED_OPTION_NAME;
37 + }
38 +
39 + /**
40 + * Returns the name for the IP block list enabled/disabled option.
41 + *
42 + * @since 0.22.0
43 + *
44 + * @return string
45 + */
46 + private static function get_ip_block_list_enabled_option_name() {
47 + /**
48 + * Patch: bootstrap script generated prior to 0.17.0 may have autoloaded Waf_Rules_Manager class during standalone mode execution.
49 + *
50 + * @see peb6dq-2HL-p2
51 + */
52 + if ( ! defined( 'Waf_Rules_Manager::IP_BLOCK_LIST_ENABLED_OPTION_NAME' ) ) {
53 + return 'jetpack_waf_ip_block_list_enabled';
54 + }
55 +
56 + return Waf_Rules_Manager::IP_BLOCK_LIST_ENABLED_OPTION_NAME;
57 + }
58 +
59 + /**
60 + * Add compatibilty hooks
61 + *
62 + * @since 0.8.0
63 + *
64 + * @return void
65 + */
66 + public static function add_compatibility_hooks() {
67 + add_filter( 'default_option_' . Waf_Rules_Manager::AUTOMATIC_RULES_ENABLED_OPTION_NAME, __CLASS__ . '::default_option_waf_automatic_rules', 10, 3 );
68 + add_filter( 'default_option_' . Waf_Initializer::NEEDS_UPDATE_OPTION_NAME, __CLASS__ . '::default_option_waf_needs_update', 10, 3 );
69 + add_filter( 'default_option_' . Waf_Rules_Manager::IP_ALLOW_LIST_OPTION_NAME, __CLASS__ . '::default_option_waf_ip_allow_list', 10, 3 );
70 + add_filter( 'option_' . Waf_Rules_Manager::IP_ALLOW_LIST_OPTION_NAME, __CLASS__ . '::filter_option_waf_ip_allow_list', 10, 1 );
71 + add_filter( 'default_option_' . self::get_ip_allow_list_enabled_option_name(), __CLASS__ . '::default_option_waf_ip_allow_list_enabled', 10, 3 );
72 + add_filter( 'default_option_' . self::get_ip_block_list_enabled_option_name(), __CLASS__ . '::default_option_waf_ip_block_list_enabled', 10, 3 );
73 + }
74 +
75 + /**
76 + * Run compatibility migrations.
77 + *
78 + * Note that this method should be compatible with sites where
79 + * the request firewall is not active or not supported.
80 + *
81 + * @see Waf_Runner::is_supported_environment().
82 + *
83 + * @since 0.11.0
84 + *
85 + * @return void
86 + */
87 + public static function run_compatibility_migrations() {
88 + self::migrate_brute_force_protection_ip_allow_list();
89 + }
90 +
91 + /**
92 + * Provides a default value for sites that installed the WAF
93 + * before the automatic rules option was introduced.
94 + *
95 + * @since 0.9.0
96 + *
97 + * @param mixed $default The default value to return if the option does not exist in the database.
98 + * @param string $option Option name.
99 + * @param bool $passed_default Was get_option() passed a default value.
100 + *
101 + * @return mixed The default value to return if the option does not exist in the database.
102 + */
103 + public static function default_option_waf_automatic_rules( $default, $option, $passed_default ) {
104 + // Allow get_option() to override this default value
105 + if ( $passed_default ) {
106 + return $default;
107 + }
108 +
109 + return self::get_default_automatic_rules_option();
110 + }
111 +
112 + /**
113 + * If the option is not available, use the WAF module status
114 + * to determine whether or not to run automatic rules.
115 + *
116 + * @since 0.9.0
117 + *
118 + * @return bool The default value for automatic rules.
119 + */
120 + public static function get_default_automatic_rules_option() {
121 + return Waf_Runner::is_enabled();
122 + }
123 +
124 + /**
125 + * Provides a default value for sites that installed the WAF
126 + * before the NEEDS_UPDATE_OPTION_NAME option was added.
127 + *
128 + * @since 0.8.0
129 + *
130 + * @param mixed $default The default value to return if the option does not exist in the database.
131 + * @param string $option Option name.
132 + * @param bool $passed_default Was get_option() passed a default value.
133 + *
134 + * @return mixed The default value to return if the option does not exist in the database.
135 + */
136 + public static function default_option_waf_needs_update( $default, $option, $passed_default ) {
137 + // Allow get_option() to override this default value
138 + if ( $passed_default ) {
139 + return $default;
140 + }
141 +
142 + // If the option hasn't been added yet, the WAF needs to be updated.
143 + return true;
144 + }
145 +
146 + /**
147 + * Merge the WAF and Brute Force Protection IP allow lists.
148 + *
149 + * @since 0.11.0
150 + *
151 + * @param string $waf_allow_list The WAF IP allow list.
152 + * @param array $brute_force_allow_list The Brute Force Protection IP allow list. Array of IP objects.
153 + *
154 + * @return string The merged IP allow list.
155 + */
156 + public static function merge_ip_allow_lists( $waf_allow_list, $brute_force_allow_list ) {
157 +
158 + // Drop malformed entries.
159 + $brute_force_allow_list = is_array( $brute_force_allow_list ) ? array_filter( $brute_force_allow_list, 'is_object' ) : array();
160 +
161 + if ( empty( $brute_force_allow_list ) ) {
162 + return $waf_allow_list;
163 + }
164 +
165 + // Convert the IP objects to strings.
166 + $brute_force_allow_list = array_map(
167 + function ( $ip_object ) {
168 + if ( ! empty( $ip_object->range ) ) {
169 + return $ip_object->range_low . '-' . $ip_object->range_high;
170 + }
171 +
172 + return $ip_object->ip_address;
173 + },
174 + $brute_force_allow_list
175 + );
176 +
177 + $brute_force_allow_list_string = implode( "\n", $brute_force_allow_list );
178 +
179 + if ( empty( $waf_allow_list ) ) {
180 + return $brute_force_allow_list_string;
181 + }
182 +
183 + // Return the lists merged into a single string.
184 + return "$waf_allow_list\n$brute_force_allow_list_string";
185 + }
186 +
187 + /**
188 + * Migrate the brute force protection IP allow list option to the WAF option.
189 + *
190 + * @since 0.11.0
191 + *
192 + * @return void
193 + */
194 + public static function migrate_brute_force_protection_ip_allow_list() {
195 + // Get the allow list values directly from the database to avoid filters.
196 + $brute_force_allow_list = Jetpack_Options::get_raw_option( 'jetpack_protect_whitelist' );
197 + $waf_allow_list = Jetpack_Options::get_raw_option( 'jetpack_waf_ip_allow_list' );
198 +
199 + if ( ! empty( $brute_force_allow_list ) ) {
200 +
201 + if ( empty( $waf_allow_list ) ) {
202 + $waf_allow_list = '';
203 + }
204 +
205 + // Merge the two allow lists.
206 + $merged_allow_list = self::merge_ip_allow_lists( $waf_allow_list, $brute_force_allow_list );
207 +
208 + // Update the WAF IP allow list with the merged list.
209 + Jetpack_Options::update_raw_option( 'jetpack_waf_ip_allow_list', $merged_allow_list );
210 +
211 + // Delete the old option if the update was successful.
212 + // Check the values directly as `update_raw_option()` returns false if the value hasn't changed.
213 + if ( Jetpack_Options::get_raw_option( 'jetpack_waf_ip_allow_list' ) === $merged_allow_list ) {
214 + delete_option( 'jetpack_protect_whitelist' );
215 + }
216 + }
217 + }
218 +
219 + /**
220 + * Filter for Waf_Rules_Manager::IP_ALLOW_LIST_OPTION_NAME's option value.
221 + * Merges the deprecated IP allow list from the brute force protection module
222 + * with the existing option value, and flags that the WAF needs to be updated.
223 + *
224 + * @since 0.11.0
225 + *
226 + * @param array $waf_allow_list The current value of the option.
227 + *
228 + * @return array The merged IP allow list.
229 + */
230 + public static function filter_option_waf_ip_allow_list( $waf_allow_list ) {
231 + $brute_force_allow_list = Jetpack_Options::get_raw_option( 'jetpack_protect_whitelist', false );
232 + if ( false !== $brute_force_allow_list ) {
233 + $waf_allow_list = self::merge_ip_allow_lists( $waf_allow_list, $brute_force_allow_list );
234 + update_option( Waf_Initializer::NEEDS_UPDATE_OPTION_NAME, true );
235 + }
236 +
237 + return $waf_allow_list;
238 + }
239 +
240 + /**
241 + * Default option for when the Waf_Rules_Manager::IP_ALLOW_LIST_OPTION_NAME option is not set.
242 + *
243 + * @param mixed $default The default value to return if the option does not exist in the database.
244 + * @param string $option Option name.
245 + * @param bool $passed_default Was get_option() passed a default value.
246 + *
247 + * @return mixed The default value to return if the option does not exist in the database.
248 + */
249 + public static function default_option_waf_ip_allow_list( $default, $option, $passed_default ) {
250 + // Allow get_option() to override this default value
251 + if ( $passed_default ) {
252 + return $default;
253 + }
254 +
255 + $waf_allow_list = '';
256 +
257 + // If the brute force option exists, use that and flag that the WAF needs to be updated.
258 + $brute_force_allow_list = Jetpack_Options::get_raw_option( 'jetpack_protect_whitelist', false );
259 + if ( false !== $brute_force_allow_list ) {
260 + $waf_allow_list = self::merge_ip_allow_lists( $waf_allow_list, $brute_force_allow_list );
261 + update_option( Waf_Initializer::NEEDS_UPDATE_OPTION_NAME, true );
262 + }
263 +
264 + return $waf_allow_list;
265 + }
266 +
267 + /**
268 + * Check if the brute force protection code is being run by an older version of Jetpack (< 12.0).
269 + *
270 + * @since 0.11.1
271 + *
272 + * @return bool
273 + */
274 + public static function is_brute_force_running_in_jetpack() {
275 + return defined( 'JETPACK__VERSION' ) && version_compare( JETPACK__VERSION, '12', '<' );
276 + }
277 +
278 + /**
279 + * Default the allow list enabled option to the value of the generic IP lists enabled option it replaced.
280 + *
281 + * @since 0.17.0
282 + *
283 + * @param mixed $default The default value to return if the option does not exist in the database.
284 + * @param string $option Option name.
285 + * @param bool $passed_default Was get_option() passed a default value.
286 + *
287 + * @return mixed The default value to return if the option does not exist in the database.
288 + */
289 + public static function default_option_waf_ip_allow_list_enabled( $default, $option, $passed_default ) {
290 + // Allow get_option() to override this default value
291 + if ( $passed_default ) {
292 + return $default;
293 + }
294 +
295 + // If the deprecated IP lists option was set to false, disable the allow list.
296 + // @phan-suppress-next-line PhanDeprecatedClassConstant -- Needed for backwards compatibility.
297 + $deprecated_option = Jetpack_Options::get_raw_option( Waf_Rules_Manager::IP_LISTS_ENABLED_OPTION_NAME, true );
298 + if ( ! $deprecated_option ) {
299 + return false;
300 + }
301 +
302 + // If the allow list is empty, disable the allow list.
303 + if ( ! Jetpack_Options::get_raw_option( Waf_Rules_Manager::IP_ALLOW_LIST_OPTION_NAME ) ) {
304 + return false;
305 + }
306 +
307 + // Default to enabling the allow list.
308 + return true;
309 + }
310 +
311 + /**
312 + * Default the block list enabled option to the value of the generic IP lists enabled option it replaced.
313 + *
314 + * @since 0.17.0
315 + *
316 + * @param mixed $default The default value to return if the option does not exist in the database.
317 + * @param string $option Option name.
318 + * @param bool $passed_default Was get_option() passed a default value.
319 + *
320 + * @return mixed The default value to return if the option does not exist in the database.
321 + */
322 + public static function default_option_waf_ip_block_list_enabled( $default, $option, $passed_default ) {
323 + // Allow get_option() to override this default value
324 + if ( $passed_default ) {
325 + return $default;
326 + }
327 +
328 + // @phan-suppress-next-line PhanDeprecatedClassConstant -- Needed for backwards compatibility.
329 + return Jetpack_Options::get_raw_option( Waf_Rules_Manager::IP_LISTS_ENABLED_OPTION_NAME, false );
330 + }
331 +}