PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
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 13.7.2 13.8.3 All 506 releases
jetpack / jetpack_vendor / automattic / jetpack-waf / src / class-compatibility.php

class-compatibility.php in Jetpack – WP Security, Backup, Speed, & Growth 16.2, at jetpack_vendor/automattic/jetpack-waf/src/class-compatibility.php

332 lines 11.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 }
332