PluginProbe ʕ •ᴥ•ʔ
Wordfence Security – Firewall, Malware Scan, and Login Security / 7.3.2
Wordfence Security – Firewall, Malware Scan, and Login Security v7.3.2
8.2.2 8.2.1 8.2.0 3.7.1 3.7.2 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.8.8 3.8.9 3.9.1 4.0.1 4.0.2 4.0.3 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.0.9 5.1.1 5.1.2 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.1 5.3.10 5.3.11 5.3.12 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.3.8 5.3.9 6.0.1 6.0.10 6.0.11 6.0.12 6.0.14 6.0.15 6.0.16 6.0.17 6.0.18 6.0.19 6.0.2 6.0.20 6.0.21 6.0.22 6.0.23 6.0.24 6.0.25 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.0.8 6.0.9 6.1.1 6.1.10 6.1.11 6.1.12 6.1.14 6.1.15 6.1.16 6.1.17 6.1.2 6.1.3 6.1.4 6.1.5 6.1.6 6.1.7 6.1.8 6.1.9 6.2.0 6.2.1 6.2.10 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.2.8 6.2.9 6.3.0 6.3.1 6.3.10 6.3.11 6.3.12 6.3.14 6.3.15 6.3.16 6.3.17 6.3.18 6.3.19 6.3.2 6.3.20 6.3.21 6.3.22 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.3.8 6.3.9 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1.0 7.1.1 7.1.10 7.1.11 7.1.12 7.1.14 7.1.15 7.1.16 7.1.17 7.1.18 7.1.19 7.1.2 7.1.20 7.1.3 7.1.4 7.1.5 7.1.6 7.1.7 7.1.8 7.1.9 7.10.0 7.10.1 7.10.2 7.10.3 7.10.4 7.10.5 7.10.6 7.10.7 7.11.0 7.11.1 7.11.2 7.11.3 7.11.4 7.11.5 7.11.6 7.11.7 7.2.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3.1 7.3.2 7.3.3 7.3.4 7.3.5 7.3.6 7.4.0 7.4.1 7.4.10 7.4.11 7.4.12 7.4.14 7.4.2 7.4.3 trunk 7.4.4 1.1 7.4.5 1.2 7.4.6 1.3 7.4.7 1.3.1 7.4.8 1.3.2 7.4.9 1.3.3 7.5.0 1.4.2 7.5.1 1.4.3 7.5.10 1.4.4 7.5.11 1.4.5 7.5.2 1.4.6 7.5.3 1.4.7 7.5.4 1.4.8 7.5.5 1.5.1 7.5.6 1.5.2 7.5.7 1.5.3 7.5.8 1.5.4 7.5.9 1.5.5 7.6.0 1.5.6 7.6.1 2.0.1 7.6.2 2.0.2 7.7.0 2.0.3 7.7.1 2.0.5 7.8.0 2.0.6 7.8.1 2.0.7 7.8.2 2.1.0 7.9.0 2.1.1 7.9.1 2.1.2 7.9.2 2.1.3 7.9.3 2.1.4 8.0.0 2.1.5 8.0.1 3.0.2 8.0.2 3.0.3 8.0.3 3.0.4 8.0.4 3.0.5 8.0.5 3.0.6 8.1.0 3.0.7 8.1.1 3.0.8 8.1.2 3.0.9 8.1.3 3.1.0 8.1.4 3.1.1 v1.4.1 3.1.2 3.1.4 3.1.6 3.2.1 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.1 3.4.4 3.4.5 3.5.1 3.5.2 3.6.1 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9
wordfence / lib / wfCentralAPI.php
wordfence / lib Last commit date
Diff 8 years ago dashboard 7 years ago rest-api 7 years ago .htaccess 7 years ago Diff.php 14 years ago GeoLite2-Country.mmdb 7 years ago IPTraf.php 8 years ago IPTrafList.php 7 years ago WFLSPHP52Compatability.php 7 years ago compat.php 8 years ago conntest.php 7 years ago cronview.php 8 years ago dbview.php 8 years ago diffResult.php 8 years ago email_genericAlert.php 7 years ago email_newIssues.php 7 years ago email_unlockRequest.php 8 years ago email_unsubscribeRequest.php 7 years ago flags.php 7 years ago live_activity.php 8 years ago menu_dashboard.php 7 years ago menu_dashboard_options.php 7 years ago menu_firewall.php 7 years ago menu_firewall_blocking.php 7 years ago menu_firewall_blocking_options.php 8 years ago menu_firewall_waf.php 7 years ago menu_firewall_waf_options.php 7 years ago menu_options.php 7 years ago menu_scanner.php 7 years ago menu_scanner_credentials.php 8 years ago menu_scanner_options.php 8 years ago menu_support.php 7 years ago menu_tools.php 7 years ago menu_tools_diagnostic.php 7 years ago menu_tools_importExport.php 7 years ago menu_tools_livetraffic.php 7 years ago menu_tools_twoFactor.php 7 years ago menu_tools_whois.php 8 years ago menu_wordfence_central.php 7 years ago noc1.key 7 years ago sysinfo.php 8 years ago unknownFiles.php 8 years ago viewFullActivityLog.php 8 years ago wf503.php 7 years ago wfAPI.php 7 years ago wfActivityReport.php 7 years ago wfAdminNoticeQueue.php 8 years ago wfArray.php 7 years ago wfBrowscap.php 8 years ago wfBrowscapCache.php 7 years ago wfBulkCountries.php 7 years ago wfCache.php 9 years ago wfCentralAPI.php 7 years ago wfConfig.php 7 years ago wfCrawl.php 8 years ago wfCredentialsController.php 7 years ago wfCrypt.php 7 years ago wfDB.php 7 years ago wfDashboard.php 7 years ago wfDateLocalization.php 8 years ago wfDiagnostic.php 7 years ago wfDict.php 8 years ago wfDirectoryIterator.php 7 years ago wfHelperBin.php 11 years ago wfHelperString.php 11 years ago wfIPWhitelist.php 7 years ago wfImportExportController.php 7 years ago wfIssues.php 7 years ago wfJWT.php 7 years ago wfLockedOut.php 7 years ago wfLog.php 7 years ago wfMD5BloomFilter.php 8 years ago wfModuleController.php 7 years ago wfNotification.php 8 years ago wfOnboardingController.php 7 years ago wfPersistenceController.php 8 years ago wfRESTAPI.php 7 years ago wfScan.php 7 years ago wfScanEngine.php 7 years ago wfSchema.php 7 years ago wfStyle.php 7 years ago wfSupportController.php 7 years ago wfUnlockMsg.php 7 years ago wfUpdateCheck.php 8 years ago wfUtils.php 7 years ago wfVersionCheckController.php 8 years ago wfView.php 10 years ago wfViewResult.php 8 years ago wordfenceClass.php 7 years ago wordfenceConstants.php 7 years ago wordfenceHash.php 7 years ago wordfenceScanner.php 7 years ago wordfenceURLHoover.php 7 years ago
wfCentralAPI.php
499 lines
1 <?php
2
3 class wfCentralAPIRequest {
4 /**
5 * @var string
6 */
7 private $endpoint;
8 /**
9 * @var string
10 */
11 private $method;
12 /**
13 * @var null
14 */
15 private $token;
16 /**
17 * @var array
18 */
19 private $body;
20 /**
21 * @var array
22 */
23 private $args;
24
25
26 /**
27 * @param string $endpoint
28 * @param string $method
29 * @param string|null $token
30 * @param array $body
31 * @param array $args
32 */
33 public function __construct($endpoint, $method = 'GET', $token = null, $body = array(), $args = array()) {
34 $this->endpoint = $endpoint;
35 $this->method = $method;
36 $this->token = $token;
37 $this->body = $body;
38 $this->args = $args;
39 }
40
41 public function execute() {
42 $args = array(
43 'timeout' => 10,
44 );
45 $args = wp_parse_args($this->getArgs(), $args);
46 $args['method'] = $this->getMethod();
47 if (empty($args['headers'])) {
48 $args['headers'] = array();
49 }
50 $args['cookies']['XDEBUG_SESSION'] = 'XDEBUG_ECLIPSE';
51
52 $token = $this->getToken();
53 if ($token) {
54 $args['headers']['Authorization'] = 'Bearer ' . $token;
55 }
56 if ($this->getBody()) {
57 $args['headers']['Content-Type'] = 'application/json';
58 $args['body'] = json_encode($this->getBody());
59 }
60
61 $http = _wp_http_get_object();
62 $response = $http->request(WORDFENCE_CENTRAL_API_URL_SEC . $this->getEndpoint(), $args);
63 return new wfCentralAPIResponse($response);
64 }
65
66 /**
67 * @return string
68 */
69 public function getEndpoint() {
70 return $this->endpoint;
71 }
72
73 /**
74 * @param string $endpoint
75 */
76 public function setEndpoint($endpoint) {
77 $this->endpoint = $endpoint;
78 }
79
80 /**
81 * @return string
82 */
83 public function getMethod() {
84 return $this->method;
85 }
86
87 /**
88 * @param string $method
89 */
90 public function setMethod($method) {
91 $this->method = $method;
92 }
93
94 /**
95 * @return null
96 */
97 public function getToken() {
98 return $this->token;
99 }
100
101 /**
102 * @param null $token
103 */
104 public function setToken($token) {
105 $this->token = $token;
106 }
107
108 /**
109 * @return array
110 */
111 public function getBody() {
112 return $this->body;
113 }
114
115 /**
116 * @param array $body
117 */
118 public function setBody($body) {
119 $this->body = $body;
120 }
121
122 /**
123 * @return array
124 */
125 public function getArgs() {
126 return $this->args;
127 }
128
129 /**
130 * @param array $args
131 */
132 public function setArgs($args) {
133 $this->args = $args;
134 }
135 }
136
137 class wfCentralAPIResponse {
138
139 public static function parseErrorJSON($json) {
140 $data = json_decode($json, true);
141 if (is_array($data) && array_key_exists('message', $data)) {
142 return $data['message'];
143 }
144 return $json;
145 }
146
147 /**
148 * @var array|null
149 */
150 private $response;
151
152 /**
153 * @param array $response
154 */
155 public function __construct($response = null) {
156 $this->response = $response;
157 }
158
159 public function getStatusCode() {
160 return wp_remote_retrieve_response_code($this->getResponse());
161 }
162
163 public function getBody() {
164 return wp_remote_retrieve_body($this->getResponse());
165 }
166
167 public function getJSONBody() {
168 return json_decode($this->getBody(), true);
169 }
170
171 public function isError() {
172 if (is_wp_error($this->getResponse())) {
173 return true;
174 }
175 $statusCode = $this->getStatusCode();
176 return !($statusCode >= 200 && $statusCode < 300);
177 }
178
179 public function returnErrorArray() {
180 return array(
181 'err' => 1,
182 'errorMsg' => sprintf(__('HTTP %d received from Wordfence Central: %s', 'wordfence'),
183 $this->getStatusCode(), $this->parseErrorJSON($this->getBody())),
184 );
185 }
186
187 /**
188 * @return array|null
189 */
190 public function getResponse() {
191 return $this->response;
192 }
193
194 /**
195 * @param array|null $response
196 */
197 public function setResponse($response) {
198 $this->response = $response;
199 }
200 }
201
202
203 class wfCentralAuthenticatedAPIRequest extends wfCentralAPIRequest {
204
205 private $retries = 3;
206
207 /**
208 * @param string $endpoint
209 * @param string $method
210 * @param array $body
211 * @param array $args
212 */
213 public function __construct($endpoint, $method = 'GET', $body = array(), $args = array()) {
214 parent::__construct($endpoint, $method, null, $body, $args);
215 }
216
217 /**
218 * @return mixed|null
219 * @throws wfCentralAPIException
220 */
221 public function getToken() {
222 $token = parent::getToken();
223 if ($token) {
224 return $token;
225 }
226
227 $token = get_transient('wordfenceCentralJWT' . wfConfig::get('wordfenceCentralSiteID'));
228 if ($token) {
229 return $token;
230 }
231
232 for ($i = 0; $i < $this->retries; $i++) {
233 try {
234 $token = $this->fetchToken();
235 break;
236 } catch (wfCentralAPIException $e) {
237 continue;
238 }
239 }
240 if (empty($token)) {
241 if (isset($e)) {
242 throw $e;
243 } else {
244 throw new wfCentralAPIException(__('Unable to authenticate with Wordfence Central.', 'wordfence'));
245 }
246 }
247 $tokenContents = wfJWT::extractTokenContents($token);
248
249 if (!empty($tokenContents['body']['exp'])) {
250 set_transient('wordfenceCentralJWT' . wfConfig::get('wordfenceCentralSiteID'), $token, $tokenContents['body']['exp'] - time());
251 }
252 return $token;
253 }
254
255 public function fetchToken() {
256 require_once WORDFENCE_PATH . '/vendor/paragonie/sodium_compat/autoload-fast.php';
257
258 $defaultArgs = array(
259 'timeout' => 6,
260 );
261 $siteID = wfConfig::get('wordfenceCentralSiteID');
262 if (!$siteID) {
263 throw new wfCentralAPIException(__('Wordfence Central site ID has not been created yet.', 'wordfence'));
264 }
265 $secretKey = wfConfig::get('wordfenceCentralSecretKey');
266 if (!$secretKey) {
267 throw new wfCentralAPIException(__('Wordfence Central secret key has not been created yet.', 'wordfence'));
268 }
269
270 // Pull down nonce.
271 $request = new wfCentralAPIRequest(sprintf('/site/%s/login', $siteID), 'GET', null, array(), $defaultArgs);
272 $nonceResponse = $request->execute();
273 if ($nonceResponse->isError()) {
274 $errorArray = $nonceResponse->returnErrorArray();
275 throw new wfCentralAPIException($errorArray['errorMsg']);
276 }
277 $body = $nonceResponse->getJSONBody();
278 if (!is_array($body) || !isset($body['nonce'])) {
279 throw new wfCentralAPIException(__('Invalid response received from Wordfence Central when fetching nonce.', 'wordfence'));
280 }
281 $nonce = $body['nonce'];
282
283 // Sign nonce to pull down JWT.
284 $data = $nonce . '|' . $siteID;
285 $signature = ParagonIE_Sodium_Compat::crypto_sign_detached($data, $secretKey);
286 $request = new wfCentralAPIRequest(sprintf('/site/%s/login', $siteID), 'POST', null, array(
287 'data' => $data,
288 'signature' => ParagonIE_Sodium_Compat::bin2hex($signature),
289 ), $defaultArgs);
290 $authResponse = $request->execute();
291 if ($authResponse->isError()) {
292 $errorArray = $authResponse->returnErrorArray();
293 throw new wfCentralAPIException($errorArray['errorMsg']);
294 }
295 $body = $authResponse->getJSONBody();
296 if (!is_array($body)) {
297 throw new wfCentralAPIException(__('Invalid response received from Wordfence Central when fetching token.', 'wordfence'));
298 }
299 if (!isset($body['jwt'])) { // Possible authentication error.
300 throw new wfCentralAPIException(__('Unable to authenticate with Wordfence Central.', 'wordfence'));
301 }
302 return $body['jwt'];
303 }
304 }
305
306 class wfCentralAPIException extends Exception {
307
308 }
309
310 class wfCentral {
311
312 /**
313 * @return bool
314 */
315 public static function isSupported() {
316 return function_exists('register_rest_route');
317 }
318
319 /**
320 * @return bool
321 */
322 public static function isConnected() {
323 return self::isSupported() && ((bool) wfConfig::get('wordfenceCentralConnected', false));
324 }
325
326 /**
327 * @return bool
328 */
329 public static function isPartialConnection() {
330 return !wfConfig::get('wordfenceCentralConnected') && wfConfig::get('wordfenceCentralSiteID');
331 }
332
333 /**
334 * @param array $issue
335 * @return bool|wfCentralAPIResponse
336 */
337 public static function sendIssue($issue) {
338 return self::sendIssues(array($issue));
339 }
340
341 /**
342 * @param $issues
343 * @return bool|wfCentralAPIResponse
344 */
345 public static function sendIssues($issues) {
346 $data = array();
347 foreach ($issues as $issue) {
348 $issueData = array(
349 'type' => 'issue',
350 'attributes' => $issue,
351 );
352 if (array_key_exists('id', $issueData)) {
353 $issueData['id'] = $issue['id'];
354 }
355 $data[] = $issueData;
356 }
357
358 $siteID = wfConfig::get('wordfenceCentralSiteID');
359 $request = new wfCentralAuthenticatedAPIRequest('/site/' . $siteID . '/issues', 'POST', array(
360 'data' => $data,
361 ));
362 try {
363 $response = $request->execute();
364 return $response;
365 } catch (wfCentralAPIException $e) {
366 error_log($e);
367 }
368 return false;
369 }
370
371 /**
372 * @param int $issueID
373 * @return bool|wfCentralAPIResponse
374 */
375 public static function deleteIssue($issueID) {
376 return self::deleteIssues(array($issueID));
377 }
378
379 /**
380 * @param $issues
381 * @return bool|wfCentralAPIResponse
382 */
383 public static function deleteIssues($issues) {
384 $siteID = wfConfig::get('wordfenceCentralSiteID');
385 $request = new wfCentralAuthenticatedAPIRequest('/site/' . $siteID . '/issues', 'DELETE', array(
386 'data' => array(
387 'type' => 'issue-list',
388 'attributes' => array(
389 'ids' => $issues,
390 )
391 ),
392 ));
393 try {
394 $response = $request->execute();
395 return $response;
396 } catch (wfCentralAPIException $e) {
397 error_log($e);
398 }
399 return false;
400 }
401
402 /**
403 * @return bool|wfCentralAPIResponse
404 */
405 public static function deleteNewIssues() {
406 $siteID = wfConfig::get('wordfenceCentralSiteID');
407 $request = new wfCentralAuthenticatedAPIRequest('/site/' . $siteID . '/issues', 'DELETE', array(
408 'data' => array(
409 'type' => 'issue-list',
410 'attributes' => array(
411 'status' => 'new',
412 )
413 ),
414 ));
415 try {
416 $response = $request->execute();
417 return $response;
418 } catch (wfCentralAPIException $e) {
419 error_log($e);
420 }
421 return false;
422 }
423
424 /**
425 * @param array $types Array of issue types to delete
426 * @param string $status Issue status to delete
427 * @return bool|wfCentralAPIResponse
428 */
429 public static function deleteIssueTypes($types, $status = 'new') {
430 $siteID = wfConfig::get('wordfenceCentralSiteID');
431 $request = new wfCentralAuthenticatedAPIRequest('/site/' . $siteID . '/issues', 'DELETE', array(
432 'data' => array(
433 'type' => 'issue-list',
434 'attributes' => array(
435 'types' => $types,
436 'status' => $status,
437 )
438 ),
439 ));
440 try {
441 $response = $request->execute();
442 return $response;
443 } catch (wfCentralAPIException $e) {
444 error_log($e);
445 }
446 return false;
447 }
448
449 public static function requestConfigurationSync() {
450 if (! wfCentral::isConnected()) {
451 return;
452 }
453
454 $endpoint = '/site/'.wfConfig::get('wordfenceCentralSiteID').'/config';
455 $args = array('timeout' => 0.01, 'blocking' => false);
456 $request = new wfCentralAuthenticatedAPIRequest($endpoint, 'POST', array(), $args);
457
458 try {
459 $request->execute();
460 } catch (Exception $e) {
461 // We can safely ignore an error here for now.
462 }
463 }
464
465 /**
466 * @param $scan
467 * @param $running
468 * @return bool|wfCentralAPIResponse
469 */
470 public static function updateScanStatus($scan = null) {
471 if ($scan === null) {
472 $scan = wfConfig::get_ser('scanStageStatuses');
473 if (!is_array($scan)) {
474 $scan = array();
475 }
476 }
477
478 $siteID = wfConfig::get('wordfenceCentralSiteID');
479 $running = wfScanner::shared()->isRunning();
480 $request = new wfCentralAuthenticatedAPIRequest('/site/' . $siteID . '/scan', 'PATCH', array(
481 'data' => array(
482 'type' => 'scan',
483 'attributes' => array(
484 'running' => $running,
485 'scan' => $scan,
486 'scan-summary' => wfConfig::get('wf_summaryItems'),
487 ),
488 ),
489 ));
490 try {
491 $response = $request->execute();
492 return $response;
493 } catch (wfCentralAPIException $e) {
494 error_log($e);
495 }
496 return false;
497 }
498 }
499