iThemes Sync - Version 2.1.6

Version Description

  • Bug Fix: Fixed an issue where a user couldn't be unsynced if already removed from the dashboard
Download this release

Release Info

Developer oakesjosh
Plugin Icon 128x128 iThemes Sync
Version 2.1.6
Comparing to
See all releases

Code changes from version 2.1.5 to 2.1.6

Files changed (8) hide show
  1. functions.php +53 -0
  2. history.txt +3 -1
  3. init.php +1 -1
  4. lang/ithemes-sync.pot +2 -2
  5. readme.txt +5 -2
  6. request-handler.php +46 -0
  7. server.php +11 -5
  8. settings-page.php +3 -2
functions.php CHANGED
@@ -1030,4 +1030,57 @@ class Ithemes_Sync_Functions {
1030
  return false;
1031
  }
1032
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1033
  }
1030
  return false;
1031
  }
1032
 
1033
+ /**
1034
+ * Checks if sodium library and methods we use are available
1035
+ * Also checks if sodium is fast enough on this system
1036
+ * If available: include the compatiability layer, core utilities, and Base64 UrlSafe classes
1037
+ *
1038
+ * @return bool
1039
+ */
1040
+ public static function is_sodium_available() {
1041
+ $requiredFiles = array(
1042
+ 'wp-includes/sodium_compat/autoload.php',
1043
+ );
1044
+
1045
+ foreach ( $requiredFiles as $file ) {
1046
+ if ( file_exists( ABSPATH . $file ) ) {
1047
+ require_once( ABSPATH . $file );
1048
+ } else {
1049
+ return false;
1050
+ }
1051
+ }
1052
+
1053
+ // Verify the functions we need are callable
1054
+ if ( ! is_callable( 'sodium_base642bin' ) || ! is_callable( 'sodium_crypto_sign_verify_detached' ) ) {
1055
+ return false;
1056
+ }
1057
+
1058
+ // Check for a edge-case affecting PHP Maths abilities
1059
+ // Sodium_Compat isn't compatible with PHP 7.2.0~7.2.2 due to a bug in the PHP Opcache extension, bail early as it'll fail.
1060
+ if (
1061
+ ! extension_loaded( 'sodium' ) &&
1062
+ in_array( PHP_VERSION_ID, [ 70200, 70201, 70202 ], true ) &&
1063
+ extension_loaded( 'opcache' )
1064
+ ) {
1065
+ return false;
1066
+ }
1067
+
1068
+ // Verify runtime speed of Sodium_Compat is acceptable.
1069
+ if ( ! extension_loaded( 'sodium' ) && ! ParagonIE_Sodium_Compat::polyfill_is_fast() ) {
1070
+
1071
+ // Allow for an old version of Sodium_Compat being loaded before the bundled WordPress one.
1072
+ if ( method_exists( 'ParagonIE_Sodium_Compat', 'runtime_speed_test' ) ) {
1073
+ // Run `ParagonIE_Sodium_Compat::runtime_speed_test()` in optimized integer mode, as that's what is used for signing verifications.
1074
+ $old_fastMult = ParagonIE_Sodium_Compat::$fastMult;
1075
+ ParagonIE_Sodium_Compat::$fastMult = true;
1076
+ $sodium_compat_is_fast = ParagonIE_Sodium_Compat::runtime_speed_test( 100, 10 );
1077
+ ParagonIE_Sodium_Compat::$fastMult = $old_fastMult;
1078
+
1079
+ return $sodium_compat_is_fast;
1080
+ }
1081
+
1082
+ }
1083
+
1084
+ return true;
1085
+ }
1086
  }
history.txt CHANGED
@@ -233,4 +233,6 @@
233
  2.1.4.1 - 2020-03-17 - Josh Oakes
234
  Bug Fix: Roll back public-key signed request support
235
  2.1.5 - 2020-04-03 - Josh Oakes
236
- Bug Fix: Limit the total number of unsent notices that can be queued
 
 
233
  2.1.4.1 - 2020-03-17 - Josh Oakes
234
  Bug Fix: Roll back public-key signed request support
