PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 7.2.1
Jetpack – WP Security, Backup, Speed, & Growth v7.2.1
15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / class.jetpack-signature.php
jetpack Last commit date
3rd-party 7 years ago _inc 7 years ago bin 7 years ago css 7 years ago extensions 7 years ago images 7 years ago json-endpoints 7 years ago languages 7 years ago logs 9 years ago modules 7 years ago sal 7 years ago scss 7 years ago sync 7 years ago views 7 years ago .svnignore 12 years ago CODE-OF-CONDUCT.md 9 years ago changelog.txt 7 years ago class.frame-nonce-preview.php 9 years ago class.jetpack-admin.php 7 years ago class.jetpack-affiliate.php 7 years ago class.jetpack-autoupdate.php 8 years ago class.jetpack-bbpress-json-api-compat.php 9 years ago class.jetpack-cli.php 7 years ago class.jetpack-client-server.php 8 years ago class.jetpack-client.php 7 years ago class.jetpack-connection-banner.php 7 years ago class.jetpack-constants.php 8 years ago class.jetpack-data.php 7 years ago class.jetpack-debugger.php 7 years ago class.jetpack-error.php 10 years ago class.jetpack-gutenberg.php 7 years ago class.jetpack-heartbeat.php 7 years ago class.jetpack-idc.php 8 years ago class.jetpack-ixr-client.php 10 years ago class.jetpack-jitm.php 7 years ago class.jetpack-modules-list-table.php 7 years ago class.jetpack-network-sites-list-table.php 9 years ago class.jetpack-network.php 7 years ago class.jetpack-options.php 7 years ago class.jetpack-plan.php 7 years ago class.jetpack-post-images.php 7 years ago class.jetpack-signature.php 7 years ago class.jetpack-tracks.php 7 years ago class.jetpack-twitter-cards.php 7 years ago class.jetpack-user-agent.php 8 years ago class.jetpack-xmlrpc-server.php 7 years ago class.jetpack.php 7 years ago class.json-api-endpoints.php 7 years ago class.json-api.php 7 years ago class.photon.php 7 years ago composer.json 7 years ago functions.compat.php 7 years ago functions.gallery.php 8 years ago functions.global.php 7 years ago functions.opengraph.php 7 years ago functions.photon.php 7 years ago jetpack.php 7 years ago json-api-config.php 10 years ago json-endpoints.php 7 years ago locales.php 7 years ago readme.txt 7 years ago require-lib.php 7 years ago uninstall.php 8 years ago wpml-config.xml 10 years ago
class.jetpack-signature.php
267 lines
1 <?php
2
3 // These constants can be set in wp-config.php to ensure sites behind proxies will still work.
4 // Setting these constants, though, is *not* the preferred method. It's better to configure
5 // the proxy to send the X-Forwarded-Port header.
6 defined( 'JETPACK_SIGNATURE__HTTP_PORT' ) or define( 'JETPACK_SIGNATURE__HTTP_PORT' , 80 );
7 defined( 'JETPACK_SIGNATURE__HTTPS_PORT' ) or define( 'JETPACK_SIGNATURE__HTTPS_PORT', 443 );
8
9 class Jetpack_Signature {
10 public $token;
11 public $secret;
12
13 function __construct( $access_token, $time_diff = 0 ) {
14 $secret = explode( '.', $access_token );
15 if ( 2 != count( $secret ) )
16 return;
17
18 $this->token = $secret[0];
19 $this->secret = $secret[1];
20 $this->time_diff = $time_diff;
21 }
22
23 function sign_current_request( $override = array() ) {
24 if ( isset( $override['scheme'] ) ) {
25 $scheme = $override['scheme'];
26 if ( !in_array( $scheme, array( 'http', 'https' ) ) ) {
27 return new Jetpack_Error( 'invalid_scheme', 'Invalid URL scheme' );
28 }
29 } else {
30 if ( is_ssl() ) {
31 $scheme = 'https';
32 } else {
33 $scheme = 'http';
34 }
35 }
36
37 $host_port = isset( $_SERVER['HTTP_X_FORWARDED_PORT'] ) ? $_SERVER['HTTP_X_FORWARDED_PORT'] : $_SERVER['SERVER_PORT'];
38
39 /**
40 * Note: This port logic is tested in the Jetpack_Cxn_Tests->test__server_port_value() test.
41 * Please update the test if any changes are made in this logic.
42 */
43 if ( is_ssl() ) {
44 // 443: Standard Port
45 // 80: Assume we're behind a proxy without X-Forwarded-Port. Hardcoding "80" here means most sites
46 // with SSL termination proxies (self-served, Cloudflare, etc.) don't need to fiddle with
47 // the JETPACK_SIGNATURE__HTTPS_PORT constant. The code also implies we can't talk to a
48 // site at https://example.com:80/ (which would be a strange configuration).
49 // JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the back end webserver's port
50 // if the site is behind a proxy running on port 443 without
51 // X-Forwarded-Port and the back end's port is *not* 80. It's better,
52 // though, to configure the proxy to send X-Forwarded-Port.
53 $port = in_array( $host_port, array( 443, 80, JETPACK_SIGNATURE__HTTPS_PORT ) ) ? '' : $host_port;
54 } else {
55 // 80: Standard Port
56 // JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the back end webserver's port
57 // if the site is behind a proxy running on port 80 without
58 // X-Forwarded-Port. It's better, though, to configure the proxy to
59 // send X-Forwarded-Port.
60 $port = in_array( $host_port, array( 80, JETPACK_SIGNATURE__HTTP_PORT ) ) ? '' : $host_port;
61 }
62
63 $url = "{$scheme}://{$_SERVER['HTTP_HOST']}:{$port}" . stripslashes( $_SERVER['REQUEST_URI'] );
64
65 if ( array_key_exists( 'body', $override ) && ! empty( $override['body'] ) ) {
66 $body = $override['body'];
67 } else if ( 'POST' == strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
68 $body = isset( $GLOBALS['HTTP_RAW_POST_DATA'] ) ? $GLOBALS['HTTP_RAW_POST_DATA'] : null;
69
70 // Convert the $_POST to the body, if the body was empty. This is how arrays are hashed
71 // and encoded on the Jetpack side.
72 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
73 if ( empty( $body ) && is_array( $_POST ) && count( $_POST ) > 0 ) {
74 $body = $_POST;
75 }
76 }
77 } else if ( 'PUT' == strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
78 // This is a little strange-looking, but there doesn't seem to be another way to get the PUT body
79 $raw_put_data = file_get_contents( 'php://input' );
80 parse_str( $raw_put_data, $body );
81
82 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
83 $put_data = json_decode( $raw_put_data, true );
84 if ( is_array( $put_data ) && count( $put_data ) > 0 ) {
85 $body = $put_data;
86 }
87 }
88 } else {
89 $body = null;
90 }
91
92 if ( empty( $body ) ) {
93 $body = null;
94 }
95
96 $a = array();
97 foreach ( array( 'token', 'timestamp', 'nonce', 'body-hash' ) as $parameter ) {
98 if ( isset( $override[$parameter] ) ) {
99 $a[$parameter] = $override[$parameter];
100 } else {
101 $a[$parameter] = isset( $_GET[$parameter] ) ? stripslashes( $_GET[$parameter] ) : '';
102 }
103 }
104
105 $method = isset( $override['method'] ) ? $override['method'] : $_SERVER['REQUEST_METHOD'];
106 return $this->sign_request( $a['token'], $a['timestamp'], $a['nonce'], $a['body-hash'], $method, $url, $body, true );
107 }
108
109 // body_hash v. body-hash is annoying. Refactor to accept an array?
110 function sign_request( $token = '', $timestamp = 0, $nonce = '', $body_hash = '', $method = '', $url = '', $body = null, $verify_body_hash = true ) {
111 if ( !$this->secret ) {
112 return new Jetpack_Error( 'invalid_secret', 'Invalid secret' );
113 }
114
115 if ( !$this->token ) {
116 return new Jetpack_Error( 'invalid_token', 'Invalid token' );
117 }
118
119 list( $token ) = explode( '.', $token );
120
121 if ( 0 !== strpos( $token, "$this->token:" ) ) {
122 return new Jetpack_Error( 'token_mismatch', 'Incorrect token' );
123 }
124
125 // If we got an array at this point, let's encode it, so we can see what it looks like as a string.
126 if ( is_array( $body ) ) {
127 if ( count( $body ) > 0 ) {
128 $body = json_encode( $body );
129
130 } else {
131 $body = '';
132 }
133 }
134
135 $required_parameters = array( 'token', 'timestamp', 'nonce', 'method', 'url' );
136 if ( !is_null( $body ) ) {
137 $required_parameters[] = 'body_hash';
138 if ( !is_string( $body ) ) {
139 return new Jetpack_Error( 'invalid_body', 'Body is malformed.' );
140 }
141 }
142
143 foreach ( $required_parameters as $required ) {
144 if ( !is_scalar( $$required ) ) {
145 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is malformed.', str_replace( '_', '-', $required ) ) );
146 }
147
148 if ( !strlen( $$required ) ) {
149 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is missing.', str_replace( '_', '-', $required ) ) );
150 }
151 }
152
153 if ( empty( $body ) ) {
154 if ( $body_hash ) {
155 return new Jetpack_Error( 'invalid_body_hash', 'The body hash does not match.' );
156 }
157 } else {
158 if ( $verify_body_hash && jetpack_sha1_base64( $body ) !== $body_hash ) {
159 return new Jetpack_Error( 'invalid_body_hash', 'The body hash does not match.' );
160 }
161 }
162
163 $parsed = parse_url( $url );
164 if ( !isset( $parsed['host'] ) ) {
165 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is malformed.', 'url' ) );
166 }
167
168 if ( !empty( $parsed['port'] ) ) {
169 $port = $parsed['port'];
170 } else {
171 if ( 'http' == $parsed['scheme'] ) {
172 $port = 80;
173 } else if ( 'https' == $parsed['scheme'] ) {
174 $port = 443;
175 } else {
176 return new Jetpack_Error( 'unknown_scheme_port', "The scheme's port is unknown" );
177 }
178 }
179
180 if ( !ctype_digit( "$timestamp" ) || 10 < strlen( $timestamp ) ) { // If Jetpack is around in 275 years, you can blame mdawaffe for the bug.
181 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is malformed.', 'timestamp' ) );
182 }
183
184 $local_time = $timestamp - $this->time_diff;
185 if ( $local_time < time() - 600 || $local_time > time() + 300 ) {
186 return new Jetpack_Error( 'invalid_signature', 'The timestamp is too old.' );
187 }
188
189 if ( 12 < strlen( $nonce ) || preg_match( '/[^a-zA-Z0-9]/', $nonce ) ) {
190 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is malformed.', 'nonce' ) );
191 }
192
193 $normalized_request_pieces = array(
194 $token,
195 $timestamp,
196 $nonce,
197 $body_hash,
198 strtoupper( $method ),
199 strtolower( $parsed['host'] ),
200 $port,
201 $parsed['path'],
202 // Normalized Query String
203 );
204
205 $normalized_request_pieces = array_merge( $normalized_request_pieces, $this->normalized_query_parameters( isset( $parsed['query'] ) ? $parsed['query'] : '' ) );
206 $flat_normalized_request_pieces = array();
207 foreach ($normalized_request_pieces as $piece) {
208 if ( is_array( $piece ) ) {
209 foreach ( $piece as $subpiece ) {
210 $flat_normalized_request_pieces[] = $subpiece;
211 }
212 } else {
213 $flat_normalized_request_pieces[] = $piece;
214 }
215 }
216 $normalized_request_pieces = $flat_normalized_request_pieces;
217
218 $normalized_request_string = join( "\n", $normalized_request_pieces ) . "\n";
219
220 return base64_encode( hash_hmac( 'sha1', $normalized_request_string, $this->secret, true ) );
221 }
222
223 function normalized_query_parameters( $query_string ) {
224 parse_str( $query_string, $array );
225 if ( get_magic_quotes_gpc() )
226 $array = stripslashes_deep( $array );
227
228 unset( $array['signature'] );
229
230 $names = array_keys( $array );
231 $values = array_values( $array );
232
233 $names = array_map( array( $this, 'encode_3986' ), $names );
234 $values = array_map( array( $this, 'encode_3986' ), $values );
235
236 $pairs = array_map( array( $this, 'join_with_equal_sign' ), $names, $values );
237
238 sort( $pairs );
239
240 return $pairs;
241 }
242
243 function encode_3986( $string_or_array ) {
244 if ( is_array( $string_or_array ) ) {
245 return array_map( array( $this, 'encode_3986' ), $string_or_array );
246 }
247
248 $string_or_array = rawurlencode( $string_or_array );
249 return str_replace( '%7E', '~', $string_or_array ); // prior to PHP 5.3, rawurlencode was RFC 1738
250 }
251
252 function join_with_equal_sign( $name, $value ) {
253 if ( is_array( $value ) ) {
254 $result = array();
255 foreach ( $value as $array_key => $array_value ) {
256 $result[] = $name . '[' . $array_key . ']' . '=' . $array_value;
257 }
258 return $result;
259 }
260 return "{$name}={$value}";
261 }
262 }
263
264 function jetpack_sha1_base64( $text ) {
265 return base64_encode( sha1( $text, true ) );
266 }
267