function sign_current_request($override = array())
{
if (isset($override['scheme'])) {
$scheme = $override['scheme'];
if (!in_array($scheme, array('http', 'https'))) {
return new Jetpack_Error('invalid_sheme', 'Invalid URL scheme');
}
} else {
if (is_ssl()) {
$scheme = 'https';
} else {
$scheme = 'http';
}
}
$host_port = isset($_SERVER['HTTP_X_FORWARDED_PORT']) ? $_SERVER['HTTP_X_FORWARDED_PORT'] : $_SERVER['SERVER_PORT'];
if (is_ssl()) {
// 443: Standard Port
// 80: Assume we're behind a proxy without X-Forwarded-Port. Hardcoding "80" here means most sites
// with SSL termination proxies (self-served, Cloudflare, etc.) don't need to fiddle with
// the JETPACK_SIGNATURE__HTTPS_PORT constant. The code also implies we can't talk to a
// site at https://example.com:80/ (which would be a strange configuration).
// JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the back end webserver's port
// if the site is behind a proxy running on port 443 without
// X-Forwarded-Port and the back end's port is *not* 80. It's better,
// though, to configure the proxy to send X-Forwarded-Port.
$port = in_array($host_port, array(443, 80, JETPACK_SIGNATURE__HTTPS_PORT)) ? '' : $host_port;
} else {
// 80: Standard Port
// JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the back end webserver's port
// if the site is behind a proxy running on port 80 without
// X-Forwarded-Port. It's better, though, to configure the proxy to
// send X-Forwarded-Port.
$port = in_array($host_port, array(80, JETPACK_SIGNATURE__HTTP_PORT)) ? '' : $host_port;
}
$url = "{$scheme}://{$_SERVER['HTTP_HOST']}:{$port}" . stripslashes($_SERVER['REQUEST_URI']);
if (array_key_exists('body', $override) && !is_null($override['body'])) {
$body = $override['body'];
} else {
if ('POST' == strtoupper($_SERVER['REQUEST_METHOD'])) {
$body = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : null;
// Convert the $_POST to the body, if the body was empty. This is how arrays are hashed
// and encoded on the Jetpack side.
if (defined('IS_WPCOM') && IS_WPCOM) {
if (empty($body) && is_array($_POST) && count($_POST) > 0) {
$body = $_POST;
}
}
} else {
$body = null;
}
}
$a = array();
foreach (array('token', 'timestamp', 'nonce', 'body-hash') as $parameter) {
if (isset($override[$parameter])) {
$a[$parameter] = $override[$parameter];
} else {
$a[$parameter] = isset($_GET[$parameter]) ? stripslashes($_GET[$parameter]) : '';
}
}
$method = isset($override['method']) ? $override['method'] : $_SERVER['REQUEST_METHOD'];
return $this->sign_request($a['token'], $a['timestamp'], $a['nonce'], $a['body-hash'], $method, $url, $body, true);
}
/** * Authenticates XML-RPC and other requests from the Jetpack Server */ function authenticate_jetpack($user, $username, $password) { if (is_a($user, 'WP_User')) { return $user; } // It's not for us if (!isset($_GET['token']) || empty($_GET['signature'])) { return $user; } @(list($token_key, $version, $user_id) = explode(':', $_GET['token'])); if (empty($token_key) || empty($version) || strval(JETPACK__API_VERSION) !== $version || empty($user_id) || !ctype_digit($user_id) || !get_userdata($user_id)) { return $user; } $token = Jetpack_Data::get_access_token($user_id); if (!$token) { return $user; } if (0 !== strpos($token->secret, "{$token_key}.")) { return $user; } require_once dirname(__FILE__) . '/class.jetpack-signature.php'; $jetpack_signature = new Jetpack_Signature($token->secret, (int) Jetpack::get_option('time_diff')); if (isset($_POST['_jetpack_is_multipart'])) { $post_data = $_POST; $file_hashes = array(); foreach ($post_data as $post_data_key => $post_data_value) { if (0 !== strpos($post_data_key, '_jetpack_file_hmac_')) { continue; } $post_data_key = substr($post_data_key, strlen('_jetpack_file_hmac_')); $file_hashes[$post_data_key] = $post_data_value; } foreach ($file_hashes as $post_data_key => $post_data_value) { unset($post_data["_jetpack_file_hmac_{$post_data_key}"]); $post_data[$post_data_key] = $post_data_value; } ksort($post_data); $body = http_build_query(stripslashes_deep($post_data)); } elseif (is_null($this->HTTP_RAW_POST_DATA)) { $body = file_get_contents('php://input'); } else { $body = null; } $signature = $jetpack_signature->sign_current_request(array('body' => is_null($body) ? $this->HTTP_RAW_POST_DATA : $body)); if (!$signature) { return $user; } else { if (is_wp_error($signature)) { return $signature; } else { if ($signature !== $_GET['signature']) { return $user; } } } $timestamp = (int) $_GET['timestamp']; $nonce = stripslashes((string) $_GET['nonce']); if (!$this->add_nonce($timestamp, $nonce)) { return $user; } nocache_headers(); return new WP_User($token->external_user_id); }