235
  2.1.5 - 2020-04-03 - Josh Oakes
236
+ Bug Fix: Limit the total number of unsent notices that can be queued
237
+ 2.1.6 - 2020-05-20 - Josh Oakes
238
+ Bug Fix: Fixed an issue where a user couldn't be unsynced if already removed from the dashboard
init.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: iThemes Sync
4
  Plugin URI: http://ithemes.com/sync
5
  Description: Manage updates to your WordPress sites easily in one place.
6
  Author: iThemes
7
- Version: 2.1.5
8
  Author URI: http://ithemes.com/
9
  Domain Path: /lang/
10
  iThemes Package: ithemes-sync
4
  Plugin URI: http://ithemes.com/sync
5
  Description: Manage updates to your WordPress sites easily in one place.
6
  Author: iThemes
7
+ Version: 2.1.6
8
  Author URI: http://ithemes.com/
9
  Domain Path: /lang/
10
  iThemes Package: ithemes-sync
lang/ithemes-sync.pot CHANGED
@@ -4,7 +4,7 @@ msgid ""
4
  msgstr ""
5
  "Project-Id-Version: iThemes Sync 2.1.5\n"
6
  "Report-Msgid-Bugs-To: http://ithemes.com/support/\n"
7
- "POT-Creation-Date: 2020-04-03 16:05:35+00:00\n"
8
  "PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
@@ -350,7 +350,7 @@ msgstr ""
350
  msgid "The Sync server returned an unknown response."
351
  msgstr ""
352
 
353
- #: server.php:192
354
  msgid "An unrecognized server response format was received from the iThemes Sync server."
355
  msgstr ""
356
 
4
  msgstr ""
5
  "Project-Id-Version: iThemes Sync 2.1.5\n"
6
  "Report-Msgid-Bugs-To: http://ithemes.com/support/\n"
7
+ "POT-Creation-Date: 2020-05-20 20:44:47+00:00\n"
8
  "PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
350
  msgid "The Sync server returned an unknown response."
351
  msgstr ""
352
 
353
+ #: server.php:195
354
  msgid "An unrecognized server response format was received from the iThemes Sync server."
355
  msgstr ""
356
 
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === iThemes Sync ===
2
- Contributors: ithemes, layotte
3
  Tags: manage multiple Sites, backup, security, migrate, SEO, manage updates, administration, update manager, reports, sync, google analytics, optimize, uptime, ithemes, customize dashboard, client sites, maintenance, management, google webmaster tools, reporting
4
  Requires at least: 4.5
5
  Requires PHP: 5.6
6
  Tested up to: 5.4
7
- Stable tag: 2.1.5
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/quick-guide-gplv3.html
10
 
@@ -87,6 +87,9 @@ Make steady, reliable income for WordPress maintenance with iThemes Sync Pro’s
87
 
88
  == Changelog ==
89
 
 
 
 
90
  = 2.1.5 =
91
  * Bug Fix: Limit the total number of unsent notices that can be queued
92
 
1
  === iThemes Sync ===
2
+ Contributors: ithemes, layotte, oakesjosh
3
  Tags: manage multiple Sites, backup, security, migrate, SEO, manage updates, administration, update manager, reports, sync, google analytics, optimize, uptime, ithemes, customize dashboard, client sites, maintenance, management, google webmaster tools, reporting
4
  Requires at least: 4.5
5
  Requires PHP: 5.6
6
  Tested up to: 5.4
7
+ Stable tag: 2.1.6
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/quick-guide-gplv3.html
10
 
87
 
88
  == Changelog ==
89
 
90
+ = 2.1.6 =
91
+ * Bug Fix: Fixed an issue where a user couldn't be unsynced if already removed from the dashboard
92
+
93
  = 2.1.5 =
94
  * Bug Fix: Limit the total number of unsent notices that can be queued
95
 
request-handler.php CHANGED
@@ -61,6 +61,25 @@ class Ithemes_Sync_Request_Handler {
61
 
62
  $request = $_POST['request'];
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
65
  $request = stripslashes( $request );
66
  }
