Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2019 The Chromium Authors |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 5 | #include "content/browser/renderer_host/ipc_utils.h" |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 6 | |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 7 | #include <optional> |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 8 | #include <utility> |
| 9 | |
Lei Zhang | 58c9bd1 | 2025-06-17 23:12:02 | [diff] [blame] | 10 | #include "base/debug/crash_logging.h" |
Helmut Januschka | 42c83207 | 2025-03-02 01:13:12 | [diff] [blame] | 11 | #include "base/strings/to_string.h" |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 12 | #include "content/browser/bad_message.h" |
| 13 | #include "content/browser/blob_storage/chrome_blob_storage_context.h" |
| 14 | #include "content/browser/child_process_security_policy_impl.h" |
Yao Xiao | 1ac702d | 2022-06-08 17:20:49 | [diff] [blame] | 15 | #include "content/browser/renderer_host/frame_tree_node.h" |
| 16 | #include "content/browser/renderer_host/render_frame_host_impl.h" |
Alex Moshchuk | 4043b73 | 2024-06-14 06:02:39 | [diff] [blame] | 17 | #include "content/common/features.h" |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 18 | #include "content/common/frame.mojom.h" |
danakj | 837b1c4 | 2020-11-25 23:59:54 | [diff] [blame] | 19 | #include "content/common/navigation_params_utils.h" |
Marijn Kruisselbrink | 8ffda44 | 2020-09-03 18:29:47 | [diff] [blame] | 20 | #include "content/public/browser/browser_context.h" |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 21 | #include "content/public/browser/browser_thread.h" |
Will Harris | cd57b83 | 2023-01-05 20:03:10 | [diff] [blame] | 22 | #include "content/public/browser/child_process_host.h" |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 23 | #include "content/public/browser/render_process_host.h" |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 24 | #include "content/public/common/url_constants.h" |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 25 | #include "mojo/public/cpp/system/message_pipe.h" |
Minggang Wang | b9f3fa9 | 2021-07-01 15:30:31 | [diff] [blame] | 26 | #include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h" |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 27 | |
| 28 | namespace content { |
| 29 | |
| 30 | namespace { |
| 31 | |
Daniel Cheng | 247bd93 | 2020-06-04 20:09:25 | [diff] [blame] | 32 | // Validates that |received_token| is non-null iff associated with a blob: URL. |
| 33 | bool VerifyBlobToken( |
| 34 | int process_id, |
| 35 | const mojo::PendingRemote<blink::mojom::BlobURLToken>& received_token, |
| 36 | const GURL& received_url) { |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 37 | DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id); |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 38 | |
Daniel Cheng | 13251e5 | 2020-11-25 17:41:23 | [diff] [blame] | 39 | if (received_token.is_valid()) { |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 40 | if (!received_url.SchemeIsBlob()) { |
| 41 | bad_message::ReceivedBadMessage( |
| 42 | process_id, bad_message::BLOB_URL_TOKEN_FOR_NON_BLOB_URL); |
| 43 | return false; |
| 44 | } |
| 45 | } |
| 46 | |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 47 | return true; |
| 48 | } |
| 49 | |
Rakina Zata Amni | fad6ad4b | 2023-08-23 02:22:36 | [diff] [blame] | 50 | bool VerifyInitiatorOrigin( |
| 51 | int process_id, |
| 52 | const url::Origin& initiator_origin, |
Rakina Zata Amni | 6013105 | 2023-09-05 22:33:54 | [diff] [blame] | 53 | const RenderFrameHostImpl* current_rfh = nullptr, |
Rakina Zata Amni | fad6ad4b | 2023-08-23 02:22:36 | [diff] [blame] | 54 | GURL* navigation_url = nullptr, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 55 | std::optional<blink::LocalFrameToken>* initiator_frame_token = nullptr) { |
Alex Moshchuk | 4043b73 | 2024-06-14 06:02:39 | [diff] [blame] | 56 | // TODO(crbug.com/40109437): Ideally, origin verification should be performed |
| 57 | // even if `initiator_origin` is opaque, to ensure that the precursor origin |
| 58 | // matches the process lock. However, there are a couple of cases where this |
| 59 | // doesn't yet work, which are documented and skipped below. |
| 60 | if (initiator_origin.opaque()) { |
| 61 | // TODO(alexmos): This used to allow all opaque origins; this behavior is |
| 62 | // now behind a kill switch and should be removed once the rollout in M128 |
| 63 | // is complete. |
| 64 | if (!base::FeatureList::IsEnabled( |
| 65 | features::kAdditionalOpaqueOriginEnforcements)) { |
| 66 | return true; |
| 67 | } |
| 68 | |
| 69 | // Reloads initiated from error pages may currently lead to a precursor |
| 70 | // mismatch, since the error page loads with an opaque origin with the |
| 71 | // original URL's origin as its precursor, which may not match the error |
| 72 | // page's process lock. This is seen in the following |
| 73 | // RenderFrameHostManagerTest tests: |
| 74 | // 1. ErrorPageNavigationReload: |
| 75 | // - renderer origin lock = chrome-error://chromewebdata/ |
| 76 | // - precursor of initiator origin = http://127.0.0.1:.../ |
| 77 | // 2. ErrorPageNavigationReload_InSubframe_BlockedByClient |
| 78 | // - renderer origin lock = http://b.com:.../ |
| 79 | // - precursor of initiator origin = http://c.com:.../ |
| 80 | if (current_rfh && current_rfh->IsErrorDocument()) { |
| 81 | return true; |
| 82 | } |
| 83 | |
| 84 | // Certain (e.g., data:) navigations in subframes of MHTML documents may |
| 85 | // have precursor origins that do not match the process lock of the MHTML |
| 86 | // document. This is seen in NavigationMhtmlBrowserTest.DataIframe, where: |
| 87 | // - renderer origin lock = { file:/// sandboxed } |
| 88 | // - precursor of initiator origin = http://8.8.8.8/ |
| 89 | // Note that RenderFrameHostImpl::CanCommitOriginAndUrl() similarly allows |
| 90 | // such navigations to commit, and it also ensures that they can only commit |
| 91 | // in the main frame MHTML document's process. |
| 92 | if (current_rfh && current_rfh->IsMhtmlSubframe()) { |
| 93 | return true; |
| 94 | } |
| 95 | } |
Lukasz Anforowicz | 56211d45 | 2019-02-05 18:05:51 | [diff] [blame] | 96 | |
| 97 | auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); |
Alex Moshchuk | 99c2268 | 2024-03-28 22:43:46 | [diff] [blame] | 98 | if (!policy->HostsOrigin(process_id, initiator_origin)) { |
Rakina Zata Amni | fad6ad4b | 2023-08-23 02:22:36 | [diff] [blame] | 99 | if (navigation_url) { |
| 100 | static auto* const navigation_url_key = |
| 101 | base::debug::AllocateCrashKeyString( |
| 102 | "navigation_url", base::debug::CrashKeySize::Size256); |
| 103 | base::debug::SetCrashKeyString( |
| 104 | navigation_url_key, |
| 105 | navigation_url->DeprecatedGetOriginAsURL().spec()); |
| 106 | } |
Rakina Zata Amni | f6902af | 2023-11-09 00:07:58 | [diff] [blame] | 107 | if (initiator_frame_token && initiator_frame_token->has_value()) { |
Rakina Zata Amni | fad6ad4b | 2023-08-23 02:22:36 | [diff] [blame] | 108 | if (RenderFrameHostImpl* initiator_render_frame_host = |
| 109 | RenderFrameHostImpl::FromFrameToken( |
| 110 | process_id, initiator_frame_token->value())) { |
| 111 | static auto* const initiator_rfh_origin_key = |
| 112 | base::debug::AllocateCrashKeyString( |
| 113 | "initiator_rfh_origin", base::debug::CrashKeySize::Size256); |
| 114 | base::debug::SetCrashKeyString( |
| 115 | initiator_rfh_origin_key, |
| 116 | initiator_render_frame_host->GetLastCommittedOrigin() |
| 117 | .GetDebugString()); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | if (current_rfh) { |
Helmut Januschka | 42c83207 | 2025-03-02 01:13:12 | [diff] [blame] | 122 | auto bool_to_crash_key = [](bool b) { return base::ToString(b); }; |
Rakina Zata Amni | fad6ad4b | 2023-08-23 02:22:36 | [diff] [blame] | 123 | static auto* const is_main_frame_key = |
| 124 | base::debug::AllocateCrashKeyString( |
| 125 | "is_main_frame", base::debug::CrashKeySize::Size32); |
| 126 | base::debug::SetCrashKeyString( |
| 127 | is_main_frame_key, bool_to_crash_key(current_rfh->is_main_frame())); |
| 128 | |
| 129 | static auto* const is_outermost_frame_key = |
| 130 | base::debug::AllocateCrashKeyString( |
| 131 | "is_outermost_frame", base::debug::CrashKeySize::Size32); |
| 132 | base::debug::SetCrashKeyString( |
| 133 | is_outermost_frame_key, |
| 134 | bool_to_crash_key(current_rfh->IsOutermostMainFrame())); |
| 135 | |
| 136 | static auto* const is_on_initial_empty_document_key = |
| 137 | base::debug::AllocateCrashKeyString( |
| 138 | "is_on_initial_empty_doc", base::debug::CrashKeySize::Size32); |
| 139 | base::debug::SetCrashKeyString( |
| 140 | is_on_initial_empty_document_key, |
| 141 | bool_to_crash_key( |
| 142 | current_rfh->frame_tree_node()->is_on_initial_empty_document())); |
| 143 | |
| 144 | static auto* const last_committed_origin_key = |
| 145 | base::debug::AllocateCrashKeyString( |
| 146 | "last_committed_origin", base::debug::CrashKeySize::Size256); |
| 147 | base::debug::SetCrashKeyString( |
| 148 | last_committed_origin_key, |
| 149 | current_rfh->GetLastCommittedOrigin().GetDebugString()); |
| 150 | |
| 151 | if (current_rfh->GetParentOrOuterDocumentOrEmbedder()) { |
| 152 | static auto* const parent_etc_origin_key = |
| 153 | base::debug::AllocateCrashKeyString( |
| 154 | "parent_etc_origin", base::debug::CrashKeySize::Size256); |
| 155 | base::debug::SetCrashKeyString( |
| 156 | parent_etc_origin_key, |
| 157 | current_rfh->GetParentOrOuterDocumentOrEmbedder() |
| 158 | ->GetLastCommittedOrigin() |
| 159 | .GetDebugString()); |
| 160 | } |
| 161 | |
| 162 | if (FrameTreeNode* opener = current_rfh->frame_tree_node()->opener()) { |
| 163 | static auto* const opener_origin_key = |
| 164 | base::debug::AllocateCrashKeyString( |
| 165 | "opener_origin", base::debug::CrashKeySize::Size256); |
| 166 | base::debug::SetCrashKeyString(opener_origin_key, |
| 167 | opener->current_frame_host() |
| 168 | ->GetLastCommittedOrigin() |
| 169 | .GetDebugString()); |
| 170 | } |
| 171 | } |
| 172 | |
Lukasz Anforowicz | 56211d45 | 2019-02-05 18:05:51 | [diff] [blame] | 173 | bad_message::ReceivedBadMessage(process_id, |
| 174 | bad_message::INVALID_INITIATOR_ORIGIN); |
| 175 | return false; |
| 176 | } |
| 177 | |
| 178 | return true; |
| 179 | } |
| 180 | |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 181 | } // namespace |
| 182 | |
Sharon Yang | 1987cec | 2023-03-24 23:40:19 | [diff] [blame] | 183 | bool VerifyDownloadUrlParams(RenderProcessHost* process, |
Daniel Cheng | 247bd93 | 2020-06-04 20:09:25 | [diff] [blame] | 184 | const blink::mojom::DownloadURLParams& params) { |
Lukasz Anforowicz | 6244271 | 2019-10-07 17:16:52 | [diff] [blame] | 185 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
Sharon Yang | 1987cec | 2023-03-24 23:40:19 | [diff] [blame] | 186 | CHECK(process); |
Emily Andrews | d15fd76 | 2024-12-10 20:41:54 | [diff] [blame] | 187 | int process_id = process->GetDeprecatedID(); |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 188 | |
Daniel Cheng | 247bd93 | 2020-06-04 20:09:25 | [diff] [blame] | 189 | // Verifies |params.blob_url_token| is appropriately set. |
| 190 | if (!VerifyBlobToken(process_id, params.blob_url_token, params.url)) |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 191 | return false; |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 192 | |
Lukasz Anforowicz | 56211d45 | 2019-02-05 18:05:51 | [diff] [blame] | 193 | // Verify |params.initiator_origin|. |
Daniel Cheng | 247bd93 | 2020-06-04 20:09:25 | [diff] [blame] | 194 | if (params.initiator_origin && |
| 195 | !VerifyInitiatorOrigin(process_id, *params.initiator_origin)) |
Lukasz Anforowicz | 56211d45 | 2019-02-05 18:05:51 | [diff] [blame] | 196 | return false; |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 197 | |
Daniel Cheng | 247bd93 | 2020-06-04 20:09:25 | [diff] [blame] | 198 | // If |params.url| is not set, this must be a large data URL being passed |
| 199 | // through |params.data_url_blob|. |
| 200 | if (!params.url.is_valid() && !params.data_url_blob.is_valid()) |
| 201 | return false; |
Min Qin | 3861ed0 | 2019-10-17 23:12:51 | [diff] [blame] | 202 | |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 203 | // Verification succeeded. |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 204 | return true; |
| 205 | } |
| 206 | |
Yao Xiao | 1ac702d | 2022-06-08 17:20:49 | [diff] [blame] | 207 | bool VerifyOpenURLParams(RenderFrameHostImpl* current_rfh, |
Sharon Yang | 59197b2a | 2023-03-24 17:49:24 | [diff] [blame] | 208 | RenderProcessHost* process, |
Yeunjoo Choi | 9232ea3 | 2021-03-08 16:25:17 | [diff] [blame] | 209 | const blink::mojom::OpenURLParamsPtr& params, |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 210 | GURL* out_validated_url, |
| 211 | scoped_refptr<network::SharedURLLoaderFactory>* |
| 212 | out_blob_url_loader_factory) { |
| 213 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
Yao Xiao | 1ac702d | 2022-06-08 17:20:49 | [diff] [blame] | 214 | DCHECK(current_rfh); |
Sharon Yang | 59197b2a | 2023-03-24 17:49:24 | [diff] [blame] | 215 | DCHECK(process); |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 216 | DCHECK(out_validated_url); |
| 217 | DCHECK(out_blob_url_loader_factory); |
Emily Andrews | d15fd76 | 2024-12-10 20:41:54 | [diff] [blame] | 218 | int process_id = process->GetDeprecatedID(); |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 219 | |
| 220 | // Verify |params.url| and populate |out_validated_url|. |
Gyuyoung Kim | 0028790a | 2020-06-26 00:09:00 | [diff] [blame] | 221 | *out_validated_url = params->url; |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 222 | process->FilterURL(false, out_validated_url); |
| 223 | |
| 224 | // Verify |params.blob_url_token| and populate |out_blob_url_loader_factory|. |
Daniel Cheng | 13251e5 | 2020-11-25 17:41:23 | [diff] [blame] | 225 | if (!VerifyBlobToken(process_id, params->blob_url_token, params->url)) |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 226 | return false; |
Daniel Cheng | 247bd93 | 2020-06-04 20:09:25 | [diff] [blame] | 227 | |
Daniel Cheng | 13251e5 | 2020-11-25 17:41:23 | [diff] [blame] | 228 | if (params->blob_url_token.is_valid()) { |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 229 | *out_blob_url_loader_factory = |
| 230 | ChromeBlobStorageContext::URLLoaderFactoryForToken( |
Sharon Yang | 59197b2a | 2023-03-24 17:49:24 | [diff] [blame] | 231 | process->GetStoragePartition(), std::move(params->blob_url_token)); |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 232 | } |
| 233 | |
Lukasz Anforowicz | f81687c | 2019-10-25 16:16:39 | [diff] [blame] | 234 | // Verify |params.post_body|. |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 235 | auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); |
Sharon Yang | 59197b2a | 2023-03-24 17:49:24 | [diff] [blame] | 236 | if (!policy->CanReadRequestBody(process, params->post_body)) { |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 237 | bad_message::ReceivedBadMessage(process, |
| 238 | bad_message::ILLEGAL_UPLOAD_PARAMS); |
| 239 | return false; |
| 240 | } |
| 241 | |
Lukasz Anforowicz | 56211d45 | 2019-02-05 18:05:51 | [diff] [blame] | 242 | // Verify |params.initiator_origin|. |
Rakina Zata Amni | fad6ad4b | 2023-08-23 02:22:36 | [diff] [blame] | 243 | if (!VerifyInitiatorOrigin(process_id, params->initiator_origin, current_rfh, |
| 244 | ¶ms->url, ¶ms->initiator_frame_token)) { |
Lukasz Anforowicz | 56211d45 | 2019-02-05 18:05:51 | [diff] [blame] | 245 | return false; |
Rakina Zata Amni | fad6ad4b | 2023-08-23 02:22:36 | [diff] [blame] | 246 | } |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 247 | |
W. James MacLean | 8be423a | 2023-03-31 21:35:52 | [diff] [blame] | 248 | if (params->initiator_base_url) { |
| 249 | // `initiator_base_url` should only be defined for about:blank and |
| 250 | // about:srcdoc navigations, and should never be an empty GURL (if it is not |
| 251 | // nullopt). |
| 252 | if (params->initiator_base_url->is_empty() || |
| 253 | !(out_validated_url->IsAboutBlank() || |
| 254 | out_validated_url->IsAboutSrcdoc())) { |
| 255 | return false; |
| 256 | } |
| 257 | } |
| 258 | |
Yao Xiao | 1ac702d | 2022-06-08 17:20:49 | [diff] [blame] | 259 | // Verify that the initiator frame can navigate `current_rfh`. |
| 260 | if (!VerifyNavigationInitiator(current_rfh, params->initiator_frame_token, |
| 261 | process_id)) { |
| 262 | return false; |
| 263 | } |
| 264 | |
Sergey Poromov | dd557c1 | 2023-03-01 11:28:45 | [diff] [blame] | 265 | if (params->is_container_initiated) { |
| 266 | if (!current_rfh->GetParent() || |
| 267 | (current_rfh->GetParent()->GetFrameToken() != |
| 268 | params->initiator_frame_token)) { |
| 269 | mojo::ReportBadMessage( |
| 270 | "container initiated navigation from non-parent process"); |
| 271 | return false; |
| 272 | } |
| 273 | } |
| 274 | |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 275 | // Verification succeeded. |
| 276 | return true; |
| 277 | } |
| 278 | |
Lucas Furukawa Gadani | ef8290a | 2019-07-29 20:27:51 | [diff] [blame] | 279 | bool VerifyBeginNavigationCommonParams( |
Chris Fredrickson | 73ba749 | 2023-02-21 17:08:06 | [diff] [blame] | 280 | const RenderFrameHostImpl& current_rfh, |
Rakina Zata Amni | 6013105 | 2023-09-05 22:33:54 | [diff] [blame] | 281 | blink::mojom::CommonNavigationParams* common_params, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 282 | std::optional<blink::LocalFrameToken>& initiator_frame_token) { |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 283 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 284 | DCHECK(common_params); |
Sharon Yang | 1987cec | 2023-03-24 23:40:19 | [diff] [blame] | 285 | RenderProcessHost* process = current_rfh.GetProcess(); |
Emily Andrews | d15fd76 | 2024-12-10 20:41:54 | [diff] [blame] | 286 | int process_id = process->GetDeprecatedID(); |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 287 | |
| 288 | // Verify (and possibly rewrite) |url|. |
| 289 | process->FilterURL(false, &common_params->url); |
| 290 | if (common_params->url.SchemeIs(kChromeErrorScheme)) { |
| 291 | mojo::ReportBadMessage("Renderer cannot request error page URLs directly"); |
| 292 | return false; |
| 293 | } |
| 294 | |
Lukasz Anforowicz | f81687c | 2019-10-25 16:16:39 | [diff] [blame] | 295 | // Verify |post_data|. |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 296 | auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); |
Sharon Yang | 59197b2a | 2023-03-24 17:49:24 | [diff] [blame] | 297 | if (!policy->CanReadRequestBody(process, common_params->post_data)) { |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 298 | bad_message::ReceivedBadMessage(process, |
| 299 | bad_message::ILLEGAL_UPLOAD_PARAMS); |
| 300 | return false; |
| 301 | } |
| 302 | |
Mike West | 9286cf1 | 2019-04-01 13:44:58 | [diff] [blame] | 303 | // Verify |transition| is webby. |
Minggang Wang | b9f3fa9 | 2021-07-01 15:30:31 | [diff] [blame] | 304 | if (!PageTransitionIsWebTriggerable( |
| 305 | ui::PageTransitionFromInt(common_params->transition))) { |
Mike West | 9286cf1 | 2019-04-01 13:44:58 | [diff] [blame] | 306 | bad_message::ReceivedBadMessage( |
| 307 | process, bad_message::RFHI_BEGIN_NAVIGATION_NON_WEBBY_TRANSITION); |
| 308 | return false; |
| 309 | } |
| 310 | |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 311 | // Verify |initiator_origin|. |
Lukasz Anforowicz | 2294ca8 | 2019-02-25 18:26:05 | [diff] [blame] | 312 | if (!common_params->initiator_origin.has_value()) { |
| 313 | bad_message::ReceivedBadMessage( |
| 314 | process, bad_message::RFHI_BEGIN_NAVIGATION_MISSING_INITIATOR_ORIGIN); |
| 315 | return false; |
| 316 | } |
Rakina Zata Amni | 6013105 | 2023-09-05 22:33:54 | [diff] [blame] | 317 | if (!VerifyInitiatorOrigin( |
| 318 | process_id, common_params->initiator_origin.value(), ¤t_rfh, |
| 319 | &common_params->url, &initiator_frame_token)) { |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 320 | return false; |
| 321 | } |
| 322 | |
| 323 | // Verify |base_url_for_data_url|. |
| 324 | if (!common_params->base_url_for_data_url.is_empty()) { |
| 325 | // Kills the process. http://crbug.com/726142 |
| 326 | bad_message::ReceivedBadMessage( |
| 327 | process, bad_message::RFH_BASE_URL_FOR_DATA_URL_SPECIFIED); |
| 328 | return false; |
| 329 | } |
| 330 | |
W. James MacLean | ead730a9 | 2024-06-21 18:34:20 | [diff] [blame] | 331 | // Verify |initiator_base_url|. The value is allowed to be nullopt, but if it |
| 332 | // isn't then it's required to be non-empty (the renderer is supposed to |
| 333 | // guarantee this). If this condition isn't met, CHECK in NavigationRequest's |
| 334 | // constructor will fail. |
| 335 | if (common_params->initiator_base_url && |
| 336 | common_params->initiator_base_url->is_empty()) { |
| 337 | bad_message::ReceivedBadMessage( |
| 338 | process, bad_message::RFH_INITIATOR_BASE_URL_IS_EMPTY); |
| 339 | return false; |
| 340 | } |
| 341 | |
danakj | 837b1c4 | 2020-11-25 23:59:54 | [diff] [blame] | 342 | // Asynchronous (browser-controlled, but) renderer-initiated navigations can |
| 343 | // not be same-document. Allowing this incorrectly could have us try to |
| 344 | // navigate an existing document to a different site. |
| 345 | if (NavigationTypeUtils::IsSameDocument(common_params->navigation_type)) |
| 346 | return false; |
| 347 | |
Lukasz Anforowicz | 3cfc1efd | 2019-02-22 02:29:29 | [diff] [blame] | 348 | // Verification succeeded. |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 349 | return true; |
| 350 | } |
| 351 | |
Yao Xiao | 1ac702d | 2022-06-08 17:20:49 | [diff] [blame] | 352 | bool VerifyNavigationInitiator( |
| 353 | RenderFrameHostImpl* current_rfh, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 354 | const std::optional<blink::LocalFrameToken>& initiator_frame_token, |
Yao Xiao | 1ac702d | 2022-06-08 17:20:49 | [diff] [blame] | 355 | int initiator_process_id) { |
| 356 | // Verify that a frame inside a fenced frame cannot navigate its ancestors, |
| 357 | // unless the frame being navigated is the outermost main frame. |
| 358 | if (current_rfh->IsOutermostMainFrame()) |
| 359 | return true; |
| 360 | |
| 361 | if (!initiator_frame_token) |
| 362 | return true; |
| 363 | |
| 364 | RenderFrameHostImpl* initiator_render_frame_host = |
| 365 | RenderFrameHostImpl::FromFrameToken(initiator_process_id, |
| 366 | initiator_frame_token.value()); |
| 367 | if (!initiator_render_frame_host) |
| 368 | return true; |
| 369 | |
| 370 | // Verify that a frame cannot navigate a frame with a different fenced frame |
| 371 | // nonce, unless the navigating frame is a fenced frame root and its owner |
| 372 | // frame has the same fenced frame nonce as the initiator frame (e.g. in a |
| 373 | // A(A1,A2(FF)) setup, A, A1, and A2 are all allowed to navigate FF). |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 374 | std::optional<base::UnguessableToken> initiator_fenced_frame_nonce = |
Garrett Tanzer | 34cb92fe | 2022-09-28 17:50:54 | [diff] [blame] | 375 | initiator_render_frame_host->frame_tree_node()->GetFencedFrameNonce(); |
Yao Xiao | 1ac702d | 2022-06-08 17:20:49 | [diff] [blame] | 376 | if (initiator_fenced_frame_nonce != |
Garrett Tanzer | 34cb92fe | 2022-09-28 17:50:54 | [diff] [blame] | 377 | current_rfh->frame_tree_node()->GetFencedFrameNonce()) { |
Yao Xiao | 1ac702d | 2022-06-08 17:20:49 | [diff] [blame] | 378 | if (!current_rfh->IsFencedFrameRoot() || |
| 379 | current_rfh->frame_tree_node() |
| 380 | ->GetParentOrOuterDocument() |
| 381 | ->frame_tree_node() |
Garrett Tanzer | 34cb92fe | 2022-09-28 17:50:54 | [diff] [blame] | 382 | ->GetFencedFrameNonce() != initiator_fenced_frame_nonce) { |
Yao Xiao | 1ac702d | 2022-06-08 17:20:49 | [diff] [blame] | 383 | mojo::ReportBadMessage( |
| 384 | "The fenced frame nonces of initiator and current frame don't match, " |
| 385 | "nor is the current frame a fenced frame root whose owner frame has " |
| 386 | "the same fenced frame nonce as the initiator frame."); |
| 387 | return false; |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | if (!initiator_render_frame_host->IsNestedWithinFencedFrame()) |
| 392 | return true; |
| 393 | |
| 394 | FrameTreeNode* node = initiator_render_frame_host->frame_tree_node(); |
| 395 | if (node == current_rfh->frame_tree_node()) |
| 396 | return true; |
| 397 | |
| 398 | while (node) { |
| 399 | node = node->parent() ? node->parent()->frame_tree_node() : nullptr; |
| 400 | |
| 401 | if (node == current_rfh->frame_tree_node()) { |
| 402 | mojo::ReportBadMessage( |
| 403 | "A frame in a fenced frame tree cannot navigate an ancestor frame."); |
| 404 | return false; |
| 405 | } |
| 406 | } |
| 407 | |
| 408 | return true; |
| 409 | } |
| 410 | |
Lukasz Anforowicz | 445abd4 | 2019-01-25 21:27:27 | [diff] [blame] | 411 | } // namespace content |