Version Description
- Completed support for
WP_FAIL2BAN_COMMENT_EXTRA_LOG
. - Add support for 3rd-party plugins; see Developers.
- Add-on for Contact Form 7 (experimental).
- Add-on for Gravity Forms (experimental).
- 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 bysoft
. - Bugfix for email-as-username - now logged correctly and matched by
soft
, nothard
, filters. - Bugfix for regression in code to prevent Free/Premium conflict.
Download this release
Release Info
Developer | invisnet |
Plugin | WP fail2ban |
Version | 4.2.1 |
Comparing to | |
See all releases |
Code changes from version 4.1.0 to 4.2.1
- admin/admin.php +66 -0
- admin/config.php +68 -0
- admin/config/block.php +120 -0
- admin/config/logging.php +255 -0
- admin/config/plugins.php +185 -0
- admin/config/remote-ips.php +127 -0
- admin/config/syslog.php +159 -0
- admin/lib/about.php +97 -0
- admin/lib/tab.php +260 -0
- admin/summary.php +0 -282
- feature/comments.php +12 -6
- feature/lib.php +2 -0
- feature/password.php +1 -0
- feature/plugins.php +233 -0
- feature/spam.php +1 -0
- feature/user-enum.php +1 -0
- feature/user.php +1 -0
- feature/xmlrpc.php +2 -0
- feature/xmlrpc/pingback.php +1 -0
- filters.d/wordpress-extra.conf +1 -1
- filters.d/wordpress-hard.conf +1 -1
- filters.d/wordpress-soft.conf +1 -1
- lib/constants.php +143 -0
- lib/defaults.php +79 -0
- lib/loader.php +303 -0
- readme.txt +32 -12
- wp-fail2ban-main.php +41 -83
- wp-fail2ban.php +15 -9
admin/admin.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
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 dirname( __FILE__ ) . '/config.php';
|
15 |
+
require dirname( __FILE__ ) . '/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 |
+
add_submenu_page(
|
33 |
+
'wp-fail2ban',
|
34 |
+
'Settings',
|
35 |
+
'Settings',
|
36 |
+
'manage_options',
|
37 |
+
'wp-fail2ban-settings',
|
38 |
+
__NAMESPACE__ . '\\settings'
|
39 |
+
);
|
40 |
+
$submenu['wp-fail2ban'][0][0] = __( 'Welcome' );
|
41 |
+
}
|
42 |
+
|
43 |
+
add_action( 'admin_menu', __NAMESPACE__ . '\\admin_menu' );
|
44 |
+
/**
|
45 |
+
* Add Settings link on Plugins page
|
46 |
+
*
|
47 |
+
* @since 4.2.0
|
48 |
+
*
|
49 |
+
* @param array $links
|
50 |
+
* @param string $file
|
51 |
+
*/
|
52 |
+
function plugin_action_links( $links, $file )
|
53 |
+
{
|
54 |
+
if ( preg_match( "|{$file}\$|", WP_FAIL2BAN_FILE ) ) {
|
55 |
+
// Add Settings at the start
|
56 |
+
array_unshift( $links, '<a href="' . admin_url( 'options-general.php' ) . '?page=wp-fail2ban-settings&tab=welcome">Settings</a>' );
|
57 |
+
}
|
58 |
+
return $links;
|
59 |
+
}
|
60 |
+
|
61 |
+
add_filter(
|
62 |
+
'plugin_action_links',
|
63 |
+
__NAMESPACE__ . '\\plugin_action_links',
|
64 |
+
10,
|
65 |
+
2
|
66 |
+
);
|
admin/config.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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( dirname( __FILE__ ) . '/config/*.php' ) as $filename ) {
|
16 |
+
require_once $filename;
|
17 |
+
}
|
18 |
+
/**
|
19 |
+
* Render Settings
|
20 |
+
*
|
21 |
+
* @since 4.0.0
|
22 |
+
*/
|
23 |
+
function settings()
|
24 |
+
{
|
25 |
+
$tabs = [
|
26 |
+
'logging',
|
27 |
+
'syslog',
|
28 |
+
'block',
|
29 |
+
'remote-ips',
|
30 |
+
'plugins'
|
31 |
+
];
|
32 |
+
$title = 'WP fail2ban';
|
33 |
+
?>
|
34 |
+
<div class="wrap">
|
35 |
+
<h1><?php
|
36 |
+
echo $title ;
|
37 |
+
?></h1>
|
38 |
+
<hr class="wp-header-end">
|
39 |
+
|
40 |
+
<h2 class="nav-tab-wrapper wp-clearfix">
|
41 |
+
<?php
|
42 |
+
$active_tab = Tab::getActiveTab( 'logging' );
|
43 |
+
foreach ( $tabs as $slug ) {
|
44 |
+
$class = 'nav-tab';
|
45 |
+
if ( $active_tab->getSlug() == $slug ) {
|
46 |
+
$class .= ' nav-tab-active';
|
47 |
+
}
|
48 |
+
printf(
|
49 |
+
'<a class="%s" href="?page=wp-fail2ban-settings&tab=%s">%s</a>',
|
50 |
+
$class,
|
51 |
+
$slug,
|
52 |
+
Tab::getTabName( $slug )
|
53 |
+
);
|
54 |
+
}
|
55 |
+
?>
|
56 |
+
</h2>
|
57 |
+
|
58 |
+
<form action="options.php?tab=<?php
|
59 |
+
echo $active_tab->getSlug() ;
|
60 |
+
?>" method="post">
|
61 |
+
<?php
|
62 |
+
settings_fields( 'wp-fail2ban' );
|
63 |
+
$active_tab->render();
|
64 |
+
?>
|
65 |
+
</form>
|
66 |
+
</div>
|
67 |
+
<?php
|
68 |
+
}
|
admin/config/block.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
admin/config/logging.php
ADDED
@@ -0,0 +1,255 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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>
|
190 |
+
<td>
|
191 |
+
<fieldset id="comments-extra" disabled="disabled">
|
192 |
+
<label><input type="checkbox" %s> %s</label><br>
|
193 |
+
<label><input type="checkbox" %s> %s</label><br>
|
194 |
+
<label><input type="checkbox" %s> %s</label><br>
|
195 |
+
<label><input type="checkbox" %s> %s</label><br>
|
196 |
+
<label><input type="checkbox" %s> %s</label>
|
197 |
+
</fieldset>
|
198 |
+
</td>
|
199 |
+
</tr>
|
200 |
+
<tr>
|
201 |
+
<th>%s</th>
|
202 |
+
<td>%s</td>
|
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_COMMENTS_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();
|
admin/config/plugins.php
ADDED
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
admin/config/remote-ips.php
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
* Section blurb.
|
101 |
+
*
|
102 |
+
* @since 4.0.0
|
103 |
+
*/
|
104 |
+
public function sectionGeo()
|
105 |
+
{
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* MaxMind database.
|
110 |
+
*
|
111 |
+
* @since 4.0.0
|
112 |
+
*/
|
113 |
+
public function database()
|
114 |
+
{
|
115 |
+
$settings = get_option( 'wp-fail2ban' );
|
116 |
+
$exists = file_exists( @$settings['remote-ip']['maxmind']['path'] );
|
117 |
+
$fmt = <<<__FMT__
|
118 |
+
<fieldset>
|
119 |
+
<label><input type="checkbox" name="wp-fail2ban[remote-ip][maxmind]" %s> Download now</label>
|
120 |
+
<p class="description">%s</p>
|
121 |
+
</fieldset>
|
122 |
+
__FMT__;
|
123 |
+
printf( $fmt, checked( $exists, false, false ), ( $exists ? __( 'Last modified: ' ) . gmdate( DATE_RFC1123, $settings['remote-ip']['maxmind']['modified'] ) : __( 'No database found.' ) ) );
|
124 |
+
}
|
125 |
+
|
126 |
+
}
|
127 |
+
new TabRemoteIPs();
|
admin/config/syslog.php
ADDED
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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( 'workarounds', __( '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>
|
104 |
+
<label><input type="checkbox" disabled="disabled" %s> <code>LOG_PID</code> <em>(%s)</em></label><br>
|
105 |
+
<label><input type="radio" disabled="disabled" %s> <code>LOG_NDELAY</code> <em>(%s)</em></label><br>
|
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>
|
142 |
+
<label><input type="checkbox" disabled="disabled" %s> %s</label>
|
143 |
+
<br>
|
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();
|
admin/lib/about.php
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
if ( !defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
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 |
+
?>
|
25 |
+
<div class="wrap">
|
26 |
+
<style>
|
27 |
+
div.inside ul {
|
28 |
+
list-style: disc;
|
29 |
+
padding-left: 2em;
|
30 |
+
}
|
31 |
+
</style>
|
32 |
+
<?php
|
33 |
+
if ( !$hide_title ) {
|
34 |
+
?>
|
35 |
+
<h1>WP fail2ban</h1>
|
36 |
+
<?php
|
37 |
+
}
|
38 |
+
?>
|
39 |
+
<div id="poststuff">
|
40 |
+
<div id="post-body" class="metabox-holder columns-2">
|
41 |
+
<div id="post-body-content">
|
42 |
+
<div class="meta-box-sortables ui-sortable">
|
43 |
+
<div class="postbox">
|
44 |
+
<h2>Version <?php
|
45 |
+
echo WP_FAIL2BAN_VER ;
|
46 |
+
?></h2>
|
47 |
+
<div class="inside">
|
48 |
+
<ul>
|
49 |
+
<li><p>Completed support for <tt><a href="https://docs.wp-fail2ban.com/en/4.2/defines/WP_FAIL2BAN_COMMENT_EXTRA_LOG.html" target="docs.wp-fail2ban.com">WP_FAIL2BAN_COMMENT_EXTRA_LOG</a></tt>.</p></li>
|
50 |
+
<li><p>Add support for 3rd-party plugins; see <a href="https://docs.wp-fail2ban.com/en/4.2/developers.html" target="docs.wp-fail2ban.com">Developers</a>.</p>
|
51 |
+
<ul>
|
52 |
+
<li>Add-on for <a href="https://wordpress.org/plugins/wp-fail2ban-addon-contact-form-7/">Contact Form 7</a> (experimental).</li>
|
53 |
+
<li>Add-on for <a href="https://wordpress.org/plugins/wp-fail2ban-addon-gravity-forms/">Gravity Forms</a> (experimental).</li>
|
54 |
+
</ul>
|
55 |
+
</li>
|
56 |
+
<li><p>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>.</p></li>
|
57 |
+
<li><p>Bugfix for email-as-username - now logged correctly and matched by <tt>soft</tt>, not <tt>hard</tt>, filters.</p></li>
|
58 |
+
<li><p>Bugfix for regression in code to prevent Free/Premium conflict.</p></li>
|
59 |
+
</ul>
|
60 |
+
</div>
|
61 |
+
</div>
|
62 |
+
</div>
|
63 |
+
</div>
|
64 |
+
<div id="postbox-container-1" class="postbox-container">
|
65 |
+
<div class="meta-box-sortables">
|
66 |
+
<div class="postbox">
|
67 |
+
<h2>Getting Started</h2>
|
68 |
+
<div class="inside">
|
69 |
+
<ol>
|
70 |
+
<li><a href="https://docs.wp-fail2ban.com/en/<?php
|
71 |
+
echo $wp_f2b_ver ;
|
72 |
+
?>/introduction.html" target="docs.wp-fail2ban.com">Introduction</a></li>
|
73 |
+
<li><a href="https://docs.wp-fail2ban.com/en/<?php
|
74 |
+
echo $wp_f2b_ver ;
|
75 |
+
?>/configuration.html" target="docs.wp-fail2ban.com">Configuration</a></li>
|
76 |
+
</ol>
|
77 |
+
</div>
|
78 |
+
</div>
|
79 |
+
<div class="postbox">
|
80 |
+
<h2>Getting Help</h2>
|
81 |
+
<div class="inside">
|
82 |
+
<ul>
|
83 |
+
<?php
|
84 |
+
?>
|
85 |
+
<li><a href="https://wordpress.org/support/plugin/wp-fail2ban/" target="_blank">WordPress.org Forum</a></li>
|
86 |
+
<?php
|
87 |
+
?>
|
88 |
+
</div>
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
</div>
|
92 |
+
</div>
|
93 |
+
|
94 |
+
</div>
|
95 |
+
</div>
|
96 |
+
<?php
|
97 |
+
}
|
admin/lib/tab.php
ADDED
@@ -0,0 +1,260 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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://wp-fail2ban.readthedocs.io/en/%s/defines/%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, bool $_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 ) && constant( "{$define_log}_NDEF" );
|
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, $enabled ),
|
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 |
+
}
|
admin/summary.php
DELETED
@@ -1,282 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Configuration summary
|
4 |
-
*
|
5 |
-
* @package wp-fail2ban
|
6 |
-
* @since 4.0.0
|
7 |
-
*/
|
8 |
-
namespace org\lecklider\charles\wordpress\wp_fail2ban;
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Add options page
|
12 |
-
*
|
13 |
-
* @since 4.0.0
|
14 |
-
*/
|
15 |
-
function admin_menu()
|
16 |
-
{
|
17 |
-
add_options_page(
|
18 |
-
'WP fail2ban - Summary',
|
19 |
-
'WP fail2ban',
|
20 |
-
'manage_options',
|
21 |
-
'wp-fail2ban',
|
22 |
-
__NAMESPACE__.'\summary'
|
23 |
-
);
|
24 |
-
}
|
25 |
-
add_action('admin_menu', __NAMESPACE__.'\admin_menu');
|
26 |
-
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Link to documentation
|
30 |
-
*
|
31 |
-
* @since 4.0.0
|
32 |
-
*
|
33 |
-
* @param string $define
|
34 |
-
* @param string $name
|
35 |
-
*
|
36 |
-
* @return string
|
37 |
-
*/
|
38 |
-
function _doc_link($define, $name)
|
39 |
-
{
|
40 |
-
static $wp_f2b_ver;
|
41 |
-
|
42 |
-
if (empty($wp_f2b_ver)) {
|
43 |
-
$wp_f2b_ver = substr(WP_FAIL2BAN_VER, 0, strrpos(WP_FAIL2BAN_VER, '.'));
|
44 |
-
}
|
45 |
-
|
46 |
-
return sprintf('<a href="https://wp-fail2ban.readthedocs.io/en/%s/defines.html#%s" target="_blank">%s <span class="dashicons dashicons-external"></span></a>', $wp_f2b_ver, str_replace('_', '-', strtolower($define)), $name);
|
47 |
-
}
|
48 |
-
|
49 |
-
|
50 |
-
/**
|
51 |
-
* List log facilities
|
52 |
-
*
|
53 |
-
* @param int $facility
|
54 |
-
*
|
55 |
-
* @since 4.0.0
|
56 |
-
*/
|
57 |
-
function _get_log_facility($facility)
|
58 |
-
{
|
59 |
-
$facilities = array(
|
60 |
-
LOG_AUTH => 'LOG_AUTH',
|
61 |
-
LOG_AUTHPRIV => 'LOG_AUTHPRIV',
|
62 |
-
LOG_CRON => 'LOG_CRON',
|
63 |
-
LOG_DAEMON => 'LOG_DAEMON',
|
64 |
-
LOG_KERN => 'LOG_KERN',
|
65 |
-
LOG_LOCAL0 => 'LOG_LOCAL0',
|
66 |
-
LOG_LOCAL1 => 'LOG_LOCAL1',
|
67 |
-
LOG_LOCAL2 => 'LOG_LOCAL2',
|
68 |
-
LOG_LOCAL3 => 'LOG_LOCAL3',
|
69 |
-
LOG_LOCAL4 => 'LOG_LOCAL4',
|
70 |
-
LOG_LOCAL5 => 'LOG_LOCAL5',
|
71 |
-
LOG_LOCAL6 => 'LOG_LOCAL6',
|
72 |
-
LOG_LOCAL7 => 'LOG_LOCAL7',
|
73 |
-
LOG_LPR => 'LOG_LPR',
|
74 |
-
LOG_MAIL => 'LOG_MAIL',
|
75 |
-
LOG_NEWS => 'LOG_NEWS',
|
76 |
-
LOG_SYSLOG => 'LOG_SYSLOG',
|
77 |
-
LOG_USER => 'LOG_USER',
|
78 |
-
LOG_UUCP => 'LOG_UUCP',
|
79 |
-
);
|
80 |
-
|
81 |
-
return (array_key_exists($facility, $facilities))
|
82 |
-
? $facilities[$facility]
|
83 |
-
: '(unknown)';
|
84 |
-
}
|
85 |
-
|
86 |
-
|
87 |
-
/**
|
88 |
-
*
|
89 |
-
*
|
90 |
-
* @since 4.0.0
|
91 |
-
*
|
92 |
-
* @param string $name
|
93 |
-
* @param string $enabled
|
94 |
-
* @param string $location
|
95 |
-
*/
|
96 |
-
function _log($name, $enabled, $location)
|
97 |
-
{
|
98 |
-
?>
|
99 |
-
<tr>
|
100 |
-
<th><?php echo _doc_link($enabled, $name); ?></th>
|
101 |
-
<?php if (defined($enabled) && true === constant($enabled)) : ?>
|
102 |
-
<td><?php _e('Yes'); ?></td>
|
103 |
-
<th><?php _e('Facility'); ?></th>
|
104 |
-
<td><?php echo _get_log_facility(constant($location))?> <?php echo (constant($location) == constant("DEFAULT_$location")) ? ' <em>('.__('default').')</em>' : ''; ?></td>
|
105 |
-
<?php else : ?>
|
106 |
-
<td><?php _e('No'); ?></td>
|
107 |
-
<?php endif; ?>
|
108 |
-
</tr>
|
109 |
-
<?php
|
110 |
-
}
|
111 |
-
|
112 |
-
|
113 |
-
/**
|
114 |
-
* Display syslog connection options
|
115 |
-
*
|
116 |
-
* @since 4.0.0
|
117 |
-
*/
|
118 |
-
function _log_options()
|
119 |
-
{
|
120 |
-
$options = (defined('WP_FAIL2BAN_OPENLOG_OPTIONS'))
|
121 |
-
? WP_FAIL2BAN_OPENLOG_OPTIONS
|
122 |
-
: DEFAULT_WP_FAIL2BAN_OPENLOG_OPTIONS;
|
123 |
-
|
124 |
-
$opts = array();
|
125 |
-
(LOG_CONS == ($options & LOG_CONS)) and $opts[] = 'LOG_CONS';
|
126 |
-
(LOG_PERROR == ($options & LOG_PERROR)) and $opts[] = 'LOG_PERROR';
|
127 |
-
(LOG_PID == ($options & LOG_PID)) and $opts[] = 'LOG_PID';
|
128 |
-
(LOG_NDELAY == ($options & LOG_NDELAY)) and $opts[] = 'LOG_NDELAY';
|
129 |
-
(LOG_ODELAY == ($options & LOG_ODELAY)) and $opts[] = 'LOG_ODELAY';
|
130 |
-
?>
|
131 |
-
<tr>
|
132 |
-
<th><?php echo _doc_link('WP_FAIL2BAN_OPENLOG_OPTIONS', __('Connection')); ?></th>
|
133 |
-
<td colspan="3"><?php sprintf((DEFAULT_WP_FAIL2BAN_OPENLOG_OPTIONS == $options)
|
134 |
-
? '%s <em>(%s)</em>'
|
135 |
-
: '%s', join(', ', $opts), __('default')); ?></td>
|
136 |
-
</tr>
|
137 |
-
<?php
|
138 |
-
}
|
139 |
-
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Display Yes/No/array values
|
143 |
-
*
|
144 |
-
* @param string $name
|
145 |
-
* @param string|array $option
|
146 |
-
* @param bool|null $ary
|
147 |
-
*
|
148 |
-
* @since 4.0.0
|
149 |
-
*/
|
150 |
-
function _yes_no_array($name, $option, $ary = false)
|
151 |
-
{
|
152 |
-
$th = _doc_link($option, $name);
|
153 |
-
|
154 |
-
if ($ary) {
|
155 |
-
if (defined($option)) {
|
156 |
-
$items = (is_array(constant($option)))
|
157 |
-
? constant($option)
|
158 |
-
: trim(' "', explode(',', constant($option)));
|
159 |
-
} else {
|
160 |
-
$items = array('-');
|
161 |
-
}
|
162 |
-
$td = join(', ', $items);
|
163 |
-
} elseif (is_null($ary)) {
|
164 |
-
if (defined($option)) {
|
165 |
-
$td = (is_array(constant($option)))
|
166 |
-
? join(' ,', constant($option))
|
167 |
-
: constant($option);
|
168 |
-
} else {
|
169 |
-
$td = '-';
|
170 |
-
}
|
171 |
-
} else {
|
172 |
-
$td = (defined($option) && true === constant($option))
|
173 |
-
? __('Yes')
|
174 |
-
: __('No');
|
175 |
-
}
|
176 |
-
|
177 |
-
echo <<<___YNA___
|
178 |
-
<tr>
|
179 |
-
<th>$th</th>
|
180 |
-
<td>$td</td>
|
181 |
-
</tr>
|
182 |
-
___YNA___;
|
183 |
-
}
|
184 |
-
|
185 |
-
|
186 |
-
/**
|
187 |
-
* Display configuration summary
|
188 |
-
*
|
189 |
-
* @since 4.0.0
|
190 |
-
*/
|
191 |
-
function summary()
|
192 |
-
{
|
193 |
-
?>
|
194 |
-
<div class="wrap">
|
195 |
-
<style>
|
196 |
-
table.form-table a {
|
197 |
-
text-decoration: none;
|
198 |
-
}
|
199 |
-
</style>
|
200 |
-
<h1>WP fail2ban - Summary</h1>
|
201 |
-
<?php if (wf_fs()->is_not_paying()):
|
202 |
-
$ver = PHP_VERSION;
|
203 |
-
if (version_compare($ver, '7.1.0', '<')):
|
204 |
-
$wp = '<p>WordPress will <a href="https://make.wordpress.org/core/2018/12/08/updating-the-minimum-php-version/">soon require</a> at least PHP 5.6.</p>';
|
205 |
-
?>
|
206 |
-
<h2>Please <a href="https://wordpress.org/support/update-php/">update PHP!</a></h2>
|
207 |
-
<?php if (version_compare($ver, '5.4.0', '<')): ?>
|
208 |
-
<p>Support for PHP 5.3 ended 14 Aug 2014.</p>
|
209 |
-
<p><em>WP fail2ban Premium</em> currently requires at least PHP 5.4.</p>
|
210 |
-
<?php echo $wp; ?>
|
211 |
-
<?php elseif (version_compare($ver, '5.5.0', '<')): ?>
|
212 |
-
<p>Support for PHP 5.4 ended 3 Sep 2015.</p>
|
213 |
-
<?php echo $wp; ?>
|
214 |
-
<?php elseif (version_compare($ver, '5.6.0', '<')): ?>
|
215 |
-
<p>Support for PHP 5.5 ended 21 Jul 2016.</p>
|
216 |
-
<?php echo $wp; ?>
|
217 |
-
<?php elseif (version_compare($ver, '7.0.0', '<')): ?>
|
218 |
-
<p>Support for PHP 5.6 ended 31 Dec 2018.</p>
|
219 |
-
<?php else: ?>
|
220 |
-
<p>Support for PHP 7.0 ended 3 Dec 2018.</p>
|
221 |
-
<?php endif; ?>
|
222 |
-
<hr>
|
223 |
-
<?php endif; ?>
|
224 |
-
<?php if (version_compare($ver, '5.3.0', '>')): ?>
|
225 |
-
<p>Do you want a simple GUI to change these settings?</p>
|
226 |
-
<p>Do you want reports on where and when attacks are happening?</p>
|
227 |
-
<p><a href="<?php echo wf_fs()->get_upgrade_url(); ?>">Upgrade now!</a></p>
|
228 |
-
<hr>
|
229 |
-
<?php endif; ?>
|
230 |
-
<?php endif; ?>
|
231 |
-
<div class="card">
|
232 |
-
<h2 class="title"><?php _e('Logging'); ?></h2>
|
233 |
-
<table class="form-table">
|
234 |
-
<tbody>
|
235 |
-
<?php
|
236 |
-
_log(__('Comments'), 'WP_FAIL2BAN_LOG_COMMENTS', 'WP_FAIL2BAN_COMMENT_LOG');
|
237 |
-
_log(__('Password Requests'), 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST', 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG');
|
238 |
-
_log(__('Pingbacks'), 'WP_FAIL2BAN_LOG_PINGBACKS', 'WP_FAIL2BAN_PINGBACK_LOG');
|
239 |
-
_log(__('Spam'), 'WP_FAIL2BAN_LOG_SPAM', 'WP_FAIL2BAN_SPAM_LOG');
|
240 |
-
_log_options();
|
241 |
-
?>
|
242 |
-
</tbody>
|
243 |
-
</table>
|
244 |
-
</div>
|
245 |
-
<div class="card">
|
246 |
-
<h2 class="title"><?php _e('Workarounds'); ?></h2>
|
247 |
-
<table class="form-table">
|
248 |
-
<tbody>
|
249 |
-
<?php
|
250 |
-
_yes_no_array(__('Short Tag'), 'WP_FAIL2BAN_SYSLOG_SHORT_TAG');
|
251 |
-
_yes_no_array(__('Specify Host'), 'WP_FAIL2BAN_HTTP_HOST');
|
252 |
-
_yes_no_array(__('Truncate Host'), 'WP_FAIL2BAN_TRUNCATE_HOST');
|
253 |
-
?>
|
254 |
-
</tbody>
|
255 |
-
</table>
|
256 |
-
</div>
|
257 |
-
<div class="card">
|
258 |
-
<h2 class="title"><?php _e('Block'); ?></h2>
|
259 |
-
<table class="form-table">
|
260 |
-
<tbody>
|
261 |
-
<?php
|
262 |
-
_yes_no_array(__('User Enumeration'), 'WP_FAIL2BAN_BLOCK_USER_ENUMERATION');
|
263 |
-
_yes_no_array(__('Usernames'), 'WP_FAIL2BAN_BLOCKED_USERS', null);
|
264 |
-
?>
|
265 |
-
</tbody>
|
266 |
-
</table>
|
267 |
-
</div>
|
268 |
-
<div class="card">
|
269 |
-
<h2 class="title"><?php _e('Misc'); ?></h2>
|
270 |
-
<table class="form-table">
|
271 |
-
<tbody>
|
272 |
-
<?php
|
273 |
-
_yes_no_array(__('Proxies'), 'WP_FAIL2BAN_PROXIES', true);
|
274 |
-
_yes_no_array(__('Remote Address'), 'WP_FAIL2BAN_REMOTE_ADDR', null);
|
275 |
-
?>
|
276 |
-
</tbody>
|
277 |
-
</table>
|
278 |
-
</div>
|
279 |
-
</div>
|
280 |
-
<?php
|
281 |
-
}
|
282 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
feature/comments.php
CHANGED
@@ -32,6 +32,7 @@ if ( !function_exists( __NAMESPACE__ . '\\notify_post_author' ) ) {
|
|
32 |
{
|
33 |
openlog( 'WP_FAIL2BAN_COMMENT_LOG' );
|
34 |
syslog( LOG_INFO, "Comment {$comment_ID}" );
|
|
|
35 |
// @codeCoverageIgnoreEnd
|
36 |
return $maybe_notify;
|
37 |
}
|
@@ -46,7 +47,7 @@ if ( !function_exists( __NAMESPACE__ . '\\notify_post_author' ) ) {
|
|
46 |
|
47 |
|
48 |
if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA' ) ) {
|
49 |
-
/**
|
50 |
if ( WP_FAIL2BAN_LOG_COMMENTS_EXTRA & 0x20002 ) {
|
51 |
/**
|
52 |
* @since 4.0.5 Guard
|
@@ -64,8 +65,9 @@ if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA' ) ) {
|
|
64 |
*/
|
65 |
function comment_id_not_found( $comment_post_ID )
|
66 |
{
|
67 |
-
openlog( '
|
68 |
syslog( LOG_NOTICE, "Comment post not found {$comment_post_ID}" );
|
|
|
69 |
// @codeCoverageIgnoreEnd
|
70 |
}
|
71 |
|
@@ -91,8 +93,9 @@ if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA' ) ) {
|
|
91 |
*/
|
92 |
function comment_closed( $comment_post_ID )
|
93 |
{
|
94 |
-
openlog( '
|
95 |
syslog( LOG_NOTICE, "Comments closed on post {$comment_post_ID}" );
|
|
|
96 |
// @codeCoverageIgnoreEnd
|
97 |
}
|
98 |
|
@@ -119,8 +122,9 @@ if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA' ) ) {
|
|
119 |
*/
|
120 |
function comment_on_trash( $comment_post_ID )
|
121 |
{
|
122 |
-
openlog( '
|
123 |
syslog( LOG_NOTICE, "Comment attempt on trash post {$comment_post_ID}" );
|
|
|
124 |
// @codeCoverageIgnoreEnd
|
125 |
}
|
126 |
|
@@ -147,8 +151,9 @@ if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA' ) ) {
|
|
147 |
*/
|
148 |
function comment_on_draft( $comment_post_ID )
|
149 |
{
|
150 |
-
openlog( '
|
151 |
syslog( LOG_NOTICE, "Comment attempt on draft post {$comment_post_ID}" );
|
|
|
152 |
// @codeCoverageIgnoreEnd
|
153 |
}
|
154 |
|
@@ -175,8 +180,9 @@ if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS_EXTRA' ) ) {
|
|
175 |
*/
|
176 |
function comment_on_password_protected( $comment_post_ID )
|
177 |
{
|
178 |
-
openlog( '
|
179 |
syslog( LOG_NOTICE, "Comment attempt on password-protected post {$comment_post_ID}" );
|
|
|
180 |
// @codeCoverageIgnoreEnd
|
181 |
}
|
182 |
|
32 |
{
|
33 |
openlog( 'WP_FAIL2BAN_COMMENT_LOG' );
|
34 |
syslog( LOG_INFO, "Comment {$comment_ID}" );
|
35 |
+
closelog();
|
36 |
// @codeCoverageIgnoreEnd
|
37 |
return $maybe_notify;
|
38 |
}
|
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
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
feature/lib.php
CHANGED
@@ -73,6 +73,8 @@ function syslog( $level, $msg, $remote_addr = null )
|
|
73 |
*
|
74 |
* @since 4.0.5 Add JSON support
|
75 |
* @since 3.5.0 Refactored for unit testing
|
|
|
|
|
76 |
*/
|
77 |
function bail( $is_json = false )
|
78 |
{
|
73 |
*
|
74 |
* @since 4.0.5 Add JSON support
|
75 |
* @since 3.5.0 Refactored for unit testing
|
76 |
+
*
|
77 |
+
* @param bool $is_json
|
78 |
*/
|
79 |
function bail( $is_json = false )
|
80 |
{
|
feature/password.php
CHANGED
@@ -29,6 +29,7 @@ if ( !function_exists( __NAMESPACE__ . '\\retrieve_password' ) ) {
|
|
29 |
{
|
30 |
openlog( 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG' );
|
31 |
syslog( LOG_NOTICE, "Password reset requested for {$user_login}" );
|
|
|
32 |
// @codeCoverageIgnoreEnd
|
33 |
}
|
34 |
|
29 |
{
|
30 |
openlog( 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG' );
|
31 |
syslog( LOG_NOTICE, "Password reset requested for {$user_login}" );
|
32 |
+
closelog();
|
33 |
// @codeCoverageIgnoreEnd
|
34 |
}
|
35 |
|
feature/plugins.php
ADDED
@@ -0,0 +1,233 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
);
|
feature/spam.php
CHANGED
@@ -38,6 +38,7 @@ if ( !function_exists( __NAMESPACE__ . '\\log_spam_comment' ) ) {
|
|
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 |
// @codeCoverageIgnoreEnd
|
42 |
}
|
43 |
|
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 |
|
feature/user-enum.php
CHANGED
@@ -31,6 +31,7 @@ if ( !function_exists( __NAMESPACE__ . '\\_log_bail_user_enum' ) ) {
|
|
31 |
{
|
32 |
openlog();
|
33 |
syslog( LOG_NOTICE, 'Blocked user enumeration attempt' );
|
|
|
34 |
// @codeCoverageIgnoreEnd
|
35 |
return bail( $is_json );
|
36 |
}
|
31 |
{
|
32 |
openlog();
|
33 |
syslog( LOG_NOTICE, 'Blocked user enumeration attempt' );
|
34 |
+
closelog();
|
35 |
// @codeCoverageIgnoreEnd
|
36 |
return bail( $is_json );
|
37 |
}
|
feature/user.php
CHANGED
@@ -42,6 +42,7 @@ if ( !function_exists( __NAMESPACE__ . '\\authenticate' ) ) {
|
|
42 |
if ( $matched ) {
|
43 |
openlog();
|
44 |
syslog( LOG_NOTICE, "Blocked authentication attempt for {$username}" );
|
|
|
45 |
// @codeCoverageIgnoreEnd
|
46 |
bail();
|
47 |
}
|
42 |
if ( $matched ) {
|
43 |
openlog();
|
44 |
syslog( LOG_NOTICE, "Blocked authentication attempt for {$username}" );
|
45 |
+
closelog();
|
46 |
// @codeCoverageIgnoreEnd
|
47 |
bail();
|
48 |
}
|
feature/xmlrpc.php
CHANGED
@@ -39,6 +39,7 @@ if ( !function_exists( __NAMESPACE__ . '\\xmlrpc_login_error' ) ) {
|
|
39 |
if ( ++$attempts > 1 ) {
|
40 |
openlog();
|
41 |
syslog( LOG_NOTICE, 'XML-RPC multicall authentication failure' );
|
|
|
42 |
// @codeCoverageIgnoreEnd
|
43 |
bail();
|
44 |
} else {
|
@@ -81,6 +82,7 @@ if ( !function_exists( __NAMESPACE__ . '\\xmlrpc_pingback_error' ) ) {
|
|
81 |
if ( 48 !== $ixr_error->code ) {
|
82 |
openlog();
|
83 |
syslog( LOG_NOTICE, 'Pingback error ' . $ixr_error->code . ' generated' );
|
|
|
84 |
// @codeCoverageIgnoreEnd
|
85 |
}
|
86 |
|
39 |
if ( ++$attempts > 1 ) {
|
40 |
openlog();
|
41 |
syslog( LOG_NOTICE, 'XML-RPC multicall authentication failure' );
|
42 |
+
closelog();
|
43 |
// @codeCoverageIgnoreEnd
|
44 |
bail();
|
45 |
} else {
|
82 |
if ( 48 !== $ixr_error->code ) {
|
83 |
openlog();
|
84 |
syslog( LOG_NOTICE, 'Pingback error ' . $ixr_error->code . ' generated' );
|
85 |
+
closelog();
|
86 |
// @codeCoverageIgnoreEnd
|
87 |
}
|
88 |
|
feature/xmlrpc/pingback.php
CHANGED
@@ -30,6 +30,7 @@ if ( !function_exists( __NAMESPACE__ . '\\xmlrpc_call' ) ) {
|
|
30 |
if ( 'pingback.ping' == $call ) {
|
31 |
openlog( 'WP_FAIL2BAN_PINGBACK_LOG' );
|
32 |
syslog( LOG_INFO, 'Pingback requested' );
|
|
|
33 |
// @codeCoverageIgnoreEnd
|
34 |
}
|
35 |
|
30 |
if ( 'pingback.ping' == $call ) {
|
31 |
openlog( 'WP_FAIL2BAN_PINGBACK_LOG' );
|
32 |
syslog( LOG_INFO, 'Pingback requested' );
|
33 |
+
closelog();
|
34 |
// @codeCoverageIgnoreEnd
|
35 |
}
|
36 |
|
filters.d/wordpress-extra.conf
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
# Fail2Ban filter for WordPress extra failures
|
2 |
-
# Auto-generated: 2019-
|
3 |
#
|
4 |
|
5 |
[INCLUDES]
|
1 |
# Fail2Ban filter for WordPress extra failures
|
2 |
+
# Auto-generated: 2019-04-18T14:58:18+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: 2019-
|
3 |
#
|
4 |
|
5 |
[INCLUDES]
|
1 |
# Fail2Ban filter for WordPress hard failures
|
2 |
+
# Auto-generated: 2019-04-18T14:58:18+00:00
|
3 |
#
|
4 |
|
5 |
[INCLUDES]
|
filters.d/wordpress-soft.conf
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
# Fail2Ban filter for WordPress soft failures
|
2 |
-
# Auto-generated: 2019-
|
3 |
#
|
4 |
|
5 |
[INCLUDES]
|
1 |
# Fail2Ban filter for WordPress soft failures
|
2 |
+
# Auto-generated: 2019-04-18T14:58:18+00:00
|
3 |
#
|
4 |
|
5 |
[INCLUDES]
|
lib/constants.php
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
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_SPAM', WPF2B_EVENT_CLASS_COMMENT | WPF2B_EVENT_CLASS_SPAM | 0x0001); // 0x00220001
|
110 |
+
// comment extra
|
111 |
+
define('WPF2B_EVENT_COMMENT_NOT_FOUND', WPF2B_EVENT_CLASS_COMMENT | 0x0002); // 0x00020002
|
112 |
+
define('WPF2B_EVENT_COMMENT_CLOSED', WPF2B_EVENT_CLASS_COMMENT | 0x0004); // 0x00020004
|
113 |
+
define('WPF2B_EVENT_COMMENT_TRASH', WPF2B_EVENT_CLASS_COMMENT | 0x0008); // 0x00020008
|
114 |
+
define('WPF2B_EVENT_COMMENT_DRAFT', WPF2B_EVENT_CLASS_COMMENT | 0x0010); // 0x00020010
|
115 |
+
define('WPF2B_EVENT_COMMENT_PASSWORD', WPF2B_EVENT_CLASS_COMMENT | WPF2B_EVENT_CLASS_PASSWORD | 0x0020); // 0x00020020
|
116 |
+
|
117 |
+
/**
|
118 |
+
* XML-RPC
|
119 |
+
*/
|
120 |
+
define('WPF2B_EVENT_XMLRPC_PINGBACK', WPF2B_EVENT_CLASS_XMLRPC | 0x0001);
|
121 |
+
define('WPF2B_EVENT_XMLRPC_PINGBACK_ERROR', WPF2B_EVENT_CLASS_XMLRPC | 0x0002);
|
122 |
+
define('WPF2B_EVENT_XMLRPC_MULTI_AUTH_FAIL', WPF2B_EVENT_CLASS_XMLRPC | WPF2B_EVENT_CLASS_AUTH | 0x0004);
|
123 |
+
define('WPF2B_EVENT_XMLRPC_AUTH_OK', WPF2B_EVENT_CLASS_XMLRPC | WPF2B_EVENT_CLASS_AUTH | 0x0008);
|
124 |
+
define('WPF2B_EVENT_XMLRPC_AUTH_FAIL', WPF2B_EVENT_CLASS_XMLRPC | WPF2B_EVENT_CLASS_AUTH | 0x0010);
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Password
|
128 |
+
*/
|
129 |
+
define('WPF2B_ACTION_PASSWORD_REQUEST', WPF2B_EVENT_CLASS_PASSWORD | 0x0001);
|
130 |
+
|
131 |
+
/**
|
132 |
+
* REST
|
133 |
+
* @since 4.1.0
|
134 |
+
*/
|
135 |
+
define('WPF2B_EVENT_REST_AUTH_OK', WPF2B_EVENT_CLASS_REST | WPF2B_EVENT_CLASS_AUTH | 0x0001);
|
136 |
+
define('WPF2B_EVENT_REST_AUTH_FAIL', WPF2B_EVENT_CLASS_REST | WPF2B_EVENT_CLASS_AUTH | 0x0002);
|
137 |
+
|
138 |
+
/**
|
139 |
+
*
|
140 |
+
*/
|
141 |
+
define('WPF2B_EVENT_DEACTIVATED', 0x00000000);
|
142 |
+
// phpcs:enable
|
143 |
+
|
lib/defaults.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
lib/loader.php
ADDED
@@ -0,0 +1,303 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Loader
|
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 |
+
if ( defined( 'PHPUNIT_COMPOSER_INSTALL' ) ) {
|
15 |
+
return;
|
16 |
+
}
|
17 |
+
/**
|
18 |
+
* Helper
|
19 |
+
*
|
20 |
+
* @since 4.0.0
|
21 |
+
*
|
22 |
+
* @param string $define
|
23 |
+
* @param callable $cast
|
24 |
+
* @param bool $unset
|
25 |
+
* @param array $field
|
26 |
+
*/
|
27 |
+
function _load(
|
28 |
+
$define,
|
29 |
+
$cast,
|
30 |
+
$unset,
|
31 |
+
array $field
|
32 |
+
)
|
33 |
+
{
|
34 |
+
define( "{$define}_NDEF", !defined( $define ) );
|
35 |
+
if ( constant( "{$define}_NDEF" ) ) {
|
36 |
+
|
37 |
+
if ( defined( "DEFAULT_{$define}" ) ) {
|
38 |
+
// we've got a default
|
39 |
+
define( $define, $cast( constant( "DEFAULT_{$define}" ) ) );
|
40 |
+
} else {
|
41 |
+
// bah
|
42 |
+
define( $define, $cast( false ) );
|
43 |
+
}
|
44 |
+
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Validate IP list
|
50 |
+
*
|
51 |
+
* @since 4.0.0
|
52 |
+
*
|
53 |
+
* @param array|string $value
|
54 |
+
*
|
55 |
+
* @return string
|
56 |
+
*/
|
57 |
+
function validate_ips( $value )
|
58 |
+
{
|
59 |
+
return $value;
|
60 |
+
}
|
61 |
+
|
62 |
+
// phpcs:disable Generic.Functions.FunctionCallArgumentSpacing
|
63 |
+
_load(
|
64 |
+
'WP_FAIL2BAN_AUTH_LOG',
|
65 |
+
'intval',
|
66 |
+
true,
|
67 |
+
[ 'logging', 'authentication', 'facility' ]
|
68 |
+
);
|
69 |
+
_load(
|
70 |
+
'WP_FAIL2BAN_LOG_COMMENTS',
|
71 |
+
'boolval',
|
72 |
+
true,
|
73 |
+
[ 'logging', 'comments', 'enabled' ]
|
74 |
+
);
|
75 |
+
_load(
|
76 |
+
'WP_FAIL2BAN_LOG_COMMENTS_EXTRA',
|
77 |
+
'intval',
|
78 |
+
true,
|
79 |
+
[ 'logging', 'comments', 'extra' ]
|
80 |
+
);
|
81 |
+
_load(
|
82 |
+
'WP_FAIL2BAN_COMMENT_LOG',
|
83 |
+
'intval',
|
84 |
+
false,
|
85 |
+
[ 'logging', 'comments', 'facility' ]
|
86 |
+
);
|
87 |
+
_load(
|
88 |
+
'WP_FAIL2BAN_COMMENT_EXTRA_LOG',
|
89 |
+
'intval',
|
90 |
+
false,
|
91 |
+
[ 'logging', 'comments-extra', 'facility' ]
|
92 |
+
);
|
93 |
+
_load(
|
94 |
+
'WP_FAIL2BAN_LOG_PASSWORD_REQUEST',
|
95 |
+
'boolval',
|
96 |
+
true,
|
97 |
+
[ 'logging', 'password-request', 'enabled' ]
|
98 |
+
);
|
99 |
+
_load(
|
100 |
+
'WP_FAIL2BAN_PASSWORD_REQUEST_LOG',
|
101 |
+
'intval',
|
102 |
+
false,
|
103 |
+
[ 'logging', 'password-request', 'facility' ]
|
104 |
+
);
|
105 |
+
_load(
|
106 |
+
'WP_FAIL2BAN_LOG_PINGBACKS',
|
107 |
+
'boolval',
|
108 |
+
true,
|
109 |
+
[ 'logging', 'pingback', 'enabled' ]
|
110 |
+
);
|
111 |
+
_load(
|
112 |
+
'WP_FAIL2BAN_PINGBACK_LOG',
|
113 |
+
'intval',
|
114 |
+
false,
|
115 |
+
[ 'logging', 'pingback', 'facility' ]
|
116 |
+
);
|
117 |
+
_load(
|
118 |
+
'WP_FAIL2BAN_LOG_SPAM',
|
119 |
+
'boolval',
|
120 |
+
true,
|
121 |
+
[ 'logging', 'spam', 'enabled' ]
|
122 |
+
);
|
123 |
+
_load(
|
124 |
+
'WP_FAIL2BAN_SPAM_LOG',
|
125 |
+
'intval',
|
126 |
+
false,
|
127 |
+
[ 'logging', 'spam', 'facility' ]
|
128 |
+
);
|
129 |
+
_load(
|
130 |
+
'WP_FAIL2BAN_OPENLOG_OPTIONS',
|
131 |
+
'intval',
|
132 |
+
true,
|
133 |
+
[ 'syslog', 'connection' ]
|
134 |
+
);
|
135 |
+
_load(
|
136 |
+
'WP_FAIL2BAN_SYSLOG_SHORT_TAG',
|
137 |
+
'boolval',
|
138 |
+
true,
|
139 |
+
[ 'syslog', 'workaround', 'short_tag' ]
|
140 |
+
);
|
141 |
+
_load(
|
142 |
+
'WP_FAIL2BAN_HTTP_HOST',
|
143 |
+
'boolval',
|
144 |
+
true,
|
145 |
+
[ 'syslog', 'workaround', 'http_host' ]
|
146 |
+
);
|
147 |
+
_load(
|
148 |
+
'WP_FAIL2BAN_TRUNCATE_HOST',
|
149 |
+
'boolval',
|
150 |
+
true,
|
151 |
+
[ 'syslog', 'workaround', 'truncate_host' ]
|
152 |
+
);
|
153 |
+
_load(
|
154 |
+
'WP_FAIL2BAN_BLOCK_USER_ENUMERATION',
|
155 |
+
'boolval',
|
156 |
+
true,
|
157 |
+
[ 'block', 'user_enumeration' ]
|
158 |
+
);
|
159 |
+
_load(
|
160 |
+
'WP_FAIL2BAN_BLOCKED_USERS',
|
161 |
+
'strval',
|
162 |
+
true,
|
163 |
+
[ 'block', 'users' ]
|
164 |
+
);
|
165 |
+
_load(
|
166 |
+
'WP_FAIL2BAN_PROXIES',
|
167 |
+
__NAMESPACE__ . '\\validate_ips',
|
168 |
+
true,
|
169 |
+
[ 'remote-ip', 'proxies' ]
|
170 |
+
);
|
171 |
+
_load(
|
172 |
+
'WP_FAIL2BAN_PLUGIN_LOG_AUTH',
|
173 |
+
'boolval',
|
174 |
+
true,
|
175 |
+
[
|
176 |
+
'logging',
|
177 |
+
'plugins',
|
178 |
+
'auth',
|
179 |
+
'enabled'
|
180 |
+
]
|
181 |
+
);
|
182 |
+
_load(
|
183 |
+
'WP_FAIL2BAN_PLUGIN_LOG_COMMENT',
|
184 |
+
'boolval',
|
185 |
+
true,
|
186 |
+
[
|
187 |
+
'logging',
|
188 |
+
'plugins',
|
189 |
+
'comment',
|
190 |
+
'enabled'
|
191 |
+
]
|
192 |
+
);
|
193 |
+
_load(
|
194 |
+
'WP_FAIL2BAN_PLUGIN_LOG_PASSWORD',
|
195 |
+
'boolval',
|
196 |
+
true,
|
197 |
+
[
|
198 |
+
'logging',
|
199 |
+
'plugins',
|
200 |
+
'password',
|
201 |
+
'enabled'
|
202 |
+
]
|
203 |
+
);
|
204 |
+
_load(
|
205 |
+
'WP_FAIL2BAN_PLUGIN_LOG_REST',
|
206 |
+
'boolval',
|
207 |
+
true,
|
208 |
+
[
|
209 |
+
'logging',
|
210 |
+
'plugins',
|
211 |
+
'rest',
|
212 |
+
'enabled'
|
213 |
+
]
|
214 |
+
);
|
215 |
+
_load(
|
216 |
+
'WP_FAIL2BAN_PLUGIN_LOG_SPAM',
|
217 |
+
'boolval',
|
218 |
+
true,
|
219 |
+
[
|
220 |
+
'logging',
|
221 |
+
'plugins',
|
222 |
+
'spam',
|
223 |
+
'enabled'
|
224 |
+
]
|
225 |
+
);
|
226 |
+
_load(
|
227 |
+
'WP_FAIL2BAN_PLUGIN_LOG_XMLRPC',
|
228 |
+
'boolval',
|
229 |
+
true,
|
230 |
+
[
|
231 |
+
'logging',
|
232 |
+
'plugins',
|
233 |
+
'xmlrpc',
|
234 |
+
'enabled'
|
235 |
+
]
|
236 |
+
);
|
237 |
+
_load(
|
238 |
+
'WP_FAIL2BAN_PLUGIN_AUTH_LOG',
|
239 |
+
'intval',
|
240 |
+
false,
|
241 |
+
[
|
242 |
+
'logging',
|
243 |
+
'plugins',
|
244 |
+
'auth',
|
245 |
+
'facility'
|
246 |
+
]
|
247 |
+
);
|
248 |
+
_load(
|
249 |
+
'WP_FAIL2BAN_PLUGIN_COMMENT_LOG',
|
250 |
+
'intval',
|
251 |
+
false,
|
252 |
+
[
|
253 |
+
'logging',
|
254 |
+
'plugins',
|
255 |
+
'comment',
|
256 |
+
'facility'
|
257 |
+
]
|
258 |
+
);
|
259 |
+
_load(
|
260 |
+
'WP_FAIL2BAN_PLUGIN_PASSWORD_LOG',
|
261 |
+
'intval',
|
262 |
+
false,
|
263 |
+
[
|
264 |
+
'logging',
|
265 |
+
'plugins',
|
266 |
+
'password',
|
267 |
+
'facility'
|
268 |
+
]
|
269 |
+
);
|
270 |
+
_load(
|
271 |
+
'WP_FAIL2BAN_PLUGIN_REST_LOG',
|
272 |
+
'intval',
|
273 |
+
false,
|
274 |
+
[
|
275 |
+
'logging',
|
276 |
+
'plugins',
|
277 |
+
'rest',
|
278 |
+
'facility'
|
279 |
+
]
|
280 |
+
);
|
281 |
+
_load(
|
282 |
+
'WP_FAIL2BAN_PLUGIN_SPAM_LOG',
|
283 |
+
'intval',
|
284 |
+
false,
|
285 |
+
[
|
286 |
+
'logging',
|
287 |
+
'plugins',
|
288 |
+
'spam',
|
289 |
+
'facility'
|
290 |
+
]
|
291 |
+
);
|
292 |
+
_load(
|
293 |
+
'WP_FAIL2BAN_PLUGIN_XMLRPC_LOG',
|
294 |
+
'intval',
|
295 |
+
false,
|
296 |
+
[
|
297 |
+
'logging',
|
298 |
+
'plugins',
|
299 |
+
'xmlrpc',
|
300 |
+
'facility'
|
301 |
+
]
|
302 |
+
);
|
303 |
+
// phpcs:enable
|
readme.txt
CHANGED
@@ -4,9 +4,9 @@ Donate link: https://paypal.me/invisnet/
|
|
4 |
Author URI: https://charles.lecklider.org/
|
5 |
Plugin URI: https://wp-fail2ban.com/
|
6 |
Tags: fail2ban, login, security, syslog
|
7 |
-
Requires at least:
|
8 |
Tested up to: 5.1
|
9 |
-
Stable tag: 4.1
|
10 |
Requires PHP: 5.3
|
11 |
License: GPLv2 or later
|
12 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -26,38 +26,55 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
|
|
26 |
|
27 |
= Features =
|
28 |
|
|
|
|
|
|
|
|
|
|
|
29 |
* **CloudFlare and Proxy Servers**
|
30 |
-
*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.
|
31 |
|
32 |
* **Comments**
|
33 |
-
*WPf2b* can log comments (see [`WP_FAIL2BAN_LOG_COMMENTS`](https://docs.wp-fail2ban.com/en/4.
|
34 |
|
35 |
* **Pingbacks**
|
36 |
-
*WPf2b* logs failed pingbacks, and can log all pingbacks. For an overview see [`WP_FAIL2BAN_LOG_PINGBACKS`](https://docs.wp-fail2ban.com/en/4.
|
37 |
|
38 |
* **Spam**
|
39 |
-
*WPf2b* can log comments marked as spam. See [`WP_FAIL2BAN_LOG_SPAM`](https://docs.wp-fail2ban.com/en/4.
|
40 |
|
41 |
* **Block User Enumeration**
|
42 |
-
*WPf2b* can block user enumeration. See [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://docs.wp-fail2ban.com/en/4.
|
43 |
|
44 |
* **Work-Arounds for Broken syslogd**
|
45 |
-
*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.
|
46 |
|
47 |
* **Blocking Users**
|
48 |
-
*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.
|
49 |
|
50 |
* **`mu-plugins` Support**
|
51 |
-
*WPf2b* can easily be configured as a must-use plugin - see [Configuration](https://docs.wp-fail2ban.com/en/4.
|
52 |
|
53 |
== Installation ==
|
54 |
|
55 |
1. Install via the Plugin Directory, or upload to your plugins directory.
|
56 |
1. Activate the plugin through the 'Plugins' menu in WordPress.
|
57 |
-
1. Edit `wp-config.php` to suit your needs - see [Configuration](https://docs.wp-fail2ban.com/en/4.
|
58 |
|
59 |
== Changelog ==
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
= 4.1.0 =
|
62 |
* Add separate logging for REST authentication.
|
63 |
* 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).
|
@@ -171,11 +188,14 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
|
|
171 |
|
172 |
== Upgrade Notice ==
|
173 |
|
|
|
|
|
|
|
174 |
= 4.1.0 =
|
175 |
To take advantage of the new features you will need up update your `fail2ban` filters; existing filters will continue to work as before.
|
176 |
|
177 |
= 4.0.5 =
|
178 |
-
This is a security fix: all 4.x users are strongly advised to upgrade immediately. You do not need to update your filters from 4.0.1.
|
179 |
|
180 |
= 4.0.4 =
|
181 |
This is a bugfix. You do not need to update your filters from 4.0.1.
|
4 |
Author URI: https://charles.lecklider.org/
|
5 |
Plugin URI: https://wp-fail2ban.com/
|
6 |
Tags: fail2ban, login, security, syslog
|
7 |
+
Requires at least: 4.2
|
8 |
Tested up to: 5.1
|
9 |
+
Stable tag: 4.2.1
|
10 |
Requires PHP: 5.3
|
11 |
License: GPLv2 or later
|
12 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
26 |
|
27 |
= Features =
|
28 |
|
29 |
+
* **NEW - Support for 3rd-party Plugins**
|
30 |
+
Version 4.2 introduces a simple API for authors to integrate their plugins with *WPf2b*, with 2 *experimental* add-ons:
|
31 |
+
* [Contact Form 7](https://wordpress.org/plugins/wp-fail2ban-addon-contact-form-7/)
|
32 |
+
* [Gravity Forms](https://wordpress.org/plugins/wp-fail2ban-addon-gravity-forms/)
|
33 |
+
|
34 |
* **CloudFlare and Proxy Servers**
|
35 |
+
*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#wp-fail2ban-proxies).
|
36 |
|
37 |
* **Comments**
|
38 |
+
*WPf2b* can log comments (see [`WP_FAIL2BAN_LOG_COMMENTS`](https://docs.wp-fail2ban.com/en/4.2/defines.html#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)).
|
39 |
|
40 |
* **Pingbacks**
|
41 |
+
*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#wp-fail2ban-log-pingbacks).
|
42 |
|
43 |
* **Spam**
|
44 |
+
*WPf2b* can log comments marked as spam. See [`WP_FAIL2BAN_LOG_SPAM`](https://docs.wp-fail2ban.com/en/4.2/defines.html#wp-fail2ban-log-spam).
|
45 |
|
46 |
* **Block User Enumeration**
|
47 |
+
*WPf2b* can block user enumeration. See [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://docs.wp-fail2ban.com/en/4.2/defines.html#wp-fail2ban-block-user-enumeration).
|
48 |
|
49 |
* **Work-Arounds for Broken syslogd**
|
50 |
+
*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#wp-fail2ban-syslog-short-tag) and [`WP_FAIL2BAN_HTTP_HOST`](https://docs.wp-fail2ban.com/en/4.2/defines.html#wp-fail2ban-http-host).
|
51 |
|
52 |
* **Blocking Users**
|
53 |
+
*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#wp-fail2ban-blocked-users).
|
54 |
|
55 |
* **`mu-plugins` Support**
|
56 |
+
*WPf2b* can easily be configured as a must-use plugin - see [Configuration](https://docs.wp-fail2ban.com/en/4.2/configuration.html#mu-plugins-support).
|
57 |
|
58 |
== Installation ==
|
59 |
|
60 |
1. Install via the Plugin Directory, or upload to your plugins directory.
|
61 |
1. Activate the plugin through the 'Plugins' menu in WordPress.
|
62 |
+
1. Edit `wp-config.php` to suit your needs - see [Configuration](https://docs.wp-fail2ban.com/en/4.2/configuration.html).
|
63 |
|
64 |
== Changelog ==
|
65 |
|
66 |
+
= 4.2.1 =
|
67 |
+
* Completed support for [`WP_FAIL2BAN_COMMENT_EXTRA_LOG`](https://docs.wp-fail2ban.com/en/4.2/defines/WP_FAIL2BAN_COMMENT_EXTRA_LOG.html).
|
68 |
+
* Add support for 3rd-party plugins; see [Developers](https://docs.wp-fail2ban.com/en/4.2/developers.html).
|
69 |
+
* Add-on for [Contact Form 7](https://wordpress.org/plugins/wp-fail2ban-addon-contact-form-7/) (experimental).
|
70 |
+
* Add-on for [Gravity Forms](https://wordpress.org/plugins/wp-fail2ban-addon-gravity-forms/) (experimental).
|
71 |
+
* 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`.
|
72 |
+
* Bugfix for email-as-username - now logged correctly and matched by `soft`, not `hard`, filters.
|
73 |
+
* Bugfix for regression in code to prevent Free/Premium conflict.
|
74 |
+
|
75 |
+
= 4.2.0 =
|
76 |
+
* Not released.
|
77 |
+
|
78 |
= 4.1.0 =
|
79 |
* Add separate logging for REST authentication.
|
80 |
* 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).
|
188 |
|
189 |
== Upgrade Notice ==
|
190 |
|
191 |
+
= 4.2.1 =
|
192 |
+
You do not need to update your filters from 4.1.0.
|
193 |
+
|
194 |
= 4.1.0 =
|
195 |
To take advantage of the new features you will need up update your `fail2ban` filters; existing filters will continue to work as before.
|
196 |
|
197 |
= 4.0.5 =
|
198 |
+
This is a security fix (Freemius SDK): all 4.x users are strongly advised to upgrade immediately. You do not need to update your filters from 4.0.1.
|
199 |
|
200 |
= 4.0.4 =
|
201 |
This is a bugfix. You do not need to update your filters from 4.0.1.
|
wp-fail2ban-main.php
CHANGED
@@ -11,37 +11,24 @@ namespace org\lecklider\charles\wordpress\wp_fail2ban;
|
|
11 |
if ( !defined( 'ABSPATH' ) ) {
|
12 |
exit;
|
13 |
}
|
14 |
-
|
15 |
-
|
16 |
-
|
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 |
register_activation_hook( WP_FAIL2BAN_FILE, function () {
|
32 |
foreach ( get_mu_plugins() as $plugin => $data ) {
|
33 |
|
34 |
-
if (
|
35 |
$wp_f2b_ver = substr( WP_FAIL2BAN_VER, 0, strrpos( WP_FAIL2BAN_VER, '.' ) );
|
36 |
$wpf2b = 'WP fail2ban';
|
37 |
-
$error_msg =
|
38 |
$mu_file = WPMU_PLUGIN_DIR . '/' . $plugin;
|
39 |
|
40 |
if ( is_link( $mu_file ) ) {
|
41 |
|
42 |
if ( false === ($link = readlink( $mu_file )) || false === ($path = realpath( $mu_file )) ) {
|
|
|
43 |
$error_msg .= <<<__ERROR__
|
44 |
-
<h3>
|
45 |
<p><tt>{$mu_file}</tt></p>
|
46 |
__ERROR__;
|
47 |
} elseif ( WP_FAIL2BAN_FILE == $path ) {
|
@@ -49,8 +36,9 @@ __ERROR__;
|
|
49 |
} else {
|
50 |
$mu_file = str_replace( '/', '/<wbr>', $mu_file );
|
51 |
$mu_file = substr( $mu_file, strlen( WPMU_PLUGIN_DIR ) - 1 );
|
|
|
52 |
$error_msg .= <<<__ERROR__
|
53 |
-
<h3>
|
54 |
<style>
|
55 |
table { text-align: center; }
|
56 |
td { width: 50%; }
|
@@ -77,64 +65,25 @@ __ERROR__;
|
|
77 |
} else {
|
78 |
$mu_file = str_replace( '/', '/<wbr>', $mu_file );
|
79 |
$mu_file = substr( $mu_file, strlen( WPMU_PLUGIN_DIR ) - 1 );
|
|
|
80 |
$error_msg .= <<<__ERROR__
|
81 |
-
<h3>
|
82 |
<p><tt>{$mu_file}</tt></p>
|
83 |
__ERROR__;
|
84 |
}
|
85 |
|
86 |
-
$error_msg .=
|
87 |
-
$error_msg .= '<p>Click <a href="
|
88 |
deactivate_plugins( plugin_basename( WP_FAIL2BAN_FILE ) );
|
89 |
wp_die( $error_msg );
|
90 |
}
|
91 |
|
92 |
}
|
93 |
} );
|
94 |
-
|
95 |
-
* Allow custom openlog options.
|
96 |
-
* e.g. you may not want the PID if logging remotely.
|
97 |
-
*
|
98 |
-
* @since 3.6.0 Add LOG_NDELAY
|
99 |
-
* @since 3.5.0
|
100 |
-
*/
|
101 |
-
if ( !defined( 'WP_FAIL2BAN_OPENLOG_OPTIONS' ) ) {
|
102 |
-
define( 'WP_FAIL2BAN_OPENLOG_OPTIONS', DEFAULT_WP_FAIL2BAN_OPENLOG_OPTIONS );
|
103 |
-
}
|
104 |
-
/**
|
105 |
-
* Make sure all custom logs are defined.
|
106 |
-
* @since 3.5.0
|
107 |
-
*/
|
108 |
-
if ( !defined( 'WP_FAIL2BAN_AUTH_LOG' ) ) {
|
109 |
-
define( 'WP_FAIL2BAN_AUTH_LOG', DEFAULT_WP_FAIL2BAN_AUTH_LOG );
|
110 |
-
}
|
111 |
-
if ( !defined( 'WP_FAIL2BAN_COMMENT_LOG' ) ) {
|
112 |
-
define( 'WP_FAIL2BAN_COMMENT_LOG', DEFAULT_WP_FAIL2BAN_COMMENT_LOG );
|
113 |
-
}
|
114 |
-
if ( !defined( 'WP_FAIL2BAN_PINGBACK_LOG' ) ) {
|
115 |
-
define( 'WP_FAIL2BAN_PINGBACK_LOG', DEFAULT_WP_FAIL2BAN_PINGBACK_LOG );
|
116 |
-
}
|
117 |
-
/**
|
118 |
-
* @since 4.0.0
|
119 |
-
*/
|
120 |
-
if ( !defined( 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG' ) ) {
|
121 |
-
define( 'WP_FAIL2BAN_PASSWORD_REQUEST_LOG', DEFAULT_WP_FAIL2BAN_PASSWORD_REQUEST_LOG );
|
122 |
-
}
|
123 |
-
if ( !defined( 'WP_FAIL2BAN_SPAM_LOG' ) ) {
|
124 |
-
define( 'WP_FAIL2BAN_SPAM_LOG', DEFAULT_WP_FAIL2BAN_SPAM_LOG );
|
125 |
-
}
|
126 |
-
/**
|
127 |
-
* @since 4.0.5
|
128 |
-
*/
|
129 |
-
if ( !defined( 'WP_FAIL2BAN_COMMENT_EXTRA_LOG' ) ) {
|
130 |
-
define( 'WP_FAIL2BAN_COMMENT_EXTRA_LOG', DEFAULT_WP_FAIL2BAN_COMMENT_EXTRA_LOG );
|
131 |
-
}
|
132 |
-
if ( !defined( 'WP_FAIL2BAN_PINGBACK_ERROR_LOG' ) ) {
|
133 |
-
define( 'WP_FAIL2BAN_PINGBACK_ERROR_LOG', DEFAULT_WP_FAIL2BAN_PINGBACK_ERROR_LOG );
|
134 |
-
}
|
135 |
|
136 |
if ( is_admin() ) {
|
137 |
-
require 'admin/
|
138 |
} else {
|
139 |
require dirname( __FILE__ ) . '/feature/lib.php';
|
140 |
/**
|
@@ -143,26 +92,30 @@ if ( is_admin() ) {
|
|
143 |
|
144 |
if ( !function_exists( __NAMESPACE__ . '\\wp_login' ) ) {
|
145 |
/**
|
146 |
-
*
|
147 |
-
*
|
|
|
|
|
148 |
* @since 1.0.0
|
149 |
*
|
150 |
* @param string $user_login
|
|
|
151 |
*/
|
152 |
function wp_login( $user_login, $user )
|
153 |
{
|
154 |
global $wp_xmlrpc_server ;
|
155 |
|
156 |
if ( defined( 'REST_REQUEST' ) ) {
|
157 |
-
$
|
158 |
} elseif ( $wp_xmlrpc_server ) {
|
159 |
-
$
|
160 |
} else {
|
161 |
-
$
|
162 |
}
|
163 |
|
164 |
openlog();
|
165 |
syslog( LOG_INFO, "Accepted password for {$user_login}" );
|
|
|
166 |
// @codeCoverageIgnoreEnd
|
167 |
}
|
168 |
|
@@ -180,8 +133,11 @@ if ( is_admin() ) {
|
|
180 |
|
181 |
if ( !function_exists( __NAMESPACE__ . '\\wp_login_failed' ) ) {
|
182 |
/**
|
183 |
-
*
|
184 |
-
*
|
|
|
|
|
|
|
185 |
* @since 1.0.0
|
186 |
*
|
187 |
* @param string $username
|
@@ -198,19 +154,21 @@ if ( is_admin() ) {
|
|
198 |
global $wp_xmlrpc_server ;
|
199 |
|
200 |
if ( defined( 'REST_REQUEST' ) ) {
|
201 |
-
$
|
202 |
$msg = 'REST a';
|
203 |
} elseif ( $wp_xmlrpc_server ) {
|
204 |
-
$
|
205 |
$msg = 'XML-RPC a';
|
206 |
} else {
|
207 |
-
$
|
208 |
$msg = 'A';
|
209 |
}
|
210 |
|
211 |
-
$
|
|
|
212 |
openlog();
|
213 |
syslog( LOG_NOTICE, $msg );
|
|
|
214 |
// @codeCoverageIgnoreEnd
|
215 |
}
|
216 |
|
@@ -220,7 +178,7 @@ if ( is_admin() ) {
|
|
220 |
/**
|
221 |
* Comments
|
222 |
*
|
223 |
-
* @since 4.0.0
|
224 |
* @since 3.5.0
|
225 |
*/
|
226 |
if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS' ) && true === WP_FAIL2BAN_LOG_COMMENTS ) {
|
@@ -229,7 +187,7 @@ if ( is_admin() ) {
|
|
229 |
/**
|
230 |
* Password
|
231 |
*
|
232 |
-
* @since 4.0.0
|
233 |
* @since 3.5.0
|
234 |
*/
|
235 |
if ( defined( 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST' ) && true === WP_FAIL2BAN_LOG_PASSWORD_REQUEST ) {
|
@@ -238,7 +196,7 @@ if ( is_admin() ) {
|
|
238 |
/**
|
239 |
* Spam
|
240 |
*
|
241 |
-
* @since 4.0.0
|
242 |
* @since 3.5.0
|
243 |
*/
|
244 |
if ( defined( 'WP_FAIL2BAN_LOG_SPAM' ) && true === WP_FAIL2BAN_LOG_SPAM ) {
|
@@ -247,7 +205,7 @@ if ( is_admin() ) {
|
|
247 |
/**
|
248 |
* Users
|
249 |
*
|
250 |
-
* @since 4.0.0
|
251 |
* @since 2.0.0
|
252 |
*/
|
253 |
if ( defined( 'WP_FAIL2BAN_BLOCKED_USERS' ) && '' < WP_FAIL2BAN_BLOCKED_USERS ) {
|
@@ -256,7 +214,7 @@ if ( is_admin() ) {
|
|
256 |
/**
|
257 |
* User enumeration
|
258 |
*
|
259 |
-
* @since 4.0.0
|
260 |
* @since 2.1.0
|
261 |
*/
|
262 |
if ( defined( 'WP_FAIL2BAN_BLOCK_USER_ENUMERATION' ) && true === WP_FAIL2BAN_BLOCK_USER_ENUMERATION ) {
|
@@ -265,7 +223,7 @@ if ( is_admin() ) {
|
|
265 |
/**
|
266 |
* XML-RPC
|
267 |
*
|
268 |
-
* @since 4.0.0
|
269 |
* @since 3.0.0
|
270 |
*/
|
271 |
if ( defined( 'XMLRPC_REQUEST' ) && true === XMLRPC_REQUEST ) {
|
11 |
if ( !defined( 'ABSPATH' ) ) {
|
12 |
exit;
|
13 |
}
|
14 |
+
require_once dirname( __FILE__ ) . '/lib/constants.php';
|
15 |
+
require_once dirname( __FILE__ ) . '/lib/loader.php';
|
16 |
+
require_once dirname( __FILE__ ) . '/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 ) {
|
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%; }
|
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 |
+
require dirname( __FILE__ ) . '/feature/plugins.php';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
|
85 |
if ( is_admin() ) {
|
86 |
+
require 'admin/admin.php';
|
87 |
} else {
|
88 |
require dirname( __FILE__ ) . '/feature/lib.php';
|
89 |
/**
|
92 |
|
93 |
if ( !function_exists( __NAMESPACE__ . '\\wp_login' ) ) {
|
94 |
/**
|
95 |
+
* Hook: wp_login
|
96 |
+
*
|
97 |
+
* @since 4.1.0 Add REST support
|
98 |
+
* @since 3.5.0 Refactored for unit testing
|
99 |
* @since 1.0.0
|
100 |
*
|
101 |
* @param string $user_login
|
102 |
+
* @param mixed $user
|
103 |
*/
|
104 |
function wp_login( $user_login, $user )
|
105 |
{
|
106 |
global $wp_xmlrpc_server ;
|
107 |
|
108 |
if ( defined( 'REST_REQUEST' ) ) {
|
109 |
+
$event = 'WPF2B_EVENT_REST_AUTH_OK';
|
110 |
} elseif ( $wp_xmlrpc_server ) {
|
111 |
+
$event = 'WPF2B_EVENT_XMLRPC_AUTH_OK';
|
112 |
} else {
|
113 |
+
$event = 'WPF2B_EVENT_AUTH_OK';
|
114 |
}
|
115 |
|
116 |
openlog();
|
117 |
syslog( LOG_INFO, "Accepted password for {$user_login}" );
|
118 |
+
closelog();
|
119 |
// @codeCoverageIgnoreEnd
|
120 |
}
|
121 |
|
133 |
|
134 |
if ( !function_exists( __NAMESPACE__ . '\\wp_login_failed' ) ) {
|
135 |
/**
|
136 |
+
* Hook: wp_login_failed
|
137 |
+
*
|
138 |
+
* @since 4.2.0 Change username check
|
139 |
+
* @since 4.1.0 Add REST support
|
140 |
+
* @since 3.5.0 Refactored for unit testing
|
141 |
* @since 1.0.0
|
142 |
*
|
143 |
* @param string $username
|
154 |
global $wp_xmlrpc_server ;
|
155 |
|
156 |
if ( defined( 'REST_REQUEST' ) ) {
|
157 |
+
$event = 'WPF2B_EVENT_REST_AUTH_FAIL';
|
158 |
$msg = 'REST a';
|
159 |
} elseif ( $wp_xmlrpc_server ) {
|
160 |
+
$event = 'WPF2B_EVENT_XMLRPC_AUTH_FAIL';
|
161 |
$msg = 'XML-RPC a';
|
162 |
} else {
|
163 |
+
$event = 'WPF2B_EVENT_AUTH_FAIL';
|
164 |
$msg = 'A';
|
165 |
}
|
166 |
|
167 |
+
$username = trim( $username );
|
168 |
+
$msg .= ( wp_cache_get( $username, 'useremail' ) || wp_cache_get( sanitize_user( $username ), 'userlogins' ) ? "uthentication failure for {$username}" : "uthentication attempt for unknown user {$username}" );
|
169 |
openlog();
|
170 |
syslog( LOG_NOTICE, $msg );
|
171 |
+
closelog();
|
172 |
// @codeCoverageIgnoreEnd
|
173 |
}
|
174 |
|
178 |
/**
|
179 |
* Comments
|
180 |
*
|
181 |
+
* @since 4.0.0 Refactored
|
182 |
* @since 3.5.0
|
183 |
*/
|
184 |
if ( defined( 'WP_FAIL2BAN_LOG_COMMENTS' ) && true === WP_FAIL2BAN_LOG_COMMENTS ) {
|
187 |
/**
|
188 |
* Password
|
189 |
*
|
190 |
+
* @since 4.0.0 Refactored
|
191 |
* @since 3.5.0
|
192 |
*/
|
193 |
if ( defined( 'WP_FAIL2BAN_LOG_PASSWORD_REQUEST' ) && true === WP_FAIL2BAN_LOG_PASSWORD_REQUEST ) {
|
196 |
/**
|
197 |
* Spam
|
198 |
*
|
199 |
+
* @since 4.0.0 Refactored
|
200 |
* @since 3.5.0
|
201 |
*/
|
202 |
if ( defined( 'WP_FAIL2BAN_LOG_SPAM' ) && true === WP_FAIL2BAN_LOG_SPAM ) {
|
205 |
/**
|
206 |
* Users
|
207 |
*
|
208 |
+
* @since 4.0.0 Refactored
|
209 |
* @since 2.0.0
|
210 |
*/
|
211 |
if ( defined( 'WP_FAIL2BAN_BLOCKED_USERS' ) && '' < WP_FAIL2BAN_BLOCKED_USERS ) {
|
214 |
/**
|
215 |
* User enumeration
|
216 |
*
|
217 |
+
* @since 4.0.0 Refactored
|
218 |
* @since 2.1.0
|
219 |
*/
|
220 |
if ( defined( 'WP_FAIL2BAN_BLOCK_USER_ENUMERATION' ) && true === WP_FAIL2BAN_BLOCK_USER_ENUMERATION ) {
|
223 |
/**
|
224 |
* XML-RPC
|
225 |
*
|
226 |
+
* @since 4.0.0 Refactored
|
227 |
* @since 3.0.0
|
228 |
*/
|
229 |
if ( defined( 'XMLRPC_REQUEST' ) && true === XMLRPC_REQUEST ) {
|
wp-fail2ban.php
CHANGED
@@ -5,7 +5,7 @@
|
|
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.1
|
9 |
* Author: Charles Lecklider
|
10 |
* Author URI: https://charles.lecklider.org/
|
11 |
* License: GPLv2
|
@@ -30,6 +30,8 @@
|
|
30 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
31 |
*/
|
32 |
/**
|
|
|
|
|
33 |
* @package wp-fail2ban
|
34 |
*/
|
35 |
namespace org\lecklider\charles\wordpress\wp_fail2ban;
|
@@ -37,20 +39,27 @@ namespace org\lecklider\charles\wordpress\wp_fail2ban;
|
|
37 |
/**
|
38 |
* @since 4.0.5
|
39 |
*/
|
40 |
-
define( 'WP_FAIL2BAN_VER', '4.1
|
41 |
define( 'WP_FAIL2BAN_FILE', __FILE__ );
|
|
|
|
|
|
|
|
|
|
|
42 |
/**
|
43 |
* Freemius integration
|
44 |
*
|
45 |
* @since 4.0.0
|
46 |
*/
|
47 |
|
48 |
-
if ( function_exists( 'wf_fs' ) ) {
|
49 |
// @codeCoverageIgnoreStart
|
50 |
wf_fs()->set_basename( false, __FILE__ );
|
51 |
return;
|
52 |
} else {
|
53 |
-
|
|
|
|
|
54 |
function wf_fs()
|
55 |
{
|
56 |
global $wf_fs ;
|
@@ -64,7 +73,7 @@ if ( function_exists( 'wf_fs' ) ) {
|
|
64 |
'type' => 'plugin',
|
65 |
'public_key' => 'pk_146d2c2a5bee3b157e43501ef8682',
|
66 |
'is_premium' => false,
|
67 |
-
'has_addons' =>
|
68 |
'has_paid_plans' => true,
|
69 |
'trial' => array(
|
70 |
'days' => 7,
|
@@ -72,11 +81,8 @@ if ( function_exists( 'wf_fs' ) ) {
|
|
72 |
),
|
73 |
'menu' => array(
|
74 |
'slug' => 'wp-fail2ban',
|
75 |
-
'first-path' => '
|
76 |
'support' => false,
|
77 |
-
'parent' => array(
|
78 |
-
'slug' => 'options-general.php',
|
79 |
-
),
|
80 |
),
|
81 |
'is_live' => true,
|
82 |
) );
|
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.1
|
9 |
* Author: Charles Lecklider
|
10 |
* Author URI: https://charles.lecklider.org/
|
11 |
* License: GPLv2
|
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;
|
39 |
/**
|
40 |
* @since 4.0.5
|
41 |
*/
|
42 |
+
define( 'WP_FAIL2BAN_VER', '4.2.1' );
|
43 |
define( 'WP_FAIL2BAN_FILE', __FILE__ );
|
44 |
+
/**
|
45 |
+
* @since 4.2.0
|
46 |
+
*/
|
47 |
+
global $wp_fail2ban ;
|
48 |
+
$wp_fail2ban['plugins'] = [];
|
49 |
/**
|
50 |
* Freemius integration
|
51 |
*
|
52 |
* @since 4.0.0
|
53 |
*/
|
54 |
|
55 |
+
if ( function_exists( __NAMESPACE__ . '\\wf_fs' ) ) {
|
56 |
// @codeCoverageIgnoreStart
|
57 |
wf_fs()->set_basename( false, __FILE__ );
|
58 |
return;
|
59 |
} else {
|
60 |
+
/**
|
61 |
+
* Create a helper function for easy SDK access.
|
62 |
+
*/
|
63 |
function wf_fs()
|
64 |
{
|
65 |
global $wf_fs ;
|
73 |
'type' => 'plugin',
|
74 |
'public_key' => 'pk_146d2c2a5bee3b157e43501ef8682',
|
75 |
'is_premium' => false,
|
76 |
+
'has_addons' => true,
|
77 |
'has_paid_plans' => true,
|
78 |
'trial' => array(
|
79 |
'days' => 7,
|
81 |
),
|
82 |
'menu' => array(
|
83 |
'slug' => 'wp-fail2ban',
|
84 |
+
'first-path' => 'admin.php?page=wp-fail2ban',
|
85 |
'support' => false,
|
|
|
|
|
|
|
86 |
),
|
87 |
'is_live' => true,
|
88 |
) );
|