@@ -461,6 +480,33 @@ class Ithemes_Sync_Request_Handler {
461
  return $json;
462
  }
463
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
464
  }
465
 
466
  new Ithemes_Sync_Request_Handler();
61
 
62
  $request = $_POST['request'];
63
 
64
+ if ( !empty( $_POST['signature'] ) ) {
65
+
66
+ // Append success and failures to response
67
+ $sodium_available = Ithemes_Sync_Functions::is_sodium_available();
68
+
69
+ if ( $sodium_available && ! $this->verify_request_signature( $request, $_POST['signature'] ) ) {
70
+ // Sodium is available and verification failed
71
+ do_action( 'ithemes-sync-add-log', 'signature-verification', array( 'available' => true, 'verified' => false ) );
72
+
73
+ // $this->send_response( new WP_Error( 'request-signature-invalid', 'The request signature could not be verified' ) );
74
+ } elseif ( $sodium_available ) {
75
+ // Sodium available and signature was verified
76
+ do_action( 'ithemes-sync-add-log', 'signature-verification', array( 'available' => true, 'verified' => true ) );
77
+ } else {
78
+ // Sodium is not available
79
+ do_action( 'ithemes-sync-add-log', 'signature-verification', array( 'available' => false, 'verified' => false ) );
80
+ }
81
+ }
82
+
83
  if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
84
  $request = stripslashes( $request );
85
  }
480
  return $json;
481
  }
482
 
483
+ /**
484
+ * Determine if signature supplied in the request can be verified using the public key
485
+ *
486
+ * @param $request
487
+ * @param $signature
488
+ *
489
+ * @return bool
490
+ */
491
+ private function verify_request_signature( $request, $signature ) {
492
+
493
+ // Verify the functions we need are callable
494
+ if ( ! is_callable( 'sodium_base642bin' ) || ! is_callable( 'sodium_crypto_sign_verify_detached' ) ) {
495
+ return false;
496
+ }
497
+
498
+ try {
499
+
500
+ $public_key = sodium_base642bin( file_get_contents( $GLOBALS['ithemes_sync_path'] . '/public.key' ), 5 );
501
+ $signature = sodium_base642bin( $signature, 5 );
502
+
503
+ } catch ( Exception $e ) {
504
+ return false;
505
+ }
506
+
507
+ return sodium_crypto_sign_verify_detached( $signature, $request, $public_key );
508
+ }
509
+
510
  }
511
 
512
  new Ithemes_Sync_Request_Handler();
server.php CHANGED
@@ -110,6 +110,9 @@ class Ithemes_Sync_Server {
110
  }
111
 
