PluginProbe
The WP Remote WordPress Plugin / trunk
The WP Remote WordPress Plugin vtrunk
6.72 6.69 6.65 6.62 6.48 6.47 4.87 4.97 5.05 5.09 5.16 5.22 5.24 5.25 5.38 5.41 5.42 5.45 5.47 5.53 5.56 5.65 5.68 5.72 5.73 All 53 releases
← All changes | callback/request.php +97 -53 5.16trunk View file →
@@ -1,18 +1,21 @@
1 1 <?php
2 2
3 3 if (!defined('ABSPATH')) exit;
4 -if (!class_exists('BVCallbackRequest')) :
5 - class BVCallbackRequest {
4 +if (!class_exists('WPRCallbackRequest')) :
5 + class WPRCallbackRequest {
6 6 public $params;
7 7 public $method;
8 8 public $wing;
9 9 public $is_afterload;
10 + public $is_aftershutdown;
11 + public $keep_page_output;
10 12 public $is_admin_ajax;
11 13 public $is_debug;
12 14 public $account;
13 15 public $settings;
14 16 public $sig;
17 + public $sighshalgo;
15 18 public $time;
16 19 public $version;
17 20 public $is_sha1;
18 21 public $bvb64stream;
@@ -18,9 +21,17 @@
18 21 public $bvb64stream;
19 22 public $bvb64cksize;
20 23 public $checksum;
21 24 public $error = array();
25 + public $pubkey_name;
26 + public $bvprmsmac;
27 + public $bvboundry;
22 28
29 + private static $SIG_HASH_ALGO_MAP = array(
30 + '1' => OPENSSL_ALGO_SHA1,
31 + '7' => OPENSSL_ALGO_SHA256
32 + );
33 +
23 34 public function __construct($account, $in_params, $settings) {
24 35 $this->params = array();
25 36 $this->account = $account;
26 37 $this->settings = $settings;
@@ -26,17 +37,25 @@
26 37 $this->settings = $settings;
27 38 $this->wing = $in_params['wing'];
28 39 $this->method = $in_params['bvMethod'];
29 40 $this->is_afterload = array_key_exists('afterload', $in_params);
41 + $this->is_aftershutdown = array_key_exists('aftershutdown', $in_params);
42 + $this->keep_page_output = $this->is_aftershutdown &&
43 + array_key_exists('keeppageoutput', $in_params);
30 44 $this->is_admin_ajax = array_key_exists('adajx', $in_params);
31 45 $this->is_debug = array_key_exists('bvdbg', $in_params);
32 46 $this->sig = $in_params['sig'];
47 + $this->sighshalgo = !empty($in_params['sighshalgo']) ? $in_params['sighshalgo'] : '1';
33 48 $this->time = intval($in_params['bvTime']);
34 49 $this->version = $in_params['bvVersion'];
35 50 $this->is_sha1 = array_key_exists('sha1', $in_params);
36 51 $this->bvb64stream = isset($in_params['bvb64stream']);
37 - $this->bvb64cksize = array_key_exists('bvb64cksize', $in_params) ? intval($in_params['bvb64cksize']) : false;
52 + $this->bvb64cksize = array_key_exists('bvb64cksize', $in_params) ? intval($in_params['bvb64cksize']) : 0;
38 53 $this->checksum = array_key_exists('checksum', $in_params) ? $in_params['checksum'] : false;
54 + $this->pubkey_name = !empty($in_params['pubkeyname']) ?
55 + WPRAccount::sanitizeKey($in_params['pubkeyname']) : 'm_public';
56 + $this->bvprmsmac = !empty($in_params['bvprmsmac']) ? WPRAccount::sanitizeKey($in_params['bvprmsmac']) : "";
57 + $this->bvboundry = !empty($in_params['bvboundry']) ? $in_params['bvboundry'] : "";
39 58 }
40 59
41 60 public function isAPICall() {
42 61 return array_key_exists('apicall', $this->params);
@@ -41,38 +60,25 @@
41 60 public function isAPICall() {
42 61 return array_key_exists('apicall', $this->params);
43 62 }
44 63
45 - public function curlRequest($url, $body) {
46 - $ch = curl_init($url);
47 - curl_setopt($ch, CURLOPT_POST, 1);
48 - curl_setopt($ch, CURLOPT_TIMEOUT, 15);
49 - curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($body));
50 - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
51 - return curl_exec($ch);
52 - }
64 + public function http_request($url, $body) {
65 + $body = http_build_query($body);
66 + $response = wp_remote_post($url, array(
67 + 'body' => $body,
68 + 'timeout' => 15,
69 + 'headers' => array(
70 + 'Content-Type' => 'application/x-www-form-urlencoded',
71 + ),
72 + ));
53 73
54 - public function fileGetContentRequest($url, $body) {
55 - $options = array(
56 - 'http' => array(
57 - 'header' => "Content-type: application/x-www-form-urlencoded\r\n",
58 - 'method' => 'POST',
59 - 'content' => http_build_query($body)
60 - )
61 - );
74 + if (is_wp_error($response)) {
75 + return false;
76 + }
62 77
63 - $context = stream_context_create($options);
64 - return file_get_contents($url, false, $context);
78 + return wp_remote_retrieve_body($response);
65 79 }
66 80
67 - public function http_request($url, $body) {
68 - if (in_array('curl', get_loaded_extensions())) {
69 - return $this->curlRequest($url, $body);
70 - } else {
71 - return $this->fileGetContentRequest($url, $body);
72 - }
73 - }
74 -
75 81 public function get_params_via_api($params_key, $apiurl) {
76 82 $res = $this->http_request($apiurl, array('bvkey' => $params_key));
77 83
78 84 if ($res === FALSE) {
@@ -97,8 +103,14 @@
97 103 }
98 104 if ($this->is_afterload) {
99 105 $info["afterload"] = true;
100 106 }
107 + if ($this->is_aftershutdown) {
108 + $info["aftershutdown"] = true;
109 + }
110 + if ($this->keep_page_output) {
111 + $info["keeppageoutput"] = true;
112 + }
101 113 return $info;
102 114 }
103 115
104 116 public function processParams($in_params) {
@@ -127,12 +139,16 @@
127 139 $in_params["bvprms"] = $pdata;
128 140 }
129 141 }
130 142
131 - if (array_key_exists('bvprms', $in_params) && isset($in_params['bvprms']) &&
132 - array_key_exists('bvprmsmac', $in_params) && isset($in_params['bvprmsmac'])) {
143 + if (array_key_exists('bvprms', $in_params) && isset($in_params['bvprms'])) {
144 + if (!empty($in_params['bvprmshshalgo']) && $in_params['bvprmshshalgo'] === 'sha256') {
145 + $calculated_mac = hash_hmac('SHA256', $in_params['bvprms'], $this->account->secret);
146 + } else {
147 + $calculated_mac = hash_hmac('SHA1', $in_params['bvprms'], $this->account->secret);
148 + }
133 149
134 - if ($this->verify($in_params['bvprms'], base64_decode($in_params['bvprmsmac'])) === true) {
150 + if ($this->compare_mac($this->bvprmsmac, $calculated_mac) === true) {
135 151
136 152 if (array_key_exists('b64', $in_params)) {
137 153 foreach ($in_params['b64'] as $key) {
138 154 if (is_array($in_params[$key])) {
@@ -150,9 +166,9 @@
150 166 }
151 167
152 168 if (array_key_exists('sersafe', $in_params)) {
153 169 $key = $in_params['sersafe'];
154 - $in_params[$key] = BVCallbackRequest::serialization_safe_decode($in_params[$key]);
170 + $in_params[$key] = WPRCallbackRequest::serialization_safe_decode($in_params[$key]);
155 171 }
156 172
157 173 if (array_key_exists('bvprms', $in_params) && isset($in_params['bvprms'])) {
158 174 $params = $in_params['bvprms'];
@@ -172,8 +188,9 @@
172 188 }
173 189
174 190 if (array_key_exists('memset', $in_params)) {
175 191 $val = intval($in_params['memset']);
192 + // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- Required for memory limit adjustment
176 193 @ini_set('memory_limit', $val.'M');
177 194 }
178 195
179 196 return $params;
@@ -178,15 +195,30 @@
178 195
179 196 return $params;
180 197 }
181 198 }
199 + return false;
200 + }
182 201
183 - return false;
202 + private function compare_mac($l_hash, $r_hash) {
203 + if (!is_string($l_hash) || !is_string($r_hash)) {
204 + return false;
205 + }
206 +
207 + if (strlen($l_hash) !== strlen($r_hash)) {
208 + return false;
209 + }
210 +
211 + if (function_exists('hash_equals')) {
212 + return hash_equals($l_hash, $r_hash);
213 + } else {
214 + return $l_hash === $r_hash;
215 + }
184 216 }
185 217
186 218 public static function serialization_safe_decode($data) {
187 219 if (is_array($data)) {
188 - $data = array_map(array('BVCallbackRequest', 'serialization_safe_decode'), $data);
220 + $data = array_map(array('WPRCallbackRequest', 'serialization_safe_decode'), $data);
189 221 } elseif (is_string($data)) {
190 222 $data = base64_decode($data);
191 223 }
192 224
@@ -194,9 +226,9 @@
194 226 }
195 227
196 228 public function authenticate() {
197 229 if (!$this->account) {
198 - array_push($this->error, "ACCOUNT_NOT_FOUND");
230 + $this->error["message"] = "ACCOUNT_NOT_FOUND";
199 231 return false;
200 232 }
201 233
202 234 $bv_last_recv_time = $this->settings->getOption('bvLastRecvTime');
@@ -203,10 +235,10 @@
203 235 if ($this->time < intval($bv_last_recv_time) - 300) {
204 236 return false;
205 237 }
206 238
207 - $data = $this->method.$this->account->secret.$this->time.$this->version;
208 - if (!$this->verify($data, base64_decode($this->sig))) {
239 + $data = $this->method.$this->account->secret.$this->time.$this->version.$this->bvprmsmac;
240 + if (!$this->verify($data, base64_decode($this->sig), $this->sighshalgo)) {
209 241 return false;
210 242 }
211 243 $this->settings->updateOption('bvLastRecvTime', $this->time);
212 244
@@ -212,32 +244,42 @@
212 244
213 245 return 1;
214 246 }
215 247
216 - public function verify($data, $sig) {
217 - if (!function_exists('openssl_verify')) {
218 - array_push($this->error, "OPENSSL_VERIFY_FUNC_NOT_FOUND");
248 + public function verify($data, $sig, $sighshalgo) {
249 + if (!function_exists('openssl_verify') || !function_exists('openssl_pkey_get_public')) {
250 + $this->error["message"] = "OPENSSL_FUNCS_NOT_FOUND";
219 251 return false;
220 252 }
221 253
222 - $key_file = dirname( __FILE__ ) . '/../public_keys/m_public.pub';
254 + $openssl_algo = array_key_exists($sighshalgo, self::$SIG_HASH_ALGO_MAP) ? self::$SIG_HASH_ALGO_MAP[$sighshalgo] : null;
255 + if ($openssl_algo === null) {
256 + $this->error["message"] = "UNSUPPORTED_HASH_ALGORITHM: " . $sighshalgo;
257 + return false;
258 + }
259 +
260 + $key_file = dirname( __DIR__ ) . '/public_keys/' . $this->pubkey_name . '.pub';
223 261 if (!file_exists($key_file)) {
224 - array_push($this->error, "PUBLIC_KEY_NOT_FOUND");
262 + $this->error["message"] = "PUBLIC_KEY_NOT_FOUND";
225 263 return false;
226 264 }
227 - $public_key = file_get_contents($key_file);
265 +
266 + $public_key_str = WPRWPFileSystem::getInstance()->getContents($key_file);
267 +
268 + $public_key = openssl_pkey_get_public($public_key_str);
228 269 if (!$public_key) {
229 - array_push($this->error, "UNABLE_TO_LOAD_PUBLIC_KEY");
270 + $this->error["message"] = "UNABLE_TO_LOAD_PUBLIC_KEY";
230 271 return false;
231 272 }
232 273
233 - $verify = openssl_verify($data, $sig, $public_key);
274 + $verify = openssl_verify($data, $sig, $public_key, $openssl_algo);
234 275 if ($verify === 1) {
235 276 return true;
236 277 } elseif ($verify === 0) {
237 - array_push($this->error, "INCORRECT_SIGNATURE");
278 + $this->error["message"] = "INCORRECT_SIGNATURE";
279 + $this->error["pubkey_sig"] = substr(hash('md5', $public_key_str), 0, 8);
238 280 } else {
239 - array_push($this->error, "OPENSSL_VERIFY_FAILED");
281 + $this->error["message"] = "OPENSSL_VERIFY_FAILED";
240 282 }
241 283 return false;
242 284 }
243 285
@@ -253,21 +295,23 @@
253 295 }
254 296
255 297 public function authFailedResp() {
256 298 $api_public_key = WPRAccount::getApiPublicKey($this->settings);
257 - $default_secret = WPRRecover::getDefaultSecret($this->settings);
299 + $default_account_pubkey = WPRAccount::getDefaultPublicKey();
258 300 $bvinfo = new WPRInfo($this->settings);
259 301 $resp = array(
260 302 "request_info" => $this->info(),
261 303 "bvinfo" => $bvinfo->info(),
262 304 "statusmsg" => "FAILED_AUTH",
263 - "api_pubkey" => substr($api_public_key, 0, 8),
264 - "def_sigmatch" => substr(hash('sha1', $this->method.$default_secret.$this->time.$this->version), 0, 8)
305 + "api_pubkey" => substr($api_public_key, 0, 8)
265 306 );
266 307
308 + if (is_string($default_account_pubkey) && strlen($default_account_pubkey) >= 32) {
309 + $resp["default_account_pubkey"] = substr($default_account_pubkey, 0, 8);
310 + }
311 +
267 312 if ($this->account) {
268 313 $resp["account_info"] = $this->account->info();
269 - $resp["sigmatch"] = substr(hash('sha1', $this->method.$this->account->secret.$this->time.$this->version), 0, 6);
270 314 } else {
271 315 $resp["account_info"] = array("error" => "ACCOUNT_NOT_FOUND");
272 316 }
273 317
@@ -273,5 +317,5 @@
273 317
274 318 return $resp;
275 319 }
276 320 }
277 -endif;
321 +endif;