PluginProbe
Patchstack – WordPress & Plugins Security / 2.2.7
Patchstack – WordPress & Plugins Security v2.2.7
2.3.7 trunk 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.17 2.1.18 2.1.19 2.1.2 2.1.20 2.1.21 2.1.22 2.1.23 2.1.24 2.1.25 2.1.3 2.1.4 2.1.5 2.1.6 All 49 releases
← All changes | includes/api.php +85 -37 2.1.32.2.7 View file →
@@ -23,10 +23,10 @@
23 23 */
24 24 public function __construct( $core ) {
25 25 parent::__construct( $core );
26 26 $this->blog_id = get_current_blog_id();
27 - add_action( 'patchstack_update_license_status', array( $this, 'update_license_status' ) );
28 - add_action( 'patchstack_send_ping', array( $this, 'ping' ) );
27 + add_action( 'patchstack_update_license_status', [ $this, 'update_license_status' ] );
28 + add_action( 'patchstack_send_ping', [ $this, 'ping' ] );
29 29 }
30 30
31 31 /**
32 32 * Get the API token.
@@ -50,12 +50,12 @@
50 50 if ( $response && $response->result == 'success' ) {
51 51 $this->update_blog_option(
52 52 $this->blog_id,
53 53 'patchstack_api_token',
54 - array(
54 + [
55 55 'token' => $response->message,
56 56 'expiresin' => $response->expiresin,
57 - )
57 + ]
58 58 );
59 59 return $response->message;
60 60 }
61 61
@@ -72,17 +72,25 @@
72 72 * @return string|array
73 73 */
74 74 public function fetch_access_token( $clientid = '', $secretkey = '' ) {
75 75 // Skeleton for the response data.
76 - $response_data = (object) array(
76 + $response_data = (object) [
77 77 'result' => '',
78 78 'message' => '',
79 79 'expiresin' => '',
80 - );
80 + ];
81 81
82 82 // Determine if the license id/key is set.
83 - $client_id = $this->get_blog_option( $this->blog_id, 'patchstack_clientid', false ) ? $this->get_blog_option( $this->blog_id, 'patchstack_clientid', false ) : $clientid;
84 - $client_secret = $this->get_blog_option( $this->blog_id, 'patchstack_secretkey', false ) ? $this->get_blog_option( $this->blog_id, 'patchstack_secretkey', false ) : $secretkey;
83 + $client_id = $this->get_blog_option( $this->blog_id, 'patchstack_clientid', $clientid );
84 +
85 + // Decrypt the secret key, if it is encrypted.
86 + $client_secret = $this->get_blog_option( $this->blog_id, 'patchstack_secretkey', $secretkey );
87 + $client_nonce = $this->get_blog_option( $this->blog_id, 'patchstack_secretkey_nonce', false );
88 + if ( $client_nonce ) {
89 + $client_secret = $this->decrypt( $client_secret, $client_nonce );
90 + }
91 +
92 + // Make sure these values are set.
85 93 if ( empty( $client_id ) || empty( $client_secret ) ) {
86 94 $response_data->result = 'failed';
87 95 $response_data->message = __( 'API keys missing! Unable to obtain an access token.', 'patchstack' );
88 96 return $response_data;
@@ -90,22 +98,22 @@
90 98
91 99 // Send a request to our server to obtain the access token.
92 100 $response = wp_remote_post(
93 101 $this->plugin->auth_url . '/oauth/token',
94 - array(
102 + [
95 103 'method' => 'POST',
96 104 'timeout' => 60,
97 105 'redirection' => 5,
98 106 'httpversion' => '1.0',
99 107 'blocking' => true,
100 - 'headers' => array(),
101 - 'body' => array(
108 + 'headers' => [],
109 + 'body' => [
102 110 'client_id' => $client_id,
103 111 'client_secret' => $client_secret,
104 112 'grant_type' => 'client_credentials',
105 - ),
106 - 'cookies' => array(),
107 - )
113 + ],
114 + 'cookies' => [],
115 + ]
108 116 );
109 117
110 118 // Stop if we received an error from the API.
111 119 if ( is_wp_error( $response ) ) {
@@ -128,17 +136,10 @@
128 136 $response_data->message = 'expires_in value must be an integer';
129 137 return $response_data;
130 138 }
131 139 $response_data->expiresin = $result->expires_in != 0 ? time() + $result->expires_in : 0;
132 - } elseif ( ! empty( $result->expires_in ) ) {
133 - // Some providers supply the seconds until expiration rather than
134 - // the exact timestamp. Take a best guess at which we received.
135 - $expires = $options['expires'];
136 - if ( ! $this->isExpirationTimestamp( $expires ) ) {
137 - $expires += time();
138 - }
139 - $response_data->expiresin = $expires;
140 140 }
141 +
141 142 return $response_data;
142 143 } elseif ( isset( $result->error ) ) {
143 144 $response_data->result = $result->error;
144 145 $response_data->message = __( 'Unexpected error! Unable to obtain an access token.', 'patchstack' ) . $result->message;
@@ -174,15 +175,32 @@
174 175 $this->update_blog_option( $this->blog_id, 'patchstack_license_free', $response['free'] == false ? 0 : 1 );
175 176
176 177 if ( $response['free'] == true ) {
177 178 $this->update_blog_option( $this->blog_id, 'patchstack_show_settings', 0 );
179 + $this->update_blog_option( $this->blog_id, 'patchstack_firewall_rules_v3', '[]' );
180 + } else {
181 + $this->send_header_request();
178 182 }
179 183 }
180 184
181 - if ( isset( $response['active'] ) && $response['active'] == true ) {
182 - $this->update_blog_option( $this->blog_id, 'patchstack_license_activated', true );
185 + if ( isset( $response['active'] ) ) {
186 + $this->update_blog_option( $this->blog_id, 'patchstack_license_activated', $response['active'] == true );
183 187 }
184 188
189 + if ( isset( $response['class'] ) ) {
190 + $this->update_blog_option( $this->blog_id, 'patchstack_subscription_class', $response['class'] );
191 + $this->update_blog_option( $this->blog_id, 'patchstack_last_license_check', time() );
192 + }
193 +
194 + if ( isset( $response['managed'], $response['managed_string'] ) ) {
195 + $this->update_blog_option( $this->blog_id, 'patchstack_managed', $response['managed'] );
196 + $this->update_blog_option( $this->blog_id, 'patchstack_managed_text', $response['managed_string'] );
197 + }
198 +
199 + if ( isset( $response['site_id'] ) ) {
200 + $this->update_blog_option( $this->blog_id, 'patchstack_site_id', $response['site_id'] );
201 + }
202 +
185 203 return $response;
186 204 }
187 205
188 206 /**
@@ -192,9 +210,9 @@
192 210 * @param string $request
193 211 * @param array $data
194 212 * @return void|array If successful array, otherwise void.
195 213 */
196 - public function send_request( $url, $request, $data = array() ) {
214 + public function send_request( $url, $request, $data = [] ) {
197 215 // Attempt to get the access token.
198 216 $token = $this->get_access_token();
199 217 if ( empty( $token ) ) {
200 218 return;
@@ -202,22 +220,22 @@
202 220
203 221 // Send the remote request using the WordPress built-in method.
204 222 $response = wp_remote_request(
205 223 $this->plugin->api_url . $url,
206 - array(
224 + [
207 225 'method' => $request,
208 226 'timeout' => 60,
209 227 'redirection' => 5,
210 228 'httpversion' => '1.0',
211 229 'blocking' => true,
212 - 'headers' => array(
230 + 'headers' => [
213 231 'Authorization' => 'Bearer ' . $token,
214 232 'LicenseID' => $this->get_blog_option( $this->blog_id, 'patchstack_clientid', 0 ),
215 233 'Source-Host' => get_site_url(),
216 - ),
234 + ],
217 235 'body' => $data,
218 - 'cookies' => array(),
219 - )
236 + 'cookies' => [],
237 + ]
220 238 );
221 239
222 240 // Check error or status code.
223 241 if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) != 200 ) {
@@ -228,19 +246,49 @@
228 246 return json_decode( wp_remote_retrieve_body( $response ), true );
229 247 }
230 248
231 249 /**
250 + * Send a request to our API for the IP address header.
251 + */
252 + public function send_header_request()
253 + {
254 + $header = get_option( 'patchstack_firewall_ip_header', '' );
255 + $computed = get_option( 'patchstack_ip_header_computed', 0 );
256 +
257 + if ( $header == '' && ! $computed ) {
258 + // Create an OTT token.
259 + $ott = md5( wp_generate_password( 32, true, true ) );
260 + update_option( 'patchstack_ott_action', $ott );
261 +
262 + // Tell our API.
263 + wp_remote_request(
264 + $this->plugin->api_url . '/api/header',
265 + [
266 + 'method' => 'POST',
267 + 'timeout' => 60,
268 + 'redirection' => 5,
269 + 'httpversion' => '1.0',
270 + 'blocking' => true,
271 + 'headers' => [
272 + 'Source-Host' => get_site_url(),
273 + ],
274 + 'body' => [
275 + 'token' => $ott,
276 + 'url' => get_site_url()
277 + ],
278 + 'cookies' => [],
279 + ]
280 + );
281 + }
282 + }
283 +
284 + /**
232 285 * Get the firewall rules.
233 286 *
234 287 * @return array The firewall rules.
235 288 */
236 289 public function post_firewall_rule_json() {
237 - // If the request is coming from the API, fetch fresh rules.
238 - if ( isset( $_POST['webarx_refresh_rules'] ) ) {
239 - return $this->send_request( '/api/get-rules/2?bypass=cache', 'POST' );
240 - }
241 -
242 - return $this->send_request( '/api/get-rules/2', 'POST' );
290 + return $this->send_request( '/api/get-rules/3', 'POST' );
243 291 }
244 292
245 293 /**
246 294 * Get the .htaccess rules.
@@ -330,7 +378,7 @@
330 378 *
331 379 * @return void
332 380 */
333 381 public function ping() {
334 - $this->send_request( '/api/ping', 'POST', array( 'firewall' => $this->get_option( 'patchstack_basic_firewall' ) == 1 ? 1 : 0 ) );
382 + $this->send_request( '/api/ping', 'POST', [ 'firewall' => $this->get_option( 'patchstack_basic_firewall' ) == 1 ? 1 : 0 ] );
335 383 }
336 384 }