112
  public static function request( $action, $query = array(), $data = array() ) {
 
 
 
113
  if ( isset( $data['auth_token'] ) ) {
114
  $data['iterations'] = self::$password_iterations;
115
  }
@@ -152,13 +155,13 @@ class Ithemes_Sync_Server {
152
  $response = self::do_patched_post( $request, $remote_post_args );
153
 
154
  if ( is_wp_error( $response ) ) {
155
- $response = wp_remote_post( self::$secure_server_url . $request, $remote_post_args );
156
  } else {
157
  $options['use_ca_patch'] = true;
158
  }
159
  }
160
  else {
161
- $response = wp_remote_post( self::$secure_server_url . $request, $remote_post_args );
162
 
163
  if ( is_wp_error( $response ) ) {
164
  $response = self::do_patched_post( $request, $remote_post_args );
@@ -170,7 +173,7 @@ class Ithemes_Sync_Server {
170
  }
171
 
172
  if ( is_wp_error( $response ) ) {
173
- $response = wp_remote_post( self::$insecure_server_url . $request . '&insecure=1', $remote_post_args );
174
 
175
  $options['use_ssl'] = false;
176
  $options['use_ca_patch'] = false;
@@ -201,8 +204,10 @@ class Ithemes_Sync_Server {
201
  }
202
 
203
  private static function do_patched_post( $request, $remote_post_args ) {
 
 
204
  self::enable_ssl_ca_patch();
205
- $response = wp_remote_post( self::$secure_server_url . $request . '&ca_patch=1', $remote_post_args );
206
  self::disable_ssl_ca_patch();
207
 
208
  return $response;
@@ -224,9 +229,10 @@ class Ithemes_Sync_Server {
224
  }
225
 
226
  public static function add_ca_patch_to_curl_opts( $handle ) {
 
227
  $url = curl_getinfo( $handle, CURLINFO_EFFECTIVE_URL );
228
 
229
- if ( ! preg_match( '/^' . preg_quote( self::$secure_server_url, '/' ) . '/', $url ) ) {
230
  return;
231
  }
232
 
110
  }
111
 
112
  public static function request( $action, $query = array(), $data = array() ) {
113
+
114
+ $secure_url = apply_filters( 'sync_api_request_url', self::$secure_server_url );
115
+
116
  if ( isset( $data['auth_token'] ) ) {
117
  $data['iterations'] = self::$password_iterations;
118
  }
155
  $response = self::do_patched_post( $request, $remote_post_args );
156
 
157
  if ( is_wp_error( $response ) ) {
158
+ $response = wp_remote_post( $secure_url . $request, $remote_post_args );
159
  } else {
160
  $options['use_ca_patch'] = true;
161
  }
162
  }
163
  else {
164
+ $response = wp_remote_post( $secure_url . $request, $remote_post_args );
165
 
166
  if ( is_wp_error( $response ) ) {
167
  $response = self::do_patched_post( $request, $remote_post_args );
173
  }
174
 
175
  if ( is_wp_error( $response ) ) {
176
+ $response = wp_remote_post( $secure_url . $request . '&insecure=1', $remote_post_args );
177
 
178
  $options['use_ssl'] = false;
179
  $options['use_ca_patch'] = false;
204
  }
205
 
206
  private static function do_patched_post( $request, $remote_post_args ) {
207
+ $secure_url = apply_filters( 'sync_api_request_url', self::$secure_server_url );
208
+
209
  self::enable_ssl_ca_patch();
210
+ $response = wp_remote_post( $secure_url . $request . '&ca_patch=1', $remote_post_args );
211
  self::disable_ssl_ca_patch();
212
 
213
  return $response;
229
  }
230
 
231
  public static function add_ca_patch_to_curl_opts( $handle ) {
232
+ $secure_url = apply_filters( 'sync_api_request_url', self::$secure_server_url );
233
  $url = curl_getinfo( $handle, CURLINFO_EFFECTIVE_URL );
234
 
235
+ if ( ! preg_match( '/^' . preg_quote( $secure_url, '/' ) . '/', $url ) ) {
236
  return;
237
  }
238
 
settings-page.php CHANGED
@@ -155,8 +155,8 @@ class Ithemes_Sync_Settings_Page {
155
 
156
 
157
  $result = Ithemes_Sync_Server::deauthenticate( $data['user'], $user_details['username'], $user_details['key'] );
158
-
159
- if ( is_wp_error( $result ) && ( 'authentication' != $result->get_error_code() ) ) {
160
  $heading = __( 'The user could not be unsynced.', 'it-l10n-ithemes-sync' );
161
  $message = $result->get_error_message();
162
 
@@ -336,6 +336,7 @@ class Ithemes_Sync_Settings_Page {
336
  <?php wp_nonce_field( 'authenticate-user' ); ?>
337
  </form>
338
  </div>
 
339
  </div>
340
  <?php
341
 
155
 
156
 
157
  $result = Ithemes_Sync_Server::deauthenticate( $data['user'], $user_details['username'], $user_details['key'] );
158
+
159
+ if ( is_wp_error( $result ) && ( 'authentication' != $result->get_error_code() ) && 'This site has not been authenticated by this user.' != $result->get_error_message() ) {
160
  $heading = __( 'The user could not be unsynced.', 'it-l10n-ithemes-sync' );
161
  $message = $result->get_error_message();
162
 
336
  <?php wp_nonce_field( 'authenticate-user' ); ?>
337
  </form>
338
  </div>
339
+ <?php do_action('sync_dev_render'); ?>
340
  </div>
341
  <?php
342