WP fail2ban - Version 4.3.0-RC4

Version Description

Download this release

Release Info

Developer invisnet
Plugin Icon 128x128 WP fail2ban
Version 4.3.0-RC4
Comparing to
See all releases

Code changes from version 4.2.8 to 4.3.0-RC4

admin/admin.php CHANGED
@@ -4,96 +4,211 @@
4
  * Admin
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- require __DIR__ . '/config.php';
15
- require __DIR__ . '/lib/about.php';
16
- /**
17
- * Register admin menus
18
- *
19
- * @since 4.0.0
20
- */
21
- function admin_menu()
22
- {
23
- global $submenu ;
24
- add_menu_page(
25
- 'WP fail2ban',
26
- 'WP fail2ban',
27
- 'manage_options',
28
- 'wp-fail2ban',
29
- __NAMESPACE__ . '\\about',
30
- 'dashicons-analytics'
31
- );
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
- if ( function_exists( '\\add_security_page' ) ) {
34
- $slug = 'wp-fail2ban';
35
- add_security_page(
36
- 'WP fail2ban',
37
- 'WP fail2ban',
38
- $slug,
39
- __NAMESPACE__ . '\\security'
40
- );
41
- } else {
42
- add_submenu_page(
43
- 'wp-fail2ban',
44
- 'Settings',
45
- 'Settings',
46
- 'manage_options',
 
 
 
47
  'wpf2b-settings',
48
  __NAMESPACE__ . '\\settings'
49
  );
 
 
 
 
50
  }
51
 
52
- $hook = add_submenu_page(
53
- 'wp-fail2ban',
54
- 'WP fail2ban - Remote Tools',
55
- 'Remote Tools',
56
- 'manage_options',
57
- 'wp-fail2ban-tools',
58
- __NAMESPACE__ . '\\remote_tools'
59
- );
60
- add_action( "load-{$hook}", function () {
61
- if ( function_exists( '\\org\\lecklider\\charles\\wordpress\\wp_fail2ban\\addons\\remote_tools\\help' ) ) {
62
- \org\lecklider\charles\wordpress\wp_fail2ban\addons\remote_tools\help();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  }
64
- } );
65
- if ( array_key_exists( 'wp-fail2ban', $submenu ) ) {
66
- $submenu['wp-fail2ban'][0][0] = __( 'Welcome' );
67
  }
68
- }
69
-
70
- add_action( 'admin_menu', __NAMESPACE__ . '\\admin_menu' );
71
- /**
72
- * Add Settings link on Plugins page
73
- *
74
- * @since 4.2.6 Add support for ClassicPress security page
75
- * @since 4.2.0
76
- *
77
- * @param array $links
78
- * @param string $file
79
- */
80
- function plugin_action_links( $links, $file )
81
- {
82
- if ( preg_match( "|{$file}\$|", WP_FAIL2BAN_FILE ) ) {
83
- array_unshift( $links, sprintf(
84
- '<a href="%s?page=%s" title="%s">%s</a>',
85
- admin_url( 'admin.php' ),
86
- 'wpf2b-settings',
87
- __( 'Settings' ),
88
- ( function_exists( '\\add_security_page' ) ? '<span class="dashicon dashicons-admin-generic"></span>' : __( 'Settings' ) )
89
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  }
91
- return $links;
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
93
-
94
- add_filter(
95
- 'plugin_action_links',
96
- __NAMESPACE__ . '\\plugin_action_links',
97
- 10,
98
- 2
99
- );
4
  * Admin
5
  *
6
  * @package wp-fail2ban
7
+ * @since 4.0.0
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
+
12
+ if ( defined( 'ABSPATH' ) ) {
13
+ require_once __DIR__ . '/config.php';
14
+ require_once __DIR__ . '/tools.php';
15
+ require_once __DIR__ . '/lib/about.php';
16
+ include_once_exists( WP_FAIL2BAN_DIR . '/premium/admin/admin.php' );
17
+ /**
18
+ * Helper: Security and Settings menu
19
+ *
20
+ * @since 4.3.0
21
+ *
22
+ * @param string $capability Capability
23
+ */
24
+ function _security_settings( $capability = 'manage_options' )
25
+ {
26
+
27
+ if ( function_exists( '\\add_security_page' ) ) {
28
+ $hook = add_security_page(
29
+ 'WP fail2ban',
30
+ 'WP fail2ban',
31
+ plugin_basename( WP_FAIL2BAN_DIR ),
32
+ __NAMESPACE__ . '\\security'
33
+ );
34
+ add_action( "load-{$hook}", function () {
35
+ TabBase::setDefaultTab( 'logging' );
36
+ TabBase::getActiveTab()->current_screen();
37
+ } );
38
+ if ( class_exists( __NAMESPACE__ . '\\premium\\WPf2b' ) ) {
39
+ _settings( 'status', $capability );
40
+ }
41
+ } else {
42
+ _settings( apply_filters( __METHOD__ . '.page', 'logging' ), $capability );
43
+ }
44
 
45
+ }
46
+
47
+ /**
48
+ * Helper: Settings menu
49
+ *
50
+ * @since 4.3.0
51
+ *
52
+ * @param $page string|null
53
+ * @param $capability string
54
+ */
55
+ function _settings( $page = null, $capability = 'manage_options' )
56
+ {
57
+ $hook = add_submenu_page(
58
+ 'wp-fail2ban-menu',
59
+ __( 'Settings', 'wp-fail2ban' ),
60
+ __( 'Settings', 'wp-fail2ban' ),
61
+ $capability,
62
  'wpf2b-settings',
63
  __NAMESPACE__ . '\\settings'
64
  );
65
+ add_action( "load-{$hook}", function () use( $page ) {
66
+ TabBase::setDefaultTab( $page );
67
+ TabBase::getActiveTab()->current_screen();
68
+ } );
69
  }
70
 
71
+ /**
72
+ * Helper: Remote Tools menu
73
+ *
74
+ * @since 4.3.0
75
+ *
76
+ * @param string $capability Capability
77
+ */
78
+ function _remote_tools( $capability = 'manage_options' )
79
+ {
80
+ add_submenu_page(
81
+ 'wp-fail2ban-menu',
82
+ __( 'Tools', 'wp-fail2ban' ),
83
+ __( ' - Remote Tools (&beta;)', 'wp-fail2ban' ),
84
+ $capability,
85
+ 'wp-fail2ban-tools',
86
+ __NAMESPACE__ . '\\remote_tools'
87
+ );
88
+ }
89
+
90
+ /**
91
+ * Register admin menus
92
+ *
93
+ * @since 4.0.0
94
+ */
95
+ function admin_menu()
96
+ {
97
+ if ( wf_fs()->is_free_plan() && !wf_fs()->is_trial() || wf_fs()->is_plan( 'remote', true ) ) {
98
+
99
+ if ( !is_multisite() ) {
100
+ add_menu_page(
101
+ 'WP fail2ban',
102
+ 'WP fail2ban',
103
+ 'manage_options',
104
+ 'wp-fail2ban-menu',
105
+ __NAMESPACE__ . '\\about',
106
+ plugin_dir_url( WP_FAIL2BAN_FILE ) . 'assets/menu.svg'
107
+ );
108
+ add_action( 'admin_menu', __NAMESPACE__ . '\\admin_menu_fix', PHP_INT_MAX );
109
+
110
+ if ( !is_multisite() ) {
111
+ _security_settings();
112
+ _remote_tools();
113
+ }
114
+
115
+ }
116
+
117
  }
 
 
 
118
  }
119
+
120
+ add_action( 'admin_menu', __NAMESPACE__ . '\\admin_menu' );
121
+ /**
122
+ * Register network admin menus
123
+ *
124
+ * @since 4.3.0
125
+ */
126
+ function network_admin_menu()
127
+ {
128
+
129
+ if ( wf_fs()->is_free_plan() && !wf_fs()->is_trial() ) {
130
+ add_menu_page(
131
+ 'WP fail2ban',
132
+ 'WP fail2ban',
133
+ 'manage_options',
134
+ 'wp-fail2ban-menu',
135
+ __NAMESPACE__ . '\\about',
136
+ plugin_dir_url( WP_FAIL2BAN_FILE ) . 'assets/menu.svg'
137
+ );
138
+ add_action( 'network_admin_menu', __NAMESPACE__ . '\\admin_menu_fix', PHP_INT_MAX );
139
+ _security_settings();
140
+ _remote_tools();
141
+ }
142
+
143
+ }
144
+
145
+ add_action( 'network_admin_menu', __NAMESPACE__ . '\\network_admin_menu' );
146
+ /**
147
+ * Fix first submenu name.
148
+ *
149
+ * @since 4.3.0
150
+ */
151
+ function admin_menu_fix()
152
+ {
153
+ global $submenu ;
154
+ if ( isset( $submenu['wp-fail2ban-menu'] ) && 'WP fail2ban' == @$submenu['wp-fail2ban-menu'][0][0] ) {
155
+ $submenu['wp-fail2ban-menu'][0][0] = __( 'Welcome', 'wp-fail2ban' );
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Add Settings link on Plugins page
161
+ *
162
+ * @since 4.2.0
163
+ *
164
+ * @param string[] $actions An array of plugin action links. By default this can include 'activate',
165
+ * 'deactivate', and 'delete'.
166
+ * @param string $plugin_file Path to the plugin file relative to the plugins directory.
167
+ * @param array $plugin_data An array of plugin data. See `get_plugin_data()`.
168
+ * @param string $context The plugin context. By default this can include 'all', 'active', 'inactive',
169
+ * 'recently_activated', 'upgrade', 'mustuse', 'dropins', and 'search'.
170
+ */
171
+ function plugin_action_links(
172
+ $actions,
173
+ $plugin_file,
174
+ $plugin_data,
175
+ $context
176
+ )
177
+ {
178
+
179
+ if ( preg_match( "|{$plugin_file}\$|", WP_FAIL2BAN_FILE ) && (!is_multisite() || is_network_admin()) ) {
180
+
181
+ if ( function_exists( '\\add_security_page' ) ) {
182
+ return $actions;
183
+ } else {
184
+ $page = 'wpf2b-fail2ban-menu';
185
+ }
186
+
187
+ $settings = sprintf(
188
+ '<a href="%s?page=wpf2b-settings&tab=about" title="%s">%s</a>',
189
+ network_admin_url( 'admin.php' ),
190
+ __( 'Settings', 'wp-fail2ban' ),
191
+ ( function_exists( '\\add_security_page' ) ? '<span class="dashicon dashicons-admin-generic"></span>' : __( 'Settings', 'wp-fail2ban' ) )
192
+ );
193
+ // Add Settings at the start
194
+ $actions = array_merge( [
195
+ 'settings' => $settings,
196
+ ], $actions );
197
+ }
198
+
199
+ return $actions;
200
  }
201
+
202
+ add_filter(
203
+ 'plugin_action_links',
204
+ __NAMESPACE__ . '\\plugin_action_links',
205
+ 10,
206
+ 4
207
+ );
208
+ add_filter(
209
+ 'network_admin_plugin_action_links',
210
+ __NAMESPACE__ . '\\plugin_action_links',
211
+ 10,
212
+ 4
213
+ );
214
  }
 
 
 
 
 
 
 
admin/config.php CHANGED
@@ -1,160 +1,186 @@
1
  <?php
2
-
3
  /**
4
  * Config
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- require_once 'lib/tab.php';
15
- foreach ( glob( __DIR__ . '/config/*.php' ) as $filename ) {
16
- require_once $filename;
17
- }
18
- /**
19
- * Render Security settings.
20
- *
21
- * @since 4.2.6
22
- */
23
- function security()
24
- {
25
- $tabs = [
26
- 'logging',
27
- 'syslog',
28
- 'block',
29
- 'remote-ips'
30
- ];
31
- if ( version_compare( PHP_VERSION, '5.6.0', '>=' ) ) {
32
- $tabs[] = 'plugins';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  }
34
- $page = 'wp-fail2ban';
35
- if ( wf_fs()->is_premium() ) {
36
- $page .= '-premium';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
38
- render_tabs( $tabs, 'logging', $page );
39
- }
40
 
41
- /**
42
- * Render Settings.
43
- *
44
- * @since 4.2.6
45
- */
46
- function settings()
47
- {
48
- $tabs = [];
49
-
50
- if ( !function_exists( '\\add_security_page' ) ) {
51
  $tabs = [
52
  'logging',
53
  'syslog',
54
  'block',
55
- 'remote-ips'
 
56
  ];
57
- if ( version_compare( PHP_VERSION, '5.6.0', '>=' ) ) {
58
- $tabs[] = 'plugins';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
 
 
 
60
  }
61
-
62
- $default = 'logging';
63
- render_tabs( $tabs, $default, 'wpf2b-settings' );
64
- }
65
 
66
- /**
67
- * Render Tabs.
68
- *
69
- * @since 4.2.6
70
- *
71
- * @param array $tabs List of slugs of tabs to render
72
- * @param string $default Default tab slug
73
- * @param string $menu Menu slug
74
- */
75
- function render_tabs( array $tabs, $default, $menu )
76
- {
77
- ?>
78
- <div class="wrap">
79
- <?php
80
- echo apply_filters( __METHOD__ . '.title', "<h1>WP fail2ban</h1>" ) ;
81
- ?>
82
- <hr class="wp-header-end">
83
-
84
- <h2 class="nav-tab-wrapper wp-clearfix">
85
- <?php
86
- $active_tab = Tab::getActiveTab( $default );
87
- foreach ( $tabs as $slug ) {
88
- $class = 'nav-tab';
89
- if ( $active_tab->getSlug() == $slug ) {
90
- $class .= ' nav-tab-active';
 
 
 
 
91
  }
92
- $params = apply_filters( __METHOD__ . '.params', [
93
- 'page' => $menu,
94
- 'tab' => $slug,
95
- ] );
96
- printf(
97
- '<a class="%s" href="?%s">%s</a>',
98
- $class,
99
- http_build_query( $params ),
100
- Tab::getTabName( $slug )
 
 
101
  );
102
- }
103
- ?>
104
- </h2>
105
-
106
- <form action="options.php?tab=<?php
107
- echo $active_tab->getSlug() ;
108
- ?>" method="post">
109
- <?php
110
- settings_fields( 'wp-fail2ban' );
111
- $active_tab->render();
112
- echo '<hr><p>' . __( '<strong>Note:</strong> The Free version of <em>WP fail2ban</em> is configured by defining constants in <tt>wp-config.php</tt>; these tabs display those values.' ) . '<br>' . __( 'Upgrade to the Premium version to enable this interface.' ) . '</p>' ;
113
- ?>
114
- </form>
115
- </div>
116
- <?php
117
- }
118
 
119
- /**
120
- * Proxy for api.wp-fail2ban.com
121
- *
122
- * @since 4.2.6
123
- */
124
- function remote_tools()
125
- {
126
- global $current_user ;
127
- ?>
128
- <div class="wrap">
129
- <h1>Remote Tools (&beta;)</h1>
130
- <hr class="wp-header-end">
131
- <?php
132
-
133
- if ( function_exists( '\\org\\lecklider\\charles\\wordpress\\wp_fail2ban\\addons\\remote_tools\\tab' ) ) {
134
- \org\lecklider\charles\wordpress\wp_fail2ban\addons\remote_tools\tab();
135
- } else {
136
  ?>
137
- <h2 class="nav-tab-wrapper wp-clearfix">
138
- <a class="nav-tab nav-tab-active" href="#">Overview</a>
139
- </h2>
140
- <div class="card">
141
- <h2>Remote Tools Add-on</h2>
142
- <p>This add-on provides features that make life with WP fail2ban easier, all from a remote server. This gives access to valuable but infrequently used tools without bloating the core plugin.</p>
143
- <p>The first of these is a <strong>Custom Filter Tool</strong> (CFT).</p>
144
- <blockquote>
145
- <p>The filter files included are intended only as a starting point for those who want <em>WPf2b</em> to work “out of the box”.</p>
146
- <p>There is no &ldquo;one size fits all&rdquo; configuration possible for <em>fail2ban</em> - what may be a soft failure for one site should be treated as a hard failure for another, and vice versa.</p>
147
- </blockquote>
148
- <p>You could simply edit the filter files included, but it&lsquo;s surprisingly easy to make a mistake; I learned this the hard way with earlier versions of <em>WPf2b</em>.... The CFT removes most of the opportunities for human error - always a good thing!</p>
149
- <hr>
150
- <p>The Remote Tools Add-on is available from the <a href="<?php
151
- echo admin_url( 'admin.php?page=wp-fail2ban-addons' ) ;
152
- ?>">Add-Ons menu</a>.</p>
153
  </div>
154
- <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  }
156
-
157
- ?>
158
- </div>
159
- <?php
160
  }
 
1
  <?php
 
2
  /**
3
  * Config
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
11
+ require_once 'lib/tab.php';
12
+ require_once 'config/block.php';
13
+ require_once 'config/logging.php';
14
+ require_once 'config/plugins.php';
15
+ require_once 'config/remote-ips.php';
16
+ require_once 'config/syslog.php';
17
+
18
+ if (false === (@include_once WP_FAIL2BAN_DIR.'/premium/admin/config.php')) {
19
+ /**
20
+ * Init
21
+ *
22
+ */
23
+ function init_tabs()
24
+ {
25
+ new TabBlock();
26
+ new TabLogging();
27
+ new TabPlugins();
28
+ new TabRemoteIPs();
29
+ new TabSyslog();
30
+ }
31
+ add_action('init', __NAMESPACE__.'\init_tabs', 999);
32
+ } // @include
33
+
34
+ /**
35
+ * Display settings messages.
36
+ *
37
+ * @since 4.3.0
38
+ */
39
+ function admin_notices()
40
+ {
41
+ $screen = get_current_screen();
42
+ switch ($screen->id) {
43
+ case 'security_page_wp-fail2ban-premium':
44
+ case 'wp-fail2ban_page_wpf2b-settings':
45
+ settings_errors();
46
+ break;
47
+ }
48
  }
49
+ add_action('admin_notices', __NAMESPACE__.'\admin_notices');
50
+
51
+ /**
52
+ * Get network settings messages.
53
+ *
54
+ * @since 4.3.0
55
+ */
56
+ function network_admin_notices()
57
+ {
58
+ $screen = get_current_screen();
59
+ switch ($screen->id) {
60
+ case 'security_page_wp-fail2ban-premium-network':
61
+ case 'wp-fail2ban_page_wpf2b-settings-network':
62
+ if ($transients = get_site_transient('settings_errors')) {
63
+ global $wp_settings_errors;
64
+
65
+ $wp_settings_errors = array_merge((array)$wp_settings_errors, $transients);
66
+ delete_site_transient('settings_errors');
67
+ }
68
+ settings_errors();
69
+ break;
70
+ }
71
  }
72
+ add_action('network_admin_notices', __NAMESPACE__.'\network_admin_notices');
 
73
 
74
+ /**
75
+ * Render Security settings.
76
+ *
77
+ * @since 4.3.0
78
+ */
79
+ function security()
80
+ {
 
 
 
81
  $tabs = [
82
  'logging',
83
  'syslog',
84
  'block',
85
+ 'remote-ips',
86
+ 'plugins'
87
  ];
88
+ $tabs = apply_filters(__METHOD__.'.tabs', $tabs);
89
+ $page = apply_filters(__METHOD__.'.page', plugin_basename(WP_FAIL2BAN_DIR));
90
+
91
+ render_tabs($tabs, $page);
92
+ }
93
+
94
+ /**
95
+ * Render Settings.
96
+ *
97
+ * @since 4.0.0
98
+ */
99
+ function settings()
100
+ {
101
+ $tabs = [];
102
+
103
+ if (!function_exists('\add_security_page')) {
104
+ $tabs = [
105
+ 'logging',
106
+ 'syslog',
107
+ 'block',
108
+ 'remote-ips'
109
+ ];
110
+ if (version_compare(PHP_VERSION, '5.6.0', '>=')) {
111
+ $tabs[] = 'plugins';
112
+ }
113
  }
114
+ $tabs = apply_filters(__METHOD__.'.tabs', $tabs);
115
+
116
+ render_tabs($tabs, 'wpf2b-settings');
117
  }
 
 
 
 
118
 
119
+ /**
120
+ * Render Tabs.
121
+ *
122
+ * @since 4.3.0
123
+ *
124
+ * @param array $tabs List of slugs of tabs to render
125
+ * @param string $menu Menu slug
126
+ */
127
+ function render_tabs(array $tabs, $menu)
128
+ {
129
+ $active_tab = TabBase::getActiveTab();
130
+
131
+ ?>
132
+ <div class="wrap">
133
+ <?=apply_filters(__METHOD__.'.title', sprintf('<h1>%s</h1>', __('Settings', 'wp-fail2ban')))?>
134
+ <hr class="wp-header-end">
135
+
136
+ <h2 class="nav-tab-wrapper wp-clearfix">
137
+ <?php
138
+ foreach ($tabs as $slug) {
139
+ $class = 'nav-tab';
140
+ if ($active_tab->getSlug() == $slug) {
141
+ $class .= ' nav-tab-active';
142
+ }
143
+ $params = apply_filters(__METHOD__.'.params', [
144
+ 'page' => $menu,
145
+ 'tab' => $slug
146
+ ]);
147
+ printf('<a class="%s" href="?%s">%s</a>', $class, http_build_query($params), TabBase::getTabName($slug));
148
  }
149
+ ?>
150
+ </h2>
151
+
152
+ <?php
153
+ // Because the settings API was never finished we need an ugly hack
154
+ $action = sprintf(
155
+ '%s?tab=%s',
156
+ admin_url(is_network_admin()
157
+ ? 'admin-post.php'
158
+ : 'options.php'),
159
+ $active_tab->getSlug()
160
  );
161
+ ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
+ <form action="<?=$action?>" method="post">
164
+ <?php
165
+ settings_fields('wp-fail2ban');
166
+ $active_tab->render();
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  ?>
168
+ </form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  </div>
170
+ <?php
171
+ }
172
+
173
+ /**
174
+ * Helper: filtered defined(...)
175
+ *
176
+ * @since 4.3.0
177
+ *
178
+ * @param string $define
179
+ * @return mixed
180
+ */
181
+ function have_defined($define)
182
+ {
183
+ return apply_filters(__NAMESPACE__.'\have_defined', defined($define), $define);
184
  }
 
 
 
 
185
  }
186
+
admin/config/block.php CHANGED
@@ -1,120 +1,144 @@
1
  <?php
2
-
3
  /**
4
  * Settings - Block
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
- namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * Tab: Block
16
- *
17
- * @since 4.0.0
18
- */
19
- class TabBlock extends Tab
20
- {
21
- /**
22
- * {@inheritDoc}
23
- *
24
- * @since 4.0.0
25
- */
26
- public function __construct()
27
- {
28
- add_action( 'admin_init', [ $this, 'admin_init' ] );
29
- parent::__construct( 'block', 'Users' );
30
- }
31
-
32
- /**
33
- * {@inheritDoc}
34
- *
35
- * @since 4.0.0
36
- */
37
- public function admin_init()
38
- {
39
- // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
40
- add_settings_section(
41
- 'wp-fail2ban-block',
42
- __( 'Block' ),
43
- [ $this, 'section' ],
44
- 'wp-fail2ban-block'
45
- );
46
- add_settings_field(
47
- 'block-user-enumeration',
48
- parent::doc_link( 'WP_FAIL2BAN_BLOCK_USER_ENUMERATION', __( 'User Enumeration' ) ),
49
- [ $this, 'userEnumeration' ],
50
- 'wp-fail2ban-block',
51
- 'wp-fail2ban-block'
52
- );
53
- add_settings_field(
54
- 'block-users',
55
- parent::doc_link( 'WP_FAIL2BAN_BLOCKED_USERS', __( 'Usernames' ) ),
56
- [ $this, 'usernames' ],
57
- 'wp-fail2ban-block',
58
- 'wp-fail2ban-block'
59
- );
60
- // phpcs:enable
61
- }
62
-
63
- /**
64
- * {@inheritDoc}
65
- *
66
- * @since 4.0.0
67
- *
68
- * @param array $settings
69
- * @param array $input
70
- */
71
- public function sanitize( array $settings, array $input = null )
72
- {
73
- return $settings;
74
- }
75
-
76
- /**
77
- * {@inheritDoc}
78
- *
79
- * @since 4.0.0
80
- */
81
- public function section()
82
- {
83
- echo '' ;
84
- }
85
-
86
  /**
87
- * User Enumeration
88
  *
89
  * @since 4.0.0
90
  */
91
- public function userEnumeration()
92
  {
93
- printf( '<input type="checkbox" disabled="disabled" %s>', checked( WP_FAIL2BAN_BLOCK_USER_ENUMERATION, true, false ) );
94
- }
95
-
96
- /**
97
- * Blocked usernames
98
- *
99
- * @since 4.0.0
100
- */
101
- public function usernames()
102
- {
103
-
104
- if ( defined( 'WP_FAIL2BAN_BLOCKED_USERS' ) ) {
105
-
106
- if ( is_array( WP_FAIL2BAN_BLOCKED_USERS ) ) {
107
- $value = join( ', ', WP_FAIL2BAN_BLOCKED_USERS );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  } else {
109
- $value = WP_FAIL2BAN_BLOCKED_USERS;
110
  }
111
-
112
- } else {
113
- $value = '';
 
114
  }
115
-
116
- printf( '<input class="regular-text" type="text" disabled="disabled" value="%s">', esc_attr( $value ) );
117
- }
118
 
 
 
 
 
 
 
 
 
 
 
119
  }
120
- new TabBlock();
1
  <?php
 
2
  /**
3
  * Settings - Block
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
+ * Tab: Block
13
  *
14
  * @since 4.0.0
15
  */
16
+ class TabBlock extends TabBase
17
  {
18
+ /**
19
+ * {@inheritDoc}
20
+ *
21
+ * @since 4.0.0
22
+ */
23
+ public function __construct()
24
+ {
25
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
26
+ $this->__['users'] = __('Users', 'wp-fail2ban');
27
+ $this->__['user-enumeration'] = __('Block User Enumeration', 'wp-fail2ban');
28
+ $this->__['blacklist'] = __('Blacklisted Usernames', 'wp-fail2ban');
29
+ $this->__['username-login'] = __('Block username logins', 'wp-fail2ban');
30
+ // phpcs:enable
31
+
32
+ parent::__construct('block', __('Block', 'wp-fail2ban'));
33
+ }
34
+
35
+ /**
36
+ * {@inheritDoc}
37
+ *
38
+ * @since 4.0.0
39
+ */
40
+ public function admin_init()
41
+ {
42
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
43
+ add_settings_section('wp-fail2ban-users', $this->__['users'], [$this, 'section'], 'wp-fail2ban-block');
44
+ add_settings_field('user-enumeration', $this->__['user-enumeration'], [$this, 'userEnumeration'], 'wp-fail2ban-block', 'wp-fail2ban-users');
45
+ add_settings_field('blacklist', $this->__['blacklist'], [$this, 'users'], 'wp-fail2ban-block', 'wp-fail2ban-users');
46
+ add_settings_field('username-login', $this->__['username-login'], [$this, 'usernames'], 'wp-fail2ban-block', 'wp-fail2ban-users');
47
+ // phpcs:enable
48
+ }
49
+
50
+ /**
51
+ * {*inheritDoc}
52
+ *
53
+ * @since 4.3.0
54
+ */
55
+ public function current_screen()
56
+ {
57
+ $fmt = <<<___FMT___
58
+ <dl><style>dt{font-weight:bold;}</style>
59
+ <dt>%s</dt>
60
+ <dd><p>%s</p><p>%s</p><p>%s</p>%s</dd>
61
+ <dt>%s</dt>
62
+ <dd><p>%s</p><p>%s</p>%s</dd>
63
+ <dt>%s</dt>
64
+ <dd><p>%s</p><p>%s</p>%s</dd>
65
+ </dl>
66
+ ___FMT___;
67
+ get_current_screen()->add_help_tab([
68
+ 'id' => 'users',
69
+ 'title' => $this->__['users'],
70
+ 'content' => sprintf(
71
+ $fmt,
72
+ $this->__['user-enumeration'],
73
+ __('Automated brute-force attacks ("bots") typically start by getting a list of valid usernames ("user enumeration").', 'wp-fail2ban'),
74
+ __('Blocking user enumeration can force attackers to guess usernames, making these attacks much less likely to succeed.', 'wp-fail2ban'),
75
+ __('<strong>N.B.</strong> Some Themes "leak" usernames (for example, via Author profile pages); see <strong>Block username logins</strong> for an alternative.', 'wp-fail2ban'),
76
+ $this->see_also(['WP_FAIL2BAN_BLOCK_USER_ENUMERATION']),
77
+ $this->__['blacklist'],
78
+ __('Automated brute-force attacks ("bots") will often use well-known usernames, e.g. <tt>admin</tt>.', 'wp-fail2ban'),
79
+ __('Blacklisted usernames are blocked early in the login process, reducing server load.', 'wp-fail2ban'),
80
+ $this->see_also(['WP_FAIL2BAN_BLOCKED_USERS']),
81
+ $this->__['username-login'],
82
+ __('It is sometimes not possible to block user enumeration (for example, if your theme provides Author profiles). An alternative is to require users to login with their email address.', 'wp-fail2ban'),
83
+ __('<strong>N.B.</strong> This also applies to Blacklisted Usernames; you must list <em>email addresses</em>, not usernames.', 'wp-fail2ban'),
84
+ $this->see_also(['WP_FAIL2BAN_BLOCK_USERNAME_LOGIN'])
85
+ )
86
+ ]);
87
+
88
+ parent::current_screen();
89
+ }
90
+
91
+ /**
92
+ * {@inheritDoc}
93
+ *
94
+ * @since 4.0.0
95
+ */
96
+ public function section()
97
+ {
98
+ echo '';
99
+ }
100
+
101
+ /**
102
+ * User Enumeration
103
+ *
104
+ * @since 4.0.0
105
+ */
106
+ public function userEnumeration()
107
+ {
108
+ $this->checkbox('WP_FAIL2BAN_BLOCK_USER_ENUMERATION');
109
+ }
110
+
111
+ /**
112
+ * Blocked usernames
113
+ *
114
+ * @since 4.0.0
115
+ */
116
+ public function users()
117
+ {
118
+ if (defined('WP_FAIL2BAN_BLOCKED_USERS')) {
119
+ if (is_array(WP_FAIL2BAN_BLOCKED_USERS)) {
120
+ $value = join(', ', WP_FAIL2BAN_BLOCKED_USERS);
121
+ } else {
122
+ $value = WP_FAIL2BAN_BLOCKED_USERS;
123
+ }
124
  } else {
125
+ $value = '';
126
  }
127
+ printf(
128
+ '<input class="regular-text" type="text" disabled="disabled" value="%s">',
129
+ esc_attr($value)
130
+ );
131
  }
 
 
 
132
 
133
+ /**
134
+ * Block username logins
135
+ *
136
+ * @since 4.3.0
137
+ */
138
+ public function usernames()
139
+ {
140
+ $this->checkbox('WP_FAIL2BAN_BLOCK_USERNAME_LOGIN');
141
+ }
142
+ }
143
  }
144
+
admin/config/logging.php CHANGED
@@ -1,189 +1,182 @@
1
  <?php
2
-
3
  /**
4
  * Settings - Logging
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
- namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * Tab: Logging
16
- *
17
- * @since 4.0.0
18
- */
19
- class TabLogging extends Tab
20
- {
21
- /**
22
- * {@inheritDoc}
23
- */
24
- public function __construct()
25
- {
26
- add_action( 'admin_init', [ $this, 'admin_init' ], 100 );
27
- parent::__construct( 'logging', 'Logging' );
28
- }
29
-
30
- /**
31
- * {@inheritDoc}
32
- *
33
- * @since 4.0.0
34
- */
35
- public function admin_init()
36
- {
37
- // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
38
- add_settings_section(
39
- 'wp-fail2ban-logging',
40
- __( 'What & Where' ),
41
- [ $this, 'sectionWhatWhere' ],
42
- 'wp-fail2ban-logging'
43
- );
44
- add_settings_field(
45
- 'logging-log-authentication',
46
- parent::doc_link( 'WP_FAIL2BAN_AUTH_LOG', __( 'Authentication' ) ),
47
- [ $this, 'authentication' ],
48
- 'wp-fail2ban-logging',
49
- 'wp-fail2ban-logging'
50
- );
51
- add_settings_field(
52
- 'logging-log-comments',
53
- parent::doc_link( 'WP_FAIL2BAN_LOG_COMMENTS', __( 'Comments' ) ),
54
- [ $this, 'comments' ],
55
- 'wp-fail2ban-logging',
56
- 'wp-fail2ban-logging'
57
- );
58
- add_settings_field(
59
- 'logging-log-spam',
60
- parent::doc_link( 'WP_FAIL2BAN_LOG_SPAM', __( 'Spam' ) ),
61
- [ $this, 'spam' ],
62
- 'wp-fail2ban-logging',
63
- 'wp-fail2ban-logging'
64
- );
65
- add_settings_field(
66
- 'logging-log-password-request',
67
- parent::doc_link( 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST', __( 'Password Requests' ) ),
68
- [ $this, 'passwordRequest' ],
69
- 'wp-fail2ban-logging',
70
- 'wp-fail2ban-logging'
71
- );
72
- add_settings_field(
73
- 'logging-log-pingbacks',
74
- parent::doc_link( 'WP_FAIL2BAN_LOG_PINGBACKS', __( 'Pingbacks' ) ),
75
- [ $this, 'pingbacks' ],
76
- 'wp-fail2ban-logging',
77
- 'wp-fail2ban-logging'
78
- );
79
- // phpcs:enable
80
- }
81
-
82
- /**
83
- * {@inheritDoc}
84
- *
85
- * @since 4.0.0
86
- */
87
- public function render()
88
- {
89
- parent::render();
90
- }
91
-
92
- /**
93
- * {@inheritDoc}
94
- *
95
- * @since 4.0.0
96
- *
97
- * @param array $settings {@inheritDoc}
98
- * @param array $input {@inheritDoc}
99
- *
100
- * @return array {@inheritDoc}
101
- */
102
- public function sanitize( array $settings, array $input = null )
103
- {
104
- return $settings;
105
- }
106
-
107
- /**
108
- * Section summary.
109
- *
110
- * @since 4.0.0
111
- */
112
- public function sectionWhatWhere()
113
- {
114
- echo '' ;
115
- }
116
-
117
- /**
118
- * Authentication.
119
- *
120
- * @since 4.0.0
121
- */
122
- public function authentication()
123
- {
124
- printf( '<label>%s: %s</label>', __( 'Use facility' ), $this->getLogFacilities( 'WP_FAIL2BAN_AUTH_LOG', true ) );
125
- }
126
-
127
  /**
128
- * Comments.
129
  *
130
  * @since 4.0.0
131
  */
132
- public function comments()
133
  {
134
- add_filter(
135
- 'wp_fail2ban_log_WP_FAIL2BAN_LOG_COMMENTS',
136
- [ $this, 'commentsExtra' ],
137
- 10,
138
- 3
139
- );
140
- $this->log(
141
- 'WP_FAIL2BAN_LOG_COMMENTS',
142
- 'WP_FAIL2BAN_COMMENT_LOG',
143
- '',
144
- [ 'comments-extra', 'logging-comments-extra-facility' ]
145
- );
146
- }
147
-
148
- /**
149
- * Comments extra helper - checked.
150
- *
151
- * @since 4.0.0
152
- *
153
- * @param int $value Value to check
154
- */
155
- protected function commentExtraChecked( $value )
156
- {
157
- if ( !defined( 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA' ) ) {
158
- return '';
159
  }
160
- return checked( $value & WP_FAIL2BAN_LOG_COMMENTS_EXTRA, $value, false );
161
- }
162
-
163
- /**
164
- * Comments extra helper - disabled.
165
- *
166
- * @since 4.0.0
167
- */
168
- protected function commentExtraDisabled()
169
- {
170
- return 'disabled="disabled';
171
- }
172
-
173
- /**
174
- * Comments extra.
175
- *
176
- * @since 4.0.0
177
- *
178
- * @param string $html HTML prefixed to output
179
- * @param string $define_name Not used
180
- * @param string $define_log Not used
181
- *
182
- * @return string
183
- */
184
- public function commentsExtra( $html, $define_name, $define_log )
185
- {
186
- $fmt = <<<___HTML___
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  <table>
188
  <tr>
189
  <th>%s</th>
@@ -203,53 +196,63 @@ class TabLogging extends Tab
203
  </tr>
204
  </table>
205
  ___HTML___;
206
- return $html . sprintf(
207
- $fmt,
208
- parent::doc_link( 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA', __( 'Also log:' ) ),
209
- $this->commentExtraChecked( WPF2B_EVENT_COMMENT_NOT_FOUND ),
210
- __( 'Post not found' ),
211
- $this->commentExtraChecked( WPF2B_EVENT_COMMENT_CLOSED ),
212
- __( 'Comments closed' ),
213
- $this->commentExtraChecked( WPF2B_EVENT_COMMENT_TRASH ),
214
- __( 'Trash post' ),
215
- $this->commentExtraChecked( WPF2B_EVENT_COMMENT_DRAFT ),
216
- __( 'Draft post' ),
217
- $this->commentExtraChecked( WPF2B_EVENT_COMMENT_PASSWORD ),
218
- __( 'Password-protected post' ),
219
- parent::doc_link( 'WP_FAIL2BAN_COMMENT_EXTRA_LOG', __( 'Use facility:' ) ),
220
- $this->getLogFacilities( 'WP_FAIL2BAN_COMMENT_EXTRA_LOG', false )
221
- );
222
- }
223
-
224
- /**
225
- * Password request
226
- *
227
- * @since 4.0.0
228
- */
229
- public function passwordRequest()
230
- {
231
- $this->log( 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST', 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG' );
232
- }
233
-
234
- /**
235
- * Pingbacks
236
- *
237
- * @since 4.0.0
238
- */
239
- public function pingbacks()
240
- {
241
- $this->log( 'WP_FAIL2BAN_LOG_PINGBACKS', 'WP_FAIL2BAN_PINGBACK_LOG' );
242
- }
243
-
244
- /**
245
- * Spam
246
- *
247
- * @since 4.0.0
248
- */
249
- public function spam()
250
- {
251
- $this->log( 'WP_FAIL2BAN_LOG_SPAM', 'WP_FAIL2BAN_SPAM_LOG' );
252
- }
253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  }
255
- new TabLogging();
1
  <?php
 
2
  /**
3
  * Settings - Logging
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
+ * Tab: Logging
13
  *
14
  * @since 4.0.0
15
  */
16
+ class TabLogging extends TabBase
17
  {
18
+ /**
19
+ * {@inheritDoc}
20
+ */
21
+ public function __construct()
22
+ {
23
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
24
+ $this->__['what-where'] = __('What & Where', 'wp-fail2ban');
25
+ $this->__['authentication'] = __('Authentication', 'wp-fail2ban');
26
+ $this->__['comments'] = __('Comments', 'wp-fail2ban');
27
+ $this->__['spam'] = __('Spam', 'wp-fail2ban');
28
+ $this->__['password-request'] = __('Password Requests', 'wp-fail2ban');
29
+ $this->__['pingbacks'] = __('Pingbacks', 'wp-fail2ban');
30
+ // phpcs:enable
31
+
32
+ parent::__construct('logging', __('Logging', 'wp-fail2ban'));
 
 
 
 
 
 
 
 
 
 
33
  }
34
+
35
+ /**
36
+ * {@inheritDoc}
37
+ *
38
+ * @since 4.0.0
39
+ */
40
+ public function admin_init()
41
+ {
42
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
43
+ add_settings_section('wp-fail2ban-logging', $this->__['what-where'], [$this, 'sectionWhatWhere'],'wp-fail2ban-logging');
44
+ add_settings_field('logging-log-authentication', $this->__['authentication'], [$this, 'authentication'], 'wp-fail2ban-logging', 'wp-fail2ban-logging');
45
+ add_settings_field('logging-log-comments', $this->__['comments'], [$this, 'comments'], 'wp-fail2ban-logging', 'wp-fail2ban-logging');
46
+ add_settings_field('logging-log-spam', $this->__['spam'], [$this, 'spam'], 'wp-fail2ban-logging', 'wp-fail2ban-logging');
47
+ add_settings_field('logging-log-password-request', $this->__['password-request'], [$this, 'passwordRequest'], 'wp-fail2ban-logging', 'wp-fail2ban-logging');
48
+ add_settings_field('logging-log-pingbacks', $this->__['pingbacks'], [$this, 'pingbacks'], 'wp-fail2ban-logging', 'wp-fail2ban-logging');
49
+ // phpcs:enable
50
+ }
51
+
52
+ /**
53
+ * {@inheritDoc}
54
+ *
55
+ * @since 4.3.0
56
+ */
57
+ public function current_screen()
58
+ {
59
+ $fmt = <<<___FMT___
60
+ <dl><style>dt{font-weight:bold;}</style>
61
+ <dt>%s</dt><dd>%s</dd>
62
+ <dt>%s</dt><dd>%s</dd>
63
+ <dt>%s</dt><dd>%s</dd>
64
+ <dt>%s</dt><dd>%s</dd>
65
+ <dt>%s</dt><dd>%s</dd>
66
+ </dl>
67
+ ___FMT___;
68
+ get_current_screen()->add_help_tab([
69
+ 'id' => 'what-where',
70
+ 'title' => $this->__['what-where'],
71
+ 'content' => sprintf(
72
+ $fmt,
73
+ $this->__['authentication'],
74
+ $this->see_also([
75
+ 'WP_FAIL2BAN_AUTH_LOG'
76
+ ]),
77
+ $this->__['comments'],
78
+ $this->see_also([
79
+ 'WP_FAIL2BAN_LOG_COMMENTS',
80
+ 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA',
81
+ 'WP_FAIL2BAN_COMMENT_EXTRA_LOG'
82
+ ]),
83
+ $this->__['spam'],
84
+ $this->see_also([
85
+ 'WP_FAIL2BAN_LOG_SPAM',
86
+ 'WP_FAIL2BAN_SPAM_LOG'
87
+ ]),
88
+ $this->__['password-request'],
89
+ $this->see_also([
90
+ 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST',
91
+ 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG'
92
+ ]),
93
+ $this->__['pingbacks'],
94
+ $this->see_also([
95
+ 'WP_FAIL2BAN_LOG_PINGBACKS',
96
+ 'WP_FAIL2BAN_PINGBACK_LOG'
97
+ ])
98
+ )
99
+ ]);
100
+ parent::current_screen();
101
+ }
102
+
103
+ /**
104
+ * Section summary.
105
+ *
106
+ * @since 4.0.0
107
+ */
108
+ public function sectionWhatWhere()
109
+ {
110
+ // noop
111
+ }
112
+
113
+ /**
114
+ * Authentication.
115
+ *
116
+ * @since 4.0.0
117
+ */
118
+ public function authentication()
119
+ {
120
+ printf(
121
+ '<label>%s: %s</label><p class="description">%s</p>',
122
+ __('Use facility', 'wp-fail2ban'),
123
+ $this->getLogFacilities('WP_FAIL2BAN_AUTH_LOG', true),
124
+ Config::desc('WP_FAIL2BAN_AUTH_LOG')
125
+ );
126
+ }
127
+
128
+ /**
129
+ * Comments.
130
+ *
131
+ * @since 4.0.0
132
+ */
133
+ public function comments()
134
+ {
135
+ add_filter('wp_fail2ban_log_WP_FAIL2BAN_LOG_COMMENTS', [$this, 'commentsExtra'], 10, 3);
136
+
137
+ $this->log(
138
+ 'WP_FAIL2BAN_LOG_COMMENTS',
139
+ 'WP_FAIL2BAN_COMMENT_LOG',
140
+ ['comments-extra', 'logging-comments-extra-facility']
141
+ );
142
+ }
143
+
144
+ /**
145
+ * Comments extra helper - checked.
146
+ *
147
+ * @since 4.0.0
148
+ *
149
+ * @param int $value Value to check
150
+ */
151
+ protected function commentExtraChecked($value)
152
+ {
153
+ return checked($value == ($value & Config::get('WP_FAIL2BAN_LOG_COMMENTS_EXTRA')), true, false);
154
+ }
155
+
156
+ /**
157
+ * Comments extra helper - disabled.
158
+ *
159
+ * @since 4.0.0
160
+ */
161
+ protected function commentExtraDisabled()
162
+ {
163
+ return 'disabled="disabled';
164
+ }
165
+
166
+ /**
167
+ * Comments extra.
168
+ *
169
+ * @since 4.0.0
170
+ *
171
+ * @param string $html HTML prefixed to output
172
+ * @param string $define_name Not used
173
+ * @param string $define_log Not used
174
+ *
175
+ * @return string
176
+ */
177
+ public function commentsExtra($html, $define_name, $define_log)
178
+ {
179
+ $fmt = <<< ___HTML___
180
  <table>
181
  <tr>
182
  <th>%s</th>
196
  </tr>
197
  </table>
198
  ___HTML___;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
+ return $html.sprintf(
201
+ $fmt,
202
+ __('Also log:', 'wp-fail2ban'),
203
+ $this->commentExtraChecked(WPF2B_EVENT_COMMENT_NOT_FOUND),
204
+ __('Post not found', 'wp-fail2ban'),
205
+ $this->commentExtraChecked(WPF2B_EVENT_COMMENT_CLOSED),
206
+ __('Comments closed', 'wp-fail2ban'),
207
+ $this->commentExtraChecked(WPF2B_EVENT_COMMENT_TRASH),
208
+ __('Trash post', 'wp-fail2ban'),
209
+ $this->commentExtraChecked(WPF2B_EVENT_COMMENT_DRAFT),
210
+ __('Draft post', 'wp-fail2ban'),
211
+ $this->commentExtraChecked(WPF2B_EVENT_COMMENT_PASSWORD),
212
+ __('Password-protected post', 'wp-fail2ban'),
213
+ __('Use facility:', 'wp-fail2ban'),
214
+ $this->getLogFacilities('WP_FAIL2BAN_COMMENT_EXTRA_LOG', false)
215
+ );
216
+ }
217
+
218
+ /**
219
+ * Password request
220
+ *
221
+ * @since 4.0.0
222
+ */
223
+ public function passwordRequest()
224
+ {
225
+ $this->log(
226
+ 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST',
227
+ 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG'
228
+ );
229
+ }
230
+
231
+ /**
232
+ * Pingbacks
233
+ *
234
+ * @since 4.0.0
235
+ */
236
+ public function pingbacks()
237
+ {
238
+ $this->log(
239
+ 'WP_FAIL2BAN_LOG_PINGBACKS',
240
+ 'WP_FAIL2BAN_PINGBACK_LOG'
241
+ );
242
+ }
243
+
244
+ /**
245
+ * Spam
246
+ *
247
+ * @since 4.0.0
248
+ */
249
+ public function spam()
250
+ {
251
+ $this->log(
252
+ 'WP_FAIL2BAN_LOG_SPAM',
253
+ 'WP_FAIL2BAN_SPAM_LOG'
254
+ );
255
+ }
256
+ }
257
  }
258
+
admin/config/plugins.php CHANGED
@@ -1,185 +1,124 @@
1
  <?php
2
-
3
  /**
4
  * Settings - Plugins
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.2.0
8
  */
9
- namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * Tab: Plugins
16
- *
17
- * @since 4.2.0
18
- */
19
- class TabPlugins extends Tab
20
- {
21
- /**
22
- * {@inheritDoc}
23
- */
24
- public function __construct()
25
- {
26
- add_action( 'admin_init', [ $this, 'admin_init' ], 100 );
27
- parent::__construct( 'plugins', 'Plugins' );
28
- }
29
-
30
- /**
31
- * {@inheritDoc}
32
- *
33
- * @since 4.0.0
34
- */
35
- public function admin_init()
36
- {
37
- // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
38
- add_settings_section(
39
- 'wp-fail2ban-plugins',
40
- __( 'Event Class Facilities' ),
41
- [ $this, 'sectionLoggingEventClasses' ],
42
- 'wp-fail2ban-plugins'
43
- );
44
- add_settings_field(
45
- 'plugins-log-auth',
46
- parent::doc_link( 'WP_FAIL2BAN_PLUGIN_LOG_AUTH', __( 'Authentication' ) ),
47
- [ $this, 'auth' ],
48
- 'wp-fail2ban-plugins',
49
- 'wp-fail2ban-plugins'
50
- );
51
- add_settings_field(
52
- 'plugins-log-comment',
53
- parent::doc_link( 'WP_FAIL2BAN_PLUGIN_LOG_COMMENT', __( 'Comment' ) ),
54
- [ $this, 'comment' ],
55
- 'wp-fail2ban-plugins',
56
- 'wp-fail2ban-plugins'
57
- );
58
- add_settings_field(
59
- 'plugins-log-password',
60
- parent::doc_link( 'WP_FAIL2BAN_PLUGIN_LOG_PASSWORD', __( 'Password' ) ),
61
- [ $this, 'password' ],
62
- 'wp-fail2ban-plugins',
63
- 'wp-fail2ban-plugins'
64
- );
65
- add_settings_field(
66
- 'plugins-log-rest',
67
- parent::doc_link( 'WP_FAIL2BAN_PLUGIN_LOG_REST', __( 'REST' ) ),
68
- [ $this, 'rest' ],
69
- 'wp-fail2ban-plugins',
70
- 'wp-fail2ban-plugins'
71
- );
72
- add_settings_field(
73
- 'plugins-log-spam',
74
- parent::doc_link( 'WP_FAIL2BAN_PLUGIN_LOG_SPAM', __( 'Spam' ) ),
75
- [ $this, 'spam' ],
76
- 'wp-fail2ban-plugins',
77
- 'wp-fail2ban-plugins'
78
- );
79
- add_settings_field(
80
- 'plugins-log-xmlrpc',
81
- parent::doc_link( 'WP_FAIL2BAN_PLUGIN_LOG_XMLRPC', __( 'XML-RPC' ) ),
82
- [ $this, 'xmlrpc' ],
83
- 'wp-fail2ban-plugins',
84
- 'wp-fail2ban-plugins'
85
- );
86
- // phpcs:enable
87
- }
88
-
89
- /**
90
- * {@inheritDoc}
91
- *
92
- * @since 4.2.0
93
- */
94
- public function render()
95
- {
96
- parent::render();
97
- }
98
-
99
- /**
100
- * {@inheritDoc}
101
- *
102
- * @since 4.2.0
103
- *
104
- * @param array $settings {@inheritDoc}
105
- * @param array $input {@inheritDoc}
106
- *
107
- * @return array {@inheritDoc}
108
- */
109
- public function sanitize( array $settings, array $input = null )
110
- {
111
- return $settings;
112
- }
113
-
114
  /**
115
- * Section summary.
116
  *
117
  * @since 4.2.0
118
  */
119
- public function sectionLoggingEventClasses()
120
  {
121
- echo __( 'Facilities to use for plugin-generated messages. The defaults follow the Core defaults.' ) ;
122
- }
123
-
124
- /**
125
- * Auth
126
- *
127
- * @since 4.2.0
128
- */
129
- public function auth()
130
- {
131
- $this->log( 'WP_FAIL2BAN_PLUGIN_LOG_AUTH', 'WP_FAIL2BAN_PLUGIN_AUTH_LOG' );
132
- }
133
-
134
- /**
135
- * Comment
136
- *
137
- * @since 4.2.0
138
- */
139
- public function comment()
140
- {
141
- $this->log( 'WP_FAIL2BAN_PLUGIN_LOG_COMMENT', 'WP_FAIL2BAN_PLUGIN_COMMENT_LOG' );
142
- }
143
-
144
- /**
145
- * Password
146
- *
147
- * @since 4.2.0
148
- */
149
- public function password()
150
- {
151
- $this->log( 'WP_FAIL2BAN_PLUGIN_LOG_PASSWORD', 'WP_FAIL2BAN_PLUGIN_PASSWORD_LOG' );
152
- }
153
-
154
- /**
155
- * REST
156
- *
157
- * @since 4.2.0
158
- */
159
- public function rest()
160
- {
161
- $this->log( 'WP_FAIL2BAN_PLUGIN_LOG_REST', 'WP_FAIL2BAN_PLUGIN_REST_LOG' );
162
- }
163
-
164
- /**
165
- * Spam
166
- *
167
- * @since 4.2.0
168
- */
169
- public function spam()
170
- {
171
- $this->log( 'WP_FAIL2BAN_PLUGIN_LOG_SPAM', 'WP_FAIL2BAN_PLUGIN_SPAM_LOG' );
172
- }
173
-
174
- /**
175
- * XML-RPC
176
- *
177
- * @since 4.2.0
178
- */
179
- public function xmlrpc()
180
- {
181
- $this->log( 'WP_FAIL2BAN_PLUGIN_LOG_XMLRPC', 'WP_FAIL2BAN_PLUGIN_XMLRPC_LOG' );
182
- }
183
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  }
185
- new TabPlugins();
1
  <?php
 
2
  /**
3
  * Settings - Plugins
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.2.0
7
  */
8
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
+ * Tab: Plugins
13
  *
14
  * @since 4.2.0
15
  */
16
+ class TabPlugins extends TabBase
17
  {
18
+ /**
19
+ * {@inheritDoc}
20
+ */
21
+ public function __construct()
22
+ {
23
+ parent::__construct('plugins', __('Plugins', 'wp-fail2ban'));
24
+ }
25
+
26
+ /**
27
+ * {@inheritDoc}
28
+ *
29
+ * @since 4.0.0
30
+ */
31
+ public function admin_init()
32
+ {
33
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
34
+ add_settings_section('wp-fail2ban-plugins', __('Event Class Facilities', 'wp-fail2ban'), [$this, 'sectionLoggingEventClasses'], 'wp-fail2ban-plugins');
35
+ add_settings_field('plugins-log-auth', __('Authentication', 'wp-fail2ban'), [$this, 'auth'], 'wp-fail2ban-plugins', 'wp-fail2ban-plugins');
36
+ add_settings_field('plugins-log-comment', __('Comment', 'wp-fail2ban'), [$this, 'comment'], 'wp-fail2ban-plugins', 'wp-fail2ban-plugins');
37
+ add_settings_field('plugins-log-password', __('Password', 'wp-fail2ban'), [$this, 'password'], 'wp-fail2ban-plugins', 'wp-fail2ban-plugins');
38
+ add_settings_field('plugins-log-rest', __('REST', 'wp-fail2ban'), [$this, 'rest'], 'wp-fail2ban-plugins', 'wp-fail2ban-plugins');
39
+ add_settings_field('plugins-log-spam', __('Spam', 'wp-fail2ban'), [$this, 'spam'], 'wp-fail2ban-plugins', 'wp-fail2ban-plugins');
40
+ add_settings_field('plugins-log-xmlrpc', __('XML-RPC', 'wp-fail2ban'), [$this, 'xmlrpc'], 'wp-fail2ban-plugins', 'wp-fail2ban-plugins');
41
+ // phpcs:enable
42
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
+ /**
45
+ * {@inheritDoc}
46
+ *
47
+ * @since 4.3.0
48
+ */
49
+ public function current_screen()
50
+ {
51
+ }
52
+
53
+ /**
54
+ * Section summary.
55
+ *
56
+ * @since 4.2.0
57
+ */
58
+ public function sectionLoggingEventClasses()
59
+ {
60
+ echo __('Facilities to use for plugin-generated messages. The defaults follow the Core defaults.', 'wp-fail2ban');
61
+ }
62
+
63
+ /**
64
+ * Auth
65
+ *
66
+ * @since 4.2.0
67
+ */
68
+ public function auth()
69
+ {
70
+ $this->log('WP_FAIL2BAN_PLUGIN_LOG_AUTH', 'WP_FAIL2BAN_PLUGIN_AUTH_LOG');
71
+ }
72
+
73
+ /**
74
+ * Comment
75
+ *
76
+ * @since 4.2.0
77
+ */
78
+ public function comment()
79
+ {
80
+ $this->log('WP_FAIL2BAN_PLUGIN_LOG_COMMENT', 'WP_FAIL2BAN_PLUGIN_COMMENT_LOG');
81
+ }
82
+
83
+ /**
84
+ * Password
85
+ *
86
+ * @since 4.2.0
87
+ */
88
+ public function password()
89
+ {
90
+ $this->log('WP_FAIL2BAN_PLUGIN_LOG_PASSWORD', 'WP_FAIL2BAN_PLUGIN_PASSWORD_LOG');
91
+ }
92
+
93
+ /**
94
+ * REST
95
+ *
96
+ * @since 4.2.0
97
+ */
98
+ public function rest()
99
+ {
100
+ $this->log('WP_FAIL2BAN_PLUGIN_LOG_REST', 'WP_FAIL2BAN_PLUGIN_REST_LOG');
101
+ }
102
+
103
+ /**
104
+ * Spam
105
+ *
106
+ * @since 4.2.0
107
+ */
108
+ public function spam()
109
+ {
110
+ $this->log('WP_FAIL2BAN_PLUGIN_LOG_SPAM', 'WP_FAIL2BAN_PLUGIN_SPAM_LOG');
111
+ }
112
+
113
+ /**
114
+ * XML-RPC
115
+ *
116
+ * @since 4.2.0
117
+ */
118
+ public function xmlrpc()
119
+ {
120
+ $this->log('WP_FAIL2BAN_PLUGIN_LOG_XMLRPC', 'WP_FAIL2BAN_PLUGIN_XMLRPC_LOG');
121
+ }
122
+ }
123
  }
124
+
admin/config/remote-ips.php CHANGED
@@ -1,100 +1,112 @@
1
  <?php
2
-
3
  /**
4
  * Settings - Remote IPs
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
- namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * Tab: Remote IPs
16
- *
17
- * @since 4.0.0
18
- */
19
- class TabRemoteIPs extends Tab
20
- {
21
- /**
22
- * {@inheritDoc}
23
- *
24
- * @since 4.0.0
25
- */
26
- public function __construct()
27
- {
28
- add_action( 'admin_init', [ $this, 'admin_init' ] );
29
- parent::__construct( 'remote-ips', 'Remote IPs' );
30
- }
31
-
32
  /**
33
- * {@inheritDoc}
34
  *
35
  * @since 4.0.0
36
  */
37
- public function admin_init()
38
  {
39
- // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
40
- add_settings_section(
41
- 'wp-fail2ban-proxies',
42
- __( 'Proxies' ),
43
- [ $this, 'section' ],
44
- 'wp-fail2ban-remote-ips'
45
- );
46
- add_settings_field(
47
- 'remote-ips-proxies',
48
- parent::doc_link( 'WP_FAIL2BAN_PROXIES', __( 'IP list' ) ),
49
- [ $this, 'proxies' ],
50
- 'wp-fail2ban-remote-ips',
51
- 'wp-fail2ban-proxies'
52
- );
53
- // phpcs:enable
54
- }
55
-
56
- /**
57
- * {@inheritDoc}
58
- *
59
- * @since 4.0.0
60
- *
61
- * @param array $settings
62
- * @param array $input
63
- */
64
- public function sanitize( array $settings, array $input = null )
65
- {
66
- return $settings;
67
- }
68
-
69
- /**
70
- * Section blurb.
71
- *
72
- * @since 4.0.0
73
- */
74
- public function section()
75
- {
76
- echo '' ;
77
- }
78
-
79
- /**
80
- * Proxies.
81
- *
82
- * @since 4.0.0
83
- */
84
- public function proxies()
85
- {
86
- $value = '';
87
- if ( defined( 'WP_FAIL2BAN_PROXIES' ) ) {
88
-
89
- if ( is_array( WP_FAIL2BAN_PROXIES ) ) {
90
- $value = join( "\n", WP_FAIL2BAN_PROXIES );
91
- } else {
92
- $value = join( "\n", array_map( 'trim', explode( ',', WP_FAIL2BAN_PROXIES ) ) );
93
- }
94
-
95
  }
96
- printf( '<fieldset><textarea class="code" cols="20" rows="10" disabled="disabled">%s</textarea></fieldset>', esc_html( $value ) );
97
- }
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  }
100
- new TabRemoteIPs();
1
  <?php
 
2
  /**
3
  * Settings - Remote IPs
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
+ * Tab: Remote IPs
13
  *
14
  * @since 4.0.0
15
  */
16
+ class TabRemoteIPs extends TabBase
17
  {
18
+ /**
19
+ * {@inheritDoc}
20
+ *
21
+ * @since 4.0.0
22
+ */
23
+ public function __construct()
24
+ {
25
+ $this->__['wp-fail2ban-proxies'] = __('Proxies', 'wp-fail2ban');
26
+ $this->__['remote-ips-proxies'] = __('IP list', 'wp-fail2ban');
27
+
28
+ parent::__construct('remote-ips', __('Remote IPs', 'wp-fail2ban'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  }
 
 
30
 
31
+ /**
32
+ * {@inheritDoc}
33
+ *
34
+ * @since 4.0.0
35
+ */
36
+ public function admin_init()
37
+ {
38
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
39
+ add_settings_section('wp-fail2ban-proxies', $this->__['wp-fail2ban-proxies'], [$this, 'section'], 'wp-fail2ban-remote-ips');
40
+ add_settings_field('remote-ips-proxies', $this->__['remote-ips-proxies'], [$this, 'proxies'], 'wp-fail2ban-remote-ips', 'wp-fail2ban-proxies');
41
+ // phpcs:enable
42
+ }
43
+
44
+ /**
45
+ * {@inheritDoc}
46
+ *
47
+ * @since 4.3.0
48
+ */
49
+ public function current_screen()
50
+ {
51
+ $fmt = <<<___FMT___
52
+ <dl><style>dt{font-weight:bold;}</style>
53
+ <dt>%s</dt>
54
+ <dd><p>%s</p><p>%s</p>%s</dd>
55
+ </dl>
56
+ ___FMT___;
57
+ get_current_screen()->add_help_tab([
58
+ 'id' => 'remote-ips-proxies',
59
+ 'title' => $this->__['wp-fail2ban-proxies'],
60
+ 'content' => sprintf(
61
+ $fmt,
62
+ $this->__['remote-ips-proxies'],
63
+ __('A list of IPv4 addresses in CIDR notation. The list of CloudFlare IPs can be found <a href="https://www.cloudflare.com/ips-v4" rel="noopener" target="_blank">here</a>', 'wp-fail2ban'),
64
+ __('<strong>NB:</strong> IPv6 is not yet supported.', 'wp-fail2ban'),
65
+ $this->doc_link('WP_FAIL2BAN_PROXIES')
66
+ )
67
+ ]);
68
+ parent::current_screen();
69
+ }
70
+
71
+ /**
72
+ * Section blurb.
73
+ *
74
+ * @since 4.0.0
75
+ */
76
+ public function section()
77
+ {
78
+ echo '';
79
+ }
80
+
81
+ /**
82
+ * Helper - multi-line string from proxies list.
83
+ *
84
+ * @since 4.3.0
85
+ *
86
+ * @return string
87
+ */
88
+ protected function proxies_value()
89
+ {
90
+ $proxies = Config::get('WP_FAIL2BAN_PROXIES');
91
+ return (is_array($proxies))
92
+ ? join("\n", $proxies)
93
+ : join("\n", array_map('trim', explode(',', $proxies)));
94
+ }
95
+
96
+ /**
97
+ * Proxies.
98
+ *
99
+ * @since 4.3.0 Refactored.
100
+ * @since 4.0.0
101
+ */
102
+ public function proxies()
103
+ {
104
+ printf(
105
+ '<fieldset><textarea class="code" cols="20" rows="10" disabled="disabled">%s</textarea></fieldset>',
106
+ esc_html($this->proxies_value())
107
+ );
108
+ $this->description('WP_FAIL2BAN_PROXIES');
109
+ }
110
+ }
111
  }
112
+
admin/config/syslog.php CHANGED
@@ -1,103 +1,137 @@
1
  <?php
2
-
3
  /**
4
  * Settings - syslog
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
- namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * Tab: Syslog
16
- *
17
- * @since 4.0.0
18
- */
19
- class TabSyslog extends Tab
20
- {
21
- /**
22
- * {@inheritDoc}
23
- */
24
- public function __construct()
25
- {
26
- add_action( 'admin_init', [ $this, 'admin_init' ], 100 );
27
- parent::__construct( 'syslog', '<tt>syslog</tt>' );
28
- }
29
-
30
- /**
31
- * {@inheritDoc}
32
- *
33
- * @since 4.0.0
34
- */
35
- public function admin_init()
36
- {
37
- // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
38
- add_settings_section(
39
- 'wp-fail2ban-connection',
40
- __( 'Connection' ),
41
- [ $this, 'sectionConnection' ],
42
- 'wp-fail2ban-syslog'
43
- );
44
- add_settings_field(
45
- 'logging-connection',
46
- parent::doc_link( 'WP_FAIL2BAN_OPENLOG_OPTIONS', __( 'Options' ) ),
47
- [ $this, 'connection' ],
48
- 'wp-fail2ban-syslog',
49
- 'wp-fail2ban-connection'
50
- );
51
- add_settings_section(
52
- 'wp-fail2ban-workarounds',
53
- __( 'Workarounds' ),
54
- [ $this, 'sectionWorkarounds' ],
55
- 'wp-fail2ban-syslog'
56
- );
57
- add_settings_field(
58
- 'logging-workarounds',
59
- parent::doc_link( '../syslog', __( 'Options' ) ),
60
- [ $this, 'workarounds' ],
61
- 'wp-fail2ban-syslog',
62
- 'wp-fail2ban-workarounds'
63
- );
64
- // phpcs:enable
65
- }
66
-
67
- /**
68
- * {@inheritDoc}
69
- *
70
- * @since 4.0.0
71
- *
72
- * @param array $settings {@inheritDoc}
73
- * @param array $input {@inheritDoc}
74
- *
75
- * @return array {@inheritDoc}
76
- */
77
- public function sanitize( array $settings, array $input = null )
78
- {
79
- return $settings;
80
- }
81
-
82
- /**
83
- * Connection section blurb.
84
- *
85
- * @since 4.0.0
86
- */
87
- public function sectionConnection()
88
- {
89
- echo '' ;
90
- }
91
-
92
  /**
93
- * Connection.
94
  *
95
  * @since 4.0.0
96
  */
97
- public function connection()
98
  {
99
- $class = '';
100
- $fmt = <<<___STR___
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  <fieldset>
102
  <label><input type="checkbox" disabled="disabled" %s> <code>LOG_CONS</code></label><br>
103
  <label><input type="checkbox" disabled="disabled" %s> <code>LOG_PERROR</code></label><br>
@@ -106,36 +140,37 @@ class TabSyslog extends Tab
106
  <label><input type="radio" disabled="disabled" %s> <code>LOG_ODELAY</code></label>
107
  </fieldset>
108
  ___STR___;
109
- printf(
110
- $fmt,
111
- checked( WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_CONS, LOG_CONS, false ),
112
- checked( WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_PERROR, LOG_PERROR, false ),
113
- checked( WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_PID, LOG_PID, false ),
114
- __( 'default' ),
115
- checked( WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_NDELAY, LOG_NDELAY, false ),
116
- __( 'default' ),
117
- checked( WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_ODELAY, LOG_ODELAY, false )
118
- );
119
- }
120
-
121
- /**
122
- * Workarounds section blurb.
123
- *
124
- * @since 4.0.0
125
- */
126
- public function sectionWorkarounds()
127
- {
128
- echo '' ;
129
- }
130
-
131
- /**
132
- * Workarounds.
133
- *
134
- * @since 4.0.0
135
- */
136
- public function workarounds()
137
- {
138
- $fmt = <<<___STR___
 
139
  <fieldset>
140
  <label><input type="checkbox" disabled="disabled" %s> %s</label>
141
  <br>
@@ -144,16 +179,16 @@ ___STR___;
144
  <label><input type="checkbox" disabled="disabled" %s> %s</label>
145
  </fieldset>
146
  ___STR___;
147
- printf(
148
- $fmt,
149
- checked( @WP_FAIL2BAN_SYSLOG_SHORT_TAG, true, false ),
150
- __( 'Short Tag' ),
151
- checked( @WP_FAIL2BAN_HTTP_HOST, true, false ),
152
- __( 'Specify Host' ),
153
- checked( @WP_FAIL2BAN_TRUNCATE_HOST, true, false ),
154
- __( 'Truncate Host' )
155
- );
 
156
  }
157
-
158
  }
159
- new TabSyslog();
1
  <?php
 
2
  /**
3
  * Settings - syslog
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
+ * Tab: Syslog
13
  *
14
  * @since 4.0.0
15
  */
16
+ class TabSyslog extends TabBase
17
  {
18
+ /**
19
+ * {@inheritDoc}
20
+ */
21
+ public function __construct()
22
+ {
23
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
24
+ $this->__['wp-fail2ban-connection'] = __('Connection', 'wp-fail2ban');
25
+ $this->__['syslog-connection-options'] = __('Options', 'wp-fail2ban');
26
+ $this->__['wp-fail2ban-workarounds'] = __('Workarounds', 'wp-fail2ban');
27
+ $this->__['syslog-workarounds'] = __('Options', 'wp-fail2ban');
28
+ // phpcs:enable
29
+
30
+ parent::__construct('syslog', 'syslog');
31
+ }
32
+
33
+ /**
34
+ * {@inheritDoc}
35
+ *
36
+ * @since 4.0.0
37
+ */
38
+ public function admin_init()
39
+ {
40
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
41
+ add_settings_section('wp-fail2ban-connection', $this->__['wp-fail2ban-connection'], [$this, 'sectionConnection'], 'wp-fail2ban-syslog');
42
+ add_settings_field('syslog-connection-options', $this->__['syslog-connection-options'], [$this, 'connection'], 'wp-fail2ban-syslog', 'wp-fail2ban-connection');
43
+
44
+ add_settings_section('wp-fail2ban-workarounds', $this->__['wp-fail2ban-workarounds'], [$this, 'sectionWorkarounds'], 'wp-fail2ban-syslog');
45
+ add_settings_field('syslog-workarounds', $this->__['syslog-workarounds'], [$this, 'workarounds'], 'wp-fail2ban-syslog', 'wp-fail2ban-workarounds');
46
+ // phpcs:enable
47
+ }
48
+
49
+ /**
50
+ * {@inheritDoc}
51
+ *
52
+ * @since 4.3.0
53
+ */
54
+ public function current_screen()
55
+ {
56
+ $fmt = <<<___FMT___
57
+ <p>%s</p>
58
+ <table><style>th{text-align:left;vertical-align:top;}</style>
59
+ <tr><th scope="row">LOG_CONS</th><td>%s</td></tr>
60
+ <tr><th scope="row">LOG_NDELAY</th><td>%s</td></tr>
61
+ <tr><th scope="row">LOG_ODELAY</th><td>%s</td></tr>
62
+ <tr><th scope="row">LOG_PERROR</th><td>%s</td></tr>
63
+ <tr><th scope="row">LOG_PID</th><td>%s</td></tr>
64
+ </table>
65
+ %s
66
+ ___FMT___;
67
+ get_current_screen()->add_help_tab([
68
+ 'id' => 'syslog-connection-options',
69
+ 'title' => $this->__['wp-fail2ban-connection'],
70
+ 'content' => sprintf(
71
+ $fmt,
72
+ __('Used to indicate what logging options will be used when generating a log message.', 'wp-fail2ban'),
73
+ __('if there is an error while sending data to the system logger, write directly to the system console', 'wp-fail2ban'),
74
+ __('open the connection to the logger immediately', 'wp-fail2ban'),
75
+ __('(default) delay opening the connection until the first message is logged', 'wp-fail2ban'),
76
+ __('print log message also to standard error', 'wp-fail2ban'),
77
+ __('include PID with each message', 'wp-fail2ban'),
78
+ $this->see_also(['WP_FAIL2BAN_OPENLOG_OPTIONS'])
79
+ )
80
+ ]);
81
+ $fmt = <<<___FMT___
82
+ <p>%s</p>
83
+ <p>%s</p>
84
+ <dl><style>dt{font-weight:bold;}</style>
85
+ <dt>%s</dt>
86
+ <dd><p>%s</p>%s</dd>
87
+ <dt>%s</dt>
88
+ <dd><p>%s</p>%s</dd>
89
+ <dt>%s</dt>
90
+ <dd><p>%s</p><p>%s</p>%s</dd>
91
+ </dl>
92
+ ___FMT___;
93
+ get_current_screen()->add_help_tab([
94
+ 'id' => 'syslog-workarounds',
95
+ 'title' => $this->__['wp-fail2ban-workarounds'],
96
+ 'content' => sprintf(
97
+ $fmt,
98
+ __('<tt>syslog</tt> was only <a href="https://tools.ietf.org/html/rfc5424" target="_blank">standardised</a> in 2009, so unfortunately there are still implementations that need some help.', 'wp-fail2ban'),
99
+ __('By far the most common limitation is the length of the initial information fields; these options provide ways to shorten the data in those fields.', 'wp-fail2ban'),
100
+ __('Short Tag', 'wp-fail2ban'),
101
+ __('Some syslog implementations assume that the first part of the message (the tag) won&lsquo;t exceed some (small) number of characters. This option tells <em>WPf2b</em> to use <tt>wp</tt> instead of <tt>wordpress</tt>, thereby saving 7 characters; this may be enough to make syslog happy.', 'wp-fail2ban'),
102
+ $this->see_also(['WP_FAIL2BAN_SYSLOG_SHORT_TAG']),
103
+ __('Specify Host', 'wp-fail2ban'),
104
+ __('"Short Tag" may not be enough, so this allows you to specify the hostname. See the <a href="https://docs.wp-fail2ban.com/en/___WPF2BVER___/defines/constants/WP_FAIL2BAN_HTTP_HOST.html" target="_blank">documentation</a> for more details.', 'wp-fail2ban'),
105
+ $this->see_also(['WP_FAIL2BAN_HTTP_HOST']),
106
+ __('Truncate Host', 'wp-fail2ban'),
107
+ __('When all else fails, this allows you to truncate the hostname after a number of characters.', 'wp-fail2ban'),
108
+ __('<strong>N.B.</strong> This may be removed in a future release; it was broken prior to 4.3 and there were no bug reports, so it seems likely absolutely no-one is using it.', 'wp-fail2ban'),
109
+ $this->see_also(['WP_FAIL2BAN_TRUNCATE_HOST'])
110
+ )
111
+ ]);
112
+
113
+ parent::current_screen();
114
+ }
115
+
116
+ /**
117
+ * Connection section blurb.
118
+ *
119
+ * @since 4.0.0
120
+ */
121
+ public function sectionConnection()
122
+ {
123
+ echo '';
124
+ }
125
+
126
+ /**
127
+ * Connection.
128
+ *
129
+ * @since 4.3.0 Refactor to premium.
130
+ * @since 4.0.0
131
+ */
132
+ public function connection()
133
+ {
134
+ $fmt = <<<___STR___
135
  <fieldset>
136
  <label><input type="checkbox" disabled="disabled" %s> <code>LOG_CONS</code></label><br>
137
  <label><input type="checkbox" disabled="disabled" %s> <code>LOG_PERROR</code></label><br>
140
  <label><input type="radio" disabled="disabled" %s> <code>LOG_ODELAY</code></label>
141
  </fieldset>
142
  ___STR___;
143
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing, PSR2.Methods.FunctionCallSignature.MultipleArguments
144
+ printf(
145
+ $fmt,
146
+ checked(WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_CONS, LOG_CONS, false),
147
+ checked(WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_PERROR, LOG_PERROR, false),
148
+ checked(WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_PID, LOG_PID, false), __('default'),
149
+ checked(WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_NDELAY, LOG_NDELAY, false), __('default'),
150
+ checked(WP_FAIL2BAN_OPENLOG_OPTIONS & LOG_ODELAY, LOG_ODELAY, false)
151
+ );
152
+ // phpcs:enable
153
+ }
154
+
155
+ /**
156
+ * Workarounds section blurb.
157
+ *
158
+ * @since 4.0.0
159
+ */
160
+ public function sectionWorkarounds()
161
+ {
162
+ echo '';
163
+ }
164
+
165
+ /**
166
+ * Workarounds.
167
+ *
168
+ * @since 4.3.0 Refactor to premium.
169
+ * @since 4.0.0
170
+ */
171
+ public function workarounds()
172
+ {
173
+ $fmt = <<<___STR___
174
  <fieldset>
175
  <label><input type="checkbox" disabled="disabled" %s> %s</label>
176
  <br>
179
  <label><input type="checkbox" disabled="disabled" %s> %s</label>
180
  </fieldset>
181
  ___STR___;
182
+ printf(
183
+ $fmt,
184
+ checked(@WP_FAIL2BAN_SYSLOG_SHORT_TAG, true, false),
185
+ __('Short Tag', 'wp-fail2ban'),
186
+ checked(@WP_FAIL2BAN_HTTP_HOST, true, false),
187
+ __('Specify Host', 'wp-fail2ban'),
188
+ checked(@WP_FAIL2BAN_TRUNCATE_HOST, true, false),
189
+ __('Truncate Host', 'wp-fail2ban')
190
+ );
191
+ }
192
  }
 
193
  }
194
+
admin/lib/about.php CHANGED
@@ -1,191 +1,142 @@
1
  <?php
 
2
  /**
3
  * About
4
  *
5
  * @package wp-fail2ban
6
- * @since 4.2.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
- if (!defined('ABSPATH')) {
11
- exit;
12
- }
13
 
14
- /**
15
- * About content
16
- *
17
- * @since 4.2.0
18
- *
19
- * @param bool $hide_title
20
- */
21
- function about($hide_title = false)
22
- {
23
- $wp_f2b_ver = substr(WP_FAIL2BAN_VER, 0, strrpos(WP_FAIL2BAN_VER, '.'));
24
- $notice = version_compare(PHP_VERSION, '5.6.0', '<');
25
- ?>
26
- <div class="wrap">
27
- <style>
28
- div.inside ul {
29
- list-style: disc;
30
- padding-left: 2em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
- </style>
33
- <?php if (!$hide_title): ?>
34
- <h1>WP fail2ban</h1>
35
- <?php endif; ?>
36
- <div id="poststuff">
37
- <div id="post-body" class="metabox-holder columns-2">
38
- <div id="post-body-content">
39
- <div class="meta-box-sortables ui-sortable">
40
- <div class="postbox">
41
- <h2>Version 4.2.8</h2>
42
- <div class="inside">
43
- <h4>News</h4>
44
- <ul>
45
- <?php if (strtotime('1 May 2020') > time()): ?>
46
- <li><a href="https://forums.invis.net/?utm_source=about&utm_medium=about&utm_campaign=4.2.8" target="_blank"><strong>Support has moved</strong></a>. Please come join the new <em>WPf2b</em> community!</li>
47
- <?php endif; ?>
48
- <li><a href="https://wp-fail2ban.com/blog/2020/04/16/testers-needed-v4-3-0-is-imminent/?utm_source=about&utm_medium=about&utm_campaign=4.2.8" target="_blank">Testers needed</a>! Version 4.3.0 will be released soon - I need your help to make sure it works properly.</li>
49
- <?php if ($notice): ?>
50
- <li><strong>This is the last release that supports PHP <?php echo PHP_VERSION; ?></strong>.<br>The <strong>minimum version</strong> required for <strong>v4.3.0</strong> is <strong>PHP 5.6</strong>.<br>Please <a href="https://wordpress.org/support/update-php/" target="_blank"><strong>update your PHP</strong></a>.</li>
51
- <?php endif; ?>
52
- </ul>
53
- <h4>Changes</h4>
54
- <ul>
55
- <li>Add link to new <a href="https://forums.invis.net/c/wp-fail2ban/?utm_source=about&utm_medium=about&utm_campaign=4.2.8" target="_blank">support forum</a>.</li>
56
- <li>Fix user enumeration conflict with Gutenberg (h/t @dinghy).</li>
57
- <li>Fix notices wrt admin menu (h/t @marioivangf).</li>
58
- <li>Fix harmless XDebug notice (h/t @dinghy).</li>
59
- <li>Update Freemius library.</li>
60
- </ul>
61
- </div>
62
- </div>
63
- </div>
64
- <div class="meta-box-sortables ui-sortable">
65
- <div class="postbox">
66
- <h2>Version 4.2.7.1</h2>
67
- <div class="inside">
68
- <ul>
69
- <li>Fix error when blocking user enumeration via <tt>oembed</tt>.</li>
70
- </ul>
71
- </div>
72
- </div>
73
- </div>
74
- <div class="meta-box-sortables ui-sortable">
75
- <div class="postbox">
76
- <h2>Version 4.2.7</h2>
77
- <div class="inside">
78
- <ul>
79
- <li>Fix error when blocking user enumeration via REST.</li>
80
- <li>Fix buttons on Settings tabs.</li>
81
- </ul>
82
- </div>
83
- </div>
84
- </div>
85
- <div class="meta-box-sortables ui-sortable">
86
- <div class="postbox">
87
- <h2>Version 4.2.6</h2>
88
- <div class="inside">
89
- <ul>
90
- <li>Add support for <a href="<?php echo admin_url('admin.php?page=wp-fail2ban-tools'); ?>">Remote Tools</a> add-on.
91
- <li>Add support for the new ClassicPress security page.</li>
92
- <li>Improved user enumeration blocking.</li>
93
- </ul>
94
- </div>
95
- </div>
96
- </div>
97
- <div class="meta-box-sortables ui-sortable">
98
- <div class="postbox">
99
- <h2>Version 4.2.5</h2>
100
- <div class="inside">
101
- <ul>
102
- <li>Properly fix PHP 5.3 support; tested on CentOS 6. Does not support any UI or Premium features.</li>
103
- <li>Fix potential issue with <tt>WP_FAIL2BAN_BLOCK_USER_ENUMERATION</tt> if calling REST API or XMLRPC from admin area.</li>
104
- </ul>
105
- </div>
106
- </div>
107
- </div>
108
- <div class="meta-box-sortables ui-sortable">
109
- <div class="postbox">
110
- <h2>Version 4.2.4</h2>
111
- <div class="inside">
112
- <ul>
113
- <li>Add filter for login failed message.</li>
114
- <li>Fix logging spam comments from admin area.</li>
115
- <li>Fix Settings link from Plugins page.</li>
116
- <li>Update Freemius library.</li>
117
- </ul>
118
- </div>
119
- </div>
120
- </div>
121
- <div class="meta-box-sortables ui-sortable">
122
- <div class="postbox">
123
- <h2>Version 4.2.3</h2>
124
- <div class="inside">
125
- <ul>
126
- <li>Workaround for some versions of PHP 7.x that would cause <tt>define()</tt>s to be ignored.</li>
127
- <li>Add config note to settings tabs.</li>
128
- <li>Fix documentation links.</li>
129
- </ul>
130
  </div>
131
  </div>
132
- </div>
133
- <div class="meta-box-sortables ui-sortable">
134
- <div class="postbox">
135
- <h2>Version 4.2.2</h2>
136
- <div class="inside">
137
- <ul>
138
- <li>Fix 5.3 compatibility.</li>
139
- </ul>
140
- </div>
141
- </div>
142
- </div>
143
- <div class="meta-box-sortables ui-sortable">
144
- <div class="postbox">
145
- <h2>Version 4.2.1</h2>
146
- <div class="inside">
147
- <ul>
148
- <li>Completed support for <tt><a href="https://docs.wp-fail2ban.com/en/4.2/defines/WP_FAIL2BAN_COMMENT_EXTRA_LOG.html?utm_source=about&utm_medium=about&utm_campaign=4.2.8" target="docs.wp-fail2ban.com">WP_FAIL2BAN_COMMENT_EXTRA_LOG</a></tt>.</li>
149
- <li>Add support for 3rd-party plugins; see <a href="https://docs.wp-fail2ban.com/en/4.2/developers.html?utm_source=about&utm_medium=about&utm_campaign=4.2.8" target="docs.wp-fail2ban.com">Developers</a>.<br>
150
- <p><ul>
151
- <li>Add-on for <a href="https://wordpress.org/plugins/wp-fail2ban-addon-contact-form-7/">Contact Form 7</a> (experimental).</li>
152
- <li>Add-on for <a href="https://wordpress.org/plugins/wp-fail2ban-addon-gravity-forms/">Gravity Forms</a> (experimental).</li>
153
- </ul></p>
154
- </li>
155
- <li>Change logging for known-user with incorrect password; previously logged as unknown user and matched by <tt>hard</tt> filters (due to limitations in older versions of WordPress), now logged as known user and matched by <tt>soft</tt>.</li>
156
- <li>Bugfix for email-as-username - now logged correctly and matched by <tt>soft</tt>, not <tt>hard</tt>, filters.</li>
157
- <li>Bugfix for regression in code to prevent Free/Premium conflict.</li>
158
- </ul>
159
- </div>
160
- </div>
161
- </div>
162
- </div>
163
- <div id="postbox-container-1" class="postbox-container">
164
- <div class="meta-box-sortables">
165
- <div class="postbox">
166
- <h2>Getting Started</h2>
167
- <div class="inside">
168
- <ol>
169
- <li><a href="https://docs.wp-fail2ban.com/en/<?=$wp_f2b_ver?>/introduction.html?utm_source=about&utm_medium=about&utm_campaign=4.2.8" target="docs.wp-fail2ban.com">Introduction</a></li>
170
- <li><a href="https://docs.wp-fail2ban.com/en/<?=$wp_f2b_ver?>/configuration.html?utm_source=about&utm_medium=about&utm_campaign=4.2.8" target="docs.wp-fail2ban.com">Configuration</a></li>
171
- </ol>
172
- </div>
173
- </div>
174
- <div class="postbox">
175
- <h2>Getting Help</h2>
176
- <div class="inside">
177
- <ul>
178
- <li><a href="<?=wf_fs()->apply_filters('support_forum_url', '')?>?utm_source=about&utm_medium=about&utm_campaign=4.2.8" target="_blank">Support Forum</a></li>
179
- </ul>
180
- <p><strong>Note:</strong> The WordPress.org forum is no longer used for support. Please do not ask questions there as they are likely to go unanswered.</p>
181
  </div>
182
  </div>
183
  </div>
 
184
  </div>
185
  </div>
186
- &nbsp;
187
- </div>
188
- </div>
189
- <?php
190
- }
191
 
 
1
  <?php
2
+
3
  /**
4
  * About
5
  *
6
  * @package wp-fail2ban
7
+ * @since 4.2.0
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
 
 
 
11
 
12
+ if ( defined( 'ABSPATH' ) ) {
13
+ /**
14
+ * Pull in extra "about" information
15
+ *
16
+ * @since 4.3.0
17
+ *
18
+ * @return string
19
+ */
20
+ function _get_extra_about()
21
+ {
22
+ $extra = '';
23
+ /**
24
+ * Don't make a remote call if the user hasn't opted in
25
+ */
26
+
27
+ if ( !wf_fs()->is_tracking_prohibited() ) {
28
+ $extra = get_site_transient( 'wp_fail2ban_extra_about' );
29
+
30
+ if ( false === apply_filters( 'wp_fail2ban_extra_about_transient', $extra ) ) {
31
+ $url = apply_filters( 'wp_fail2ban_extra_about_url', 'https://wp-fail2ban.com/extra-about/?version=' . $wp_f2b_ver );
32
+
33
+ if ( !is_wp_error( $rv = wp_remote_get( $url ) ) ) {
34
+ /**
35
+ * Try not to fetch more than once per day
36
+ */
37
+ set_site_transient( 'wp_fail2ban_extra_about', $rv['body'], DAY_IN_SECONDS );
38
+ $extra = $rv['body'];
39
+ }
40
+
41
+ }
42
+
43
+ }
44
+
45
+ return $extra;
46
  }
47
+
48
+ /**
49
+ * About content
50
+ *
51
+ * @since 4.2.0
52
+ *
53
+ * @param bool $hide_title
54
+ */
55
+ function about( $hide_title = false )
56
+ {
57
+ $wp_f2b_ver = substr( WP_FAIL2BAN_VER, 0, strrpos( WP_FAIL2BAN_VER, '.' ) );
58
+ $extra = _get_extra_about();
59
+ ?>
60
+ <div class="wrap">
61
+ <style>
62
+ div.inside ul {
63
+ list-style: disc;
64
+ padding-left: 2em;
65
+ }
66
+ </style>
67
+ <?php
68
+ if ( !$hide_title ) {
69
+ ?>
70
+ <h1>WP fail2ban</h1>
71
+ <?php
72
+ }
73
+ ?>
74
+ <div id="poststuff">
75
+ <div id="post-body" class="metabox-holder columns-2">
76
+ <div id="post-body-content">
77
+ <div class="meta-box-sortables ui-sortable">
78
+ <?php
79
+ echo $extra ;
80
+ ?>
81
+ <div class="postbox">
82
+ <h2>Version 4.3.0</h2>
83
+ <div class="inside">
84
+ <ul>
85
+ <li>Add full multisite support. See <a href="https://wp-fail2ban.com/blog/changes-to-multisite-support/" rel="noopener" target="_blank">here</a> for more information.</li>
86
+ <li>Add separate logging for empty usernames.</li>
87
+ <li>Improve user enumeration blocking compatibility with the WordPress block editor (Gutenberg).</li>
88
+ <li>Log extra information for events <em>(premium)</em>.</li>
89
+ <li>Add new event class for blocked actions <em>(premium)</em>.</li>
90
+ </ul>
91
+ </div>
92
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  </div>
94
  </div>
95
+ <div id="postbox-container-1" class="postbox-container">
96
+ <div class="meta-box-sortables">
97
+ <div class="postbox">
98
+ <h2>Getting Started</h2>
99
+ <div class="inside">
100
+ <ol>
101
+ <li><a href="https://docs.wp-fail2ban.com/en/<?php
102
+ echo $wp_f2b_ver ;
103
+ ?>/introduction.html" rel="noopener" target="docs.wp-fail2ban.com">Introduction</a></li>
104
+ <li><a href="https://docs.wp-fail2ban.com/en/<?php
105
+ echo $wp_f2b_ver ;
106
+ ?>/configuration.html" rel="noopener" target="docs.wp-fail2ban.com">Configuration</a></li>
107
+ </ol>
108
+ </div>
109
+ </div>
110
+ <div class="postbox">
111
+ <h2>Getting Help</h2>
112
+ <div class="inside">
113
+ <ul>
114
+ <?php
115
+
116
+ if ( wf_fs()->is_trial() ) {
117
+ ?>
118
+ <li><a href="https://forums.invis.net/c/wp-fail2ban/support-trial/" rel="noopener" target="_blank">Trial Support Forum</a></li>
119
+ <?php
120
+ } elseif ( wf_fs()->is_free_plan() ) {
121
+ ?>
122
+ <li><a href="https://forums.invis.net/c/wp-fail2ban/support-free/" rel="noopener" target="_blank">Free Support Forum</a></li>
123
+ <?php
124
+ }
125
+
126
+ ?>
127
+ <?php
128
+ ?>
129
+ <?php
130
+ ?>
131
+ </div>
132
+ </div>
 
 
 
 
 
 
 
 
 
 
 
133
  </div>
134
  </div>
135
  </div>
136
+ &nbsp;
137
  </div>
138
  </div>
139
+ <?php
140
+ }
 
 
 
141
 
142
+ }
admin/lib/tab.php CHANGED
@@ -1,260 +1,499 @@
1
  <?php
2
-
3
  /**
4
  * Tab base class
5
  *
6
- * @package wp-fail2ban-premium
7
- * @since 4.0.0
 
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * Base Tab class
16
- *
17
- * @since 4.0.0
18
- */
19
- abstract class Tab
20
- {
21
- /**
22
- * @var array Array of Tab objects
23
- */
24
- protected static $tabs = array() ;
25
- /**
26
- * @var string Active tab slug
27
- */
28
- protected static $active_tab ;
29
- /**
30
- * @var string Tab slug
31
- */
32
- protected $tab_slug ;
33
- /**
34
- * @var string Tab name
35
- */
36
- protected $tab_name ;
37
- /**
38
- * Hook: admin_init
39
- *
40
- * @since 4.0.0
41
- */
42
- public abstract function admin_init();
43
-
44
- /**
45
- * Sanitize and store form fields
46
- *
47
- * @since 4.0.0
48
- *
49
- * @param array $settings Settings to update
50
- * @param array $input Form fields
51
- *
52
- * @return array $settings
53
- */
54
- public abstract function sanitize( array $settings, array $input = null );
55
-
56
- /**
57
- * Contruct.
58
- *
59
- * @since 4.0.0
60
- *
61
- * @param string $slug Tab slug
62
- * @param string $name Tab name
63
- */
64
- public function __construct( $slug, $name )
65
- {
66
- $this->tab_slug = $slug;
67
- $this->tab_name = $name;
68
- self::$tabs[$slug] = $this;
69
- }
70
-
71
  /**
72
- * Getter - slug
73
  *
74
  * @since 4.0.0
75
- *
76
- * @return string Tab slug
77
- */
78
- public function getSlug()
79
- {
80
- return $this->tab_slug;
81
- }
82
-
83
- /**
84
- * Getter - name
85
- *
86
- * @since 4.0.0
87
- *
88
- * @return string Tab name
89
  */
90
- public function getName()
91
  {
92
- return $this->tab_name;
93
- }
94
-
95
- /**
96
- * Render settings section
97
- *
98
- * @since 4.0.0
99
- */
100
- public function render()
101
- {
102
- do_settings_sections( 'wp-fail2ban-' . $this->tab_slug );
103
- }
104
-
105
- /**
106
- * Helper - tab
107
- *
108
- * @since 4.0.0
109
- *
110
- * @param string $slug Tab slug
111
- *
112
- * @return Tab Tab
113
- */
114
- public static function getTab( $slug )
115
- {
116
- return self::$tabs[$slug];
117
- }
118
-
119
- /**
120
- * Helper - current tab
121
- *
122
- * @since 4.0.0
123
- *
124
- * @param string $default Default slug
125
- *
126
- * @return Tab Tab
127
- */
128
- public static function getActiveTab( $default = null )
129
- {
130
- if ( !empty(self::$active_tab) ) {
131
- return self::$active_tab;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  }
133
- return self::$active_tab = ( array_key_exists( @$_GET['tab'], self::$tabs ) ? self::$tabs[$_GET['tab']] : self::$tabs[$default] );
134
- }
135
-
136
- /**
137
- * Helper - tab name
138
- *
139
- * @since 4.0.0
140
- *
141
- * @param string $slug Tab slug
142
- *
143
- * @return string Tab name
144
- */
145
- public static function getTabName( $slug )
146
- {
147
- return self::getTab( $slug )->getName();
148
- }
149
-
150
- /**
151
- * Link to documentation
152
- *
153
- * @since 4.2.0
154
- *
155
- * @param string $define
156
- * @param string $name
157
- *
158
- * @return string
159
- */
160
- public static function doc_link( $define, $name )
161
- {
162
- static $wp_f2b_ver ;
163
- if ( empty($wp_f2b_ver) ) {
164
- $wp_f2b_ver = substr( WP_FAIL2BAN_VER, 0, strrpos( WP_FAIL2BAN_VER, '.' ) );
165
  }
166
- return sprintf(
167
- '<a href="https://docs.wp-fail2ban.com/en/%s/defines/constants/%s.html" style="text-decoration: none;" target="_blank" title="Documentation"><span class="dashicons dashicons-external" style="vertical-align: text-bottom"></span></a> %s',
168
- $wp_f2b_ver,
169
- $define,
170
- $name
171
- );
172
- }
173
-
174
- /**
175
- * Helper - drop-down list of facilities
176
- *
177
- * @since 4.0.0
178
- *
179
- * @param string $def Name of define for selected value
180
- * @param bool $_enabled Enabled?
181
- */
182
- protected function getLogFacilities( $def, $_enabled = false )
183
- {
184
- $enabled = false;
185
- $facilities = [
186
- LOG_AUTH => 'LOG_AUTH',
187
- LOG_AUTHPRIV => 'LOG_AUTHPRIV',
188
- LOG_CRON => 'LOG_CRON',
189
- LOG_DAEMON => 'LOG_DAEMON',
190
- LOG_KERN => 'LOG_KERN',
191
- LOG_LOCAL0 => 'LOG_LOCAL0',
192
- LOG_LOCAL1 => 'LOG_LOCAL1',
193
- LOG_LOCAL2 => 'LOG_LOCAL2',
194
- LOG_LOCAL3 => 'LOG_LOCAL3',
195
- LOG_LOCAL4 => 'LOG_LOCAL4',
196
- LOG_LOCAL5 => 'LOG_LOCAL5',
197
- LOG_LOCAL6 => 'LOG_LOCAL6',
198
- LOG_LOCAL7 => 'LOG_LOCAL7',
199
- LOG_LPR => 'LOG_LPR',
200
- LOG_MAIL => 'LOG_MAIL',
201
- LOG_NEWS => 'LOG_NEWS',
202
- LOG_SYSLOG => 'LOG_SYSLOG',
203
- LOG_USER => 'LOG_USER',
204
- LOG_UUCP => 'LOG_UUCP',
205
- ];
206
- $default = constant( "DEFAULT_{$def}" );
207
- $value = ( defined( $def ) ? constant( $def ) : $default );
208
- $str = '<select disabled="disabled">';
209
- foreach ( $facilities as $facility => $name ) {
210
- $str .= sprintf(
211
- '<option value="%s" %s>%s%s</option>',
212
- $facility,
213
- selected( $value, $facility, false ),
214
- $name,
215
- ( $facility == $default ? __( ' (default)' ) : '' )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  );
217
  }
218
- $str .= '</select>';
219
- return $str;
220
- }
221
-
222
- /**
223
- * Log helper - enable/disable+facility
224
- *
225
- * @since 4.2.0 Moved to Tab
226
- * @since 4.0.0
227
- *
228
- * @param string $define_name Name of define to enable logging
229
- * @param string $define_log Name of define for log facility
230
- * @param string $description Description
231
- * @param array $toggle Array of IDs to sync toggle state
232
- */
233
- protected function log(
234
- $define_name,
235
- $define_log,
236
- $description = '',
237
- array $toggle = array()
238
- )
239
- {
240
- $enabled = defined( $define_name ) && true === constant( $define_name );
241
- $fmt = <<<___FMT___
242
- <label><input type="checkbox" disabled="disabled" %s> Enable logging</label>,
243
- <label>use facility: %s</label>
244
- <p class="description">%s</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  ___FMT___;
246
- $html = sprintf(
247
- $fmt,
248
- checked( $enabled, true, false ),
249
- $this->getLogFacilities( $define_log ),
250
- $description
251
- );
252
- echo apply_filters(
253
- "wp_fail2ban_log_{$define_name}",
254
- $html,
255
- $define_name,
256
- $define_log
257
- ) ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  }
 
259
 
260
- }
1
  <?php
 
2
  /**
3
  * Tab base class
4
  *
5
+ * @package wp-fail2ban
6
+ * @since 4.0.0
7
+ * @php 5.6
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
+ if (defined('ABSPATH')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  /**
13
+ * Tab: Base class
14
  *
15
  * @since 4.0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  */
17
+ abstract class TabBase
18
  {
19
+ /**
20
+ * @var array Array of Tab objects
21
+ */
22
+ protected static $tabs = [];
23
+ /**
24
+ * @var string Default tab slug
25
+ */
26
+ protected static $default_tab;
27
+ /**
28
+ * @var string Active tab slug
29
+ */
30
+ protected static $active_tab;
31
+
32
+ /**
33
+ * @var string Tab slug
34
+ */
35
+ protected $tab_slug;
36
+ /**
37
+ * @var string Tab name
38
+ */
39
+ protected $tab_name;
40
+ /**
41
+ * @since 4.3.0
42
+ * @var bool Apply/Reset buttons?
43
+ */
44
+ protected $tab_apply;
45
+
46
+ /**
47
+ * @var array Settings
48
+ * @since 4.3.0
49
+ */
50
+ protected $settings;
51
+
52
+ /**
53
+ * @var int admin_init priority
54
+ * @since 4.3.0
55
+ */
56
+ protected $admin_init_priority = 10;
57
+
58
+ /**
59
+ * Hook: admin_init
60
+ *
61
+ * @since 4.0.0
62
+ */
63
+ abstract public function admin_init();
64
+
65
+ /**
66
+ * Hook: current_screen
67
+ *
68
+ * @since 4.3.0
69
+ */
70
+ public function current_screen()
71
+ {
72
+ get_current_screen()->set_help_sidebar(
73
+ '<p><strong>' . __('For more information:') . '</strong></p>' .
74
+ '<p>' . __('<a href="https://codex.wordpress.org/Managing_Plugins#Plugin_Management">Documentation on Managing Plugins</a>') . '</p>' .
75
+ '<p>' . __('<a href="https://wordpress.org/support/">Support</a>') . '</p>'
76
+ );
77
  }
78
+
79
+ /**
80
+ * Sanitize and store form fields
81
+ *
82
+ * @since 4.3.0 Refactor
83
+ * @since 4.0.0
84
+ *
85
+ * @param array $input Form fields
86
+ */
87
+ public function sanitize(array $input = null)
88
+ {
89
+ return [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  }
91
+
92
+ /**
93
+ * Contruct.
94
+ *
95
+ * @since 4.0.0
96
+ *
97
+ * @param string $slug Tab slug
98
+ * @param string $name Tab name
99
+ * @param bool $apply Show Apply/Reset buttons
100
+ */
101
+ public function __construct($slug, $name, $apply = true)
102
+ {
103
+ $this->tab_slug = $slug;
104
+ $this->tab_name = $name;
105
+ $this->tab_apply = $apply;
106
+
107
+ self::$tabs[$slug] = $this;
108
+
109
+ $this->settings = Config::settings();
110
+
111
+ add_action('admin_init', [$this, 'admin_init'], $this->admin_init_priority);
112
+
113
+ add_filter('gettext', [$this, 'gettext'], PHP_INT_MAX, 3);
114
+ }
115
+
116
+ /**
117
+ * Hook: gettext
118
+ *
119
+ * @since 4.3.0
120
+ *
121
+ * @param string $translation
122
+ * @param string $text
123
+ * @param string $domain
124
+ * @return stringq
125
+ */
126
+ public function gettext($translation, $text, $domain)
127
+ {
128
+ static $wp_f2b_ver;
129
+
130
+ if (empty($wp_f2b_ver)) {
131
+ $wp_f2b_ver = substr(WP_FAIL2BAN_VER, 0, strrpos(WP_FAIL2BAN_VER, '.'));
132
+ }
133
+
134
+ return str_replace('___WPF2BVER___', $wp_f2b_ver, $translation);
135
+ }
136
+
137
+ /**
138
+ * Getter - slug
139
+ *
140
+ * @since 4.0.0
141
+ *
142
+ * @return string Tab slug
143
+ */
144
+ public function getSlug()
145
+ {
146
+ return $this->tab_slug;
147
+ }
148
+
149
+ /**
150
+ * Getter - name
151
+ *
152
+ * @since 4.0.0
153
+ *
154
+ * @return string Tab name
155
+ */
156
+ public function getName()
157
+ {
158
+ return $this->tab_name;
159
+ }
160
+
161
+ /**
162
+ * Render settings section
163
+ *
164
+ * @since 4.3.0 Refactored.
165
+ * @since 4.0.0
166
+ */
167
+ public function render()
168
+ {
169
+ do_settings_sections('wp-fail2ban-'.$this->tab_slug);
170
+ $this->render_buttons();
171
+ }
172
+
173
+ /**
174
+ * Render settings section buttons
175
+ *
176
+ * @since 4.3.0
177
+ */
178
+ protected function render_buttons()
179
+ {
180
+ echo '<hr><p>'.__('<strong>Note:</strong> The Free version of <em>WP fail2ban</em> is configured by defining constants in <tt>wp-config.php</tt>; these tabs display those values.').'<br>'.
181
+ __('Upgrade to the Premium version to enable this interface.').'</p>';
182
+ }
183
+
184
+ /**
185
+ * Helper: is this the active tab?
186
+ *
187
+ * @since 4.3.0
188
+ *
189
+ * @return bool
190
+ */
191
+ protected function isActiveTab()
192
+ {
193
+ return ($this->tab_name == self::getActiveTab()->getName());
194
+ }
195
+
196
+ /**
197
+ * Helper - tab
198
+ *
199
+ * @since 4.0.0
200
+ *
201
+ * @param string $slug Tab slug
202
+ * @return Tab Tab
203
+ */
204
+ public static function getTab($slug)
205
+ {
206
+ return self::$tabs[$slug];
207
+ }
208
+
209
+ /**
210
+ * Helper - set the default tab.
211
+ *
212
+ * @since 4.3.0
213
+ *
214
+ * @param string $default Default tab slug
215
+ */
216
+ public static function setDefaultTab($default)
217
+ {
218
+ self::$default_tab = $default;
219
+ }
220
+
221
+ /**
222
+ * Helper - current tab
223
+ *
224
+ * @since 4.0.0
225
+ *
226
+ * @return TabBase Tab
227
+ */
228
+ public static function getActiveTab()
229
+ {
230
+ if (!empty(self::$active_tab)) {
231
+ return self::$active_tab;
232
+ }
233
+
234
+ return (self::$active_tab = (array_key_exists(@$_GET['tab'], self::$tabs))
235
+ ? self::$tabs[$_GET['tab']]
236
+ : self::$tabs[self::$default_tab]
237
  );
238
  }
239
+
240
+ /**
241
+ * Helper - tab name
242
+ *
243
+ * @since 4.0.0
244
+ *
245
+ * @param string $slug Tab slug
246
+ * @return string Tab name
247
+ */
248
+ public static function getTabName($slug)
249
+ {
250
+ return self::getTab($slug)->getName();
251
+ }
252
+
253
+ /**
254
+ * Helper - tab exists?
255
+ *
256
+ * @since 4.3.0
257
+ *
258
+ * @param string $slug Tab slug
259
+ * @return bool
260
+ */
261
+ public static function tabExists($slug)
262
+ {
263
+ return array_key_exists($slug, self::$tabs);
264
+ }
265
+
266
+ /**
267
+ * Link to documentation
268
+ *
269
+ * @since 4.3.0 Protected
270
+ * @since 4.2.0
271
+ *
272
+ * @param string $define
273
+ * @return string
274
+ */
275
+ protected function doc_link($define)
276
+ {
277
+ static $wp_f2b_ver;
278
+
279
+ if (empty($wp_f2b_ver)) {
280
+ $wp_f2b_ver = substr(WP_FAIL2BAN_VER, 0, strrpos(WP_FAIL2BAN_VER, '.'));
281
+ }
282
+
283
+ return sprintf('<a href="https://docs.wp-fail2ban.com/en/%s/defines/constants/%s.html" style="text-decoration: none;" target="_blank" title="%s">%s<span class="dashicons dashicons-external" style="vertical-align: text-bottom"></span></a>', $wp_f2b_ver, $define, __('Documentation', 'wp-fail2ban'), $define);
284
+ }
285
+
286
+ /**
287
+ * Standard list of links to docs
288
+ *
289
+ * @since 4.3.0
290
+ *
291
+ * @param array $defines List of defines
292
+ * @return string HTML
293
+ */
294
+ protected function see_also(array $defines)
295
+ {
296
+ return sprintf(
297
+ '<p><em>%s</em>&nbsp;&nbsp;%s',
298
+ __('See also:', 'wp-fail2ban'),
299
+ implode('&nbsp;/&nbsp;', array_map(function ($i) {
300
+ return $this->doc_link($i);
301
+ }, $defines))
302
+ );
303
+ }
304
+
305
+ /**
306
+ * Helper - build drop-down list of facilities
307
+ *
308
+ * @since 4.3.0
309
+ *
310
+ * @param string $def Name of define for selected value
311
+ * @param string $str Opening select html
312
+ *
313
+ * @return string
314
+ */
315
+ protected function getLogFacilitiesOptions($def, $str)
316
+ {
317
+ $default = Config::get_default($def);
318
+ $value = Config::get($def);
319
+
320
+ foreach (ConvertData::$FacilityName2Value as $name => $facility) {
321
+ $str .= sprintf(
322
+ '<option value="%s" %s>%s%s</option>',
323
+ $facility,
324
+ selected($value, $facility, false),
325
+ $name,
326
+ ($facility == $default) ? __(' (default)') : ''
327
+ );
328
+ }
329
+ $str .= '</select>';
330
+
331
+ return $str;
332
+ }
333
+
334
+ /**
335
+ * Helper - drop-down list of facilities
336
+ *
337
+ * @since 4.3.0 Refactored.
338
+ * @since 4.0.0
339
+ *
340
+ * @param string $def Name of define for selected value
341
+ * @param bool $_enabled Enabled?
342
+ *
343
+ * @return string
344
+ */
345
+ protected function getLogFacilities($def, $_enabled = false)
346
+ {
347
+ return $this->getLogFacilitiesOptions($def, '<select disabled="disabled">');
348
+ }
349
+
350
+ /**
351
+ * Log helper - enable/disable+facility
352
+ *
353
+ * @since 4.3.0 Refactored
354
+ * @since 4.2.0 Moved to Tab
355
+ * @since 4.0.0
356
+ *
357
+ * @param string $define_name Name of define to enable logging
358
+ * @param string $define_log Name of define for log facility
359
+ * @param array $toggle Array of IDs to sync toggle state
360
+ * @param bool $echo Echo?
361
+ */
362
+ protected function log($define_name, $define_log, array $toggle = [], $echo = true)
363
+ {
364
+ $enabled = (true === Config::get($define_name)); // @TODO
365
+ $fmt = <<<___FMT___
366
+ <input type="checkbox" disabled="disabled" %s> <label>%s</label>,
367
+ <label>%s:</label> %s
368
  ___FMT___;
369
+ $html = sprintf(
370
+ $fmt,
371
+ checked($enabled, true, false),
372
+ __('Enable logging', 'wp-fail2ban'),
373
+ __('use facility', 'wp-fail2ban'),
374
+ $this->getLogFacilities($define_log)
375
+ );
376
+ $html .= sprintf('<p class="description">%s</p>', Config::desc($define_name));
377
+ $rv = apply_filters("wp_fail2ban_log_{$define_name}", $html, $define_name, $define_log);
378
+ if ($echo) {
379
+ echo $rv;
380
+ } else {
381
+ return $rv;
382
+ }
383
+ }
384
+
385
+ /**
386
+ * id="%s" Helper
387
+ *
388
+ * @since 4.3.0 Moved here.
389
+ * @since 4.0.0
390
+ *
391
+ * @param string $define
392
+ *
393
+ * @return string
394
+ */
395
+ protected function field_name($define)
396
+ {
397
+ global $wp_fail2ban;
398
+
399
+ return 'wp-fail2ban['.join('][', $wp_fail2ban['config'][$define]['field']).']';
400
+ }
401
+
402
+ /**
403
+ * name="%s" Helper
404
+ *
405
+ * @since 4.3.0 Moved here.
406
+ * @since 4.0.0
407
+ *
408
+ * @param string $define
409
+ *
410
+ * @return string
411
+ */
412
+ protected function field_id($define)
413
+ {
414
+ global $wp_fail2ban;
415
+
416
+ return join('-', $wp_fail2ban['config'][$define]['field']);
417
+ }
418
+
419
+ /**
420
+ * Helper: checked()
421
+ *
422
+ * @since 4.3.0
423
+ *
424
+ * @param string $define
425
+ * @param bool $current
426
+ * @param bool $echo
427
+ * @return mixed
428
+ */
429
+ protected function def_checked($define, $current = true, $echo = true)
430
+ {
431
+ return checked(Config::get($define), $current, $echo);
432
+ }
433
+
434
+ /**
435
+ * NDEF disabled helper
436
+ *
437
+ * @since 4.3.0 Add $override; moved here.
438
+ * @since 4.0.0
439
+ *
440
+ * @param string $define
441
+ * @param bool $override
442
+ * @return string
443
+ */
444
+ protected function ndef_disabled($define, $override = false)
445
+ {
446
+ return disabled(Config::def($define) || $override, true, false);
447
+ }
448
+
449
+ /**
450
+ * Display standard checkbox
451
+ *
452
+ * @since 4.3.0
453
+ *
454
+ * @param string $define Constant
455
+ * @param bool $show_desc Show description?
456
+ * @param string $plan Freemius plan
457
+ * @param bool $echo Echo?
458
+ *
459
+ * @return string
460
+ */
461
+ protected function checkbox($define, $show_desc = true, $plan = 'bronze', $echo = true)
462
+ {
463
+ $html = sprintf(
464
+ '<input type="checkbox" disabled="disabled" %s>',
465
+ checked(constant($define), true, false)
466
+ );
467
+ if ($show_desc) {
468
+ $html = '<label>'.$html.' '.$this->description($define, false).'</label>';
469
+ }
470
+ if ($echo) {
471
+ echo $html;
472
+ }
473
+ return $html;
474
+ }
475
+
476
+ /**
477
+ * Helper: setting description
478
+ *
479
+ * @since 4.3.0
480
+ *
481
+ * @param string $define
482
+ * @param bool $echo
483
+ *
484
+ * @return string
485
+ */
486
+ protected function description($define, $echo = true)
487
+ {
488
+ if (!is_null($desc = Config::desc($define))) {
489
+ if ($echo) {
490
+ echo '<p class="description">'.$desc.'</p>';
491
+ }
492
+ return $desc;
493
+ } else {
494
+ return '';
495
+ }
496
+ }
497
  }
498
+ }
499
 
 
admin/tools.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Tools
4
+ *
5
+ * @package wp-fail2ban
6
+ * @since 4.3.0
7
+ */
8
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
+
10
+ if (defined('ABSPATH')) {
11
+ /**
12
+ * Proxy for api.wp-fail2ban.com
13
+ *
14
+ * @since 4.2.6
15
+ */
16
+ function remote_tools()
17
+ {
18
+ global $current_user;
19
+
20
+ ?>
21
+ <div class="wrap">
22
+ <h1><?=__('Remote Tools (&beta;)', 'wp-fail2ban')?></h1>
23
+ <hr class="wp-header-end">
24
+ <?php
25
+ if (function_exists(__NAMESPACE__.'\addons\remote_tools\tab')) {
26
+ addons\remote_tools\tab();
27
+ } else {
28
+ ?>
29
+ <h2 class="nav-tab-wrapper wp-clearfix">
30
+ <a class="nav-tab nav-tab-active" href="#"><?=__('Overview', 'wp-fail2ban')?></a>
31
+ </h2>
32
+ <div class="card">
33
+ <h2>Remote Tools Add-on</h2>
34
+ <p>This add-on provides features that make life with WP fail2ban easier, all from a remote server. This gives access to valuable but infrequently used tools without bloating the core plugin.</p>
35
+ <p>The first of these is a <strong>Custom Filter Tool</strong> (CFT).</p>
36
+ <blockquote>
37
+ <p>The filter files included are intended only as a starting point for those who want <em>WPf2b</em> to work &ldquo;out of the box&rdquo;.</p>
38
+ <p>There is no &ldquo;one size fits all&rdquo; configuration possible for <em>fail2ban</em> - what may be a soft failure for one site should be treated as a hard failure for another, and vice versa.</p>
39
+ </blockquote>
40
+ <p>You could simply edit the filter files included, but it&lsquo;s surprisingly easy to make a mistake; I learned this the hard way with earlier versions of <em>WPf2b</em>.... The CFT removes most of the opportunities for human error - always a good thing!</p>
41
+ <hr>
42
+ <p>The Remote Tools Add-on is available from the <a href="<?php echo admin_url('admin.php?page=wp-fail2ban-addons') ?>">Add-Ons menu</a>.</p>
43
+ </div>
44
+ <?php
45
+ }
46
+
47
+ ?>
48
+ </div>
49
+ <?php
50
+ }
51
+ }
52
+
assets/icon.svg ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -4 40 40" stroke-width="0" fill="#fff">
3
+ <style>svg { background-color: #180c30; }</style>
4
+ <path d="M16,0 l6.5,6.5 l-3.5,3.5 l-3,-3 l-9,9 l3,3 l-3.5,3.5 L0,16 z" />
5
+ <path d="M0,31 L31,0 L32,1 L1,32 z" />
6
+ <path d="M16,32 L32,16 l-6.5,-6.5 l-3.5,3.5 l3,3 l-9,9 l-3,-3 l-3.5,3.5 z" />
7
+ </svg>
assets/menu.svg ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -1 34 34" fill="#fff" stroke="#fff" width="20" height="20">
3
+ <path d="M16,0 l7,7 l-4,4 l-3,-3 l-8,8 l3,3 l-4,4 l-7,-7 z"/>
4
+ <path d="M16,32 l16,-16 l-7,-7 l-4,4 l3,3 l-8,8 l-3,-3 l-4,4 z"/>
5
+ <path d="M2,31 l-1,-1 l29,-29 l1,1 z"/>
6
+ </svg>
7
+
feature/comments.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Comment logging
5
  *
@@ -8,186 +7,176 @@
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * @since 4.0.5 Guard
16
- */
17
 
18
- if ( !function_exists( __NAMESPACE__ . '\\notify_post_author' ) ) {
19
  /**
20
- * Log new comment
21
- *
22
- * @since 3.5.0
23
- *
24
- * @param bool $maybe_notify
25
- * @param int $comment_ID
26
- *
27
- * @return bool
28
- *
29
- * @wp-f2b-extra Comment \d+
30
  */
31
- function notify_post_author( $maybe_notify, $comment_ID )
32
- {
33
- openlog( 'WP_FAIL2BAN_COMMENT_LOG' );
34
- syslog( LOG_INFO, "Comment {$comment_ID}" );
35
- closelog();
36
- // @codeCoverageIgnoreEnd
37
- return $maybe_notify;
38
- }
39
-
40
- add_filter(
41
- 'notify_post_author',
42
- __NAMESPACE__ . '\\notify_post_author',
43
- 10,
44
- 2
45
- );
46
- }
47
-
48
-
49
- if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA' ) ) {
50
- /** WPF2B_EVENT_COMMENT_NOT_FOUND */
51
- if ( WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x20002 ) {
52
  /**
53
- * @since 4.0.5 Guard
 
 
 
 
 
 
 
 
 
54
  */
55
-
56
- if ( !function_exists( __NAMESPACE__ . '\\comment_id_not_found' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  /**
58
- * Log attempted comment on non-existent post
59
- *
60
- * @since 4.0.0
61
- *
62
- * @param int $comment_post_ID
63
- *
64
- * @wp-f2b-extra Comment post not found \d+
65
  */
66
- function comment_id_not_found( $comment_post_ID )
67
- {
68
- openlog( 'WP_FAIL2BAN_COMMENT_EXTRA_LOG' );
69
- syslog( LOG_NOTICE, "Comment post not found {$comment_post_ID}" );
70
- closelog();
71
- // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
-
74
- add_action( 'comment_id_not_found', __NAMESPACE__ . '\\comment_id_not_found' );
75
  }
76
-
77
- }
78
- /** LOG_ACTION_LOG_COMMENT_CLOSED */
79
- if ( WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x20004 ) {
80
- /**
81
- * @since 4.0.5 Guard
82
- */
83
-
84
- if ( !function_exists( __NAMESPACE__ . '\\comment_closed' ) ) {
85
  /**
86
- * Log attempted comment on closed post
87
- *
88
- * @since 4.0.0
89
- *
90
- * @param int $comment_post_ID
91
- *
92
- * @wp-f2b-extra Comments closed on post \d+
93
  */
94
- function comment_closed( $comment_post_ID )
95
- {
96
- openlog( 'WP_FAIL2BAN_COMMENT_EXTRA_LOG' );
97
- syslog( LOG_NOTICE, "Comments closed on post {$comment_post_ID}" );
98
- closelog();
99
- // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
101
-
102
- add_action( 'comment_closed', __NAMESPACE__ . '\\comment_closed' );
103
  }
104
-
105
- }
106
- /** LOG_ACTION_LOG_COMMENT_TRASH */
107
- if ( WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x20008 ) {
108
- /**
109
- * @since 4.0.5 Guard
110
- */
111
-
112
- if ( !function_exists( __NAMESPACE__ . '\\comment_on_trash' ) ) {
113
  /**
114
- * Log attempted comment on trashed post
115
- *
116
- * @since 4.0.2 Fix message
117
- * @since 4.0.0
118
- *
119
- * @param int $comment_post_ID
120
- *
121
- * @wp-f2b-extra Comment attempt on trash post \d+
122
  */
123
- function comment_on_trash( $comment_post_ID )
124
- {
125
- openlog( 'WP_FAIL2BAN_COMMENT_EXTRA_LOG' );
126
- syslog( LOG_NOTICE, "Comment attempt on trash post {$comment_post_ID}" );
127
- closelog();
128
- // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  }
130
-
131
- add_action( 'comment_on_trash', __NAMESPACE__ . '\\comment_on_trash' );
132
  }
133
-
134
- }
135
- /** LOG_ACTION_LOG_COMMENT_DRAFT */
136
- if ( WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x20010 ) {
137
- /**
138
- * @since 4.0.5 Guard
139
- */
140
-
141
- if ( !function_exists( __NAMESPACE__ . '\\comment_on_draft' ) ) {
142
  /**
143
- * Log attempted comment on draft post
144
- *
145
- * @since 4.0.2 Fix message
146
- * @since 4.0.0
147
- *
148
- * @param int $comment_post_ID
149
- *
150
- * @wp-f2b-extra Comment attempt on draft post \d+
151
  */
152
- function comment_on_draft( $comment_post_ID )
153
- {
154
- openlog( 'WP_FAIL2BAN_COMMENT_EXTRA_LOG' );
155
- syslog( LOG_NOTICE, "Comment attempt on draft post {$comment_post_ID}" );
156
- closelog();
157
- // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  }
159
-
160
- add_action( 'comment_on_draft', __NAMESPACE__ . '\\comment_on_draft' );
161
  }
162
-
163
- }
164
- /** LOG_ACTION_LOG_COMMENT_PASSWORD */
165
- if ( WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x20020 ) {
166
- /**
167
- * @since 4.0.5 Guard
168
- */
169
-
170
- if ( !function_exists( __NAMESPACE__ . '\\comment_on_password_protected' ) ) {
171
  /**
172
- * Log attempted comment on password-protected post
173
- *
174
- * @since 4.0.2 Fix message
175
- * @since 4.0.0
176
- *
177
- * @param int $comment_post_ID
178
- *
179
- * @wp-f2b-extra Comment attempt on password-protected post \d+
180
  */
181
- function comment_on_password_protected( $comment_post_ID )
182
- {
183
- openlog( 'WP_FAIL2BAN_COMMENT_EXTRA_LOG' );
184
- syslog( LOG_NOTICE, "Comment attempt on password-protected post {$comment_post_ID}" );
185
- closelog();
186
- // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  }
188
-
189
- add_action( 'comment_on_password_protected', __NAMESPACE__ . '\\comment_on_password_protected' );
190
  }
191
-
192
  }
193
  }
 
1
  <?php
 
2
  /**
3
  * Comment logging
4
  *
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
11
+ include_once_exists(WP_FAIL2BAN_DIR.'/premium/feature/comments.php');
 
 
 
 
12
 
 
13
  /**
14
+ * @since 4.0.5 Guard
 
 
 
 
 
 
 
 
 
15
  */
16
+ if (!function_exists(__NAMESPACE__.'\notify_post_author')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  /**
18
+ * Log new comment
19
+ *
20
+ * @since 3.5.0
21
+ *
22
+ * @param bool $maybe_notify
23
+ * @param int $comment_ID
24
+ *
25
+ * @return bool
26
+ *
27
+ * @wp-f2b-extra Comment \d+
28
  */
29
+ function notify_post_author($maybe_notify, $comment_ID)
30
+ {
31
+ openlog('WP_FAIL2BAN_COMMENT_LOG');
32
+ syslog(LOG_INFO, "Comment {$comment_ID}");
33
+ closelog();
34
+
35
+ do_action(__FUNCTION__, $maybe_notify, $comment_ID);
36
+
37
+ return $maybe_notify;
38
+ }
39
+ add_filter('notify_post_author', __NAMESPACE__.'\notify_post_author', 10, 2);
40
+ }
41
+
42
+ if (defined('WP_FAIL2BAN_LOG_COMMENTS_EXTRA')) {
43
+ /** WPF2B_EVENT_COMMENT_NOT_FOUND */
44
+ if (WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x00020002) {
45
  /**
46
+ * @since 4.0.5 Guard
 
 
 
 
 
 
47
  */
48
+ if (!function_exists(__NAMESPACE__.'\comment_id_not_found')) {
49
+ /**
50
+ * Log attempted comment on non-existent post
51
+ *
52
+ * @since 4.0.0
53
+ *
54
+ * @param int $comment_post_ID
55
+ *
56
+ * @wp-f2b-extra Comment post not found \d+
57
+ */
58
+ function comment_id_not_found($comment_post_ID)
59
+ {
60
+ openlog('WP_FAIL2BAN_COMMENT_EXTRA_LOG');
61
+ syslog(LOG_NOTICE, "Comment post not found {$comment_post_ID}");
62
+ closelog();
63
+
64
+ do_action(__FUNCTION__, $comment_post_ID);
65
+ }
66
+ add_action('comment_id_not_found', __NAMESPACE__.'\comment_id_not_found');
67
  }
 
 
68
  }
69
+
70
+ /** LOG_ACTION_LOG_COMMENT_CLOSED */
71
+ if (WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x00020004) {
 
 
 
 
 
 
72
  /**
73
+ * @since 4.0.5 Guard
 
 
 
 
 
 
74
  */
75
+ if (!function_exists(__NAMESPACE__.'\comment_closed')) {
76
+ /**
77
+ * Log attempted comment on closed post
78
+ *
79
+ * @since 4.0.0
80
+ *
81
+ * @param int $comment_post_ID
82
+ *
83
+ * @wp-f2b-extra Comments closed on post \d+
84
+ */
85
+ function comment_closed($comment_post_ID)
86
+ {
87
+ openlog('WP_FAIL2BAN_COMMENT_EXTRA_LOG');
88
+ syslog(LOG_NOTICE, "Comments closed on post {$comment_post_ID}");
89
+ closelog();
90
+
91
+ do_action(__FUNCTION__, $comment_post_ID);
92
+ }
93
+ add_action('comment_closed', __NAMESPACE__.'\comment_closed');
94
  }
 
 
95
  }
96
+
97
+ /** LOG_ACTION_LOG_COMMENT_TRASH */
98
+ if (WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x00020008) {
 
 
 
 
 
 
99
  /**
100
+ * @since 4.0.5 Guard
 
 
 
 
 
 
 
101
  */
102
+ if (!function_exists(__NAMESPACE__.'\comment_on_trash')) {
103
+ /**
104
+ * Log attempted comment on trashed post
105
+ *
106
+ * @since 4.0.2 Fix message
107
+ * @since 4.0.0
108
+ *
109
+ * @param int $comment_post_ID
110
+ *
111
+ * @wp-f2b-extra Comment attempt on trash post \d+
112
+ */
113
+ function comment_on_trash($comment_post_ID)
114
+ {
115
+ openlog('WP_FAIL2BAN_COMMENT_EXTRA_LOG');
116
+ syslog(LOG_NOTICE, "Comment attempt on trash post {$comment_post_ID}");
117
+ closelog();
118
+
119
+ do_action(__FUNCTION__, $comment_post_ID);
120
+ }
121
+ add_action('comment_on_trash', __NAMESPACE__.'\comment_on_trash');
122
  }
 
 
123
  }
124
+
125
+ /** LOG_ACTION_LOG_COMMENT_DRAFT */
126
+ if (WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x00020010) {
 
 
 
 
 
 
127
  /**
128
+ * @since 4.0.5 Guard
 
 
 
 
 
 
 
129
  */
130
+ if (!function_exists(__NAMESPACE__.'\comment_on_draft')) {
131
+ /**
132
+ * Log attempted comment on draft post
133
+ *
134
+ * @since 4.0.2 Fix message
135
+ * @since 4.0.0
136
+ *
137
+ * @param int $comment_post_ID
138
+ *
139
+ * @wp-f2b-extra Comment attempt on draft post \d+
140
+ */
141
+ function comment_on_draft($comment_post_ID)
142
+ {
143
+ openlog('WP_FAIL2BAN_COMMENT_EXTRA_LOG');
144
+ syslog(LOG_NOTICE, "Comment attempt on draft post {$comment_post_ID}");
145
+ closelog();
146
+
147
+ do_action(__FUNCTION__, $comment_post_ID);
148
+ }
149
+ add_action('comment_on_draft', __NAMESPACE__.'\comment_on_draft');
150
  }
 
 
151
  }
152
+
153
+ /** LOG_ACTION_LOG_COMMENT_PASSWORD */
154
+ if (WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x00020020) {
 
 
 
 
 
 
155
  /**
156
+ * @since 4.0.5 Guard
 
 
 
 
 
 
 
157
  */
158
+ if (!function_exists(__NAMESPACE__.'\comment_on_password_protected')) {
159
+ /**
160
+ * Log attempted comment on password-protected post
161
+ *
162
+ * @since 4.0.2 Fix message
163
+ * @since 4.0.0
164
+ *
165
+ * @param int $comment_post_ID
166
+ *
167
+ * @wp-f2b-extra Comment attempt on password-protected post \d+
168
+ */
169
+ function comment_on_password_protected($comment_post_ID)
170
+ {
171
+ openlog('WP_FAIL2BAN_COMMENT_EXTRA_LOG');
172
+ syslog(LOG_NOTICE, "Comment attempt on password-protected post {$comment_post_ID}");
173
+ closelog();
174
+
175
+ do_action(__FUNCTION__, $comment_post_ID);
176
+ }
177
+ add_action('comment_on_password_protected', __NAMESPACE__.'\comment_on_password_protected');
178
  }
 
 
179
  }
 
180
  }
181
  }
182
+
feature/lib.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Library functions
5
  *
@@ -8,130 +7,175 @@
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * Wrapper for \openlog
16
- *
17
- * @since 3.5.0 Refactored for unit testing
18
- *
19
- * @param string $log
20
- */
21
- function openlog( $log = 'WP_FAIL2BAN_AUTH_LOG' )
22
- {
23
- $tag = ( defined( 'WP_FAIL2BAN_SYSLOG_SHORT_TAG' ) && true === WP_FAIL2BAN_SYSLOG_SHORT_TAG ? 'wp' : 'wordpress' );
24
- $host = ( array_key_exists( 'WP_FAIL2BAN_HTTP_HOST', $_ENV ) ? $_ENV['WP_FAIL2BAN_HTTP_HOST'] : $_SERVER['HTTP_HOST'] );
25
  /**
26
- * Some varieties of syslogd have difficulty if $host is too long
27
- * @since 3.5.0
 
 
 
 
 
28
  */
29
- if ( defined( 'WP_FAIL2BAN_TRUNCATE_HOST' ) && 1 < intval( WP_FAIL2BAN_TRUNCATE_HOST ) ) {
30
- $host = substr( $host, 0, intval( WP_FAIL2BAN_TRUNCATE_HOST ) );
 
 
 
31
  }
32
-
33
- if ( false === \openlog( "{$tag}({$host})", WP_FAIL2BAN_OPENLOG_OPTIONS, constant( $log ) ) ) {
34
- error_log( 'WPf2b: Cannot open syslog', 0 );
35
- // @codeCoverageIgnore
36
- } elseif ( defined( 'WP_FAIL2BAN_TRACE' ) ) {
37
- error_log( 'WPf2b: Opened syslog', 0 );
38
- // @codeCoverageIgnore
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  }
40
 
41
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- /**
44
- * Wrapper for \syslog
45
- *
46
- * @since 3.5.0
47
- *
48
- * @param int $level
49
- * @param string $msg
50
- * @param string|null $remote_addr
51
- */
52
- function syslog( $level, $msg, $remote_addr = null )
53
- {
54
- $msg .= ' from ';
55
- $msg .= ( is_null( $remote_addr ) ? remote_addr() : $remote_addr );
56
-
57
- if ( false === \syslog( $level, $msg ) ) {
58
- error_log( "WPf2b: Cannot write to syslog: '{$msg}'", 0 );
59
- // @codeCoverageIgnore
60
- } elseif ( defined( 'WP_FAIL2BAN_TRACE' ) ) {
61
- error_log( "WPf2b: Wrote to syslog: '{$msg}'", 0 );
62
- // @codeCoverageIgnore
63
  }
64
-
65
- \closelog();
66
- if ( defined( 'PHPUNIT_COMPOSER_INSTALL' ) ) {
67
- echo "{$level}|{$msg}" ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  }
69
- }
70
 
71
- /**
72
- * Graceful immediate exit
73
- *
74
- * @since 4.2.7 Remove JSON support
75
- * @since 4.0.5 Add JSON support
76
- * @since 3.5.0 Refactored for unit testing
77
- */
78
- function bail()
79
- {
80
- wp_die( 'Forbidden', 'Forbidden', array(
81
- 'response' => 403,
82
- ) );
83
- }
84
 
85
- /**
86
- * Compute remote IP address
87
- *
88
- * @return string
89
- *
90
- * @todo Test me!
91
- * @codeCoverageIgnore
92
- */
93
- function remote_addr()
94
- {
95
- static $remote_addr = null ;
96
  /**
97
- * @since 4.0.0
 
 
 
 
 
98
  */
99
-
100
- if ( is_null( $remote_addr ) ) {
101
- if ( defined( 'WP_FAIL2BAN_PROXIES' ) ) {
102
-
103
- if ( array_key_exists( 'HTTP_X_FORWARDED_FOR', $_SERVER ) ) {
104
- $ip = ip2long( $_SERVER['REMOTE_ADDR'] );
105
- /**
106
- * PHP 7 lets you define an array
107
- * @since 3.5.4
108
- */
109
- $proxies = ( is_array( WP_FAIL2BAN_PROXIES ) ? WP_FAIL2BAN_PROXIES : explode( ',', WP_FAIL2BAN_PROXIES ) );
110
- foreach ( $proxies as $proxy ) {
111
-
112
- if ( '#' == $proxy[0] ) {
113
- continue;
114
- } elseif ( 2 == count( $cidr = explode( '/', $proxy ) ) ) {
115
- $net = ip2long( $cidr[0] );
116
- $mask = ~(pow( 2, 32 - $cidr[1] ) - 1);
117
- } else {
118
- $net = ip2long( $proxy );
119
- $mask = -1;
120
- }
121
-
122
- if ( $net == ($ip & $mask) ) {
123
- return ( false === ($len = strpos( $_SERVER['HTTP_X_FORWARDED_FOR'], ',' )) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : substr( $_SERVER['HTTP_X_FORWARDED_FOR'], 0, $len ) );
 
 
 
 
 
 
 
 
124
  }
125
  }
126
  }
127
-
 
 
 
 
 
 
 
128
  }
129
- /**
130
- * For plugins and themes that anonymise requests
131
- * @since 3.6.0
132
- */
133
- $remote_addr = ( defined( 'WP_FAIL2BAN_REMOTE_ADDR' ) ? WP_FAIL2BAN_REMOTE_ADDR : $_SERVER['REMOTE_ADDR'] );
134
  }
135
-
136
- return $remote_addr;
137
  }
 
1
  <?php
 
2
  /**
3
  * Library functions
4
  *
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
+ * Helper.
13
+ *
14
+ * @since 4.3.0
15
+ *
16
+ * @param mixed $key
17
+ * @param array $ary
18
+ * @return mixed|null Array value if present, null otherwise.
19
  */
20
+ function array_value($key, array $ary)
21
+ {
22
+ return (array_key_exists($key, $ary))
23
+ ? $ary[$key]
24
+ : null;
25
  }
26
+
27
+ /**
28
+ * Wrapper for \openlog
29
+ *
30
+ * @since 3.5.0 Refactored for unit testing
31
+ *
32
+ * @param string $log
33
+ */
34
+ function openlog($log = 'WP_FAIL2BAN_AUTH_LOG')
35
+ {
36
+ $tag = (defined('WP_FAIL2BAN_SYSLOG_SHORT_TAG') && true === WP_FAIL2BAN_SYSLOG_SHORT_TAG)
37
+ ? 'wp' // @codeCoverageIgnore
38
+ : 'wordpress';
39
+ $host = (array_key_exists('WP_FAIL2BAN_HTTP_HOST', $_ENV))
40
+ ? $_ENV['WP_FAIL2BAN_HTTP_HOST'] // @codeCoverageIgnore
41
+ : $_SERVER['HTTP_HOST'];
42
+ if (is_multisite() && !SUBDOMAIN_INSTALL) {
43
+ /**
44
+ * @todo Test me!
45
+ */
46
+ // @codeCoverageIgnoreStart
47
+ if (!is_main_site()) {
48
+ $blog = get_blog_details(get_current_blog_id(), false);
49
+ $host .= '/'.trim($blog->path, '/');
50
+ } // @codeCoverageIgnoreEnd
51
+ }
52
+ /**
53
+ * Some varieties of syslogd have difficulty if $host is too long
54
+ * @since 3.5.0
55
+ */
56
+ if (defined('WP_FAIL2BAN_TRUNCATE_HOST') && 1 < intval(WP_FAIL2BAN_TRUNCATE_HOST)) {
57
+ $host = substr($host, 0, intval(WP_FAIL2BAN_TRUNCATE_HOST));
58
+ }
59
+ /**
60
+ * Refactor for unit testing.
61
+ * @since 4.3.0
62
+ */
63
+ $options = (defined('WP_FAIL2BAN_OPENLOG_OPTIONS')) ? WP_FAIL2BAN_OPENLOG_OPTIONS : null;
64
+ if (false === \openlog("$tag($host)", $options, constant($log))) {
65
+ error_log('WPf2b: Cannot open syslog', 0); // @codeCoverageIgnore
66
+ } elseif (defined('WP_FAIL2BAN_TRACE')) {
67
+ error_log('WPf2b: Opened syslog', 0); // @codeCoverageIgnore
68
+ }
69
  }
70
 
71
+ /**
72
+ * Wrapper for \syslog
73
+ *
74
+ * @since 3.5.0
75
+ *
76
+ * @param int $level
77
+ * @param string $msg
78
+ * @param string|null $remote_addr
79
+ */
80
+ function syslog($level, $msg, $remote_addr = null)
81
+ {
82
+ $msg .= ' from ';
83
+ $msg .= (is_null($remote_addr))
84
+ ? remote_addr()
85
+ : $remote_addr;
86
 
87
+ if (false === \syslog($level, $msg)) {
88
+ error_log("WPf2b: Cannot write to syslog: '{$msg}'", 0); // @codeCoverageIgnore
89
+ } elseif (defined('WP_FAIL2BAN_TRACE')) {
90
+ error_log("WPf2b: Wrote to syslog: '{$msg}'", 0); // @codeCoverageIgnore
91
+ }
92
+ \closelog();
93
+
94
+ if (defined('PHPUNIT_COMPOSER_INSTALL')) {
95
+ echo "$level|$msg";
96
+ }
 
 
 
 
 
 
 
 
 
 
97
  }
98
+
99
+ /**
100
+ * Graceful immediate exit
101
+ *
102
+ * @since 4.3.0 Remove JSON support
103
+ * @since 4.0.5 Add JSON support
104
+ * @since 3.5.0 Refactored for unit testing
105
+ *
106
+ * @param bool $is_json
107
+ */
108
+ function bail()
109
+ {
110
+ if (false === apply_filters(__FUNCTION__, true)) {
111
+ return false; // @codeCoverageIgnore
112
+ }
113
+
114
+ \wp_die('Forbidden', 'Forbidden', array('exit' => false, 'response' => 403));
115
+
116
+ if (defined('PHPUNIT_COMPOSER_INSTALL')) {
117
+ return false; // for testing
118
+ } else {
119
+ exit; // @codeCoverageIgnore
120
+ }
121
  }
 
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
 
 
 
 
 
 
 
 
 
 
 
124
  /**
125
+ * Compute remote IP address
126
+ *
127
+ * @return string
128
+ *
129
+ * @todo Test me!
130
+ * @codeCoverageIgnore
131
  */
132
+ function remote_addr()
133
+ {
134
+ static $remote_addr = null;
135
+
136
+ /**
137
+ * @since 4.0.0
138
+ */
139
+ if (is_null($remote_addr)) {
140
+ if (defined('WP_FAIL2BAN_PROXIES')) {
141
+ if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
142
+ $ip = ip2long($_SERVER['REMOTE_ADDR']);
143
+ /**
144
+ * PHP 7 lets you define an array
145
+ * @since 3.5.4
146
+ */
147
+ $proxies = (is_array(WP_FAIL2BAN_PROXIES))
148
+ ? WP_FAIL2BAN_PROXIES
149
+ : explode(',', WP_FAIL2BAN_PROXIES);
150
+ foreach ($proxies as $proxy) {
151
+ if ('#' == $proxy[0]) {
152
+ continue;
153
+ } elseif (2 == count($cidr = explode('/', $proxy))) {
154
+ $net = ip2long($cidr[0]);
155
+ $mask = ~ ( pow(2, (32 - $cidr[1])) - 1 );
156
+ } else {
157
+ $net = ip2long($proxy);
158
+ $mask = -1;
159
+ }
160
+ if ($net == ($ip & $mask)) {
161
+ return (false === ($len = strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',')))
162
+ ? $_SERVER['HTTP_X_FORWARDED_FOR']
163
+ : substr($_SERVER['HTTP_X_FORWARDED_FOR'], 0, $len);
164
+ }
165
  }
166
  }
167
  }
168
+
169
+ /**
170
+ * For plugins and themes that anonymise requests
171
+ * @since 3.6.0
172
+ */
173
+ $remote_addr = (defined('WP_FAIL2BAN_REMOTE_ADDR'))
174
+ ? WP_FAIL2BAN_REMOTE_ADDR
175
+ : $_SERVER['REMOTE_ADDR'];
176
  }
177
+
178
+ return $remote_addr;
 
 
 
179
  }
 
 
180
  }
181
+
feature/password.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * Password-related functionality
5
  *
@@ -8,30 +7,31 @@
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * @since 4.0.5
16
- */
17
 
18
- if ( !function_exists( __NAMESPACE__ . '\\retrieve_password' ) ) {
19
  /**
20
- * Log password reset requests
21
- *
22
- * @since 3.5.0
23
- *
24
- * @param string $user_login
25
- *
26
- * @wp-f2b-extra Password reset requested for .*
27
  */
28
- function retrieve_password( $user_login )
29
- {
30
- openlog( 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG' );
31
- syslog( LOG_NOTICE, "Password reset requested for {$user_login}" );
32
- closelog();
33
- // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
35
-
36
- add_action( 'retrieve_password', __NAMESPACE__ . '\\retrieve_password' );
37
  }
 
1
  <?php
 
2
  /**
3
  * Password-related functionality
4
  *
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
11
+ include_once_exists(WP_FAIL2BAN_DIR.'/premium/feature/password.php');
 
 
 
 
12
 
 
13
  /**
14
+ * @since 4.0.5
 
 
 
 
 
 
15
  */
16
+ if (!function_exists(__NAMESPACE__.'\retrieve_password')) {
17
+ /**
18
+ * Log password reset requests
19
+ *
20
+ * @since 3.5.0
21
+ *
22
+ * @param string $user_login
23
+ *
24
+ * @wp-f2b-extra Password reset requested for .*
25
+ */
26
+ function retrieve_password($user_login)
27
+ {
28
+ openlog('WP_FAIL2BAN_PASSWORD_REQUEST_LOG');
29
+ syslog(LOG_NOTICE, "Password reset requested for {$user_login}");
30
+ closelog();
31
+
32
+ do_action(__FUNCTION__, $user_login);
33
+ }
34
+ add_action('retrieve_password', __NAMESPACE__.'\retrieve_password');
35
  }
 
 
36
  }
37
+
feature/plugins.php CHANGED
@@ -1,233 +1,255 @@
1
  <?php
2
-
3
  /**
4
  * Library functions
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.2.0
 
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * Hook: plugins_loaded
16
- *
17
- * @since 4.2.0
18
- */
19
- function plugins_loaded()
20
- {
21
- do_action( 'wp_fail2ban_register' );
22
- }
23
 
24
- add_action( 'plugins_loaded', __NAMESPACE__ . '\\plugins_loaded' );
25
- /**
26
- * Register plugin
27
- *
28
- * @since 4.2.0
29
- *
30
- * @param string $slug Plugin slug. This must be the actual plugin slug. Maximum length is 255 which should be more than enough.
31
- * @param string $name Plugin display name. This should be an unescaped string - HTML is allowed.
32
- *
33
- * @return int|false ID
34
- */
35
- function register_plugin( $slug, $name )
36
- {
37
- global $wp_fail2ban, $wpdb ;
38
- if ( 255 < strlen( $slug ) ) {
39
- throw new \LengthException( 'slug too long' );
40
- }
41
- if ( 255 < strlen( $name ) ) {
42
- throw new \LengthException( 'name too long' );
43
- }
44
- if ( !is_array( @$wp_fail2ban['plugins'] ) ) {
45
- $wp_fail2ban['plugins'] = [];
46
- }
47
- if ( array_key_exists( $slug, $wp_fail2ban['plugins'] ) ) {
48
- return $wp_fail2ban['plugins'][$slug];
49
- }
50
- static $id = 0 ;
51
- return $wp_fail2ban['plugins'][$slug] = [
52
- 'id' => ++$id,
53
- 'name' => $name,
54
- 'messages' => [],
55
- ];
56
- }
57
 
58
- add_action(
59
- 'wp_fail2ban_register_plugin',
60
- __NAMESPACE__ . '\\register_plugin',
61
- 1,
62
- 2
63
- );
64
- /**
65
- * Check if plugin is registered.
66
- *
67
- * @since 4.2.0
68
- *
69
- * @param string $plugin_slug
70
- *
71
- * @return bool
72
- */
73
- function is_registered_plugin( $plugin_slug )
74
- {
75
- global $wp_fail2ban ;
76
- return array_key_exists( $plugin_slug, $wp_fail2ban['plugins'] );
77
- }
78
 
79
- /**
80
- * Register plugin message.
81
- *
82
- * @since 4.2.0
83
- *
84
- * @param string $plugin_slug
85
- * @param array $msg [
86
- * string slug: Message slug
87
- * string fail: hard|soft|extra
88
- * int facility: syslog facility
89
- * int priority: syslog priority
90
- * string event_class: Event Class
91
- * int event_id: Event ID
92
- * string message: Message with placeholders
93
- * HOST: Remote IP
94
- * USER: Current user name
95
- * array vars: Array of [name => regex] pairs
96
- */
97
- function register_message( $plugin_slug, array $msg )
98
- {
99
- global $wp_fail2ban ;
100
- $event_classes = [
101
- 'auth' => WPF2B_EVENT_CLASS_AUTH,
102
- 'comment' => WPF2B_EVENT_CLASS_COMMENT,
103
- 'password' => WPF2B_EVENT_CLASS_PASSWORD,
104
- 'rest' => WPF2B_EVENT_CLASS_REST,
105
- 'spam' => WPF2B_EVENT_CLASS_SPAM,
106
- 'xmlrpc' => WPF2B_EVENT_CLASS_XMLRPC,
107
- 'other' => 0,
108
- ];
109
- $args = [];
110
- if ( !is_registered_plugin( $plugin_slug ) ) {
111
- throw new \InvalidArgumentException( 'plugin not registered' );
112
- }
113
- if ( !array_key_exists( 'slug', $msg ) ) {
114
- throw new \InvalidArgumentException( "Missing 'slug'" );
115
- }
116
- if ( !is_string( $msg['slug'] ) ) {
117
- throw new \InvalidArgumentException( "'slug' must be string" );
118
- }
119
- if ( !array_key_exists( 'fail', $msg ) ) {
120
- throw new \InvalidArgumentException( "Missing 'fail'" );
121
- }
122
- if ( !in_array( $msg['fail'], [ 'hard', 'soft', 'extra' ] ) ) {
123
- throw new \UnexpectedValueException( "'fail' must be one of 'hard', 'soft', 'extra'" );
124
- }
125
- $args['fail'] = $msg['fail'];
126
- if ( !array_key_exists( 'priority', $msg ) ) {
127
- throw new \InvalidArgumentException( "Missing 'priority'" );
128
- }
129
- if ( !in_array( $msg['priority'], [
130
- LOG_CRIT,
131
- LOG_ERR,
132
- LOG_WARNING,
133
- LOG_NOTICE,
134
- LOG_INFO,
135
- LOG_DEBUG
136
- ] ) ) {
137
- throw new \UnexpectedValueException( "Invalid 'priority'" );
138
- }
139
- $args['priority'] = $msg['priority'];
140
- if ( !array_key_exists( 'event_class', $msg ) ) {
141
- throw new \InvalidArgumentException( "Missing 'event_class'" );
142
- }
143
- if ( !array_key_exists( $event_class = strtolower( $msg['event_class'] ), $event_classes ) ) {
144
- throw new \UnexpectedValueException( "Invalid 'event_class'" );
145
- }
146
- $args['class'] = $event_class;
147
- $event_class = $event_classes[$event_class];
148
- $log = sprintf( "WP_FAIL2BAN_%s_LOG", strtoupper( $event_class ) );
149
- if ( !array_key_exists( 'event_id', $msg ) ) {
150
- throw new \InvalidArgumentException( "Missing 'event_id'" );
151
- }
152
- if ( ($msg['event_id'] & 0xffff) !== $msg['event_id'] ) {
153
- throw new \UnexpectedValueException( "Invalid 'event_id'" );
154
- }
155
- $args['event_id'] = WPF2B_EVENT_TYPE_PLUGIN | $event_class | $msg['event_id'];
156
- if ( !array_key_exists( 'message', $msg ) ) {
157
- throw new \InvalidArgumentException( "Missing 'message'" );
158
- }
159
- if ( !is_string( $msg['message'] ) ) {
160
- throw new \UnexpectedValueException( "Invalid 'message'" );
161
- }
162
- $args['message'] = $msg['message'];
163
- if ( !array_key_exists( 'vars', $msg ) ) {
164
- throw new \InvalidArgumentException( "Missing 'vars'" );
165
  }
166
- if ( !is_array( $msg['vars'] ) ) {
167
- throw new \UnexpectedValueException( "Invalid 'vars'" );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  }
169
- $args['vars'] = $msg['vars'];
170
- $wp_fail2ban['plugins'][$plugin_slug]['messages'][$msg['slug']] = $args;
171
- }
172
 
173
- add_action(
174
- 'wp_fail2ban_register_message',
175
- __NAMESPACE__ . '\\register_message',
176
- 1,
177
- 2
178
- );
179
- /**
180
- * Check if message is registered.
181
- *
182
- * NB: Assumes plugin is registered.
183
- *
184
- * @since 4.2.0
185
- *
186
- * @param string $plugin_slug
187
- * @param string $message_slug
188
- *
189
- * @return bool
190
- */
191
- function is_registered_plugin_message( $plugin_slug, $message_slug )
192
- {
193
- global $wp_fail2ban ;
194
- return array_key_exists( $message_slug, $wp_fail2ban['plugins'][$plugin_slug]['messages'] );
195
- }
 
 
 
 
 
 
 
196
 
197
- /**
198
- * Log plugin message.
199
- *
200
- * @since 4.2.0
201
- *
202
- * @param string $plugin_slug Plugin slug for registered message
203
- * @param string $message_slug Message slug for registered message
204
- * @param array $vars Substitution vars
205
- */
206
- function log_message( $plugin_slug, $message_slug = null, array $vars = array() )
207
- {
208
- global $wp_fail2ban ;
209
- if ( !is_registered_plugin( $plugin_slug ) ) {
210
- throw new \InvalidArgumentException( 'plugin not registered' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  }
212
- if ( !is_registered_plugin_message( $plugin_slug, $message_slug ) ) {
213
- throw new \InvalidArgumentException( 'message not registered' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  }
215
- $args = $wp_fail2ban['plugins'][$plugin_slug]['messages'][$message_slug];
216
- $msg = $args['message'];
217
- foreach ( $args['vars'] as $name => $regex ) {
218
- if ( array_key_exists( $name, $vars ) ) {
219
- $msg = str_replace( "___{$name}___", $vars[$name], $msg );
 
 
 
 
 
 
 
 
 
 
 
220
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  }
222
- openlog( sprintf( 'WP_FAIL2BAN_PLUGIN_%s_LOG', strtoupper( $args['class'] ) ) );
223
- syslog( $args['priority'], "({$plugin_slug}) {$msg}" );
224
- closelog();
225
- // @codeCoverageIgnoreEnd
226
  }
227
 
228
- add_action(
229
- 'wp_fail2ban_log_message',
230
- __NAMESPACE__ . '\\log_message',
231
- 1,
232
- 3
233
- );
1
  <?php
 
2
  /**
3
  * Library functions
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.2.0
7
+ * @php 5.6
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
+ if (defined('ABSPATH')) {
12
+ include_once_exists(WP_FAIL2BAN_DIR.'/premium/feature/plugins.php');
 
 
 
 
 
 
 
 
 
 
13
 
14
+ /**
15
+ * @since 4.2.0
16
+ */
17
+ global $wp_fail2ban;
18
+ $wp_fail2ban['plugins'] = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ /**
21
+ * Hook: plugins_loaded
22
+ *
23
+ * @codeCoverageIgnore
24
+ *
25
+ * @since 4.2.0
26
+ */
27
+ function wp_fail2ban_register()
28
+ {
29
+ do_action('wp_fail2ban_register');
30
+ }
31
+ add_action('plugins_loaded', __NAMESPACE__.'\wp_fail2ban_register');
 
 
 
 
 
 
 
 
32
 
33
+ /**
34
+ * Register plugin
35
+ *
36
+ * @since 4.2.0
37
+ *
38
+ * @param string $slug Plugin slug. This must be the actual plugin slug. Maximum length is 255 which should be more than enough.
39
+ * @param string $name Plugin display name. This should be an unescaped string - HTML is allowed.
40
+ *
41
+ * @return int|false ID
42
+ */
43
+ function register_plugin($slug, $name)
44
+ {
45
+ global $wp_fail2ban, $wpdb;
46
+
47
+ if (255 < strlen($slug)) {
48
+ throw new \LengthException('slug too long');
49
+ }
50
+
51
+ if (255 < strlen($name)) {
52
+ throw new \LengthException('name too long');
53
+ }
54
+
55
+ if (!array_key_exists('plugins', $wp_fail2ban) || !is_array($wp_fail2ban['plugins'])) {
56
+ $wp_fail2ban['plugins'] = []; //@codeCoverageIgnore
57
+ }
58
+
59
+ if (array_key_exists($slug, $wp_fail2ban['plugins'])) {
60
+ return $wp_fail2ban['plugins'][$slug];
61
+ }
62
+
63
+ if (is_null($rv = apply_filters(__FUNCTION__, null, $slug, $name))) {
64
+ static $id = 0;
65
+
66
+ return ($wp_fail2ban['plugins'][$slug] = [
67
+ 'id' => ++$id,
68
+ 'name' => $name,
69
+ 'messages' => []
70
+ ]);
71
+ } else {
72
+ return $rv; // @codeCoverageIgnore
73
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  }
75
+ add_action('wp_fail2ban_register_plugin', __NAMESPACE__.'\register_plugin', 1, 2);
76
+
77
+ /**
78
+ * Check if plugin is registered.
79
+ *
80
+ * @since 4.2.0
81
+ *
82
+ * @param string $plugin_slug
83
+ *
84
+ * @return bool
85
+ */
86
+ function is_registered_plugin($plugin_slug)
87
+ {
88
+ global $wp_fail2ban;
89
+
90
+ return array_key_exists($plugin_slug, $wp_fail2ban['plugins']);
91
  }
 
 
 
92
 
93
+ /**
94
+ * Register plugin message.
95
+ *
96
+ * @since 4.2.0
97
+ *
98
+ * @param string $plugin_slug
99
+ * @param array $msg [
100
+ * string slug: Message slug
101
+ * string fail: hard|soft|extra
102
+ * int facility: syslog facility
103
+ * int priority: syslog priority
104
+ * string event_class: Event Class
105
+ * int event_id: Event ID
106
+ * string message: Message with placeholders
107
+ * HOST: Remote IP
108
+ * USER: Current user name
109
+ * array vars: Array of [name => regex] pairs
110
+ */
111
+ function register_message($plugin_slug, array $msg)
112
+ {
113
+ global $wp_fail2ban;
114
+ $event_classes = [
115
+ 'auth' => WPF2B_EVENT_CLASS_AUTH,
116
+ 'comment' => WPF2B_EVENT_CLASS_COMMENT,
117
+ 'password' => WPF2B_EVENT_CLASS_PASSWORD,
118
+ 'rest' => WPF2B_EVENT_CLASS_REST,
119
+ 'spam' => WPF2B_EVENT_CLASS_SPAM,
120
+ 'xmlrpc' => WPF2B_EVENT_CLASS_XMLRPC,
121
+ 'other' => 0
122
+ ];
123
 
124
+ $args = [];
125
+
126
+ if (!is_registered_plugin($plugin_slug)) {
127
+ throw new \InvalidArgumentException('plugin not registered');
128
+ }
129
+
130
+ if (!array_key_exists('slug', $msg)) {
131
+ throw new \InvalidArgumentException("Missing 'slug'");
132
+ }
133
+ if (!is_string($msg['slug'])) {
134
+ throw new \InvalidArgumentException("'slug' must be string");
135
+ }
136
+
137
+ if (!array_key_exists('fail', $msg)) {
138
+ throw new \InvalidArgumentException("Missing 'fail'");
139
+ }
140
+ if (!in_array($msg['fail'], ['hard', 'soft', 'extra'])) {
141
+ throw new \UnexpectedValueException("'fail' must be one of 'hard', 'soft', 'extra'");
142
+ }
143
+ $args['fail'] = $msg['fail'];
144
+
145
+ if (!array_key_exists('priority', $msg)) {
146
+ throw new \InvalidArgumentException("Missing 'priority'");
147
+ }
148
+ if (!in_array($msg['priority'], [
149
+ LOG_CRIT,
150
+ LOG_ERR,
151
+ LOG_WARNING,
152
+ LOG_NOTICE,
153
+ LOG_INFO,
154
+ LOG_DEBUG
155
+ ])) {
156
+ throw new \UnexpectedValueException("Invalid 'priority'");
157
+ }
158
+ $args['priority'] = $msg['priority'];
159
+
160
+ if (!array_key_exists('event_class', $msg)) {
161
+ throw new \InvalidArgumentException("Missing 'event_class'");
162
+ }
163
+ if (!array_key_exists($event_class = strtolower($msg['event_class']), $event_classes)) {
164
+ throw new \UnexpectedValueException("Invalid 'event_class'");
165
+ }
166
+ $args['class'] = $event_class;
167
+ $event_class = $event_classes[$event_class];
168
+
169
+ $log = sprintf("WP_FAIL2BAN_%s_LOG", strtoupper($event_class));
170
+
171
+ if (!array_key_exists('event_id', $msg)) {
172
+ throw new \InvalidArgumentException("Missing 'event_id'");
173
+ }
174
+ if (($msg['event_id'] & 0x0000FFFF) !== $msg['event_id']) {
175
+ throw new \UnexpectedValueException("Invalid 'event_id'");
176
+ }
177
+ $args['event_id'] = WPF2B_EVENT_TYPE_PLUGIN | $event_class | $msg['event_id'];
178
+
179
+ if (!array_key_exists('message', $msg)) {
180
+ throw new \InvalidArgumentException("Missing 'message'");
181
+ }
182
+ if (!is_string($msg['message'])) {
183
+ throw new \UnexpectedValueException("Invalid 'message'");
184
+ }
185
+ $args['message'] = $msg['message'];
186
+
187
+ if (!array_key_exists('vars', $msg)) {
188
+ throw new \InvalidArgumentException("Missing 'vars'");
189
+ }
190
+ if (!is_array($msg['vars'])) {
191
+ throw new \UnexpectedValueException("Invalid 'vars'");
192
+ }
193
+ $args['vars'] = $msg['vars'];
194
+
195
+ $wp_fail2ban['plugins'][$plugin_slug]['messages'][$msg['slug']] = $args;
196
  }
197
+ add_action('wp_fail2ban_register_message', __NAMESPACE__.'\register_message', 1, 2);
198
+
199
+ /**
200
+ * Check if message is registered.
201
+ *
202
+ * NB: Assumes plugin is registered.
203
+ *
204
+ * @since 4.2.0
205
+ *
206
+ * @param string $plugin_slug
207
+ * @param string $message_slug
208
+ *
209
+ * @return bool
210
+ */
211
+ function is_registered_plugin_message($plugin_slug, $message_slug)
212
+ {
213
+ global $wp_fail2ban;
214
+
215
+ return array_key_exists($message_slug, $wp_fail2ban['plugins'][$plugin_slug]['messages']);
216
  }
217
+
218
+ /**
219
+ * Log plugin message.
220
+ *
221
+ * @since 4.2.0
222
+ *
223
+ * @param string $plugin_slug Plugin slug for registered message
224
+ * @param string $message_slug Message slug for registered message
225
+ * @param array $vars Substitution vars
226
+ */
227
+ function log_message($plugin_slug, $message_slug = null, array $vars = [])
228
+ {
229
+ global $wp_fail2ban;
230
+
231
+ if (!is_registered_plugin($plugin_slug)) {
232
+ throw new \InvalidArgumentException('plugin not registered');
233
  }
234
+
235
+ if (!is_registered_plugin_message($plugin_slug, $message_slug)) {
236
+ throw new \InvalidArgumentException('message not registered');
237
+ }
238
+
239
+ $args = $wp_fail2ban['plugins'][$plugin_slug]['messages'][$message_slug];
240
+ $msg = $args['message'];
241
+ foreach ($args['vars'] as $name => $regex) {
242
+ if (array_key_exists($name, $vars)) {
243
+ $msg = str_replace("___{$name}___", $vars[$name], $msg);
244
+ }
245
+ }
246
+
247
+ openlog(sprintf('WP_FAIL2BAN_PLUGIN_%s_LOG', strtoupper($args['class'])));
248
+ syslog($args['priority'], "($plugin_slug) $msg");
249
+ closelog();
250
+
251
+ do_action(__FUNCTION__, $plugin_slug, $message_slug, $vars, $args);
252
  }
253
+ add_action('wp_fail2ban_log_message', __NAMESPACE__.'\log_message', 1, 3);
 
 
 
254
  }
255
 
 
 
 
 
 
 
feature/spam.php CHANGED
@@ -1,60 +1,51 @@
1
  <?php
2
-
3
  /**
4
  * Spam comments
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * @since 4.0.5
16
- */
17
 
18
- if ( !function_exists( __NAMESPACE__ . '\\log_spam_comment' ) ) {
19
  /**
20
- * Catch comments marked as spam
21
- *
22
- * @since 3.5.0
23
- *
24
- * @param int $comment_id
25
- * @param string $comment_status
26
- *
27
- * @wp-f2b-hard Spam comment \d+
28
  */
29
- function log_spam_comment( $comment_id, $comment_status )
30
- {
31
- if ( 'spam' === $comment_status ) {
32
-
33
- if ( is_null( $comment = get_comment( $comment_id, ARRAY_A ) ) ) {
34
- /**
35
- * @todo: decide what to do about this
36
- */
37
- } else {
38
- $remote_addr = ( empty($comment['comment_author_IP']) ? 'unknown' : $comment['comment_author_IP'] );
39
- openlog( 'WP_FAIL2BAN_SPAM_LOG' );
40
- syslog( LOG_NOTICE, "Spam comment {$comment_id}", $remote_addr );
41
- closelog();
42
- // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
44
-
45
- }
 
46
  }
47
-
48
- add_action(
49
- 'comment_post',
50
- __NAMESPACE__ . '\\log_spam_comment',
51
- 10,
52
- 2
53
- );
54
- add_action(
55
- 'wp_set_comment_status',
56
- __NAMESPACE__ . '\\log_spam_comment',
57
- 10,
58
- 2
59
- );
60
  }
 
1
  <?php
 
2
  /**
3
  * Spam comments
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
11
+ include_once_exists(WP_FAIL2BAN_DIR.'/premium/feature/spam.php');
 
 
 
 
12
 
 
13
  /**
14
+ * @since 4.0.5
 
 
 
 
 
 
 
15
  */
16
+ if (!function_exists(__NAMESPACE__.'\log_spam_comment')) {
17
+ /**
18
+ * Catch comments marked as spam
19
+ *
20
+ * @since 3.5.0
21
+ *
22
+ * @param int $comment_id
23
+ * @param string $comment_status
24
+ *
25
+ * @wp-f2b-hard Spam comment \d+
26
+ */
27
+ function log_spam_comment($comment_id, $comment_status)
28
+ {
29
+ if ('spam' === $comment_status) {
30
+ if (is_null($comment = get_comment($comment_id, ARRAY_A))) {
31
+ /**
32
+ * @todo: decide what to do about this
33
+ */
34
+ } else {
35
+ $remote_addr = (empty($comment['comment_author_IP']))
36
+ ? 'unknown' // @codeCoverageIgnore
37
+ : $comment['comment_author_IP'];
38
+
39
+ openlog('WP_FAIL2BAN_SPAM_LOG');
40
+ syslog(LOG_NOTICE, "Spam comment {$comment_id}", $remote_addr);
41
+ closelog();
42
+
43
+ do_action(__FUNCTION__, $comment_id, $comment_status);
44
+ }
45
  }
46
+ };
47
+ add_action('comment_post', __NAMESPACE__.'\log_spam_comment', 10, 2);
48
+ add_action('wp_set_comment_status', __NAMESPACE__.'\log_spam_comment', 10, 2);
49
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  }
51
+
feature/user-enum.php CHANGED
@@ -1,145 +1,129 @@
1
  <?php
2
-
3
  /**
4
  * User enumeration
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * @since 4.0.5 Guard
16
- */
17
- if ( !function_exists( __NAMESPACE__ . '\\_log_bail_user_enum' ) ) {
18
  /**
19
- * Common enumeration handling
20
- *
21
- * @since 4.2.7 Remove JSON support
22
- * @since 4.1.0 Add JSON support
23
- * @since 4.0.0
24
- *
25
- * @return \WP_Error
26
- *
27
- * @wp-f2b-hard Blocked user enumeration attempt
28
  */
29
- function _log_bail_user_enum()
30
- {
31
- openlog();
32
- syslog( LOG_NOTICE, 'Blocked user enumeration attempt' );
33
- closelog();
34
- // @codeCoverageIgnoreEnd
35
- return bail();
36
- }
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- }
39
- /**
40
- * @since 4.0.5 Guard
41
- */
 
42
 
43
- if ( !function_exists( __NAMESPACE__ . '\\parse_request' ) ) {
44
  /**
45
- * Catch traditional user enum
46
- *
47
- * @see \WP::parse_request()
48
- *
49
- * @since 4.2.8 Refactor to make XDebug happy (h/t @dinghy)
50
- * @since 3.5.0 Refactored for unit testing
51
- * @since 2.1.0
52
- *
53
- * @param \WP $query
54
- *
55
- * @return \WP
56
  */
57
- function parse_request( $query )
58
- {
59
- if ( !current_user_can( 'list_users' ) && array_key_exists( 'author', $query->query_vars ) && intval( $query->query_vars['author'] ) ) {
60
- _log_bail_user_enum();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
- return $query;
63
  }
64
-
65
- add_filter(
66
- 'parse_request',
67
- __NAMESPACE__ . '\\parse_request',
68
- 1,
69
- 2
70
- );
71
- }
72
-
73
- /**
74
- * @since 4.0.5 Guard
75
- */
76
 
77
- if ( !function_exists( __NAMESPACE__ . '\\rest_user_query' ) ) {
78
  /**
79
- * Catch RESTful user list
80
- *
81
- * @see \WP_REST_Users_Controller::get_items()
82
- *
83
- * @since 4.2.8 Change cap to edit_others_posts to play better with GB
84
- * @since 4.0.0
85
- *
86
- * @param array $prepared_args
87
- * @param \WP_REST_Request $request
88
- *
89
- * @return array|\WP_Error
90
  */
91
- function rest_user_query( $prepared_args, $request )
92
- {
93
- if ( !current_user_can( 'edit_others_posts' ) ) {
94
- return _log_bail_user_enum();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
96
- return $prepared_args;
97
  }
98
-
99
- add_filter(
100
- 'rest_user_query',
101
- __NAMESPACE__ . '\\rest_user_query',
102
- 10,
103
- 2
104
- );
105
- }
106
 
107
- /**
108
- * @since 4.2.6 Guard
109
- */
110
-
111
- if ( !function_exists( __NAMESPACE__ . '\\oembed_response_data' ) ) {
112
  /**
113
- *
114
- * @see \get_oembed_response_data()
115
- *
116
- * @since 4.2.7.1 Fix `add_filter()` params
117
- * @since 4.2.6
118
- *
119
- * @param array $data The response data.
120
- * @param \WP_Post $post The post object.
121
- * @param int $width The requested width.
122
- * @param int $height The calculated height.
123
- *
124
- * @return array
125
  */
126
- function oembed_response_data(
127
- $data,
128
- $post,
129
- $width,
130
- $height
131
- )
132
- {
133
- unset( $data['author_name'] );
134
- unset( $data['author_url'] );
135
- return $data;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  }
137
-
138
- add_filter(
139
- 'oembed_response_data',
140
- __NAMESPACE__ . '\\oembed_response_data',
141
- PHP_INT_MAX - 1,
142
- // almost last in case something expects author_xxx to be set
143
- 4
144
- );
145
  }
 
1
  <?php
 
2
  /**
3
  * User enumeration
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
11
+ include_once_exists(WP_FAIL2BAN_DIR.'/premium/feature/user-enum.php');
12
+
 
 
 
 
13
  /**
14
+ * @since 4.0.5 Guard
 
 
 
 
 
 
 
 
15
  */
16
+ if (!function_exists(__NAMESPACE__.'\_log_bail_user_enum')) {
17
+ /**
18
+ * Common enumeration handling
19
+ *
20
+ * @since 4.3.0 Remove JSON support
21
+ * @since 4.1.0 Add JSON support
22
+ * @since 4.0.0
23
+ *
24
+ * @param bool $is_json
25
+ *
26
+ * @return \WP_Error
27
+ *
28
+ * @wp-f2b-hard Blocked user enumeration attempt
29
+ */
30
+ function _log_bail_user_enum()
31
+ {
32
+ openlog();
33
+ syslog(LOG_NOTICE, 'Blocked user enumeration attempt');
34
+ closelog();
35
 
36
+ do_action(__FUNCTION__);
37
+
38
+ return bail();
39
+ }
40
+ }
41
 
 
42
  /**
43
+ * @since 4.0.5 Guard
 
 
 
 
 
 
 
 
 
 
44
  */
45
+ if (!function_exists(__NAMESPACE__.'\parse_request')) {
46
+ /**
47
+ * Catch traditional user enum
48
+ *
49
+ * @see \WP::parse_request()
50
+ *
51
+ * @since 4.3.0 Refactored to make XDebug happy; h/t @dinghy
52
+ * Changed cap to 'edit_others_posts'
53
+ * @since 3.5.0 Refactored for unit testing
54
+ * @since 2.1.0
55
+ *
56
+ * @param \WP $query
57
+ *
58
+ * @return \WP
59
+ */
60
+ function parse_request($query)
61
+ {
62
+ if (!current_user_can('edit_others_posts') && intval(array_value('author', $query->query_vars))) {
63
+ _log_bail_user_enum();
64
+ }
65
+
66
+ return $query;
67
  }
68
+ add_filter('parse_request', __NAMESPACE__.'\parse_request', 1);
69
  }
 
 
 
 
 
 
 
 
 
 
 
 
70
 
 
71
  /**
72
+ * @since 4.0.5 Guard
 
 
 
 
 
 
 
 
 
 
73
  */
74
+ if (!function_exists(__NAMESPACE__.'\rest_user_query')) {
75
+ /**
76
+ * Catch RESTful user list
77
+ *
78
+ * @see \WP_REST_Users_Controller::get_items()
79
+ *
80
+ * @since 4.3.0 Change to 'edit_others_posts'
81
+ * @since 4.0.0
82
+ *
83
+ * @param array $prepared_args
84
+ * @param \WP_REST_Request $request
85
+ *
86
+ * @return array|\WP_Error
87
+ */
88
+ function rest_user_query($prepared_args, $request)
89
+ {
90
+ if (!current_user_can('edit_others_posts')) {
91
+ return _log_bail_user_enum();
92
+ }
93
+
94
+ return $prepared_args;
95
  }
96
+ add_filter('rest_user_query', __NAMESPACE__.'\rest_user_query', 10, 2);
97
  }
 
 
 
 
 
 
 
 
98
 
 
 
 
 
 
99
  /**
100
+ * @since 4.2.7
 
 
 
 
 
 
 
 
 
 
 
101
  */
102
+ if (!function_exists(__NAMESPACE__.'\oembed_response_data')) {
103
+ /**
104
+ * Catch oembed user info
105
+ *
106
+ * @codeCoverageIgnore
107
+ *
108
+ * @see \get_oembed_response_data()
109
+ *
110
+ * @since 4.2.7
111
+ *
112
+ * @param array $data The response data.
113
+ * @param WP_Post $post The post object.
114
+ * @param int $width The requested width.
115
+ * @param int $height The calculated height.
116
+ *
117
+ * @return array
118
+ */
119
+ function oembed_response_data($data, $post, $width, $height)
120
+ {
121
+ unset($data['author_name']);
122
+ unset($data['author_url']);
123
+
124
+ return $data;
125
+ }
126
+ add_filter('oembed_response_data', __NAMESPACE__.'\oembed_response_data', PHP_INT_MAX-1, 4);
127
  }
 
 
 
 
 
 
 
 
128
  }
129
+
feature/user.php CHANGED
@@ -1,61 +1,77 @@
1
  <?php
2
-
3
  /**
4
  * Blocked user functionality
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * @since 4.0.5 Guard
16
- */
17
 
18
- if ( !function_exists( __NAMESPACE__ . '\\authenticate' ) ) {
19
  /**
20
- * Catched blocked users
21
- *
22
- * @since 3.5.0 Refactored for unit testing
23
- * @since 2.0.0
24
- *
25
- * @param mixed|null $user
26
- * @param string $username
27
- * @param string $password
28
- *
29
- * @return mixed|null
30
- *
31
- * @wp-f2b-hard Blocked authentication attempt for .*
32
  */
33
- function authenticate( $user, $username, $password )
34
- {
35
-
36
- if ( !empty($username) ) {
37
- /**
38
- * @since 3.5.0 Arrays allowed in PHP 7
39
- */
40
- $matched = ( is_array( WP_FAIL2BAN_BLOCKED_USERS ) ? in_array( $username, WP_FAIL2BAN_BLOCKED_USERS ) : preg_match( '/' . WP_FAIL2BAN_BLOCKED_USERS . '/i', $username ) );
41
-
42
- if ( $matched ) {
43
- openlog();
44
- syslog( LOG_NOTICE, "Blocked authentication attempt for {$username}" );
45
- closelog();
46
- // @codeCoverageIgnoreEnd
47
- bail();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
-
 
50
  }
51
-
52
- return $user;
53
  }
54
-
55
- add_filter(
56
- 'authenticate',
57
- __NAMESPACE__ . '\\authenticate',
58
- 1,
59
- 3
60
- );
61
  }
 
1
  <?php
 
2
  /**
3
  * Blocked user functionality
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
11
+ include_once_exists(WP_FAIL2BAN_DIR.'/premium/feature/user.php');
 
 
 
 
12
 
 
13
  /**
14
+ * @since 4.0.5 Guard
 
 
 
 
 
 
 
 
 
 
 
15
  */
16
+ if (!function_exists(__NAMESPACE__.'\block_users')) {
17
+ /**
18
+ * Catch blocked users
19
+ *
20
+ * @see \wp_authenticate()
21
+ *
22
+ * @since 4.3.0 Add blocking username logins
23
+ * @since 3.5.0 Refactored for unit testing
24
+ * @since 2.0.0
25
+ *
26
+ * @param mixed|null $user
27
+ * @param string $username
28
+ * @param string $password
29
+ *
30
+ * @return mixed|null
31
+ *
32
+ * @wp-f2b-hard Blocked authentication attempt for .*
33
+ * @wp-f2b-hard Blocked username authentication attempt for .*
34
+ */
35
+ function block_users($user, $username, $password)
36
+ {
37
+ if (!empty($username)) {
38
+ if (defined('WP_FAIL2BAN_BLOCK_USERNAME_LOGIN') && WP_FAIL2BAN_BLOCK_USERNAME_LOGIN) {
39
+ if (is_email($username)) {
40
+ // OK!
41
+ } else {
42
+ openlog();
43
+ syslog(LOG_NOTICE, "Blocked username authentication attempt for {$username}");
44
+ closelog();
45
+
46
+ do_action(__FUNCTION__.'.block_username_login', $user, $username, $password);
47
+
48
+ return bail(); // for testing
49
+ }
50
+ }
51
+
52
+ if (defined('WP_FAIL2BAN_BLOCKED_USERS') && WP_FAIL2BAN_BLOCKED_USERS) {
53
+ /**
54
+ * @since 3.5.0 Arrays allowed in PHP 7
55
+ */
56
+ $matched = (is_array(WP_FAIL2BAN_BLOCKED_USERS))
57
+ ? in_array($username, WP_FAIL2BAN_BLOCKED_USERS)
58
+ : preg_match('/'.WP_FAIL2BAN_BLOCKED_USERS.'/i', $username);
59
+
60
+ if ($matched) {
61
+ openlog();
62
+ syslog(LOG_NOTICE, "Blocked authentication attempt for {$username}");
63
+ closelog();
64
+
65
+ do_action(__FUNCTION__.'.blocked_users', $user, $username, $password);
66
+
67
+ return bail(); // for testing
68
+ }
69
+ }
70
  }
71
+
72
+ return $user;
73
  }
74
+ add_filter('authenticate', __NAMESPACE__.'\block_users', 1, 3);
 
75
  }
 
 
 
 
 
 
 
76
  }
77
+
feature/xmlrpc.php CHANGED
@@ -1,108 +1,102 @@
1
  <?php
2
-
3
  /**
4
  * XML-RPC functionality
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * @since 4.0.5 Guard
16
- */
17
 
18
- if ( !function_exists( __NAMESPACE__ . '\\xmlrpc_login_error' ) ) {
19
  /**
20
- * Catch multiple XML-RPC authentication failures
21
- *
22
- * @see \wp_xmlrpc_server::login()
23
- *
24
- * @since 4.0.0 Return $error
25
- * @since 3.5.0 Refactored for unit testing
26
- * @since 3.0.0
27
- *
28
- * @param \IXR_Error $error
29
- * @param \WP_Error $user
30
- *
31
- * @return \IXR_Error
32
- *
33
- * @wp-f2b-hard XML-RPC multicall authentication failure
34
  */
35
- function xmlrpc_login_error( $error, $user )
36
- {
37
- static $attempts = 0 ;
38
-
39
- if ( ++$attempts > 1 ) {
40
- openlog();
41
- syslog( LOG_NOTICE, 'XML-RPC multicall authentication failure' );
42
- closelog();
43
- // @codeCoverageIgnoreEnd
44
- bail();
45
- } else {
46
- return $error;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
-
49
  }
50
-
51
- add_action(
52
- 'xmlrpc_login_error',
53
- __NAMESPACE__ . '\\xmlrpc_login_error',
54
- 10,
55
- 2
56
- );
57
- }
58
 
59
- /**
60
- * @since 4.0.5 Guard
61
- */
62
 
63
- if ( !function_exists( __NAMESPACE__ . '\\xmlrpc_pingback_error' ) ) {
64
  /**
65
- * Catch failed pingbacks
66
- *
67
- * @see \wp_xmlrpc_server::pingback_error()
68
- *
69
- * @since 4.0.0 Return $ixr_error
70
- * @since 3.5.0 Refactored for unit testing
71
- * @since 3.0.0
72
- *
73
- * @param \IXR_Error $ixr_error
74
- *
75
- * @return \IXR_Error
76
- *
77
- * @wp-f2b-hard Pingback error .* generated
78
  */
79
- function xmlrpc_pingback_error( $ixr_error )
80
- {
81
-
82
- if ( 48 !== $ixr_error->code ) {
83
- openlog();
84
- syslog( LOG_NOTICE, 'Pingback error ' . $ixr_error->code . ' generated' );
85
- closelog();
86
- // @codeCoverageIgnoreEnd
87
- }
88
-
89
- return $ixr_error;
90
  }
91
-
92
- add_filter( 'xmlrpc_pingback_error', __NAMESPACE__ . '\\xmlrpc_pingback_error', 5 );
93
- }
94
 
95
- /**
96
- * @since 4.0.0 Refactored
97
- * @since 2.2.0
98
- */
99
- if ( defined( 'WP_FAIL2BAN_LOG_PINGBACKS' ) && true === WP_FAIL2BAN_LOG_PINGBACKS ) {
100
- require_once 'xmlrpc/pingback.php';
 
101
  }
102
- /**
103
- * @since 4.0.0 Refactored
104
- * @since 3.6.0
105
- */
106
- if ( defined( 'WP_FAIL2BAN_XMLRPC_LOG' ) && '' < WP_FAIL2BAN_XMLRPC_LOG ) {
107
- require_once 'xmlrpc/log.php';
108
- }
1
  <?php
 
2
  /**
3
  * XML-RPC functionality
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
11
+ include_once_exists(WP_FAIL2BAN_DIR.'/premium/feature/xmlrpc.php');
 
 
 
 
12
 
 
13
  /**
14
+ * @since 4.0.5 Guard
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  */
16
+ if (!function_exists(__NAMESPACE__.'\xmlrpc_login_error')) {
17
+ /**
18
+ * Catch multiple XML-RPC authentication failures
19
+ *
20
+ * @see \wp_xmlrpc_server::login()
21
+ *
22
+ * @since 4.0.0 Return $error
23
+ * @since 3.5.0 Refactored for unit testing
24
+ * @since 3.0.0
25
+ *
26
+ * @param \IXR_Error $error
27
+ * @param \WP_Error $user
28
+ *
29
+ * @return \IXR_Error
30
+ *
31
+ * @wp-f2b-hard XML-RPC multicall authentication failure
32
+ */
33
+ function xmlrpc_login_error($error, $user)
34
+ {
35
+ static $attempts = 0;
36
+
37
+ if (++$attempts > 1) {
38
+ openlog();
39
+ syslog(LOG_NOTICE, 'XML-RPC multicall authentication failure');
40
+ closelog();
41
+
42
+ do_action(__FUNCTION__, $error, $user);
43
+
44
+ bail();
45
+ } else {
46
+ return $error;
47
+ }
48
+ } // @codeCoverageIgnore
49
+ add_action('xmlrpc_login_error', __NAMESPACE__.'\xmlrpc_login_error', 10, 2);
50
+ }
51
+
52
+ /**
53
+ * @since 4.0.5 Guard
54
+ */
55
+ if (!function_exists(__NAMESPACE__.'\xmlrpc_pingback_error')) {
56
+ /**
57
+ * Catch failed pingbacks
58
+ *
59
+ * @see \wp_xmlrpc_server::pingback_error()
60
+ *
61
+ * @since 4.0.0 Return $ixr_error
62
+ * @since 3.5.0 Refactored for unit testing
63
+ * @since 3.0.0
64
+ *
65
+ * @param \IXR_Error $ixr_error
66
+ *
67
+ * @return \IXR_Error
68
+ *
69
+ * @wp-f2b-hard Pingback error .* generated
70
+ */
71
+ function xmlrpc_pingback_error($ixr_error)
72
+ {
73
+ if (48 !== $ixr_error->code) {
74
+ openlog();
75
+ syslog(LOG_NOTICE, 'Pingback error '.$ixr_error->code.' generated');
76
+ closelog();
77
+
78
+ do_action(__FUNCTION__, $ixr_error);
79
+ }
80
+ return $ixr_error;
81
  }
82
+ add_filter('xmlrpc_pingback_error', __NAMESPACE__.'\xmlrpc_pingback_error', 5);
83
  }
 
 
 
 
 
 
 
 
84
 
 
 
 
85
 
 
86
  /**
87
+ * @since 4.0.0 Refactored
88
+ * @since 2.2.0
 
 
 
 
 
 
 
 
 
 
 
89
  */
90
+ if (defined('WP_FAIL2BAN_LOG_PINGBACKS') && true === WP_FAIL2BAN_LOG_PINGBACKS) {
91
+ require_once 'xmlrpc/pingback.php';
 
 
 
 
 
 
 
 
 
92
  }
 
 
 
93
 
94
+ /**
95
+ * @since 4.0.0 Refactored
96
+ * @since 3.6.0
97
+ */
98
+ if (defined('WP_FAIL2BAN_XMLRPC_LOG') && '' < WP_FAIL2BAN_XMLRPC_LOG) {
99
+ require_once 'xmlrpc/log.php';
100
+ }
101
  }
102
+
 
 
 
 
 
 
feature/xmlrpc/log.php CHANGED
@@ -4,32 +4,30 @@
4
  *
5
  * @package wp-fail2ban
6
  * @since 4.0.0
 
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
- if (!defined('ABSPATH')) {
11
- exit;
12
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
- /**
15
- * Log XML-RPC requests
16
- *
17
- * It seems attackers are doing weird things with XML-RPC. This makes it easy to
18
- * log them for analysis and future blocking.
19
- *
20
- * @since 4.0.0 Fix: Removed HTTP_RAW_POST_DATA
21
- * https://wordpress.org/support/?p=10971843
22
- * @since 3.6.0
23
- *
24
- * @codeCoverageIgnore
25
- */
26
- if (false === ($fp = fopen(WP_FAIL2BAN_XMLRPC_LOG, 'a+'))) {
27
- // TODO: decided whether to log this
28
- } else {
29
- $raw_data = (version_compare(PHP_VERSION, '7.0.0') >= 0)
30
- ? file_get_contents('php://input')
31
- : $HTTP_RAW_POST_DATA;
32
-
33
- fprintf($fp, "# ---\n# Date: %s\n# IP: %s\n\n%s\n", date(DATE_ATOM), remote_addr(), $raw_data);
34
- fclose($fp);
35
  }
 
4
  *
5
  * @package wp-fail2ban
6
  * @since 4.0.0
7
+ * @codeCoverageIgnore
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
+ if (defined('ABSPATH')) {
12
+ /**
13
+ * Log XML-RPC requests
14
+ *
15
+ * It seems attackers are doing weird things with XML-RPC. This makes it easy to
16
+ * log them for analysis and future blocking.
17
+ *
18
+ * @since 4.0.0 Fix: Removed HTTP_RAW_POST_DATA
19
+ * https://wordpress.org/support/?p=10971843
20
+ * @since 3.6.0
21
+ */
22
+ if (false === ($fp = fopen(WP_FAIL2BAN_XMLRPC_LOG, 'a+'))) {
23
+ // TODO: decided whether to log this
24
+ } else {
25
+ $raw_data = (version_compare(PHP_VERSION, '7.0.0') >= 0)
26
+ ? file_get_contents('php://input')
27
+ : $HTTP_RAW_POST_DATA;
28
 
29
+ fprintf($fp, "# ---\n# Date: %s\n# IP: %s\n\n%s\n", date(DATE_ATOM), remote_addr(), $raw_data);
30
+ fclose($fp);
31
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
33
+
feature/xmlrpc/pingback.php CHANGED
@@ -1,40 +1,38 @@
1
  <?php
2
-
3
  /**
4
  * pingback logging
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.0.0
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- /**
15
- * @since 4.0.5 Guard
16
- */
17
 
18
- if ( !function_exists( __NAMESPACE__ . '\\xmlrpc_call' ) ) {
19
  /**
20
- * Log pingbacks
21
- *
22
- * @since 3.5.0 Refactored for unit testing
23
- * @since 2.2.0
24
- *
25
- * @param string $call
26
  */
27
- function xmlrpc_call( $call )
28
- {
29
-
30
- if ( 'pingback.ping' == $call ) {
31
- openlog( 'WP_FAIL2BAN_PINGBACK_LOG' );
32
- syslog( LOG_INFO, 'Pingback requested' );
33
- closelog();
34
- // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
35
  }
36
-
37
  }
38
-
39
- add_action( 'xmlrpc_call', __NAMESPACE__ . '\\xmlrpc_call' );
40
  }
 
1
  <?php
 
2
  /**
3
  * pingback logging
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
11
+ include_once_exists(WP_FAIL2BAN_DIR.'/premium/feature/xmlrpc/pingback.php');
 
 
 
 
12
 
 
13
  /**
14
+ * @since 4.0.5 Guard
 
 
 
 
 
15
  */
16
+ if (!function_exists(__NAMESPACE__.'\xmlrpc_call')) {
17
+ /**
18
+ * Log pingbacks
19
+ *
20
+ * @since 3.5.0 Refactored for unit testing
21
+ * @since 2.2.0
22
+ *
23
+ * @param string $call
24
+ */
25
+ function xmlrpc_call($call)
26
+ {
27
+ if ('pingback.ping' == $call) {
28
+ openlog('WP_FAIL2BAN_PINGBACK_LOG');
29
+ syslog(LOG_INFO, 'Pingback requested');
30
+ closelog();
31
+
32
+ do_action(__FUNCTION__, $call);
33
+ }
34
  }
35
+ add_action('xmlrpc_call', __NAMESPACE__.'\xmlrpc_call');
36
  }
 
 
37
  }
38
+
filters.d/wordpress-extra.conf CHANGED
@@ -1,5 +1,5 @@
1
  # Fail2Ban filter for WordPress extra failures
2
- # Auto-generated: 2020-04-17T15:52:10+00:00
3
  #
4
 
5
  [INCLUDES]
1
  # Fail2Ban filter for WordPress extra failures
2
+ # Auto-generated: 2020-04-30T22:51:50+00:00
3
  #
4
 
5
  [INCLUDES]
filters.d/wordpress-hard.conf CHANGED
@@ -1,5 +1,5 @@
1
  # Fail2Ban filter for WordPress hard failures
2
- # Auto-generated: 2020-04-17T15:52:10+00:00
3
  #
4
 
5
  [INCLUDES]
@@ -16,6 +16,7 @@ failregex = ^%(__prefix_line)sAuthentication attempt for unknown user .* from <H
16
  ^%(__prefix_line)sSpam comment \d+ from <HOST>$
17
  ^%(__prefix_line)sBlocked user enumeration attempt from <HOST>$
18
  ^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>$
 
19
  ^%(__prefix_line)sXML-RPC multicall authentication failure from <HOST>$
20
  ^%(__prefix_line)sPingback error .* generated from <HOST>$
21
 
1
  # Fail2Ban filter for WordPress hard failures
2
+ # Auto-generated: 2020-04-30T22:51:50+00:00
3
  #
4
 
5
  [INCLUDES]
16
  ^%(__prefix_line)sSpam comment \d+ from <HOST>$
17
  ^%(__prefix_line)sBlocked user enumeration attempt from <HOST>$
18
  ^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>$
19
+ ^%(__prefix_line)sBlocked username authentication attempt for .* from <HOST>$
20
  ^%(__prefix_line)sXML-RPC multicall authentication failure from <HOST>$
21
  ^%(__prefix_line)sPingback error .* generated from <HOST>$
22
 
filters.d/wordpress-soft.conf CHANGED
@@ -1,5 +1,5 @@
1
  # Fail2Ban filter for WordPress soft failures
2
- # Auto-generated: 2020-04-17T15:52:10+00:00
3
  #
4
 
5
  [INCLUDES]
@@ -10,7 +10,8 @@ before = common.conf
10
 
11
  _daemon = (?:wordpress|wp)
12
 
13
- failregex = ^%(__prefix_line)sAuthentication failure for .* from <HOST>$
 
14
  ^%(__prefix_line)sREST authentication failure for .* from <HOST>$
15
  ^%(__prefix_line)sXML-RPC authentication failure for .* from <HOST>$
16
 
1
  # Fail2Ban filter for WordPress soft failures
2
+ # Auto-generated: 2020-04-30T22:51:50+00:00
3
  #
4
 
5
  [INCLUDES]
10
 
11
  _daemon = (?:wordpress|wp)
12
 
13
+ failregex = ^%(__prefix_line)sEmpty username from <HOST>$
14
+ ^%(__prefix_line)sAuthentication failure for .* from <HOST>$
15
  ^%(__prefix_line)sREST authentication failure for .* from <HOST>$
16
  ^%(__prefix_line)sXML-RPC authentication failure for .* from <HOST>$
17
 
lib/activation.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WP fail2ban activation
4
+ *
5
+ * @package wp-fail2ban
6
+ * @since 4.3.0
7
+ */
8
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
+
10
+ if (defined('ABSPATH')) {
11
+ \register_activation_hook(WP_FAIL2BAN_FILE, function () {
12
+ foreach (get_mu_plugins() as $plugin => $data) {
13
+ if (0 === strpos($data['Name'], 'WP fail2ban')) {
14
+ $wp_f2b_ver = substr(WP_FAIL2BAN_VER, 0, strrpos(WP_FAIL2BAN_VER, '.'));
15
+ $error_msg = __('<h1>Cannot activate WP fail2ban</h1>', 'wp-fail2ban');
16
+ $mu_file = WPMU_PLUGIN_DIR.'/'.$plugin;
17
+ if (is_link($mu_file)) {
18
+ if (false === ($link = readlink($mu_file)) ||
19
+ false === ($path = realpath($mu_file)))
20
+ {
21
+ $h3 = __('A broken symbolic link was found in <tt>mu-plugins</tt>:');
22
+ $error_msg .= <<<__ERROR__
23
+ <h3>{$h3}</h3>
24
+ <p><tt>{$mu_file}</tt></p>
25
+ __ERROR__;
26
+ } elseif (WP_FAIL2BAN_FILE == $path) {
27
+ // OK, we're linking to ourself
28
+ } else {
29
+ $mu_file = str_replace('/', '/<wbr>', $mu_file);
30
+ $mu_file = substr($mu_file, strlen(WPMU_PLUGIN_DIR)-1);
31
+
32
+ $h3 = __('A conflicting symbolic link was found in <tt>mu-plugins</tt>:');
33
+ $error_msg .= <<<__ERROR__
34
+ <h3>{$h3}</h3>
35
+ <style>
36
+ table { text-align: center; }
37
+ td { width: 50%; }
38
+ th { font-size: 200%; }
39
+ td, th { font-family: monospace; }
40
+ span.tt { font-weight: bold; }
41
+ </style>
42
+ <table>
43
+ <tr>
44
+ <td>{$mu_file}</td>
45
+ <th>&DoubleRightArrow;</th>
46
+ <td>{$link}</td>
47
+ </tr>
48
+ <tr>
49
+ <td colspan="3"><span class="tt">&equiv;</span> <span>{$path}</span></td>
50
+ </tr>
51
+ <tr>
52
+ <td colspan="3"></td>
53
+ </tr>
54
+ </table>
55
+ __ERROR__;
56
+ }
57
+
58
+ } else {
59
+ $mu_file = str_replace('/', '/<wbr>', $mu_file);
60
+ $mu_file = substr($mu_file, strlen(WPMU_PLUGIN_DIR)-1);
61
+
62
+ $h3 = __('A conflicting file was found in <tt>mu-plugins</tt>:');
63
+ $error_msg .= <<<__ERROR__
64
+ <h3>{$h3}</h3>
65
+ <p><tt>{$mu_file}</tt></p>
66
+ __ERROR__;
67
+ }
68
+ $error_msg .= sprintf(
69
+ __('<p>Please see the <a href="%s" target="_blank">documentation</a> for how to configure %s for <tt>mu-plugins</tt>.</p>'),
70
+ "https://docs.wp-fail2ban.com/en/{$wp_f2b_ver}/configuration.html#mu-plugins-support",
71
+ $wpf2b
72
+ );
73
+ $error_msg .= sprintf(__('<p>Click <a href="%s">here</a> to return to the plugins page.</p>'), admin_url('plugins.php'));
74
+
75
+ deactivate_plugins(plugin_basename(WP_FAIL2BAN_FILE));
76
+ wp_die($error_msg);
77
+ }
78
+ }
79
+
80
+ @include_once WP_FAIL2BAN_DIR.'/premium/activation.php';
81
+ });
82
+ }
83
+
lib/constants.php CHANGED
@@ -3,142 +3,120 @@
3
  * Constants
4
  *
5
  * @package wp-fail2ban
6
- * @since 4.2.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
- if (!defined('ABSPATH')) {
11
- exit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  }
13
-
14
- // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
15
- /**
16
- * Defaults
17
- *
18
- * @since 4.0.0
19
- */
20
- define('DEFAULT_WP_FAIL2BAN_OPENLOG_OPTIONS', LOG_PID|LOG_NDELAY);
21
- define('DEFAULT_WP_FAIL2BAN_AUTH_LOG', LOG_AUTH);
22
- define('DEFAULT_WP_FAIL2BAN_COMMENT_LOG', LOG_USER);
23
- define('DEFAULT_WP_FAIL2BAN_PINGBACK_LOG', LOG_USER);
24
- define('DEFAULT_WP_FAIL2BAN_PASSWORD_REQUEST_LOG', LOG_USER);
25
- define('DEFAULT_WP_FAIL2BAN_SPAM_LOG', LOG_AUTH);
26
- /**
27
- * @since 4.0.5
28
- */
29
- define('DEFAULT_WP_FAIL2BAN_COMMENT_EXTRA_LOG', LOG_AUTH);
30
- define('DEFAULT_WP_FAIL2BAN_PINGBACK_ERROR_LOG', LOG_AUTH);
31
- /**
32
- * @since 4.2.0
33
- */
34
- define('DEFAULT_WP_FAIL2BAN_PLUGIN_AUTH_LOG', LOG_AUTH);
35
- define('DEFAULT_WP_FAIL2BAN_PLUGIN_COMMENT_LOG', LOG_USER);
36
- define('DEFAULT_WP_FAIL2BAN_PLUGIN_OTHER_LOG', LOG_USER);
37
- define('DEFAULT_WP_FAIL2BAN_PLUGIN_PASSWORD_LOG', LOG_USER);
38
- define('DEFAULT_WP_FAIL2BAN_PLUGIN_REST_LOG', LOG_USER);
39
- define('DEFAULT_WP_FAIL2BAN_PLUGIN_SPAM_LOG', LOG_AUTH);
40
- define('DEFAULT_WP_FAIL2BAN_PLUGIN_XMLRPC_LOG', LOG_USER);
41
-
42
- /*
43
- 31 | Test
44
- 30 | Plugin
45
- 29 |
46
- 28 |
47
- 27 |
48
- 26 |
49
- 25 |
50
- 24 |
51
- ---
52
- 23 | Event Class
53
- 22 | ..
54
- 21 | ..
55
- 20 | ..
56
- 19 | ..
57
- 18 | ..
58
- 17 | ..
59
- 16 | ..
60
- ---
61
- 15 | ID
62
- 14 | ..
63
- 13 | ..
64
- 12 | ..
65
- 11 | ..
66
- 10 | ..
67
- 09 | ..
68
- 08 | ..
69
- ---
70
- 07 | ..
71
- 06 | ..
72
- 05 | ..
73
- 04 | ..
74
- 03 | ..
75
- 02 | ..
76
- 01 | ..
77
- 00 | ..
78
- */
79
-
80
-
81
-
82
- define('WPF2B_EVENT_CLASS_AUTH', 0x00010000);
83
- define('WPF2B_EVENT_CLASS_COMMENT', 0x00020000);
84
- define('WPF2B_EVENT_CLASS_XMLRPC', 0x00040000);
85
- define('WPF2B_EVENT_CLASS_PASSWORD', 0x00080000);
86
- define('WPF2B_EVENT_CLASS_REST', 0x00100000); /** @since 4.1.0 */
87
- define('WPF2B_EVENT_CLASS_SPAM', 0x00200000); /** @since 4.2.0 */
88
- define('WPF2B_EVENT_TYPE_PLUGIN', 0x40000000); /** @since 4.2.0 */
89
- define('WPF2B_EVENT_TYPE_TEST', 0x80000000); /** @since 4.2.0 */
90
-
91
-
92
- /**
93
- *
94
- */
95
- define('WPF2B_EVENT_ACTIVATED', 0xffffffff);
96
-
97
-
98
- /**
99
- * Auth
100
- */
101
- define('WPF2B_EVENT_AUTH_OK', WPF2B_EVENT_CLASS_AUTH | 0x0001);
102
- define('WPF2B_EVENT_AUTH_FAIL', WPF2B_EVENT_CLASS_AUTH | 0x0002);
103
- define('WPF2B_EVENT_AUTH_BLOCK_USER', WPF2B_EVENT_CLASS_AUTH | 0x0004);
104
- define('WPF2B_EVENT_AUTH_BLOCK_USER_ENUM', WPF2B_EVENT_CLASS_AUTH | 0x0008);
105
-
106
- /**
107
- * Comment
108
- */
109
- define('WPF2B_EVENT_COMMENT', WPF2B_EVENT_CLASS_COMMENT | 0x0001); // 0x00020001
110
- define('WPF2B_EVENT_COMMENT_SPAM', WPF2B_EVENT_CLASS_COMMENT | WPF2B_EVENT_CLASS_SPAM | 0x0001); // 0x00220001
111
- // comment extra
112
- define('WPF2B_EVENT_COMMENT_NOT_FOUND', WPF2B_EVENT_CLASS_COMMENT | 0x0002); // 0x00020002
113
- define('WPF2B_EVENT_COMMENT_CLOSED', WPF2B_EVENT_CLASS_COMMENT | 0x0004); // 0x00020004
114
- define('WPF2B_EVENT_COMMENT_TRASH', WPF2B_EVENT_CLASS_COMMENT | 0x0008); // 0x00020008
115
- define('WPF2B_EVENT_COMMENT_DRAFT', WPF2B_EVENT_CLASS_COMMENT | 0x0010); // 0x00020010
116
- define('WPF2B_EVENT_COMMENT_PASSWORD', WPF2B_EVENT_CLASS_COMMENT | WPF2B_EVENT_CLASS_PASSWORD | 0x0020); // 0x00020020
117
-
118
- /**
119
- * XML-RPC
120
- */
121
- define('WPF2B_EVENT_XMLRPC_PINGBACK', WPF2B_EVENT_CLASS_XMLRPC | 0x0001);
122
- define('WPF2B_EVENT_XMLRPC_PINGBACK_ERROR', WPF2B_EVENT_CLASS_XMLRPC | 0x0002);
123
- define('WPF2B_EVENT_XMLRPC_MULTI_AUTH_FAIL', WPF2B_EVENT_CLASS_XMLRPC | WPF2B_EVENT_CLASS_AUTH | 0x0004);
124
- define('WPF2B_EVENT_XMLRPC_AUTH_OK', WPF2B_EVENT_CLASS_XMLRPC | WPF2B_EVENT_CLASS_AUTH | 0x0008);
125
- define('WPF2B_EVENT_XMLRPC_AUTH_FAIL', WPF2B_EVENT_CLASS_XMLRPC | WPF2B_EVENT_CLASS_AUTH | 0x0010);
126
-
127
- /**
128
- * Password
129
- */
130
- define('WPF2B_ACTION_PASSWORD_REQUEST', WPF2B_EVENT_CLASS_PASSWORD | 0x0001);
131
-
132
- /**
133
- * REST
134
- * @since 4.1.0
135
- */
136
- define('WPF2B_EVENT_REST_AUTH_OK', WPF2B_EVENT_CLASS_REST | WPF2B_EVENT_CLASS_AUTH | 0x0001);
137
- define('WPF2B_EVENT_REST_AUTH_FAIL', WPF2B_EVENT_CLASS_REST | WPF2B_EVENT_CLASS_AUTH | 0x0002);
138
-
139
- /**
140
- *
141
- */
142
- define('WPF2B_EVENT_DEACTIVATED', 0x00000000);
143
- // phpcs:enable
144
 
3
  * Constants
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.2.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ // @codeCoverageIgnoreStart
11
+ if (defined('ABSPATH')) {
12
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
13
+ /*
14
+ 31 | Test
15
+ 30 | Plugin
16
+ 29 |
17
+ 28 |
18
+ 27 |
19
+ 26 |
20
+ 25 |
21
+ 24 |
22
+ ---
23
+ 23 | Event Class
24
+ 22 | ..
25
+ 21 | ..
26
+ 20 | ..
27
+ 19 | ..
28
+ 18 | ..
29
+ 17 | ..
30
+ 16 | ..
31
+ ---
32
+ 15 | ID
33
+ 14 | ..
34
+ 13 | ..
35
+ 12 | ..
36
+ 11 | ..
37
+ 10 | ..
38
+ 09 | ..
39
+ 08 | ..
40
+ ---
41
+ 07 | ..
42
+ 06 | ..
43
+ 05 | ..
44
+ 04 | ..
45
+ 03 | ..
46
+ 02 | ..
47
+ 01 | ..
48
+ 00 | ..
49
+ */
50
+
51
+
52
+
53
+ define('WPF2B_EVENT_CLASS_AUTH', 0x00010000);
54
+ define('WPF2B_EVENT_CLASS_COMMENT', 0x00020000);
55
+ define('WPF2B_EVENT_CLASS_XMLRPC', 0x00040000);
56
+ define('WPF2B_EVENT_CLASS_PASSWORD', 0x00080000);
57
+ define('WPF2B_EVENT_CLASS_REST', 0x00100000); /** @since 4.1.0 */
58
+ define('WPF2B_EVENT_CLASS_SPAM', 0x00200000); /** @since 4.2.0 */
59
+ define('WPF2B_EVENT_CLASS_BLOCK', 0x00400000); /** @since 4.3.0*/
60
+ define('WPF2B_EVENT_TYPE_PLUGIN', 0x40000000); /** @since 4.2.0 */
61
+ define('WPF2B_EVENT_TYPE_TEST', 0x80000000); /** @since 4.2.0 */
62
+
63
+
64
+ /**
65
+ *
66
+ */
67
+ define('WPF2B_EVENT_ACTIVATED', 0xffffffff);
68
+
69
+
70
+ /**
71
+ * Auth
72
+ */
73
+ define('WPF2B_EVENT_AUTH_OK', WPF2B_EVENT_CLASS_AUTH | 0x0001);
74
+ define('WPF2B_EVENT_AUTH_FAIL', WPF2B_EVENT_CLASS_AUTH | 0x0002);
75
+ define('WPF2B_EVENT_AUTH_BLOCK_USER', WPF2B_EVENT_CLASS_AUTH | WPF2B_EVENT_CLASS_BLOCK | 0x0004);
76
+ define('WPF2B_EVENT_AUTH_BLOCK_USER__', WPF2B_EVENT_CLASS_AUTH | 0x0004); /** @deprecated 4.3.0 */
77
+ define('WPF2B_EVENT_AUTH_BLOCK_USER_ENUM', WPF2B_EVENT_CLASS_AUTH | WPF2B_EVENT_CLASS_BLOCK | 0x0008);
78
+ define('WPF2B_EVENT_AUTH_BLOCK_USER_ENUM__', WPF2B_EVENT_CLASS_AUTH | 0x0008); /** @deprecated 4.3.0 */
79
+ define('WPF2B_EVENT_AUTH_EMPTY_USER', WPF2B_EVENT_CLASS_AUTH | 0x0010);
80
+ define('WPF2B_EVENT_AUTH_BLOCK_USERNAME_LOGIN', WPF2B_EVENT_CLASS_AUTH | WPF2B_EVENT_CLASS_BLOCK | 0x0020); /** @since 4.3.0 */
81
+
82
+ /**
83
+ * Comment
84
+ */
85
+ define('WPF2B_EVENT_COMMENT', WPF2B_EVENT_CLASS_COMMENT | 0x0001); // 0x00020001
86
+ define('WPF2B_EVENT_COMMENT_SPAM', WPF2B_EVENT_CLASS_COMMENT | WPF2B_EVENT_CLASS_SPAM | 0x0001); // 0x00220001
87
+ // comment extra
88
+ define('WPF2B_EVENT_COMMENT_NOT_FOUND', WPF2B_EVENT_CLASS_COMMENT | 0x0002); // 0x00020002
89
+ define('WPF2B_EVENT_COMMENT_CLOSED', WPF2B_EVENT_CLASS_COMMENT | 0x0004); // 0x00020004
90
+ define('WPF2B_EVENT_COMMENT_TRASH', WPF2B_EVENT_CLASS_COMMENT | 0x0008); // 0x00020008
91
+ define('WPF2B_EVENT_COMMENT_DRAFT', WPF2B_EVENT_CLASS_COMMENT | 0x0010); // 0x00020010
92
+ define('WPF2B_EVENT_COMMENT_PASSWORD', WPF2B_EVENT_CLASS_COMMENT | WPF2B_EVENT_CLASS_PASSWORD | 0x0020); // 0x000A0020
93
+
94
+ /**
95
+ * XML-RPC
96
+ */
97
+ define('WPF2B_EVENT_XMLRPC_PINGBACK', WPF2B_EVENT_CLASS_XMLRPC | 0x0001);
98
+ define('WPF2B_EVENT_XMLRPC_PINGBACK_ERROR', WPF2B_EVENT_CLASS_XMLRPC | 0x0002);
99
+ define('WPF2B_EVENT_XMLRPC_MULTI_AUTH_FAIL', WPF2B_EVENT_CLASS_XMLRPC | WPF2B_EVENT_CLASS_AUTH | 0x0004);
100
+ define('WPF2B_EVENT_XMLRPC_AUTH_OK', WPF2B_EVENT_CLASS_XMLRPC | WPF2B_EVENT_CLASS_AUTH | 0x0008);
101
+ define('WPF2B_EVENT_XMLRPC_AUTH_FAIL', WPF2B_EVENT_CLASS_XMLRPC | WPF2B_EVENT_CLASS_AUTH | 0x0010);
102
+
103
+ /**
104
+ * Password
105
+ */
106
+ define('WPF2B_EVENT_PASSWORD_REQUEST', WPF2B_EVENT_CLASS_PASSWORD | 0x0001);
107
+
108
+ /**
109
+ * REST
110
+ * @since 4.1.0
111
+ */
112
+ define('WPF2B_EVENT_REST_AUTH_OK', WPF2B_EVENT_CLASS_REST | WPF2B_EVENT_CLASS_AUTH | 0x0001);
113
+ define('WPF2B_EVENT_REST_AUTH_FAIL', WPF2B_EVENT_CLASS_REST | WPF2B_EVENT_CLASS_AUTH | 0x0002);
114
+
115
+ /**
116
+ *
117
+ */
118
+ define('WPF2B_EVENT_DEACTIVATED', 0x00000000);
119
+ // phpcs:enable
120
  }
121
+ // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
lib/convert-data.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Convertors
4
+ *
5
+ * @package wp-fail2ban
6
+ * @since __NEXT_RELEASE
7
+ * @php 5.3
8
+ */
9
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
+
11
+ if (defined('ABSPATH')) { // @codeCoverageIgnore
12
+ /**
13
+ * Convert various things to various other things.
14
+ *
15
+ * @since 4.3.0
16
+ */
17
+ abstract class ConvertData
18
+ {
19
+ /**
20
+ * @var string[] Map Event ID to Slug.
21
+ */
22
+ public static $Event2Slug = array(
23
+ 0x00000000 => 'deactivated',
24
+ WPF2B_EVENT_AUTH_OK => 'auth_ok',
25
+ WPF2B_EVENT_AUTH_FAIL => 'auth_fail',
26
+ WPF2B_EVENT_AUTH_BLOCK_USER => 'auth_block_user',
27
+ WPF2B_EVENT_AUTH_BLOCK_USER_ENUM => 'auth_block_user_enum',
28
+ WPF2B_EVENT_AUTH_BLOCK_USERNAME_LOGIN => 'auth_block_usernames',
29
+ WPF2B_EVENT_AUTH_EMPTY_USER => 'auth_empty_user',
30
+ WPF2B_EVENT_COMMENT => 'comment',
31
+ WPF2B_EVENT_COMMENT_SPAM => 'comment_spam',
32
+ WPF2B_EVENT_COMMENT_NOT_FOUND => 'comment_not_found',
33
+ WPF2B_EVENT_COMMENT_CLOSED => 'comment_closed',
34
+ WPF2B_EVENT_COMMENT_TRASH => 'comment_trash',
35
+ WPF2B_EVENT_COMMENT_DRAFT => 'comment_draft',
36
+ WPF2B_EVENT_COMMENT_PASSWORD => 'comment_password',
37
+ WPF2B_EVENT_XMLRPC_PINGBACK => 'xmlrpc_pingback',
38
+ WPF2B_EVENT_XMLRPC_PINGBACK_ERROR => 'xmlrpc_pingback_error',
39
+ WPF2B_EVENT_XMLRPC_MULTI_AUTH_FAIL => 'xmlrpc_multi_auth_fail',
40
+ WPF2B_EVENT_XMLRPC_AUTH_OK => 'xmlrpc_auth_ok',
41
+ WPF2B_EVENT_XMLRPC_AUTH_FAIL => 'xmlrpc_auth_fail',
42
+ WPF2B_EVENT_PASSWORD_REQUEST => 'password_request',
43
+ WPF2B_EVENT_REST_AUTH_OK => 'rest_auth_ok',
44
+ WPF2B_EVENT_REST_AUTH_FAIL => 'rest_auth_fail',
45
+ 0xFFFFFFFF => 'activated',
46
+ );
47
+
48
+ /**
49
+ * @var int[] Map Event Slug to ID.
50
+ */
51
+ public static $Slug2Event = array(
52
+ 'deactivated' => 0x00000000,
53
+ 'auth_ok' => WPF2B_EVENT_AUTH_OK,
54
+ 'auth_fail' => WPF2B_EVENT_AUTH_FAIL,
55
+ 'auth_block_user' => WPF2B_EVENT_AUTH_BLOCK_USER,
56
+ 'auth_block_user_enum' => WPF2B_EVENT_AUTH_BLOCK_USER_ENUM,
57
+ 'auth_block_usernames' => WPF2B_EVENT_AUTH_BLOCK_USERNAME_LOGIN,
58
+ 'auth_empty_user' => WPF2B_EVENT_AUTH_EMPTY_USER,
59
+ 'comment_spam' => WPF2B_EVENT_COMMENT_SPAM,
60
+ 'comment_not_found' => WPF2B_EVENT_COMMENT_NOT_FOUND,
61
+ 'comment_closed' => WPF2B_EVENT_COMMENT_CLOSED,
62
+ 'comment_trash' => WPF2B_EVENT_COMMENT_TRASH,
63
+ 'comment_draft' => WPF2B_EVENT_COMMENT_DRAFT,
64
+ 'comment_password' => WPF2B_EVENT_COMMENT_PASSWORD,
65
+ 'xmlrpc_pingback' => WPF2B_EVENT_XMLRPC_PINGBACK,
66
+ 'xmlrpc_pingback_error' => WPF2B_EVENT_XMLRPC_PINGBACK_ERROR,
67
+ 'xmlrpc_multi_auth_fail' => WPF2B_EVENT_XMLRPC_MULTI_AUTH_FAIL,
68
+ 'xmlrpc_auth_ok' => WPF2B_EVENT_XMLRPC_AUTH_OK,
69
+ 'xmlrpc_auth_fail' => WPF2B_EVENT_XMLRPC_AUTH_FAIL,
70
+ 'password_request' => WPF2B_EVENT_PASSWORD_REQUEST,
71
+ 'rest_auth_ok' => WPF2B_EVENT_REST_AUTH_OK,
72
+ 'rest_auth_fail' => WPF2B_EVENT_REST_AUTH_FAIL,
73
+ 'activated' => 0xFFFFFFFF,
74
+ );
75
+
76
+ /**
77
+ * @var int[] Map syslog facility name to value.
78
+ */
79
+ public static $FacilityName2Value = array(
80
+ 'LOG_AUTH' => LOG_AUTH,
81
+ 'LOG_AUTHPRIV' => LOG_AUTHPRIV,
82
+ 'LOG_CRON' => LOG_CRON,
83
+ 'LOG_DAEMON' => LOG_DAEMON,
84
+ 'LOG_KERN' => LOG_KERN,
85
+ 'LOG_LOCAL0' => LOG_LOCAL0,
86
+ 'LOG_LOCAL1' => LOG_LOCAL1,
87
+ 'LOG_LOCAL2' => LOG_LOCAL2,
88
+ 'LOG_LOCAL3' => LOG_LOCAL3,
89
+ 'LOG_LOCAL4' => LOG_LOCAL4,
90
+ 'LOG_LOCAL5' => LOG_LOCAL5,
91
+ 'LOG_LOCAL6' => LOG_LOCAL6,
92
+ 'LOG_LOCAL7' => LOG_LOCAL7,
93
+ 'LOG_LPR' => LOG_LPR,
94
+ 'LOG_MAIL' => LOG_MAIL,
95
+ 'LOG_NEWS' => LOG_NEWS,
96
+ 'LOG_SYSLOG' => LOG_SYSLOG,
97
+ 'LOG_USER' => LOG_USER,
98
+ 'LOG_UUCP' => LOG_UUCP,
99
+ );
100
+ }
101
+ } // @codeCoverageIgnore
102
+
lib/defaults.php CHANGED
@@ -1,79 +1,42 @@
1
  <?php
2
  /**
3
- * Default Constants
4
  *
5
  * @package wp-fail2ban
6
- * @since 4.2.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
- if (!defined('ABSPATH')) {
11
- exit;
12
- }
13
-
14
- /**
15
- * Allow custom openlog options.
16
- * e.g. you may not want the PID if logging remotely.
17
- *
18
- * @since 3.6.0 Add LOG_NDELAY
19
- * @since 3.5.0
20
- */
21
- if (!defined('WP_FAIL2BAN_OPENLOG_OPTIONS')) {
22
- define('WP_FAIL2BAN_OPENLOG_OPTIONS', DEFAULT_WP_FAIL2BAN_OPENLOG_OPTIONS);
23
- }
24
- /**
25
- * Make sure all custom logs are defined.
26
- * @since 3.5.0
27
- */
28
- if (!defined('WP_FAIL2BAN_AUTH_LOG')) {
29
- define('WP_FAIL2BAN_AUTH_LOG', DEFAULT_WP_FAIL2BAN_AUTH_LOG);
30
- }
31
- if (!defined('WP_FAIL2BAN_COMMENT_LOG')) {
32
- define('WP_FAIL2BAN_COMMENT_LOG', DEFAULT_WP_FAIL2BAN_COMMENT_LOG);
33
- }
34
- if (!defined('WP_FAIL2BAN_PINGBACK_LOG')) {
35
- define('WP_FAIL2BAN_PINGBACK_LOG', DEFAULT_WP_FAIL2BAN_PINGBACK_LOG);
36
- }
37
- /**
38
- * @since 4.0.0
39
- */
40
- if (!defined('WP_FAIL2BAN_PASSWORD_REQUEST_LOG')) {
41
- define('WP_FAIL2BAN_PASSWORD_REQUEST_LOG', DEFAULT_WP_FAIL2BAN_PASSWORD_REQUEST_LOG);
42
- }
43
- if (!defined('WP_FAIL2BAN_SPAM_LOG')) {
44
- define('WP_FAIL2BAN_SPAM_LOG', DEFAULT_WP_FAIL2BAN_SPAM_LOG);
45
- }
46
- /**
47
- * @since 4.0.5
48
- */
49
- if (!defined('WP_FAIL2BAN_COMMENT_EXTRA_LOG')) {
50
- define('WP_FAIL2BAN_COMMENT_EXTRA_LOG', DEFAULT_WP_FAIL2BAN_COMMENT_EXTRA_LOG);
51
- }
52
- if (!defined('WP_FAIL2BAN_PINGBACK_ERROR_LOG')) {
53
- define('WP_FAIL2BAN_PINGBACK_ERROR_LOG', DEFAULT_WP_FAIL2BAN_PINGBACK_ERROR_LOG);
54
- }
55
- /**
56
- * @since 4.2.0
57
- */
58
- if (!defined('WP_FAIL2BAN_PLUGIN_AUTH_LOG')) {
59
- define('WP_FAIL2BAN_PLUGIN_AUTH_LOG', DEFAULT_WP_FAIL2BAN_PLUGIN_AUTH_LOG);
60
- }
61
- if (!defined('WP_FAIL2BAN_PLUGIN_COMMENT_LOG')) {
62
- define('WP_FAIL2BAN_PLUGIN_COMMENT_LOG', DEFAULT_WP_FAIL2BAN_PLUGIN_COMMENT_LOG);
63
- }
64
- if (!defined('WP_FAIL2BAN_PLUGIN_OTHER_LOG')) {
65
- define('WP_FAIL2BAN_PLUGIN_OTHER_LOG', DEFAULT_WP_FAIL2BAN_PLUGIN_OTHER_LOG);
66
- }
67
- if (!defined('WP_FAIL2BAN_PLUGIN_PASSWORD_LOG')) {
68
- define('WP_FAIL2BAN_PLUGIN_PASSWORD_LOG', DEFAULT_WP_FAIL2BAN_PLUGIN_PASSWORD_LOG);
69
- }
70
- if (!defined('WP_FAIL2BAN_PLUGIN_REST_LOG')) {
71
- define('WP_FAIL2BAN_PLUGIN_REST_LOG', DEFAULT_WP_FAIL2BAN_PLUGIN_REST_LOG);
72
- }
73
- if (!defined('WP_FAIL2BAN_PLUGIN_SPAM_LOG')) {
74
- define('WP_FAIL2BAN_PLUGIN_SPAM_LOG', DEFAULT_WP_FAIL2BAN_PLUGIN_SPAM_LOG);
75
- }
76
- if (!defined('WP_FAIL2BAN_PLUGIN_XMLRPC_LOG')) {
77
- define('WP_FAIL2BAN_PLUGIN_XMLRPC_LOG', DEFAULT_WP_FAIL2BAN_PLUGIN_XMLRPC_LOG);
78
- }
79
 
1
  <?php
2
  /**
3
+ * Defaults
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.3.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ // @codeCoverageIgnoreStart
11
+ if (defined('ABSPATH')) {
12
+ // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
13
+ /**
14
+ * Defaults
15
+ *
16
+ * @since 4.0.0
17
+ */
18
+ define('DEFAULT_WP_FAIL2BAN_OPENLOG_OPTIONS', LOG_PID|LOG_NDELAY);
19
+ define('DEFAULT_WP_FAIL2BAN_AUTH_LOG', LOG_AUTH);
20
+ define('DEFAULT_WP_FAIL2BAN_COMMENT_LOG', LOG_USER);
21
+ define('DEFAULT_WP_FAIL2BAN_PINGBACK_LOG', LOG_USER);
22
+ define('DEFAULT_WP_FAIL2BAN_PASSWORD_REQUEST_LOG', LOG_USER);
23
+ define('DEFAULT_WP_FAIL2BAN_SPAM_LOG', LOG_AUTH);
24
+ /**
25
+ * @since 4.0.5
26
+ */
27
+ define('DEFAULT_WP_FAIL2BAN_COMMENT_EXTRA_LOG', LOG_AUTH);
28
+ define('DEFAULT_WP_FAIL2BAN_PINGBACK_ERROR_LOG', LOG_AUTH);
29
+ /**
30
+ * @since 4.2.0
31
+ */
32
+ define('DEFAULT_WP_FAIL2BAN_PLUGIN_AUTH_LOG', LOG_AUTH);
33
+ define('DEFAULT_WP_FAIL2BAN_PLUGIN_COMMENT_LOG', LOG_USER);
34
+ define('DEFAULT_WP_FAIL2BAN_PLUGIN_OTHER_LOG', LOG_USER);
35
+ define('DEFAULT_WP_FAIL2BAN_PLUGIN_PASSWORD_LOG', LOG_USER);
36
+ define('DEFAULT_WP_FAIL2BAN_PLUGIN_REST_LOG', LOG_USER);
37
+ define('DEFAULT_WP_FAIL2BAN_PLUGIN_SPAM_LOG', LOG_AUTH);
38
+ define('DEFAULT_WP_FAIL2BAN_PLUGIN_XMLRPC_LOG', LOG_USER);
39
+ // phpcs:enable
40
+ }
41
+ // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
lib/loader.php CHANGED
@@ -1,327 +1,466 @@
1
  <?php
2
-
3
  /**
4
  * Loader
5
  *
6
  * @package wp-fail2ban
7
- * @since 4.2.0
 
8
  */
9
- namespace {
10
- if ( !defined( 'ABSPATH' ) ) {
11
- exit;
12
- }
13
- if ( defined( 'PHPUNIT_COMPOSER_INSTALL' ) ) {
14
- return;
15
- }
16
- if ( !function_exists( 'boolval' ) ) {
 
 
 
 
 
 
 
 
 
 
17
  /**
18
- * PHP 5.3 helper
 
 
 
 
 
 
19
  *
20
- * @since 4.2.5
21
  *
22
- * @param mixed $val
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  *
24
- * @return bool
25
  */
26
- function boolval( $val )
27
  {
28
- return (bool) $val;
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  }
30
-
31
- }
32
- }
33
- namespace org\lecklider\charles\wordpress\wp_fail2ban {
34
- /**
35
- * Helper
36
- *
37
- * @since 4.0.0
38
- *
39
- * @param string $define
40
- * @param callable $cast
41
- * @param bool $unset
42
- * @param array $field
43
- */
44
- function _load(
45
- $define,
46
- $cast,
47
- $unset,
48
- array $field
49
- )
50
- {
51
- global $wp_fail2ban ;
52
- $wp_fail2ban['config'][$define] = array(
53
- 'validate' => $cast,
54
- 'unset' => $unset,
55
- 'field' => $field,
56
- 'ndef' => !defined( $define ),
57
- );
58
- if ( !defined( $define ) ) {
59
-
60
- if ( defined( "DEFAULT_{$define}" ) ) {
61
- // we've got a default
62
- define( $define, $cast( constant( "DEFAULT_{$define}" ) ) );
63
- } else {
64
- // bah
65
- define( $define, $cast( false ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
-
68
  }
69
  }
70
-
71
- /**
72
- * Validate IP list
73
- *
74
- * @since 4.0.0
75
- *
76
- * @param array|string $value
77
- *
78
- * @return string
79
- */
80
- function validate_ips( $value )
81
- {
82
- return $value;
83
- }
84
-
85
- // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
86
- _load(
87
- 'WP_FAIL2BAN_AUTH_LOG',
88
- 'intval',
89
- true,
90
- array( 'logging', 'authentication', 'facility' )
91
- );
92
- _load(
93
- 'WP_FAIL2BAN_LOG_COMMENTS',
94
- 'boolval',
95
- true,
96
- array( 'logging', 'comments', 'enabled' )
97
- );
98
- _load(
99
- 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA',
100
- 'intval',
101
- true,
102
- array( 'logging', 'comments', 'extra' )
103
- );
104
- _load(
105
- 'WP_FAIL2BAN_COMMENT_LOG',
106
- 'intval',
107
- false,
108
- array( 'logging', 'comments', 'facility' )
109
- );
110
- _load(
111
- 'WP_FAIL2BAN_COMMENT_EXTRA_LOG',
112
- 'intval',
113
- false,
114
- array( 'logging', 'comments-extra', 'facility' )
115
- );
116
- _load(
117
- 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST',
118
- 'boolval',
119
- true,
120
- array( 'logging', 'password-request', 'enabled' )
121
- );
122
- _load(
123
- 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG',
124
- 'intval',
125
- false,
126
- array( 'logging', 'password-request', 'facility' )
127
- );
128
- _load(
129
- 'WP_FAIL2BAN_LOG_PINGBACKS',
130
- 'boolval',
131
- true,
132
- array( 'logging', 'pingback', 'enabled' )
133
- );
134
- _load(
135
- 'WP_FAIL2BAN_PINGBACK_LOG',
136
- 'intval',
137
- false,
138
- array( 'logging', 'pingback', 'facility' )
139
- );
140
- _load(
141
- 'WP_FAIL2BAN_LOG_SPAM',
142
- 'boolval',
143
- true,
144
- array( 'logging', 'spam', 'enabled' )
145
- );
146
- _load(
147
- 'WP_FAIL2BAN_SPAM_LOG',
148
- 'intval',
149
- false,
150
- array( 'logging', 'spam', 'facility' )
151
- );
152
- _load(
153
- 'WP_FAIL2BAN_OPENLOG_OPTIONS',
154
- 'intval',
155
- true,
156
- array( 'syslog', 'connection' )
157
- );
158
- _load(
159
- 'WP_FAIL2BAN_SYSLOG_SHORT_TAG',
160
- 'boolval',
161
- true,
162
- array( 'syslog', 'workaround', 'short_tag' )
163
- );
164
- _load(
165
- 'WP_FAIL2BAN_HTTP_HOST',
166
- 'boolval',
167
- true,
168
- array( 'syslog', 'workaround', 'http_host' )
169
- );
170
- _load(
171
- 'WP_FAIL2BAN_TRUNCATE_HOST',
172
- 'boolval',
173
- true,
174
- array( 'syslog', 'workaround', 'truncate_host' )
175
- );
176
- _load(
177
- 'WP_FAIL2BAN_BLOCK_USER_ENUMERATION',
178
- 'boolval',
179
- true,
180
- array( 'block', 'user_enumeration' )
181
- );
182
- _load(
183
- 'WP_FAIL2BAN_BLOCKED_USERS',
184
- 'strval',
185
- true,
186
- array( 'block', 'users' )
187
- );
188
- _load(
189
- 'WP_FAIL2BAN_PROXIES',
190
- __NAMESPACE__ . '\\validate_ips',
191
- true,
192
- array( 'remote-ip', 'proxies' )
193
- );
194
- _load(
195
- 'WP_FAIL2BAN_PLUGIN_LOG_AUTH',
196
- 'boolval',
197
- true,
198
- array(
199
- 'logging',
200
- 'plugins',
201
- 'auth',
202
- 'enabled'
203
- )
204
- );
205
- _load(
206
- 'WP_FAIL2BAN_PLUGIN_LOG_COMMENT',
207
- 'boolval',
208
- true,
209
- array(
210
- 'logging',
211
- 'plugins',
212
- 'comment',
213
- 'enabled'
214
- )
215
- );
216
- _load(
217
- 'WP_FAIL2BAN_PLUGIN_LOG_PASSWORD',
218
- 'boolval',
219
- true,
220
- array(
221
- 'logging',
222
- 'plugins',
223
- 'password',
224
- 'enabled'
225
- )
226
- );
227
- _load(
228
- 'WP_FAIL2BAN_PLUGIN_LOG_REST',
229
- 'boolval',
230
- true,
231
- array(
232
- 'logging',
233
- 'plugins',
234
- 'rest',
235
- 'enabled'
236
- )
237
- );
238
- _load(
239
- 'WP_FAIL2BAN_PLUGIN_LOG_SPAM',
240
- 'boolval',
241
- true,
242
- array(
243
- 'logging',
244
- 'plugins',
245
- 'spam',
246
- 'enabled'
247
- )
248
- );
249
- _load(
250
- 'WP_FAIL2BAN_PLUGIN_LOG_XMLRPC',
251
- 'boolval',
252
- true,
253
- array(
254
- 'logging',
255
- 'plugins',
256
- 'xmlrpc',
257
- 'enabled'
258
- )
259
- );
260
- _load(
261
- 'WP_FAIL2BAN_PLUGIN_AUTH_LOG',
262
- 'intval',
263
- false,
264
- array(
265
- 'logging',
266
- 'plugins',
267
- 'auth',
268
- 'facility'
269
- )
270
- );
271
- _load(
272
- 'WP_FAIL2BAN_PLUGIN_COMMENT_LOG',
273
- 'intval',
274
- false,
275
- array(
276
- 'logging',
277
- 'plugins',
278
- 'comment',
279
- 'facility'
280
- )
281
- );
282
- _load(
283
- 'WP_FAIL2BAN_PLUGIN_PASSWORD_LOG',
284
- 'intval',
285
- false,
286
- array(
287
- 'logging',
288
- 'plugins',
289
- 'password',
290
- 'facility'
291
- )
292
- );
293
- _load(
294
- 'WP_FAIL2BAN_PLUGIN_REST_LOG',
295
- 'intval',
296
- false,
297
- array(
298
- 'logging',
299
- 'plugins',
300
- 'rest',
301
- 'facility'
302
- )
303
- );
304
- _load(
305
- 'WP_FAIL2BAN_PLUGIN_SPAM_LOG',
306
- 'intval',
307
- false,
308
- array(
309
- 'logging',
310
- 'plugins',
311
- 'spam',
312
- 'facility'
313
- )
314
- );
315
- _load(
316
- 'WP_FAIL2BAN_PLUGIN_XMLRPC_LOG',
317
- 'intval',
318
- false,
319
- array(
320
- 'logging',
321
- 'plugins',
322
- 'xmlrpc',
323
- 'facility'
324
- )
325
- );
326
- // phpcs:enable
327
- }
1
  <?php
 
2
  /**
3
  * Loader
4
  *
5
  * @package wp-fail2ban
6
+ * @since 4.2.0
7
+ * @php 5.6
8
  */
9
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
+
11
+ if (defined('PHPUNIT_COMPOSER_INSTALL')) {
12
+ return;
13
+
14
+ } elseif (defined('ABSPATH')) {
15
+ /**
16
+ * Config
17
+ *
18
+ * @since 4.2.0
19
+ */
20
+ class Config
21
+ {
22
+ /**
23
+ * @var array Settings
24
+ * @since 4.3.0
25
+ */
26
+ protected static $settings = null;
27
  /**
28
+ * @var Config Instance.
29
+ * @since 4.3.0
30
+ */
31
+ protected static $instance = null;
32
+
33
+ /**
34
+ * Construct
35
  *
36
+ * @since 4.3.0
37
  *
38
+ * @param array $config Existing config options
39
+ */
40
+ public static function load(array $config = [])
41
+ {
42
+ if (is_null(self::$instance)) {
43
+ global $wp_fail2ban;
44
+
45
+ $class = get_called_class();
46
+ self::$instance = new $class();
47
+
48
+ $wp_fail2ban['config'] = apply_filters(
49
+ __METHOD__.'.config',
50
+ array_merge(
51
+ $config,
52
+ array(
53
+ 'WP_FAIL2BAN_AUTH_LOG' => array(
54
+ 'validate' => 'intval',
55
+ 'unset' => true,
56
+ 'field' => array(
57
+ 'logging',
58
+ 'authentication',
59
+ 'facility')),
60
+ 'WP_FAIL2BAN_LOG_COMMENTS' => array(
61
+ 'validate' => 'boolval',
62
+ 'unset' => true,
63
+ 'field' => array(
64
+ 'logging',
65
+ 'comments',
66
+ 'enabled')),
67
+ 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA' => array(
68
+ 'validate' => 'intval',
69
+ 'unset' => true,
70
+ 'field' => array(
71
+ 'logging',
72
+ 'comments',
73
+ 'extra')),
74
+ 'WP_FAIL2BAN_COMMENT_LOG' => array(
75
+ 'validate' => 'intval',
76
+ 'unset' => false,
77
+ 'field' => array(
78
+ 'logging',
79
+ 'comments',
80
+ 'facility')),
81
+ 'WP_FAIL2BAN_COMMENT_EXTRA_LOG' => array(
82
+ 'validate' => 'intval',
83
+ 'unset' => false,
84
+ 'field' => array(
85
+ 'logging',
86
+ 'comments-extra',
87
+ 'facility')),
88
+ 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST' => array(
89
+ 'validate' => 'boolval',
90
+ 'unset' => true,
91
+ 'field' => array(
92
+ 'logging',
93
+ 'password-request',
94
+ 'enabled')),
95
+ 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG' => array(
96
+ 'validate' => 'intval',
97
+ 'unset' => false,
98
+ 'field' => array(
99
+ 'logging',
100
+ 'password-request',
101
+ 'facility')),
102
+ 'WP_FAIL2BAN_LOG_PINGBACKS' => array(
103
+ 'validate' => 'boolval',
104
+ 'unset' => true,
105
+ 'field' => array(
106
+ 'logging',
107
+ 'pingback',
108
+ 'enabled')),
109
+ 'WP_FAIL2BAN_PINGBACK_LOG' => array(
110
+ 'validate' => 'intval',
111
+ 'unset' => false,
112
+ 'field' => array(
113
+ 'logging',
114
+ 'pingback',
115
+ 'facility')),
116
+ 'WP_FAIL2BAN_LOG_SPAM' => array(
117
+ 'validate' => 'boolval',
118
+ 'unset' => true,
119
+ 'field' => array(
120
+ 'logging',
121
+ 'spam',
122
+ 'enabled')),
123
+ 'WP_FAIL2BAN_SPAM_LOG' => array(
124
+ 'validate' => 'intval',
125
+ 'unset' => false,
126
+ 'field' => array(
127
+ 'logging',
128
+ 'spam',
129
+ 'facility')),
130
+
131
+ /**
132
+ * syslog
133
+ */
134
+ 'WP_FAIL2BAN_OPENLOG_OPTIONS' => array(
135
+ 'validate' => 'intval',
136
+ 'unset' => true,
137
+ 'field' => array(
138
+ 'syslog',
139
+ 'connection')),
140
+ 'WP_FAIL2BAN_SYSLOG_SHORT_TAG' => array(
141
+ 'validate' => 'boolval',
142
+ 'unset' => true,
143
+ 'field' => array(
144
+ 'syslog',
145
+ 'workaround',
146
+ 'short_tag')),
147
+ 'WP_FAIL2BAN_HTTP_HOST' => array(
148
+ 'validate' => 'boolval',
149
+ 'unset' => true,
150
+ 'field' => array(
151
+ 'syslog',
152
+ 'workaround',
153
+ 'http_host')),
154
+ 'WP_FAIL2BAN_TRUNCATE_HOST' => array(
155
+ 'validate' => 'boolval',
156
+ 'unset' => true,
157
+ 'field' => array(
158
+ 'syslog',
159
+ 'workaround',
160
+ 'truncate_host')),
161
+
162
+ /**
163
+ * Block
164
+ */
165
+ 'WP_FAIL2BAN_BLOCK_USER_ENUMERATION' => array(
166
+ 'validate' => 'boolval',
167
+ 'unset' => true,
168
+ 'field' => array(
169
+ 'block',
170
+ 'user_enumeration')),
171
+ 'WP_FAIL2BAN_BLOCKED_USERS' => array(
172
+ 'validate' => 'strval',
173
+ 'unset' => true,
174
+ 'field' => array(
175
+ 'block',
176
+ 'users')),
177
+ 'WP_FAIL2BAN_BLOCK_USERNAME_LOGIN' => array(
178
+ 'validate' => 'boolval',
179
+ 'unset' => true,
180
+ 'field' => array(
181
+ 'block',
182
+ 'usernames')),
183
+
184
+ /**
185
+ * Plugins
186
+ */
187
+ 'WP_FAIL2BAN_PLUGIN_LOG_AUTH' => array(
188
+ 'validate' => 'boolval',
189
+ 'unset' => true,
190
+ 'field' => array(
191
+ 'logging',
192
+ 'plugins',
193
+ 'auth',
194
+ 'enabled')),
195
+ 'WP_FAIL2BAN_PLUGIN_LOG_COMMENT' => array(
196
+ 'validate' => 'boolval',
197
+ 'unset' => true,
198
+ 'field' => array(
199
+ 'logging',
200
+ 'plugins',
201
+ 'comment',
202
+ 'enabled')),
203
+ 'WP_FAIL2BAN_PLUGIN_LOG_PASSWORD' => array(
204
+ 'validate' => 'boolval',
205
+ 'unset' => true,
206
+ 'field' => array(
207
+ 'logging',
208
+ 'plugins',
209
+ 'password',
210
+ 'enabled')),
211
+ 'WP_FAIL2BAN_PLUGIN_LOG_REST' => array(
212
+ 'validate' => 'boolval',
213
+ 'unset' => true,
214
+ 'field' => array(
215
+ 'logging',
216
+ 'plugins',
217
+ 'rest',
218
+ 'enabled')),
219
+ 'WP_FAIL2BAN_PLUGIN_LOG_SPAM' => array(
220
+ 'validate' => 'boolval',
221
+ 'unset' => true,
222
+ 'field' => array(
223
+ 'logging',
224
+ 'plugins',
225
+ 'spam',
226
+ 'enabled')),
227
+ 'WP_FAIL2BAN_PLUGIN_LOG_XMLRPC' => array(
228
+ 'validate' => 'boolval',
229
+ 'unset' => true,
230
+ 'field' => array(
231
+ 'logging',
232
+ 'plugins',
233
+ 'xmlrpc',
234
+ 'enabled')),
235
+ 'WP_FAIL2BAN_PLUGIN_AUTH_LOG' => array(
236
+ 'validate' => 'intval',
237
+ 'unset' => false,
238
+ 'field' => array(
239
+ 'logging',
240
+ 'plugins',
241
+ 'auth',
242
+ 'facility')),
243
+ 'WP_FAIL2BAN_PLUGIN_COMMENT_LOG' => array(
244
+ 'validate' => 'intval',
245
+ 'unset' => false,
246
+ 'field' => array(
247
+ 'logging',
248
+ 'plugins',
249
+ 'comment',
250
+ 'facility')),
251
+ 'WP_FAIL2BAN_PLUGIN_PASSWORD_LOG' => array(
252
+ 'validate' => 'intval',
253
+ 'unset' => false,
254
+ 'field' => array(
255
+ 'logging',
256
+ 'plugins',
257
+ 'password',
258
+ 'facility')),
259
+ 'WP_FAIL2BAN_PLUGIN_REST_LOG' => array(
260
+ 'validate' => 'intval',
261
+ 'unset' => false,
262
+ 'field' => array(
263
+ 'logging',
264
+ 'plugins',
265
+ 'rest',
266
+ 'facility')),
267
+ 'WP_FAIL2BAN_PLUGIN_SPAM_LOG' => array(
268
+ 'validate' => 'intval',
269
+ 'unset' => false,
270
+ 'field' => array(
271
+ 'logging',
272
+ 'plugins',
273
+ 'spam',
274
+ 'facility')),
275
+ 'WP_FAIL2BAN_PLUGIN_XMLRPC_LOG' => array(
276
+ 'validate' => 'intval',
277
+ 'unset' => false,
278
+ 'field' => array(
279
+ 'logging',
280
+ 'plugins',
281
+ 'xmlrpc',
282
+ 'facility')),
283
+
284
+ 'WP_FAIL2BAN_PROXIES' => array(
285
+ 'validate' => __CLASS__.'::validate_ips',
286
+ 'unset' => true,
287
+ 'field' => array(
288
+ 'remote-ip',
289
+ 'proxies')),
290
+ )
291
+ )
292
+ );
293
+
294
+ static::init();
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Static initialiser
300
  *
301
+ * @since 4.3.0
302
  */
303
+ protected static function init()
304
  {
305
+ global $wp_fail2ban;
306
+
307
+ self::$settings = array();
308
+
309
+ foreach ($wp_fail2ban['config'] as $define => $args) {
310
+ if ($wp_fail2ban['config'][$define]['ndef'] = !defined($define)) {
311
+ if (defined("DEFAULT_{$define}")) {
312
+ define($define, $args['validate'](constant("DEFAULT_{$define}")));
313
+ } else {
314
+ // bah
315
+ define($define, call_user_func($args['validate'], false));
316
+ }
317
+ }
318
+ }
319
  }
320
+
321
+ /**
322
+ * Validate IP list.
323
+ *
324
+ * @since 4.3.0 Refactored
325
+ * @since 4.0.0
326
+ *
327
+ * @param array|string $value
328
+ * @return string
329
+ */
330
+ public static function validate_ips($value)
331
+ {
332
+ return self::$instance->validateIPs($value);
333
+ }
334
+
335
+ /**
336
+ * Pretend to validate IPs.
337
+ *
338
+ * @see premium\Config\validateIPs()
339
+ */
340
+ public function validateIPs($value)
341
+ {
342
+ return (false === $value) ? '' : $value;
343
+ }
344
+
345
+ /**
346
+ * Helper: filtered get_site_option('wp-fail2ban')
347
+ *
348
+ * @since 4.3.0
349
+ *
350
+ * @param bool $filter
351
+ * @return array
352
+ */
353
+ public static function settings($filter = true)
354
+ {
355
+ return self::$instance->getSettings($filter);
356
+ }
357
+
358
+ public function getSettings($filter = true)
359
+ {
360
+ return self::$settings;
361
+ }
362
+
363
+ // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
364
+ /**
365
+ * Helper: default value
366
+ *
367
+ * @since 4.3.0
368
+ *
369
+ * @param string $define
370
+ * @return mixed
371
+ */
372
+ public static function get_default($define)
373
+ {
374
+ $const = "DEFAULT_{$define}";
375
+
376
+ return (defined($const))
377
+ ? constant($const)
378
+ : null;
379
+ }
380
+ // phpcs:enable
381
+
382
+ /**
383
+ * Help:er: is defined?
384
+ *
385
+ * @since 4.3.0
386
+ *
387
+ * @param string $define Constant name
388
+ * @return bool Is defined?
389
+ */
390
+ public static function def($define)
391
+ {
392
+ return !self::ndef($define);
393
+ }
394
+
395
+ /**
396
+ * Helper: is not defined?
397
+ *
398
+ * @since 4.3.0
399
+ *
400
+ * @param string $define Constant name
401
+ * @return bool Is not defined?
402
+ */
403
+ public static function ndef($define)
404
+ {
405
+ return self::$instance->getNdef($define);
406
+ }
407
+
408
+ public function getNdef($define)
409
+ {
410
+ global $wp_fail2ban;
411
+
412
+ return @$wp_fail2ban['config'][$define]['ndef'];
413
+ }
414
+
415
+ /**
416
+ * Helper: get value
417
+ *
418
+ * @since 4.3.0
419
+ *
420
+ * @param string $define Constant name
421
+ * @param array $settings Premium: settings to use
422
+ * @return mixed Constant value
423
+ */
424
+ public static function get($define, array $settings = null)
425
+ {
426
+ return self::$instance->getter($define, $settings);
427
+ }
428
+
429
+ public function getter($define, array $settings = null)
430
+ {
431
+ return (defined($define)) ? constant($define) : null;
432
+ }
433
+
434
+ /**
435
+ * Helper: get description
436
+ *
437
+ * @since 4.3.0
438
+ *
439
+ * @param string $define Constant name.
440
+ * @return string|null Description.
441
+ */
442
+ public static function desc($define)
443
+ {
444
+ return self::$instance->getDesc($define);
445
+ }
446
+
447
+ public function getDesc($define)
448
+ {
449
+ switch ($define) {
450
+ case 'WP_FAIL2BAN_AUTH_LOG':
451
+ return __('Logins and attempted logins.', 'wp-fail2ban');
452
+ case 'WP_FAIL2BAN_LOG_SPAM':
453
+ return __('Log comments marked as spam.', 'wp-fail2ban');
454
+ case 'WP_FAIL2BAN_BLOCK_USER_ENUMERATION':
455
+ return __('Stop attackers listing existing usernames.', 'wp-fail2ban');
456
+ case 'WP_FAIL2BAN_BLOCK_USERNAME_LOGIN':
457
+ return __('Allow <b>email addresses only</b> for login.', 'wp-fail2ban');
458
+ case 'WP_FAIL2BAN_PROXIES':
459
+ return __('Trusted IPv4 list.', 'wp-fail2ban');
460
+ default:
461
+ return null;
462
  }
 
463
  }
464
  }
465
+ }
466
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -1,13 +1,13 @@
1
  === WP fail2ban ===
2
  Contributors: invisnet
3
  Donate link: https://paypal.me/invisnet/
4
- Author URI: https://charles.lecklider.org/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8
5
- Plugin URI: https://wp-fail2ban.com/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8
6
  Tags: fail2ban, login, security, syslog, brute force, protection, classicpress
7
  Requires at least: 4.2
8
  Tested up to: 5.4
9
- Stable tag: 4.2.8
10
- Requires PHP: 5.3
11
  License: GPLv2 or later
12
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
13
 
@@ -15,7 +15,7 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
15
 
16
  == Description ==
17
 
18
- [fail2ban](http://www.fail2ban.org/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) is one of the simplest and most effective security measures you can implement to prevent brute-force attacks.
19
 
20
  *WP fail2ban* logs all login attempts - including via XML-RPC, whether successful or not, to syslog using LOG_AUTH. For example:
21
 
@@ -26,56 +26,59 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
26
 
27
  = Features =
28
 
29
- * **NEW - Remote Tools Add-on**
30
- The Remote Tools add-on provides extra features without adding bloat to the core plugin. For more details see the [add-on page](https://wp-fail2ban.com/add-ons/remote-tools/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
31
 
32
- **NB:** Requires PHP >= 5.6
 
33
 
34
- * **NEW - Support for 3rd-party Plugins**
 
 
 
35
  Version 4.2 introduces a simple API for authors to integrate their plugins with *WPf2b*, with 2 *experimental* add-ons:
36
  * [Contact Form 7](https://wordpress.org/plugins/wp-fail2ban-addon-contact-form-7/)
37
  * [Gravity Forms](https://wordpress.org/plugins/wp-fail2ban-addon-gravity-forms/)
38
 
39
- **NB:** Requires PHP >= 5.6
40
-
41
  * **CloudFlare and Proxy Servers**
42
- *WPf2b* can be configured to work with CloudFlare and other proxy servers. For an overview see [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wp-fail2ban-proxies).
43
 
44
  * **Comments**
45
- *WPf2b* can log comments (see [`WP_FAIL2BAN_LOG_COMMENTS`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wp-fail2ban-log-comments)) and attempted comments (see [`WP_FAIL2BAN_LOG_COMMENTS_EXTRA`](https://docs.wp-fail2ban.com/en/4.2/defines.html#wp-fail2ban-log-comments-extra)).
46
 
47
  * **Pingbacks**
48
- *WPf2b* logs failed pingbacks, and can log all pingbacks. For an overview see [`WP_FAIL2BAN_LOG_PINGBACKS`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wp-fail2ban-log-pingbacks).
49
 
50
  * **Spam**
51
- *WPf2b* can log comments marked as spam. See [`WP_FAIL2BAN_LOG_SPAM`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wp-fail2ban-log-spam).
52
 
53
  * **Block User Enumeration**
54
- *WPf2b* can block user enumeration. See [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wp-fail2ban-block-user-enumeration).
55
 
56
  * **Work-Arounds for Broken syslogd**
57
- *WPf2b* can be configured to work around most syslogd weirdness. For an overview see [`WP_FAIL2BAN_SYSLOG_SHORT_TAG`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wp-fail2ban-syslog-short-tag) and [`WP_FAIL2BAN_HTTP_HOST`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wp-fail2ban-http-host).
58
 
59
  * **Blocking Users**
60
- *WPf2b* can be configured to short-cut the login process when the username matches a regex. For an overview see [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wp-fail2ban-blocked-users).
61
 
62
  * **`mu-plugins` Support**
63
- *WPf2b* can easily be configured as a must-use plugin - see [Configuration](https://docs.wp-fail2ban.com/en/4.2/configuration.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#mu-plugins-support).
64
 
65
  == Installation ==
66
 
67
  1. Install via the Plugin Directory, or upload to your plugins directory.
68
  1. Activate the plugin through the 'Plugins' menu in WordPress.
69
- 1. Edit `wp-config.php` to suit your needs - see [Configuration](https://docs.wp-fail2ban.com/en/4.2/configuration.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
70
 
71
  == Changelog ==
72
 
73
- = 4.2.8 =
74
- * Add link to new [support forum](https://forums.invis.net/c/wp-fail2ban/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
75
- * Fix user enumeration conflict with Gutenberg (h/t @dinghy).
76
- * Fix notices wrt admin menu (h/t @marioivangf).
77
- * Fix harmless XDebug notice (h/t @dinghy).
78
- * Update Freemius library.
 
79
 
80
  = 4.2.7.1 =
81
  * Fix error when blocking user enumeration via `oembed` (h/t @wordpressfab).
@@ -85,7 +88,7 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
85
  * Fix buttons on Settings tabs.
86
 
87
  = 4.2.6 =
88
- * Add support for [Remote Tools](https://wp-fail2ban.com/add-ons/remote-tools/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) add-on.
89
  * Add support for the new ClassicPress security page.
90
  * Improved user enumeration blocking.
91
 
@@ -111,8 +114,8 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
111
  * Fix 5.3 compatibility.
112
 
113
  = 4.2.1 =
114
- * Completed support for [`WP_FAIL2BAN_COMMENT_EXTRA_LOG`](https://docs.wp-fail2ban.com/en/4.2/defines/WP_FAIL2BAN_COMMENT_EXTRA_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
115
- * Add support for 3rd-party plugins; see [Developers](https://docs.wp-fail2ban.com/en/4.2/developers.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
116
  * Add-on for [Contact Form 7](https://wordpress.org/plugins/wp-fail2ban-addon-contact-form-7/) (experimental).
117
  * Add-on for [Gravity Forms](https://wordpress.org/plugins/wp-fail2ban-addon-gravity-forms/) (experimental).
118
  * Change logging for known-user with incorrect password; previously logged as unknown user and matched by `hard` filters (due to limitations in older versions of WordPress), now logged as known user and matched by `soft`.
@@ -124,11 +127,11 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
124
 
125
  = 4.1.0 =
126
  * Add separate logging for REST authentication.
127
- * Fix conflict with earlier versions pre-installed in `mu-plugins`. See [Is *WPf2b* Already Installed?](https://docs.wp-fail2ban.com/en/4.1/installation.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#is-wp-fail2ban-already-installed).
128
 
129
  = 4.0.5 =
130
- * Add [`WP_FAIL2BAN_COMMENT_EXTRA_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_COMMENT_EXTRA_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
131
- * Add [`WP_FAIL2BAN_PINGBACK_ERROR_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PINGBACK_ERROR_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) (future functionality).
132
  * Change `WP_FAIL2BAN_LOG_SPAM` to use `LOG_NOTICE`.
133
  * Change `WP_FAIL2BAN_SPAM_LOG` to `LOG_AUTH`.
134
  * Change `WP_FAIL2BAN_LOG_COMMENTS_EXTRA` events to use `LOG_NOTICE` by default.
@@ -142,9 +145,9 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
142
  = 4.0.1 =
143
  * Add extra features via Freemius. **This is entirely optional.** *WPf2b* works as before, including new features listed here.
144
  * Add settings summary page (Settings -> WP fail2ban).
145
- * Add [`WP_FAIL2BAN_PASSWORD_REQUEST_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PASSWORD_REQUEST_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
146
- * Add [`WP_FAIL2BAN_SPAM_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_SPAM_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
147
- * Add [`WP_FAIL2BAN_LOG_COMMENTS_EXTRA`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_COMMENTS_EXTRA.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) - enable logging for attempted comments on posts which are:
148
  * not found,
149
  * closed for commenting,
150
  * in the trash,
@@ -156,70 +159,70 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
156
  * Not released.
157
 
158
  = 3.6.0 =
159
- * The [filter files](https://docs.wp-fail2ban.com/en/4.1/filters.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) are now generated from PHPDoc in the code. There were too many times when the filters were out of sync with the code (programmer error) - this should resolve that by bringing the patterns closer to the code that emits them.
160
- * Added [PHPUnit tests](https://docs.wp-fail2ban.com/en/4.1/tests.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8). Almost 100% code coverage, with the exception of [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html) which is quite hard to test properly.
161
- * Bugfix for [`wordpress-soft.conf`](https://docs.wp-fail2ban.com/en/4.1/filters.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wordpress-soft-conf).
162
- * Add [`WP_FAIL2BAN_XMLRPC_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_XMLRPC_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
163
- * Add [`WP_FAIL2BAN_REMOTE_ADDR`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_REMOTE_ADDR.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
164
- * [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) now supports an array of IPs with PHP 7.
165
- * Moved all documentation to [https://docs.wp-fail2ban.com/](https://docs.wp-fail2ban.com/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
166
 
167
  = 3.5.3 =
168
- * Bugfix for [`wordpress-hard.conf`](https://docs.wp-fail2ban.com/en/4.1/filters.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8#wordpress-hard-conf).
169
 
170
  = 3.5.1 =
171
- * Bugfix for [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCK_USER_ENUMERATION.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
172
 
173
  = 3.5.0 =
174
- * Add [`WP_FAIL2BAN_OPENLOG_OPTIONS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_OPENLOG_OPTIONS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
175
- * Add [`WP_FAIL2BAN_LOG_COMMENTS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_COMMENTS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) and [`WP_FAIL2BAN_COMMENT_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_COMMENT_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
176
- * Add [`WP_FAIL2BAN_LOG_PASSWORD_REQUEST`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_PASSWORD_REQUEST.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
177
- * Add [`WP_FAIL2BAN_LOG_SPAM`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_SPAM.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
178
- * Add [`WP_FAIL2BAN_TRUNCATE_HOST`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_TRUNCATE_HOST.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
179
- * [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCKED_USERS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) now supports an array of users with PHP 7.
180
 
181
  = 3.0.3 =
182
- * Fix regex in [`wordpress-hard.conf`](https://docs.wp-fail2ban.com/en/4.1/filters.html#wordpress-hard-conf?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
183
 
184
  = 3.0.2 =
185
  * Prevent double logging in WP 4.5.x for XML-RPC authentication failure
186
 
187
  = 3.0.1 =
188
- * Fix regex in [`wordpress-hard.conf`](https://docs.wp-fail2ban.com/en/4.1/filters.html#wordpress-hard-conf?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
189
 
190
  = 3.0.0 =
191
- * Add [`WP_FAIL2BAN_SYSLOG_SHORT_TAG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_SYSLOG_SHORT_TAG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
192
- * Add [`WP_FAIL2BAN_HTTP_HOST`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_HTTP_HOST.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
193
  * Log XML-RPC authentication failure.
194
  * Add better support for MU deployment.
195
 
196
  = 2.3.2 =
197
- * Bugfix [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCKED_USERS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
198
 
199
  = 2.3.0 =
200
- * Bugfix in *experimental* [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) code (thanks to KyleCartmell).
201
 
202
  = 2.2.1 =
203
- * Fix stupid mistake with [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCKED_USERS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
204
 
205
  = 2.2.0 =
206
- * Custom authentication log is now called [`WP_FAIL2BAN_AUTH_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_AUTH_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
207
- * Add logging for pingbacks; see [`WP_FAIL2BAN_LOG_PINGBACKS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_PINGBACKS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
208
- * Custom pingback log is called [`WP_FAIL2BAN_PINGBACK_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PINGBACK_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
209
 
210
  = 2.1.1 =
211
  * Minor bugfix.
212
 
213
  = 2.1.0 =
214
- * Add support for blocking user enumeration; see [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCK_USER_ENUMERATION.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
215
- * Add support for CIDR notation in [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
216
 
217
  = 2.0.1 =
218
- * Bugfix in *experimental* [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) code.
219
 
220
  = 2.0.0 =
221
- * Add *experimental* support for X-Forwarded-For header; see [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
222
- * Add *experimental* support for regex-based login blocking; see [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCKED_USERS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
223
 
224
  = 1.2.1 =
225
  * Update FAQ.
@@ -235,8 +238,8 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
235
 
236
  == Upgrade Notice ==
237
 
238
- = 4.2.8 =
239
- This is a bugfix release. You do not need to update your filters from 4.1.0. This is the *last* release that supports PHP 5.3.
240
 
241
  = 4.2.7.1 =
242
  This is a bugfix release. You do not need to update your filters from 4.1.0.
@@ -290,7 +293,7 @@ You will need up update your `fail2ban` filters.
290
  You will need up update your `fail2ban` filters.
291
 
292
  = 3.5.1 =
293
- Bugfix: disable [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCK_USER_ENUMERATION.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8) in admin area....
294
 
295
  = 3.5.0 =
296
  You will need up update your `fail2ban` filters.
@@ -302,13 +305,13 @@ You will need up update your `fail2ban` filters.
302
  BREAKING CHANGE: The `fail2ban` filters have been split into two files. You will need up update your `fail2ban` configuration.
303
 
304
  = 2.3.0 =
305
- Fix for [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8); if you're not using it you can safely skip this release.
306
 
307
  = 2.2.1 =
308
  Bugfix.
309
 
310
  = 2.2.0 =
311
- BREAKING CHANGE: `WP_FAIL2BAN_LOG` has been renamed to [`WP_FAIL2BAN_AUTH_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_AUTH_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.2.8).
312
 
313
  Pingbacks are getting a lot of attention recently, so *WPf2b* can now log them.
314
  The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
@@ -321,3 +324,5 @@ Bugfix in experimental code; still an experimental release.
321
 
322
  = 2.0.0 =
323
  This is an experimental release. If your current version is working and you're not interested in the new features, skip this version - wait for 2.1.0. For those that do want to test this release, note that `wordpress.conf` has changed - you'll need to copy it to `fail2ban/filters.d` again.
 
 
1
  === WP fail2ban ===
2
  Contributors: invisnet
3
  Donate link: https://paypal.me/invisnet/
4
+ Author URI: https://charles.lecklider.org/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0
5
+ Plugin URI: https://wp-fail2ban.com/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0
6
  Tags: fail2ban, login, security, syslog, brute force, protection, classicpress
7
  Requires at least: 4.2
8
  Tested up to: 5.4
9
+ Stable tag: 4.3.0-RC4
10
+ Requires PHP: 5.6
11
  License: GPLv2 or later
12
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
13
 
15
 
16
  == Description ==
17
 
18
+ [fail2ban](http://www.fail2ban.org/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) is one of the simplest and most effective security measures you can implement to prevent brute-force attacks.
19
 
20
  *WP fail2ban* logs all login attempts - including via XML-RPC, whether successful or not, to syslog using LOG_AUTH. For example:
21
 
26
 
27
  = Features =
28
 
29
+ * **NEW - Multisite Support**
30
+ Version 4.3 introduces [proper support for multisite networks](https://wp-fail2ban.com/features/multisite-networks/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
31
 
32
+ * **NEW** - Block username logins**
33
+ It is sometimes not possible to block user enumeration (for example, if your theme provides Author profiles). Version 4.3 adds support for requiring the use of email addresses for login.
34
 
35
+ * **Remote Tools Add-on**
36
+ The Remote Tools add-on provides extra features without adding bloat to the core plugin. For more details see the [add-on page](https://wp-fail2ban.com/add-ons/remote-tools/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
37
+
38
+ * **Support for 3rd-party Plugins**
39
  Version 4.2 introduces a simple API for authors to integrate their plugins with *WPf2b*, with 2 *experimental* add-ons:
40
  * [Contact Form 7](https://wordpress.org/plugins/wp-fail2ban-addon-contact-form-7/)
41
  * [Gravity Forms](https://wordpress.org/plugins/wp-fail2ban-addon-gravity-forms/)
42
 
 
 
43
  * **CloudFlare and Proxy Servers**
44
+ *WPf2b* can be configured to work with [CloudFlare and other proxy servers](https://wp-fail2ban.com/features/cloudflare-and-proxy-servers/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
45
 
46
  * **Comments**
47
+ *WPf2b* can log comments (see [`WP_FAIL2BAN_LOG_COMMENTS`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wp-fail2ban-log-comments)) and attempted comments (see [`WP_FAIL2BAN_LOG_COMMENTS_EXTRA`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wp-fail2ban-log-comments-extra)).
48
 
49
  * **Pingbacks**
50
+ *WPf2b* logs failed pingbacks, and can log all pingbacks. For an overview see [`WP_FAIL2BAN_LOG_PINGBACKS`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wp-fail2ban-log-pingbacks).
51
 
52
  * **Spam**
53
+ *WPf2b* can log comments marked as spam. See [`WP_FAIL2BAN_LOG_SPAM`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wp-fail2ban-log-spam).
54
 
55
  * **Block User Enumeration**
56
+ *WPf2b* can [block user enumeration](https://wp-fail2ban.com/features/block-user-enumeration/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
57
 
58
  * **Work-Arounds for Broken syslogd**
59
+ *WPf2b* can be configured to work around most syslogd weirdness. For an overview see [`WP_FAIL2BAN_SYSLOG_SHORT_TAG`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wp-fail2ban-syslog-short-tag) and [`WP_FAIL2BAN_HTTP_HOST`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wp-fail2ban-http-host).
60
 
61
  * **Blocking Users**
62
+ *WPf2b* can be configured to short-cut the login process when the username matches a regex. For an overview see [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.2/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wp-fail2ban-blocked-users).
63
 
64
  * **`mu-plugins` Support**
65
+ *WPf2b* can easily be configured as a must-use plugin - see [Configuration](https://docs.wp-fail2ban.com/en/4.2/configuration.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#mu-plugins-support).
66
 
67
  == Installation ==
68
 
69
  1. Install via the Plugin Directory, or upload to your plugins directory.
70
  1. Activate the plugin through the 'Plugins' menu in WordPress.
71
+ 1. Edit `wp-config.php` to suit your needs - see [Configuration](https://docs.wp-fail2ban.com/en/4.2/configuration.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
72
 
73
  == Changelog ==
74
 
75
+ = 4.3.0 "Columbo" =
76
+ * Add full multisite support.
77
+ * Add separate logging for login attemtps with empty username.
78
+ * Improve user enumeration blocking compatibility with the WordPress block editor (Gutenberg).
79
+ * Log extra information for events (premium).
80
+ * Add new event class for blocked actions (premium).
81
+ * Bump the minimum PHP version to 5.6.
82
 
83
  = 4.2.7.1 =
84
  * Fix error when blocking user enumeration via `oembed` (h/t @wordpressfab).
88
  * Fix buttons on Settings tabs.
89
 
90
  = 4.2.6 =
91
+ * Add support for [Remote Tools](https://wp-fail2ban.com/add-ons/remote-tools/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) add-on.
92
  * Add support for the new ClassicPress security page.
93
  * Improved user enumeration blocking.
94
 
114
  * Fix 5.3 compatibility.
115
 
116
  = 4.2.1 =
117
+ * Completed support for [`WP_FAIL2BAN_COMMENT_EXTRA_LOG`](https://docs.wp-fail2ban.com/en/4.2/defines/WP_FAIL2BAN_COMMENT_EXTRA_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
118
+ * Add support for 3rd-party plugins; see [Developers](https://docs.wp-fail2ban.com/en/4.2/developers.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
119
  * Add-on for [Contact Form 7](https://wordpress.org/plugins/wp-fail2ban-addon-contact-form-7/) (experimental).
120
  * Add-on for [Gravity Forms](https://wordpress.org/plugins/wp-fail2ban-addon-gravity-forms/) (experimental).
121
  * Change logging for known-user with incorrect password; previously logged as unknown user and matched by `hard` filters (due to limitations in older versions of WordPress), now logged as known user and matched by `soft`.
127
 
128
  = 4.1.0 =
129
  * Add separate logging for REST authentication.
130
+ * Fix conflict with earlier versions pre-installed in `mu-plugins`. See [Is *WPf2b* Already Installed?](https://docs.wp-fail2ban.com/en/4.1/installation.html#is-wp-fail2ban-already-installed?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
131
 
132
  = 4.0.5 =
133
+ * Add [`WP_FAIL2BAN_COMMENT_EXTRA_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_COMMENT_EXTRA_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
134
+ * Add [`WP_FAIL2BAN_PINGBACK_ERROR_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PINGBACK_ERROR_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) (future functionality).
135
  * Change `WP_FAIL2BAN_LOG_SPAM` to use `LOG_NOTICE`.
136
  * Change `WP_FAIL2BAN_SPAM_LOG` to `LOG_AUTH`.
137
  * Change `WP_FAIL2BAN_LOG_COMMENTS_EXTRA` events to use `LOG_NOTICE` by default.
145
  = 4.0.1 =
146
  * Add extra features via Freemius. **This is entirely optional.** *WPf2b* works as before, including new features listed here.
147
  * Add settings summary page (Settings -> WP fail2ban).
148
+ * Add [`WP_FAIL2BAN_PASSWORD_REQUEST_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PASSWORD_REQUEST_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
149
+ * Add [`WP_FAIL2BAN_SPAM_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_SPAM_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
150
+ * Add [`WP_FAIL2BAN_LOG_COMMENTS_EXTRA`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_COMMENTS_EXTRA.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) - enable logging for attempted comments on posts which are:
151
  * not found,
152
  * closed for commenting,
153
  * in the trash,
159
  * Not released.
160
 
161
  = 3.6.0 =
162
+ * The [filter files](https://docs.wp-fail2ban.com/en/4.1/filters.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) are now generated from PHPDoc in the code. There were too many times when the filters were out of sync with the code (programmer error) - this should resolve that by bringing the patterns closer to the code that emits them.
163
+ * Added [PHPUnit tests](https://docs.wp-fail2ban.com/en/4.1/tests.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0). Almost 100% code coverage, with the exception of [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) which is quite hard to test properly.
164
+ * Bugfix for [`wordpress-soft.conf`](https://docs.wp-fail2ban.com/en/4.1/filters.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wordpress-soft-conf).
165
+ * Add [`WP_FAIL2BAN_XMLRPC_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_XMLRPC_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
166
+ * Add [`WP_FAIL2BAN_REMOTE_ADDR`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_REMOTE_ADDR.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
167
+ * [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) now supports an array of IPs with PHP 7.
168
+ * Moved all documentation to [https://docs.wp-fail2ban.com/](https://docs.wp-fail2ban.com/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
169
 
170
  = 3.5.3 =
171
+ * Bugfix for [`wordpress-hard.conf`](https://docs.wp-fail2ban.com/en/4.1/filters.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wordpress-hard-conf).
172
 
173
  = 3.5.1 =
174
+ * Bugfix for [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCK_USER_ENUMERATION.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
175
 
176
  = 3.5.0 =
177
+ * Add [`WP_FAIL2BAN_OPENLOG_OPTIONS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_OPENLOG_OPTIONS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
178
+ * Add [`WP_FAIL2BAN_LOG_COMMENTS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_COMMENTS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) and [`WP_FAIL2BAN_COMMENT_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_COMMENT_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
179
+ * Add [`WP_FAIL2BAN_LOG_PASSWORD_REQUEST`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_PASSWORD_REQUEST.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
180
+ * Add [`WP_FAIL2BAN_LOG_SPAM`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_SPAM.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
181
+ * Add [`WP_FAIL2BAN_TRUNCATE_HOST`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_TRUNCATE_HOST.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
182
+ * [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCKED_USERS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) now supports an array of users with PHP 7.
183
 
184
  = 3.0.3 =
185
+ * Fix regex in [`wordpress-hard.conf`](https://docs.wp-fail2ban.com/en/4.1/filters.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wordpress-hard-conf).
186
 
187
  = 3.0.2 =
188
  * Prevent double logging in WP 4.5.x for XML-RPC authentication failure
189
 
190
  = 3.0.1 =
191
+ * Fix regex in [`wordpress-hard.conf`](https://docs.wp-fail2ban.com/en/4.1/filters.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0#wordpress-hard-conf).
192
 
193
  = 3.0.0 =
194
+ * Add [`WP_FAIL2BAN_SYSLOG_SHORT_TAG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_SYSLOG_SHORT_TAG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
195
+ * Add [`WP_FAIL2BAN_HTTP_HOST`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_HTTP_HOST.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
196
  * Log XML-RPC authentication failure.
197
  * Add better support for MU deployment.
198
 
199
  = 2.3.2 =
200
+ * Bugfix [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCKED_USERS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
201
 
202
  = 2.3.0 =
203
+ * Bugfix in *experimental* [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) code (thanks to KyleCartmell).
204
 
205
  = 2.2.1 =
206
+ * Fix stupid mistake with [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCKED_USERS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
207
 
208
  = 2.2.0 =
209
+ * Custom authentication log is now called [`WP_FAIL2BAN_AUTH_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_AUTH_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
210
+ * Add logging for pingbacks; see [`WP_FAIL2BAN_LOG_PINGBACKS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_LOG_PINGBACKS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
211
+ * Custom pingback log is called [`WP_FAIL2BAN_PINGBACK_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PINGBACK_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
212
 
213
  = 2.1.1 =
214
  * Minor bugfix.
215
 
216
  = 2.1.0 =
217
+ * Add support for blocking user enumeration; see [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCK_USER_ENUMERATION.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
218
+ * Add support for CIDR notation in [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
219
 
220
  = 2.0.1 =
221
+ * Bugfix in *experimental* [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) code.
222
 
223
  = 2.0.0 =
224
+ * Add *experimental* support for X-Forwarded-For header; see [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
225
+ * Add *experimental* support for regex-based login blocking; see [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCKED_USERS.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
226
 
227
  = 1.2.1 =
228
  * Update FAQ.
238
 
239
  == Upgrade Notice ==
240
 
241
+ = 4.3.0 =
242
+ To take advantage of the new features you will need up update your `fail2ban` filters; existing filters will continue to work as before.
243
 
244
  = 4.2.7.1 =
245
  This is a bugfix release. You do not need to update your filters from 4.1.0.
293
  You will need up update your `fail2ban` filters.
294
 
295
  = 3.5.1 =
296
+ Bugfix: disable [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_BLOCK_USER_ENUMERATION.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0) in admin area....
297
 
298
  = 3.5.0 =
299
  You will need up update your `fail2ban` filters.
305
  BREAKING CHANGE: The `fail2ban` filters have been split into two files. You will need up update your `fail2ban` configuration.
306
 
307
  = 2.3.0 =
308
+ Fix for [`WP_FAIL2BAN_PROXIES`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_PROXIES.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0); if you're not using it you can safely skip this release.
309
 
310
  = 2.2.1 =
311
  Bugfix.
312
 
313
  = 2.2.0 =
314
+ BREAKING CHANGE: `WP_FAIL2BAN_LOG` has been renamed to [`WP_FAIL2BAN_AUTH_LOG`](https://docs.wp-fail2ban.com/en/4.1/defines/WP_FAIL2BAN_AUTH_LOG.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=4.3.0).
315
 
316
  Pingbacks are getting a lot of attention recently, so *WPf2b* can now log them.
317
  The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
324
 
325
  = 2.0.0 =
326
  This is an experimental release. If your current version is working and you're not interested in the new features, skip this version - wait for 2.1.0. For those that do want to test this release, note that `wordpress.conf` has changed - you'll need to copy it to `fail2ban/filters.d` again.
327
+
328
+
vendor/freemius/wordpress-sdk/includes/class-freemius.php CHANGED
@@ -12733,9 +12733,7 @@
12733
  return;
12734
  }
12735
 
12736
- $installs_ids_with_foreign_licenses = $this->get_installs_ids_with_foreign_licenses();
12737
-
12738
- if ( empty( $installs_ids_with_foreign_licenses ) ) {
12739
  // Handle user change only when the parent product or one of its add-ons is activated with a foreign license.
12740
  return;
12741
  }
12733
  return;
12734
  }
12735
 
12736
+ if ( empty( $this->get_installs_ids_with_foreign_licenses() ) ) {
 
 
12737
  // Handle user change only when the parent product or one of its add-ons is activated with a foreign license.
12738
  return;
12739
  }
wp-fail2ban-core.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WP fail2ban core
4
+ *
5
+ * @package wp-fail2ban
6
+ * @since 4.3.0
7
+ */
8
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
+
10
+ if (defined('ABSPATH')) {
11
+ include_once_exists(__DIR__.'/premium/core.php');
12
+
13
+ /**
14
+ * @since 4.3.0
15
+ */
16
+ if (!function_exists(__NAMESPACE__.'\authenticate')) {
17
+ /**
18
+ * Catch empty usernames
19
+ *
20
+ * @see \wp_authenticate()
21
+ *
22
+ * @since 4.3.0
23
+ *
24
+ * @param mixed|null $user
25
+ * @param string $username
26
+ * @param string $password
27
+ *
28
+ * @return mixed|null
29
+ *
30
+ * @wp-f2b-soft Empty username
31
+ */
32
+ function authenticate($user, $username, $password)
33
+ {
34
+ if (empty($username) && isset($_POST['log'])) {
35
+ openlog();
36
+ syslog(LOG_NOTICE, 'Empty username');
37
+ closelog();
38
+
39
+ do_action(__FUNCTION__, $user, $username, $password);
40
+ }
41
+
42
+ return $user;
43
+ }
44
+ add_action('authenticate', __NAMESPACE__.'\authenticate', 1, 3);
45
+ }
46
+
47
+ /**
48
+ * @since 4.0.5
49
+ */
50
+ if (!function_exists(__NAMESPACE__.'\wp_login')) {
51
+ /**
52
+ * Hook: wp_login
53
+ *
54
+ * @since 4.1.0 Add REST support
55
+ * @since 3.5.0 Refactored for unit testing
56
+ * @since 1.0.0
57
+ *
58
+ * @param string $user_login
59
+ * @param mixed $user
60
+ */
61
+ function wp_login($user_login, $user)
62
+ {
63
+ openlog();
64
+ syslog(LOG_INFO, "Accepted password for {$user_login}");
65
+ closelog();
66
+
67
+ do_action(__FUNCTION__, $user_login, $user);
68
+ }
69
+ add_action('wp_login', __NAMESPACE__.'\wp_login', 10, 2);
70
+ }
71
+
72
+ /**
73
+ * @since 4.0.5
74
+ */
75
+ if (!function_exists(__NAMESPACE__.'\wp_login_failed')) {
76
+ /**
77
+ * Hook: wp_login_failed
78
+ *
79
+ * @since 4.2.4 Add message filter
80
+ * @since 4.2.0 Change username check
81
+ * @since 4.1.0 Add REST support
82
+ * @since 3.5.0 Refactored for unit testing
83
+ * @since 1.0.0
84
+ *
85
+ * @param string $username
86
+ *
87
+ * @wp-f2b-hard Authentication attempt for unknown user .*
88
+ * @wp-f2b-hard REST authentication attempt for unknown user .*
89
+ * @wp-f2b-hard XML-RPC authentication attempt for unknown user .*
90
+ * @wp-f2b-soft Authentication failure for .*
91
+ * @wp-f2b-soft REST authentication failure for .*
92
+ * @wp-f2b-soft XML-RPC authentication failure for .*
93
+ */
94
+ function wp_login_failed($username)
95
+ {
96
+ global $wp_fail2ban, $wp_xmlrpc_server;
97
+
98
+ if (defined('REST_REQUEST')) {
99
+ $msg = 'REST a';
100
+ $filter = '::REST';
101
+ } elseif ($wp_xmlrpc_server) {
102
+ $msg = 'XML-RPC a';
103
+ $filter = '::XML-RPC';
104
+ } else {
105
+ $msg = 'A';
106
+ $filter = '';
107
+ }
108
+
109
+ $username = trim($username);
110
+ $msg .= (wp_cache_get($username, 'useremail') || wp_cache_get(sanitize_user($username), 'userlogins'))
111
+ ? "uthentication failure for {$username}"
112
+ : "uthentication attempt for unknown user {$username}";
113
+ $msg = apply_filters("wp_fail2ban::wp_login_failed{$filter}", $msg);
114
+
115
+ openlog();
116
+ syslog(LOG_NOTICE, $msg);
117
+ closelog();
118
+
119
+ do_action(__FUNCTION__, $username);
120
+ }
121
+ add_action('wp_login_failed', __NAMESPACE__.'\wp_login_failed');
122
+ }
123
+ }
124
+
wp-fail2ban-features.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WP fail2ban features
4
+ *
5
+ * @package wp-fail2ban
6
+ * @since 4.0.0
7
+ * @php 5.3
8
+ */
9
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
+
11
+ if (defined('ABSPATH')) {
12
+ include_once_exists(__DIR__.'/premium/features.php');
13
+
14
+ /**
15
+ * Load all enabled features.
16
+ *
17
+ * @since 4.3.0
18
+ */
19
+ function plugins_loaded()
20
+ {
21
+ Config::load();
22
+
23
+ /**
24
+ * Comments
25
+ *
26
+ * @since 4.0.0 Refactored
27
+ * @since 3.5.0
28
+ */
29
+ if (defined('WP_FAIL2BAN_LOG_COMMENTS') && true === WP_FAIL2BAN_LOG_COMMENTS) {
30
+ require_once __DIR__.'/feature/comments.php';
31
+ }
32
+
33
+ /**
34
+ * Password
35
+ *
36
+ * @since 4.0.0 Refactored
37
+ * @since 3.5.0
38
+ */
39
+ if (defined('WP_FAIL2BAN_LOG_PASSWORD_REQUEST') && true === WP_FAIL2BAN_LOG_PASSWORD_REQUEST) {
40
+ require_once __DIR__.'/feature/password.php';
41
+ }
42
+
43
+ /**
44
+ * Spam
45
+ *
46
+ * @since 4.0.0 Refactored
47
+ * @since 3.5.0
48
+ */
49
+ if (defined('WP_FAIL2BAN_LOG_SPAM') && true === WP_FAIL2BAN_LOG_SPAM) {
50
+ require_once __DIR__.'/feature/spam.php';
51
+ }
52
+
53
+ /**
54
+ * User enumeration
55
+ *
56
+ * @since 4.0.0 Refactored
57
+ * @since 2.1.0
58
+ */
59
+ if (defined('WP_FAIL2BAN_BLOCK_USER_ENUMERATION') && true === WP_FAIL2BAN_BLOCK_USER_ENUMERATION) {
60
+ require_once __DIR__.'/feature/user-enum.php';
61
+ }
62
+
63
+ /**
64
+ * Users
65
+ *
66
+ * @since 4.3.0 Better test
67
+ * @since 4.0.0 Refactored
68
+ * @since 2.0.0
69
+ */
70
+ if ( (defined('WP_FAIL2BAN_BLOCKED_USERS') && WP_FAIL2BAN_BLOCKED_USERS) ||
71
+ (defined('WP_FAIL2BAN_BLOCK_USERNAME_LOGIN') && WP_FAIL2BAN_BLOCK_USERNAME_LOGIN) )
72
+ {
73
+ require_once __DIR__.'/feature/user.php';
74
+ }
75
+ }
76
+ /**
77
+ * Load nice and early.
78
+ *
79
+ * @since 4.3.0
80
+ */
81
+ add_action('plugins_loaded', __NAMESPACE__.'\plugins_loaded');
82
+
83
+ /**
84
+ * Things we need a current user for.
85
+ *
86
+ * @since 4.3.0
87
+ */
88
+ function init()
89
+ {
90
+ /**
91
+ * @since 4.3.0 Check for logged in
92
+ * @since 4.2.5 Check for admin
93
+ */
94
+ if (!is_user_logged_in()) {
95
+ /**
96
+ * XML-RPC
97
+ *
98
+ * @since 4.0.0 Refactored
99
+ * @since 3.0.0
100
+ */
101
+ if (defined('XMLRPC_REQUEST') && true === XMLRPC_REQUEST) {
102
+ require_once __DIR__.'/feature/xmlrpc.php';
103
+ }
104
+ }
105
+ }
106
+ add_action('init', __NAMESPACE__.'\init');
107
+
108
+ /**
109
+ * Load plugin hooks.
110
+ *
111
+ * Called from `plugins_loaded`
112
+ *
113
+ * @since 4.3.0
114
+ */
115
+ require __DIR__.'/feature/plugins.php';
116
+ }
117
+
wp-fail2ban-main.php CHANGED
@@ -1,297 +1,31 @@
1
  <?php
2
-
3
  /**
4
- * WP fail2ban main file
5
- *
6
- * @since 4.0.0
7
- * @package wp-fail2ban
8
  */
9
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
 
11
- if ( !defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- require_once __DIR__ . '/lib/constants.php';
15
- require_once __DIR__ . '/lib/loader.php';
16
- require_once __DIR__ . '/lib/defaults.php';
17
- register_activation_hook( WP_FAIL2BAN_FILE, function () {
18
- foreach ( get_mu_plugins() as $plugin => $data ) {
19
-
20
- if ( 0 === strpos( $data['Name'], 'WP fail2ban' ) ) {
21
- $wp_f2b_ver = substr( WP_FAIL2BAN_VER, 0, strrpos( WP_FAIL2BAN_VER, '.' ) );
22
- $wpf2b = 'WP fail2ban';
23
- $error_msg = sprintf( __( '<h1>Cannot activate %s</h1>' ), $wpf2b );
24
- $mu_file = WPMU_PLUGIN_DIR . '/' . $plugin;
25
-
26
- if ( is_link( $mu_file ) ) {
27
-
28
- if ( false === ($link = readlink( $mu_file )) || false === ($path = realpath( $mu_file )) ) {
29
- $h3 = __( 'A broken symbolic link was found in <tt>mu-plugins</tt>:' );
30
- $error_msg .= <<<__ERROR__
31
- <h3>{$h3}</h3>
32
- <p><tt>{$mu_file}</tt></p>
33
- __ERROR__;
34
- } elseif ( WP_FAIL2BAN_FILE == $path ) {
35
- // OK, we're linking to ourself
36
- } else {
37
- $mu_file = str_replace( '/', '/<wbr>', $mu_file );
38
- $mu_file = substr( $mu_file, strlen( WPMU_PLUGIN_DIR ) - 1 );
39
- $h3 = __( 'A conflicting symbolic link was found in <tt>mu-plugins</tt>:' );
40
- $error_msg .= <<<__ERROR__
41
- <h3>{$h3}</h3>
42
- <style>
43
- table { text-align: center; }
44
- td { width: 50%; }
45
- th { font-size: 200%; }
46
- td, th { font-family: monospace; }
47
- span.tt { font-weight: bold; }
48
- </style>
49
- <table>
50
- <tr>
51
- <td>{$mu_file}</td>
52
- <th>&DoubleRightArrow;</th>
53
- <td>{$link}</td>
54
- </tr>
55
- <tr>
56
- <td colspan="3"><span class="tt">&equiv;</span> <span>{$path}</span></td>
57
- </tr>
58
- <tr>
59
- <td colspan="3"></td>
60
- </tr>
61
- </table>
62
- __ERROR__;
63
- }
64
-
65
- } else {
66
- $mu_file = str_replace( '/', '/<wbr>', $mu_file );
67
- $mu_file = substr( $mu_file, strlen( WPMU_PLUGIN_DIR ) - 1 );
68
- $h3 = __( 'A conflicting file was found in <tt>mu-plugins</tt>:' );
69
- $error_msg .= <<<__ERROR__
70
- <h3>{$h3}</h3>
71
- <p><tt>{$mu_file}</tt></p>
72
- __ERROR__;
73
- }
74
-
75
- $error_msg .= sprintf( __( '<p>Please see the <a href="%s" target="_blank">documentation</a> for how to configure %s for <tt>mu-plugins</tt>.</p>' ), "https://docs.wp-fail2ban.com/en/{$wp_f2b_ver}/configuration.html#mu-plugins-support", $wpf2b );
76
- $error_msg .= sprintf( __( '<p>Click <a href="%s">here</a> to return to the plugins page.</p>' ), admin_url( 'plugins.php' ) );
77
- deactivate_plugins( plugin_basename( WP_FAIL2BAN_FILE ) );
78
- wp_die( $error_msg );
79
- }
80
-
81
- }
82
- } );
83
- /**
84
- * @since 4.2.8
85
- */
86
- if ( !function_exists( __NAMESPACE__ . '\\release_notes_message' ) ) {
87
- /**
88
- * CTA for release notes
89
- *
90
- * @since 4.2.8
91
- *
92
- * @param string $link Link to release notes page or tab
93
- */
94
- function release_notes_message( $link )
95
- {
96
-
97
- if ( !defined( 'PHPUNIT_COMPOSER_INSTALL' ) ) {
98
- $msg = sprintf( ' - please check the <a href="%s">release notes</a>.', $link );
99
- add_action( 'init', function () use( $msg ) {
100
- if ( current_user_can( 'manage_options' ) ) {
101
-
102
- if ( isset( $_GET['wp-fail2ban-notice'] ) || false === ($notice = get_site_option( 'wp-fail2ban-notice' )) || !isset( $notice['4.2.8'] ) || false === $notice['4.2.8'] ) {
103
- wf_fs()->add_sticky_admin_message(
104
- $msg,
105
- 'wpf2b-4.2.8',
106
- 'Important news',
107
- 'info'
108
- );
109
- update_site_option( 'wp-fail2ban-notice', array(
110
- '4.2.8' => true,
111
- ) );
112
- }
113
-
114
- }
115
- } );
116
- }
117
-
118
- }
119
-
120
- }
121
- require __DIR__ . '/feature/lib.php';
122
- /**
123
- * @since 4.2.5
124
- */
125
-
126
- if ( version_compare( PHP_VERSION, '5.6.0', '>=' ) ) {
127
- /**
128
- * @since 4.2.0
129
- */
130
- global $wp_fail2ban ;
131
- $wp_fail2ban['plugins'] = array();
132
- require __DIR__ . '/feature/plugins.php';
133
-
134
- if ( is_admin() ) {
135
- $page = ( wf_fs()->is_free_plan() ? 'wp-fail2ban' : 'wpf2b-settings&tab=about' );
136
- release_notes_message( admin_url( 'admin.php?page=' . $page ) );
137
- require 'admin/admin.php';
138
- }
139
-
140
- } elseif ( is_admin() ) {
141
- release_notes_message( admin_url( 'admin.php?page=wp-fail2ban' ) );
142
- require __DIR__ . '/admin/lib/about.php';
143
- add_action( 'admin_menu', function () {
144
- add_menu_page(
145
- 'WP fail2ban',
146
- 'WP fail2ban',
147
- 'manage_options',
148
- 'wp-fail2ban',
149
- __NAMESPACE__ . '\\about',
150
- 'dashicons-analytics'
151
- );
152
- } );
153
- }
154
-
155
- /**
156
- * @since 4.0.5
157
- */
158
-
159
- if ( !function_exists( __NAMESPACE__ . '\\wp_login' ) ) {
160
- /**
161
- * Hook: wp_login
162
- *
163
- * @since 4.1.0 Add REST support
164
- * @since 3.5.0 Refactored for unit testing
165
- * @since 1.0.0
166
- *
167
- * @param string $user_login
168
- * @param mixed $user
169
- */
170
- function wp_login( $user_login, $user )
171
- {
172
- global $wp_xmlrpc_server ;
173
- openlog();
174
- syslog( LOG_INFO, "Accepted password for {$user_login}" );
175
- closelog();
176
- // @codeCoverageIgnoreEnd
177
- }
178
-
179
- add_action(
180
- 'wp_login',
181
- __NAMESPACE__ . '\\wp_login',
182
- 10,
183
- 2
184
- );
185
- }
186
 
187
- /**
188
- * @since 4.0.5
189
- */
190
 
191
- if ( !function_exists( __NAMESPACE__ . '\\wp_login_failed' ) ) {
192
  /**
193
- * Hook: wp_login_failed
194
- *
195
- * @since 4.2.4 Add message filter
196
- * @since 4.2.0 Change username check
197
- * @since 4.1.0 Add REST support
198
- * @since 3.5.0 Refactored for unit testing
199
- * @since 1.0.0
200
- *
201
- * @param string $username
202
- *
203
- * @wp-f2b-hard Authentication attempt for unknown user .*
204
- * @wp-f2b-hard REST authentication attempt for unknown user .*
205
- * @wp-f2b-hard XML-RPC authentication attempt for unknown user .*
206
- * @wp-f2b-soft Authentication failure for .*
207
- * @wp-f2b-soft REST authentication failure for .*
208
- * @wp-f2b-soft XML-RPC authentication failure for .*
209
  */
210
- function wp_login_failed( $username )
211
- {
212
- global $wp_xmlrpc_server ;
213
-
214
- if ( defined( 'REST_REQUEST' ) ) {
215
- $msg = 'REST a';
216
- $filter = '::REST';
217
- } elseif ( $wp_xmlrpc_server ) {
218
- $msg = 'XML-RPC a';
219
- $filter = '::XML-RPC';
220
- } else {
221
- $msg = 'A';
222
- $filter = '';
223
- }
224
-
225
- $username = trim( $username );
226
- $msg .= ( wp_cache_get( $username, 'useremail' ) || wp_cache_get( sanitize_user( $username ), 'userlogins' ) ? "uthentication failure for {$username}" : "uthentication attempt for unknown user {$username}" );
227
- $msg = apply_filters( "wp_fail2ban::wp_login_failed{$filter}", $msg );
228
- openlog();
229
- syslog( LOG_NOTICE, $msg );
230
- closelog();
231
- // @codeCoverageIgnoreEnd
232
  }
233
-
234
- add_action( 'wp_login_failed', __NAMESPACE__ . '\\wp_login_failed' );
235
- }
236
 
237
- /**
238
- * @since 4.2.5
239
- */
240
-
241
- if ( !is_admin() ) {
242
- /**
243
- * User enumeration
244
- *
245
- * @since 4.0.0 Refactored
246
- * @since 2.1.0
247
- */
248
- if ( defined( 'WP_FAIL2BAN_BLOCK_USER_ENUMERATION' ) && true === WP_FAIL2BAN_BLOCK_USER_ENUMERATION ) {
249
- require_once __DIR__ . '/feature/user-enum.php';
250
- }
251
- /**
252
- * XML-RPC
253
- *
254
- * @since 4.0.0 Refactored
255
- * @since 3.0.0
256
- */
257
- if ( defined( 'XMLRPC_REQUEST' ) && true === XMLRPC_REQUEST ) {
258
- require_once __DIR__ . '/feature/xmlrpc.php';
259
- }
260
  }
261
 
262
- /**
263
- * Comments
264
- *
265
- * @since 4.0.0 Refactored
266
- * @since 3.5.0
267
- */
268
- if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS' ) && true === WP_FAIL2BAN_LOG_COMMENTS ) {
269
- require_once __DIR__ . '/feature/comments.php';
270
- }
271
- /**
272
- * Password
273
- *
274
- * @since 4.0.0 Refactored
275
- * @since 3.5.0
276
- */
277
- if ( defined( 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST' ) && true === WP_FAIL2BAN_LOG_PASSWORD_REQUEST ) {
278
- require_once __DIR__ . '/feature/password.php';
279
- }
280
- /**
281
- * Spam
282
- *
283
- * @since 4.0.0 Refactored
284
- * @since 3.5.0
285
- */
286
- if ( defined( 'WP_FAIL2BAN_LOG_SPAM' ) && true === WP_FAIL2BAN_LOG_SPAM ) {
287
- require_once __DIR__ . '/feature/spam.php';
288
- }
289
- /**
290
- * Users
291
- *
292
- * @since 4.0.0 Refactored
293
- * @since 2.0.0
294
- */
295
- if ( defined( 'WP_FAIL2BAN_BLOCKED_USERS' ) && '' < WP_FAIL2BAN_BLOCKED_USERS ) {
296
- require_once __DIR__ . '/feature/user.php';
297
- }
1
  <?php
 
2
  /**
3
+ * WP fail2ban main file
4
+ *
5
+ * @package wp-fail2ban
6
+ * @since 4.0.0
7
  */
8
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
9
 
10
+ if (defined('ABSPATH')) {
11
+ require_once __DIR__.'/lib/defaults.php';
12
+ include_once_exists(__DIR__.'/lib/constants.php');
13
+ include_once_exists(__DIR__.'/lib/convert-data.php');
14
+ require_once __DIR__.'/lib/activation.php';
15
+ require_once __DIR__.'/lib/loader.php';
16
+ require_once __DIR__.'/feature/lib.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
+ include_once_exists(__DIR__.'/premium/main.php');
 
 
19
 
 
20
  /**
21
+ * @since 4.3.0 Relocate.
22
+ * @since 4.2.5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  */
24
+ if (defined('WP_ADMIN') && WP_ADMIN) {
25
+ require_once __DIR__.'/admin/admin.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
 
 
 
27
 
28
+ require_once __DIR__.'/wp-fail2ban-core.php';
29
+ require_once __DIR__.'/wp-fail2ban-features.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  }
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wp-fail2ban-premium.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * WP fail2ban premium
5
+ *
6
+ * @package wp-fail2ban
7
+ * @since 4.3.0
8
+ */
9
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
+
11
+
12
+ if ( defined( 'ABSPATH' ) ) {
13
+ /**
14
+ * Freemius integration
15
+ *
16
+ * @since 4.0.0
17
+ */
18
+
19
+ if ( function_exists( __NAMESPACE__ . '\\wf_fs' ) ) {
20
+ // @codeCoverageIgnoreStart
21
+ wf_fs()->set_basename( true, WP_FAIL2BAN_FILE );
22
+ return;
23
+ } else {
24
+ /**
25
+ * Create a helper function for easy SDK access.
26
+ */
27
+ function wf_fs()
28
+ {
29
+ global $wf_fs ;
30
+
31
+ if ( !isset( $wf_fs ) ) {
32
+ // Activate multisite network integration.
33
+ if ( !defined( 'WP_FS__PRODUCT_3072_MULTISITE' ) ) {
34
+ define( 'WP_FS__PRODUCT_3072_MULTISITE', true );
35
+ }
36
+ // Include Freemius SDK.
37
+ require_once __DIR__ . '/vendor/freemius/wordpress-sdk/start.php';
38
+ $wf_fs = fs_dynamic_init( array(
39
+ 'id' => '3072',
40
+ 'slug' => 'wp-fail2ban',
41
+ 'type' => 'plugin',
42
+ 'public_key' => 'pk_146d2c2a5bee3b157e43501ef8682',
43
+ 'is_premium' => false,
44
+ 'has_addons' => true,
45
+ 'has_paid_plans' => true,
46
+ 'trial' => array(
47
+ 'days' => 14,
48
+ 'is_require_payment' => false,
49
+ ),
50
+ 'menu' => array(
51
+ 'slug' => 'wp-fail2ban-menu',
52
+ 'support' => true,
53
+ 'network' => true,
54
+ ),
55
+ 'is_live' => true,
56
+ ) );
57
+ }
58
+
59
+ return $wf_fs;
60
+ }
61
+
62
+ // Init Freemius.
63
+ wf_fs();
64
+ // Set currency to GBP
65
+ wf_fs()->add_filter( 'default_currency', function () {
66
+ return 'gbp';
67
+ } );
68
+ // Set custom icon
69
+ wf_fs()->add_filter( 'plugin_icon', function () {
70
+ return __DIR__ . '/assets/icon.svg';
71
+ } );
72
+ // Set forum URL
73
+ wf_fs()->add_filter( 'support_forum_url', function () {
74
+ if ( wf_fs()->is_trial() ) {
75
+ /** Trial forum: Invite-only */
76
+ return 'https://forums.invis.net/c/wp-fail2ban/support-trial/';
77
+ }
78
+ if ( wf_fs()->is_free_plan() ) {
79
+ /** Free forum: available to all */
80
+ return 'https://forums.invis.net/c/wp-fail2ban/support-free/';
81
+ }
82
+ if ( wf_fs()->is_paying() ) {
83
+ /** Paying forum: Invite-only */
84
+ return 'https://forums.invis.net/c/wp-fail2ban/support-premium/';
85
+ }
86
+ /** Just in case... */
87
+ return 'https://forums.invis.net/c/wp-fail2ban/';
88
+ } );
89
+ // Signal that SDK was initiated.
90
+ do_action( 'wf_fs_loaded' );
91
+ }
92
+
93
+ // @codeCoverageIgnoreEnd
94
+ }
wp-fail2ban.php CHANGED
@@ -1,20 +1,21 @@
1
  <?php
2
-
3
  /*
4
  * Plugin Name: WP fail2ban
5
  * Plugin URI: https://wp-fail2ban.com/
6
  * Description: Write a myriad of WordPress events to syslog for integration with fail2ban.
7
  * Text Domain: wp-fail2ban
8
- * Version: 4.2.8
9
  * Author: Charles Lecklider
10
  * Author URI: https://charles.lecklider.org/
11
  * License: GPLv2
12
  * SPDX-License-Identifier: GPL-2.0
13
- * Requires PHP: 5.3
 
14
  *
15
- */
 
16
  /*
17
- * Copyright 2012-19 Charles Lecklider (email : wordpress@charles.lecklider.org)
18
  *
19
  * This program is free software; you can redistribute it and/or modify
20
  * it under the terms of the GNU General Public License, version 2, as
@@ -29,97 +30,51 @@
29
  * along with this program; if not, write to the Free Software
30
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31
  */
 
32
  /**
33
  * WP fail2ban
34
  *
35
- * @package wp-fail2ban
36
  */
37
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
38
 
39
  /**
 
 
40
  * @since 4.0.5
41
  */
42
- define( 'WP_FAIL2BAN_VER', '4.2.8' );
43
- define( 'WP_FAIL2BAN_FILE', __FILE__ );
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- if ( defined( 'ABSPATH' ) ) {
46
  /**
47
- * Freemius integration
 
 
48
  *
49
- * @since 4.0.0
 
 
50
  */
51
-
52
- if ( function_exists( __NAMESPACE__ . '\\wf_fs' ) ) {
53
- // @codeCoverageIgnoreStart
54
- wf_fs()->set_basename( false, __FILE__ );
55
- return;
56
- } else {
57
- /**
58
- * Create a helper function for easy SDK access.
59
- */
60
- function wf_fs()
61
- {
62
- global $wf_fs ;
63
-
64
- if ( !isset( $wf_fs ) ) {
65
- // Include Freemius SDK.
66
- require_once dirname( __FILE__ ) . '/vendor/freemius/wordpress-sdk/start.php';
67
- $wf_fs = fs_dynamic_init( array(
68
- 'id' => '3072',
69
- 'slug' => 'wp-fail2ban',
70
- 'type' => 'plugin',
71
- 'public_key' => 'pk_146d2c2a5bee3b157e43501ef8682',
72
- 'is_premium' => false,
73
- 'has_addons' => true,
74
- 'has_paid_plans' => true,
75
- 'trial' => array(
76
- 'days' => 14,
77
- 'is_require_payment' => false,
78
- ),
79
- 'menu' => array(
80
- 'slug' => 'wp-fail2ban',
81
- 'first-path' => 'admin.php?page=wp-fail2ban',
82
- 'support' => true,
83
- ),
84
- 'is_live' => true,
85
- ) );
86
- }
87
-
88
- return $wf_fs;
89
  }
90
-
91
- // Init Freemius.
92
- wf_fs();
93
- // Set currency to GBP
94
- wf_fs()->add_filter( 'default_currency', function () {
95
- return 'gbp';
96
- } );
97
- // Set forum URL
98
- wf_fs()->add_filter( 'support_forum_url', function () {
99
- if ( wf_fs()->is_trial() ) {
100
- /** Trial forum: Invite-only */
101
- return 'https://forums.invis.net/c/wp-fail2ban-premium/support-trial/';
102
- }
103
- if ( wf_fs()->is_free_plan() ) {
104
- /** Free forum: available to all */
105
- return 'https://forums.invis.net/c/wp-fail2ban/support-free/';
106
- }
107
- if ( wf_fs()->is_paying() ) {
108
- /** Paying forum: Invite-only */
109
- return 'https://forums.invis.net/c/wp-fail2ban-premium/support-premium/';
110
- }
111
- /** Just in case... */
112
- return 'https://forums.invis.net/c/wp-fail2ban/';
113
- } );
114
- // Signal that SDK was initiated.
115
- do_action( 'wf_fs_loaded' );
116
  }
117
-
118
- // @codeCoverageIgnoreEnd
119
- /**
120
- * Freemius insists on mangling the formatting of the main plugin file
121
- *
122
- * @since 4.0.0 Refactored
123
- */
124
  require_once 'wp-fail2ban-main.php';
125
  }
 
1
  <?php
 
2
  /*
3
  * Plugin Name: WP fail2ban
4
  * Plugin URI: https://wp-fail2ban.com/
5
  * Description: Write a myriad of WordPress events to syslog for integration with fail2ban.
6
  * Text Domain: wp-fail2ban
7
+ * Version: 4.3.0-RC4
8
  * Author: Charles Lecklider
9
  * Author URI: https://charles.lecklider.org/
10
  * License: GPLv2
11
  * SPDX-License-Identifier: GPL-2.0
12
+ * Requires PHP: 5.6
13
+ * Network: true
14
  *
15
+ */
16
+
17
  /*
18
+ * Copyright 2012-20 Charles Lecklider (email : wordpress@charles.lecklider.org)
19
  *
20
  * This program is free software; you can redistribute it and/or modify
21
  * it under the terms of the GNU General Public License, version 2, as
30
  * along with this program; if not, write to the Free Software
31
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
32
  */
33
+
34
  /**
35
  * WP fail2ban
36
  *
37
+ * @package wp-fail2ban
38
  */
39
  namespace org\lecklider\charles\wordpress\wp_fail2ban;
40
 
41
  /**
42
+ * Outside the guard for building
43
+ *
44
  * @since 4.0.5
45
  */
46
+ if (!defined('WP_FAIL2BAN_VER')) {
47
+ define('WP_FAIL2BAN_VER', '4.3.0-RC4');
48
+ }
49
+ if (!defined('WP_FAIL2BAN_DIR')) {
50
+ define('WP_FAIL2BAN_DIR', __DIR__);
51
+ }
52
+ if (!defined('WP_FAIL2BAN_FILE')) {
53
+ define('WP_FAIL2BAN_FILE', __FILE__);
54
+ }
55
+ if (!defined('WP_FAIL2BAN_NS')) {
56
+ define('WP_FAIL2BAN_NS', __NAMESPACE__);
57
+ }
58
+
59
+ if (defined('ABSPATH')) {
60
 
 
61
  /**
62
+ * Helper - include_once file if it exists
63
+ *
64
+ * Avoids warning with XDebug
65
  *
66
+ * @since 4.3.0
67
+ *
68
+ * @param string $file File to include_once
69
  */
70
+ function include_once_exists($file)
71
+ {
72
+ if (is_file($file)) {
73
+ require_once $file;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  }
76
+
77
+ include_once_exists(__DIR__.'/wp-fail2ban-premium.php');
 
 
 
 
 
78
  require_once 'wp-fail2ban-main.php';
79
  }
80
+