captcha.php
4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<?php
namespace WordfenceLS;
class Controller_CAPTCHA {
const RESPONSE_MODE_ALLOW = 'allow';
const RESPONSE_MODE_REQUIRE_VERIFICATION = 'verify';
const RECAPTCHA_ENDPOINT = 'https://www.google.com/recaptcha/api/siteverify';
/**
* Returns the singleton Controller_CAPTCHA.
*
* @return Controller_CAPTCHA
*/
public static function shared() {
static $_shared = null;
if ($_shared === null) {
$_shared = new Controller_CAPTCHA();
}
return $_shared;
}
/**
* Returns whether or not the authentication CAPTCHA is enabled.
*
* @return bool
*/
public function enabled() {
$key = $this->site_key();
$secret = $this->_secret();
return Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_ENABLE_AUTH_CAPTCHA) && !empty($key) && !empty($secret);
}
/**
* Returns the public reCAPTCHA key if set.
*
* @return string|bool
*/
public function site_key() {
return Controller_Settings::shared()->get(Controller_Settings::OPTION_RECAPTCHA_SITE_KEY);
}
/**
* Returns the private reCAPTCHA secret if set.
*
* @return string|bool
*/
protected function _secret() {
return Controller_Settings::shared()->get(Controller_Settings::OPTION_RECAPTCHA_SECRET);
}
/**
* Returns the bot/human threshold for comparing the score against, defaulting to 0.5.
*
* @return float
*/
public function threshold() {
return Controller_Settings::shared()->get_float(Controller_Settings::OPTION_RECAPTCHA_THRESHOLD, 0.5);
}
/**
* Determine whether or not test mode for reCAPTCHA is enabled
*
* @return bool
*/
public function test_mode() {
return Controller_Settings::shared()->get_bool(\WordfenceLS\Controller_Settings::OPTION_CAPTCHA_TEST_MODE);
}
/**
* Queries the reCAPTCHA endpoint with the given token, verifies the action matches, and returns the corresponding
* score. If validation fails, false is returned. Any other failure (e.g., mangled response or connection dropped) returns 0.0.
*
* @param string $token
* @param string $action
* @param int $timeout
* @return float|false
*/
public function score($token, $action = 'login', $timeout = 10) {
try {
$payload = array(
'secret' => $this->_secret(),
'response' => $token,
'remoteip' => Model_Request::current()->ip(),
);
$response = wp_remote_post(self::RECAPTCHA_ENDPOINT,
array(
'body' => $payload,
'headers' => array(
'Referer' => false,
),
'timeout' => $timeout,
'blocking' => true,
));
if (!is_wp_error($response)) {
$jsonResponse = wp_remote_retrieve_body($response);
$decoded = @json_decode($jsonResponse, true);
if (is_array($decoded) && isset($decoded['success']) && isset($decoded['score']) && isset($decoded['action'])) {
if ($decoded['success'] && $decoded['action'] == $action) {
return (float) $decoded['score'];
}
return false;
}
}
}
catch (\Exception $e) {
//Fall through
}
return 0.0;
}
/**
* Returns true if the score is >= the threshold to be considered a human request.
*
* @param float $score
* @return bool
*/
public function is_human($score) {
if ($this->test_mode()) {
return true;
}
$threshold = $this->threshold();
return ($score >= $threshold || abs($score - $threshold) < 0.0001);
}
/**
* Check if the current request is an XML RPC request
* @return bool
*/
private static function is_xml_rpc() {
return defined('XMLRPC_REQUEST') && XMLRPC_REQUEST;
}
/**
* Check if captcha is required for the current request
* @return bool
*/
public function is_captcha_required() {
$required = $this->enabled() && !self::is_xml_rpc();
return apply_filters('wordfence_ls_require_captcha', $required);
}
/**
* Get the captcha token provided with the current request
* @param string $key if specified, override the default token parameter
* @return string|null the captcha token, if present, null otherwise
*/
public function get_token($key = 'wfls-captcha-token') {
return (isset($_POST[$key]) && is_string($_POST[$key]) && !empty($_POST[$key]) ? $_POST[$key] : null);
}
}