|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* WordPress.com Block Editor Iframe |
|
4
|
|
|
* Allow new block editor posts to be composed on WordPress.com. |
|
5
|
|
|
* This is auto-loaded as of Jetpack v7.4 for sites connected to WordPress.com only. |
|
6
|
|
|
* |
|
7
|
|
|
* @package Jetpack |
|
8
|
|
|
*/ |
|
9
|
|
|
|
|
10
|
|
|
/** |
|
11
|
|
|
* Prevents frame options header from firing if this is a whitelisted iframe request. |
|
12
|
|
|
*/ |
|
13
|
|
|
function jetpack_disable_send_frame_options_header() { |
|
14
|
|
|
if ( jetpack_framing_allowed() ) { |
|
15
|
|
|
remove_action( 'admin_init', 'send_frame_options_header' ); |
|
16
|
|
|
} |
|
17
|
|
|
} |
|
18
|
|
|
add_action( 'admin_init', 'jetpack_disable_send_frame_options_header', 9 ); |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* Adds custom admin body class if this is a whitelisted iframe request. |
|
22
|
|
|
* |
|
23
|
|
|
* @param string $classes Admin body classes. |
|
24
|
|
|
* @return string |
|
25
|
|
|
*/ |
|
26
|
|
|
function jetpack_add_iframed_body_class( $classes ) { |
|
27
|
|
|
if ( jetpack_framing_allowed() ) { |
|
28
|
|
|
$classes .= ' is-iframed '; |
|
29
|
|
|
} |
|
30
|
|
|
|
|
31
|
|
|
return $classes; |
|
32
|
|
|
} |
|
33
|
|
|
add_filter( 'admin_body_class', 'jetpack_add_iframed_body_class' ); |
|
34
|
|
|
|
|
35
|
|
|
/** |
|
36
|
|
|
* Checks whether this is a whitelisted iframe request. |
|
37
|
|
|
* |
|
38
|
|
|
* @return bool |
|
39
|
|
|
*/ |
|
40
|
|
|
function jetpack_framing_allowed() { |
|
41
|
|
|
if ( empty( $_GET['frame-nonce'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification |
|
42
|
|
|
return false; |
|
43
|
|
|
} |
|
44
|
|
|
|
|
45
|
|
|
$verified = jetpack_verify_frame_nonce( |
|
46
|
|
|
$_GET['frame-nonce'], // phpcs:ignore WordPress.Security.NonceVerification |
|
47
|
|
|
'frame-' . Jetpack_Options::get_option( 'id' ) |
|
48
|
|
|
); |
|
49
|
|
|
|
|
50
|
|
|
if ( $verified && ! defined( 'IFRAME_REQUEST' ) ) { |
|
51
|
|
|
define( 'IFRAME_REQUEST', true ); |
|
52
|
|
|
} |
|
53
|
|
|
|
|
54
|
|
|
return (bool) $verified; |
|
55
|
|
|
} |
|
56
|
|
|
|
|
57
|
|
|
/** |
|
58
|
|
|
* Verify that correct nonce was used with time limit. |
|
59
|
|
|
* |
|
60
|
|
|
* The user is given an amount of time to use the token, so therefore, since the |
|
61
|
|
|
* UID and $action remain the same, the independent variable is the time. |
|
62
|
|
|
* |
|
63
|
|
|
* @param string $nonce Nonce that was used in the form to verify. |
|
64
|
|
|
* @param string $action Should give context to what is taking place and be the same when nonce was created. |
|
65
|
|
|
* @return boolean Whether the nonce is valid. |
|
66
|
|
|
*/ |
|
67
|
|
|
function jetpack_verify_frame_nonce( $nonce, $action ) { |
|
68
|
|
|
if ( empty( $nonce ) ) { |
|
69
|
|
|
return false; |
|
70
|
|
|
} |
|
71
|
|
|
|
|
72
|
|
|
list( $expiration, $user_id, $hash ) = explode( ':', $nonce, 3 ); |
|
73
|
|
|
|
|
74
|
|
|
$token = Jetpack_Data::get_access_token( $user_id ); |
|
75
|
|
|
if ( ! $token ) { |
|
76
|
|
|
return false; |
|
77
|
|
|
} |
|
78
|
|
|
|
|
79
|
|
|
add_filter( 'salt', 'jetpack_filter_salt', 10, 2 ); |
|
80
|
|
|
$expected_hash = wp_hash( "$expiration|$action|{$token->external_user_id}", 'jetpack_frame_nonce' ); |
|
81
|
|
|
remove_filter( 'salt', 'jetpack_filter_salt' ); |
|
82
|
|
|
|
|
83
|
|
|
if ( ! hash_equals( $hash, $expected_hash ) ) { |
|
84
|
|
|
return false; |
|
85
|
|
|
} |
|
86
|
|
|
|
|
87
|
|
|
if ( time() > $expiration ) { |
|
88
|
|
|
wp_die( 'Expired nonce.' ); |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
$current_user_id = get_current_user_id(); |
|
92
|
|
|
if ( ! $current_user_id || $current_user_id !== (int) $user_id ) { |
|
93
|
|
|
wp_die( 'User ID mismatch.' ); |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
return true; |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
/** |
|
100
|
|
|
* Filters the WordPress salt. |
|
101
|
|
|
* |
|
102
|
|
|
* @param string $salt Salt for the given scheme. |
|
103
|
|
|
* @param string $scheme Authentication scheme. |
|
104
|
|
|
* @return string |
|
105
|
|
|
*/ |
|
106
|
|
|
function jetpack_filter_salt( $salt, $scheme ) { |
|
107
|
|
|
if ( 'jetpack_frame_nonce' === $scheme ) { |
|
108
|
|
|
$token = Jetpack_Data::get_access_token( get_current_user_id() ); |
|
109
|
|
|
|
|
110
|
|
|
if ( $token ) { |
|
111
|
|
|
$salt = $token->secret; |
|
112
|
|
|
} |
|
113
|
|
|
} |
|
114
|
|
|
|
|
115
|
|
|
return $salt; |
|
116
|
|
|
} |
|
117
|
|
|
|