PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 6.7.2
Jetpack – WP Security, Backup, Speed, & Growth v6.7.2
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 6 years ago bin 7 years ago css 7 years ago images 6 years ago json-endpoints 7 years ago languages 7 years ago modules 5 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-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 8 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-post-images.php 7 years ago class.jetpack-signature.php 7 years ago class.jetpack-tracks.php 8 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 8 years ago jetpack.php 5 years ago json-api-config.php 10 years ago json-endpoints.php 7 years ago locales.php 9 years ago readme.txt 5 years ago require-lib.php 7 years ago uninstall.php 8 years ago wpml-config.xml 10 years ago
class.jetpack-signature.php
263 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 if ( is_ssl() ) {
40 // 443: Standard Port
41 // 80: Assume we're behind a proxy without X-Forwarded-Port. Hardcoding "80" here means most sites
42 // with SSL termination proxies (self-served, Cloudflare, etc.) don't need to fiddle with
43 // the JETPACK_SIGNATURE__HTTPS_PORT constant. The code also implies we can't talk to a
44 // site at https://example.com:80/ (which would be a strange configuration).
45 // JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the back end webserver's port
46 // if the site is behind a proxy running on port 443 without
47 // X-Forwarded-Port and the back end's port is *not* 80. It's better,
48 // though, to configure the proxy to send X-Forwarded-Port.
49 $port = in_array( $host_port, array( 443, 80, JETPACK_SIGNATURE__HTTPS_PORT ) ) ? '' : $host_port;
50 } else {
51 // 80: Standard Port
52 // JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the back end webserver's port
53 // if the site is behind a proxy running on port 80 without
54 // X-Forwarded-Port. It's better, though, to configure the proxy to
55 // send X-Forwarded-Port.
56 $port = in_array( $host_port, array( 80, JETPACK_SIGNATURE__HTTP_PORT ) ) ? '' : $host_port;
57 }
58
59 $url = "{$scheme}://{$_SERVER['HTTP_HOST']}:{$port}" . stripslashes( $_SERVER['REQUEST_URI'] );
60
61 if ( array_key_exists( 'body', $override ) && ! empty( $override['body'] ) ) {
62 $body = $override['body'];
63 } else if ( 'POST' == strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
64 $body = isset( $GLOBALS['HTTP_RAW_POST_DATA'] ) ? $GLOBALS['HTTP_RAW_POST_DATA'] : null;
65
66 // Convert the $_POST to the body, if the body was empty. This is how arrays are hashed
67 // and encoded on the Jetpack side.
68 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
69 if ( empty( $body ) && is_array( $_POST ) && count( $_POST ) > 0 ) {
70 $body = $_POST;
71 }
72 }
73 } else if ( 'PUT' == strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
74 // This is a little strange-looking, but there doesn't seem to be another way to get the PUT body
75 $raw_put_data = file_get_contents( 'php://input' );
76 parse_str( $raw_put_data, $body );
77
78 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
79 $put_data = json_decode( $raw_put_data, true );
80 if ( is_array( $put_data ) && count( $put_data ) > 0 ) {
81 $body = $put_data;
82 }
83 }
84 } else {
85 $body = null;
86 }
87
88 if ( empty( $body ) ) {
89 $body = null;
90 }
91
92 $a = array();
93 foreach ( array( 'token', 'timestamp', 'nonce', 'body-hash' ) as $parameter ) {
94 if ( isset( $override[$parameter] ) ) {
95 $a[$parameter] = $override[$parameter];
96 } else {
97 $a[$parameter] = isset( $_GET[$parameter] ) ? stripslashes( $_GET[$parameter] ) : '';
98 }
99 }
100
101 $method = isset( $override['method'] ) ? $override['method'] : $_SERVER['REQUEST_METHOD'];
102 return $this->sign_request( $a['token'], $a['timestamp'], $a['nonce'], $a['body-hash'], $method, $url, $body, true );
103 }
104
105 // body_hash v. body-hash is annoying. Refactor to accept an array?
106 function sign_request( $token = '', $timestamp = 0, $nonce = '', $body_hash = '', $method = '', $url = '', $body = null, $verify_body_hash = true ) {
107 if ( !$this->secret ) {
108 return new Jetpack_Error( 'invalid_secret', 'Invalid secret' );
109 }
110
111 if ( !$this->token ) {
112 return new Jetpack_Error( 'invalid_token', 'Invalid token' );
113 }
114
115 list( $token ) = explode( '.', $token );
116
117 if ( 0 !== strpos( $token, "$this->token:" ) ) {
118 return new Jetpack_Error( 'token_mismatch', 'Incorrect token' );
119 }
120
121 // If we got an array at this point, let's encode it, so we can see what it looks like as a string.
122 if ( is_array( $body ) ) {
123 if ( count( $body ) > 0 ) {
124 $body = json_encode( $body );
125
126 } else {
127 $body = '';
128 }
129 }
130
131 $required_parameters = array( 'token', 'timestamp', 'nonce', 'method', 'url' );
132 if ( !is_null( $body ) ) {
133 $required_parameters[] = 'body_hash';
134 if ( !is_string( $body ) ) {
135 return new Jetpack_Error( 'invalid_body', 'Body is malformed.' );
136 }
137 }
138
139 foreach ( $required_parameters as $required ) {
140 if ( !is_scalar( $$required ) ) {
141 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is malformed.', str_replace( '_', '-', $required ) ) );
142 }
143
144 if ( !strlen( $$required ) ) {
145 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is missing.', str_replace( '_', '-', $required ) ) );
146 }
147 }
148
149 if ( empty( $body ) ) {
150 if ( $body_hash ) {
151 return new Jetpack_Error( 'invalid_body_hash', 'The body hash does not match.' );
152 }
153 } else {
154 if ( $verify_body_hash && jetpack_sha1_base64( $body ) !== $body_hash ) {
155 return new Jetpack_Error( 'invalid_body_hash', 'The body hash does not match.' );
156 }
157 }
158
159 $parsed = parse_url( $url );
160 if ( !isset( $parsed['host'] ) ) {
161 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is malformed.', 'url' ) );
162 }
163
164 if ( !empty( $parsed['port'] ) ) {
165 $port = $parsed['port'];
166 } else {
167 if ( 'http' == $parsed['scheme'] ) {
168 $port = 80;
169 } else if ( 'https' == $parsed['scheme'] ) {
170 $port = 443;
171 } else {
172 return new Jetpack_Error( 'unknown_scheme_port', "The scheme's port is unknown" );
173 }
174 }
175
176 if ( !ctype_digit( "$timestamp" ) || 10 < strlen( $timestamp ) ) { // If Jetpack is around in 275 years, you can blame mdawaffe for the bug.
177 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is malformed.', 'timestamp' ) );
178 }
179
180 $local_time = $timestamp - $this->time_diff;
181 if ( $local_time < time() - 600 || $local_time > time() + 300 ) {
182 return new Jetpack_Error( 'invalid_signature', 'The timestamp is too old.' );
183 }
184
185 if ( 12 < strlen( $nonce ) || preg_match( '/[^a-zA-Z0-9]/', $nonce ) ) {
186 return new Jetpack_Error( 'invalid_signature', sprintf( 'The required "%s" parameter is malformed.', 'nonce' ) );
187 }
188
189 $normalized_request_pieces = array(
190 $token,
191 $timestamp,
192 $nonce,
193 $body_hash,
194 strtoupper( $method ),
195 strtolower( $parsed['host'] ),
196 $port,
197 $parsed['path'],
198 // Normalized Query String
199 );
200
201 $normalized_request_pieces = array_merge( $normalized_request_pieces, $this->normalized_query_parameters( isset( $parsed['query'] ) ? $parsed['query'] : '' ) );
202 $flat_normalized_request_pieces = array();
203 foreach ($normalized_request_pieces as $piece) {
204 if ( is_array( $piece ) ) {
205 foreach ( $piece as $subpiece ) {
206 $flat_normalized_request_pieces[] = $subpiece;
207 }
208 } else {
209 $flat_normalized_request_pieces[] = $piece;
210 }
211 }
212 $normalized_request_pieces = $flat_normalized_request_pieces;
213
214 $normalized_request_string = join( "\n", $normalized_request_pieces ) . "\n";
215
216 return base64_encode( hash_hmac( 'sha1', $normalized_request_string, $this->secret, true ) );
217 }
218
219 function normalized_query_parameters( $query_string ) {
220 parse_str( $query_string, $array );
221 if ( get_magic_quotes_gpc() )
222 $array = stripslashes_deep( $array );
223
224 unset( $array['signature'] );
225
226 $names = array_keys( $array );
227 $values = array_values( $array );
228
229 $names = array_map( array( $this, 'encode_3986' ), $names );
230 $values = array_map( array( $this, 'encode_3986' ), $values );
231
232 $pairs = array_map( array( $this, 'join_with_equal_sign' ), $names, $values );
233
234 sort( $pairs );
235
236 return $pairs;
237 }
238
239 function encode_3986( $string_or_array ) {
240 if ( is_array( $string_or_array ) ) {
241 return array_map( array( $this, 'encode_3986' ), $string_or_array );
242 }
243
244 $string_or_array = rawurlencode( $string_or_array );
245 return str_replace( '%7E', '~', $string_or_array ); // prior to PHP 5.3, rawurlencode was RFC 1738
246 }
247
248 function join_with_equal_sign( $name, $value ) {
249 if ( is_array( $value ) ) {
250 $result = array();
251 foreach ( $value as $array_key => $array_value ) {
252 $result[] = $name . '[' . $array_key . ']' . '=' . $array_value;
253 }
254 return $result;
255 }
256 return "{$name}={$value}";
257 }
258 }
259
260 function jetpack_sha1_base64( $text ) {
261 return base64_encode( sha1( $text, true ) );
262 }
263