OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2009 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 15 matching lines...) Expand all Loading... |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #include "bindings/core/v8/BindingSecurity.h" | 31 #include "bindings/core/v8/BindingSecurity.h" |
32 | 32 |
33 #include "bindings/core/v8/ExceptionState.h" | 33 #include "bindings/core/v8/ExceptionState.h" |
34 #include "bindings/core/v8/V8BindingForCore.h" | 34 #include "bindings/core/v8/V8BindingForCore.h" |
35 #include "bindings/core/v8/V8Location.h" | 35 #include "bindings/core/v8/V8Location.h" |
| 36 #include "bindings/core/v8/V8Window.h" |
36 #include "core/dom/Document.h" | 37 #include "core/dom/Document.h" |
| 38 #include "core/frame/DOMWindow.h" |
37 #include "core/frame/LocalDOMWindow.h" | 39 #include "core/frame/LocalDOMWindow.h" |
38 #include "core/frame/LocalFrame.h" | 40 #include "core/frame/LocalFrame.h" |
39 #include "core/frame/Location.h" | 41 #include "core/frame/Location.h" |
40 #include "core/frame/Settings.h" | 42 #include "core/frame/Settings.h" |
41 #include "core/html/HTMLFrameElementBase.h" | 43 #include "core/html/HTMLFrameElementBase.h" |
42 #include "core/workers/MainThreadWorkletGlobalScope.h" | 44 #include "core/workers/MainThreadWorkletGlobalScope.h" |
43 #include "platform/bindings/WrapperCreationSecurityCheck.h" | 45 #include "platform/bindings/WrapperCreationSecurityCheck.h" |
44 #include "platform/weborigin/SecurityOrigin.h" | 46 #include "platform/weborigin/SecurityOrigin.h" |
45 | 47 |
46 namespace blink { | 48 namespace blink { |
47 | 49 |
48 namespace { | 50 namespace { |
49 | 51 |
50 bool CanAccessFrameInternal(const LocalDOMWindow* accessing_window, | 52 bool CanAccessWindowInternal(const LocalDOMWindow* accessing_window, |
51 const SecurityOrigin* target_frame_origin, | 53 const DOMWindow* target_window) { |
52 const DOMWindow* target_window) { | |
53 SECURITY_CHECK(!(target_window && target_window->GetFrame()) || | 54 SECURITY_CHECK(!(target_window && target_window->GetFrame()) || |
54 target_window == target_window->GetFrame()->DomWindow()); | 55 target_window == target_window->GetFrame()->DomWindow()); |
55 | 56 |
56 // It's important to check that target_window is a LocalDOMWindow: it's | 57 // It's important to check that target_window is a LocalDOMWindow: it's |
57 // possible for a remote frame and local frame to have the same security | 58 // possible for a remote frame and local frame to have the same security |
58 // origin, depending on the model being used to allocate Frames between | 59 // origin, depending on the model being used to allocate Frames between |
59 // processes. See https://crbug.com/601629. | 60 // processes. See https://crbug.com/601629. |
60 if (!(accessing_window && target_window && target_window->IsLocalDOMWindow())) | 61 if (!(accessing_window && target_window && target_window->IsLocalDOMWindow())) |
61 return false; | 62 return false; |
62 | 63 |
63 const SecurityOrigin* accessing_origin = | 64 const SecurityOrigin* accessing_origin = |
64 accessing_window->document()->GetSecurityOrigin(); | 65 accessing_window->document()->GetSecurityOrigin(); |
65 if (!accessing_origin->CanAccess(target_frame_origin)) | 66 const LocalDOMWindow* local_target_window = ToLocalDOMWindow(target_window); |
| 67 if (!accessing_origin->CanAccess( |
| 68 local_target_window->document()->GetSecurityOrigin())) { |
66 return false; | 69 return false; |
| 70 } |
67 | 71 |
68 // Notify the loader's client if the initial document has been accessed. | 72 // Notify the loader's client if the initial document has been accessed. |
69 LocalFrame* target_frame = ToLocalDOMWindow(target_window)->GetFrame(); | 73 LocalFrame* target_frame = local_target_window->GetFrame(); |
70 if (target_frame && | 74 if (target_frame && |
71 target_frame->Loader().StateMachine()->IsDisplayingInitialEmptyDocument()) | 75 target_frame->Loader().StateMachine()->IsDisplayingInitialEmptyDocument()) |
72 target_frame->Loader().DidAccessInitialDocument(); | 76 target_frame->Loader().DidAccessInitialDocument(); |
73 | 77 |
74 return true; | 78 return true; |
75 } | 79 } |
76 | 80 |
77 bool CanAccessFrame(const LocalDOMWindow* accessing_window, | 81 bool CanAccessWindow(const LocalDOMWindow* accessing_window, |
78 const SecurityOrigin* target_frame_origin, | 82 const DOMWindow* target_window, |
79 const DOMWindow* target_window, | 83 ExceptionState& exception_state) { |
80 ExceptionState& exception_state) { | 84 if (CanAccessWindowInternal(accessing_window, target_window)) |
81 if (CanAccessFrameInternal(accessing_window, target_frame_origin, | |
82 target_window)) | |
83 return true; | 85 return true; |
84 | 86 |
85 if (target_window) | 87 if (target_window) |
86 exception_state.ThrowSecurityError( | 88 exception_state.ThrowSecurityError( |
87 target_window->SanitizedCrossDomainAccessErrorMessage(accessing_window), | 89 target_window->SanitizedCrossDomainAccessErrorMessage(accessing_window), |
88 target_window->CrossDomainAccessErrorMessage(accessing_window)); | 90 target_window->CrossDomainAccessErrorMessage(accessing_window)); |
89 return false; | 91 return false; |
90 } | 92 } |
91 | 93 |
92 bool CanAccessFrame(const LocalDOMWindow* accessing_window, | 94 bool CanAccessWindow(const LocalDOMWindow* accessing_window, |
93 SecurityOrigin* target_frame_origin, | 95 const DOMWindow* target_window, |
94 const DOMWindow* target_window, | 96 BindingSecurity::ErrorReportOption reporting_option) { |
95 BindingSecurity::ErrorReportOption reporting_option) { | 97 if (CanAccessWindowInternal(accessing_window, target_window)) |
96 if (CanAccessFrameInternal(accessing_window, target_frame_origin, | |
97 target_window)) | |
98 return true; | 98 return true; |
99 | 99 |
100 if (accessing_window && target_window && | 100 if (accessing_window && target_window && |
101 reporting_option == BindingSecurity::ErrorReportOption::kReport) | 101 reporting_option == BindingSecurity::ErrorReportOption::kReport) |
102 accessing_window->PrintErrorMessage( | 102 accessing_window->PrintErrorMessage( |
103 target_window->CrossDomainAccessErrorMessage(accessing_window)); | 103 target_window->CrossDomainAccessErrorMessage(accessing_window)); |
104 return false; | 104 return false; |
105 } | 105 } |
106 | 106 |
| 107 DOMWindow* FindWindow(v8::Isolate* isolate, |
| 108 const WrapperTypeInfo* type, |
| 109 v8::Local<v8::Object> holder) { |
| 110 if (V8Window::wrapperTypeInfo.Equals(type)) |
| 111 return V8Window::toImpl(holder); |
| 112 |
| 113 if (V8Location::wrapperTypeInfo.Equals(type)) |
| 114 return V8Location::toImpl(holder)->DomWindow(); |
| 115 |
| 116 // This function can handle only those types listed above. |
| 117 NOTREACHED(); |
| 118 return nullptr; |
| 119 } |
| 120 |
107 } // namespace | 121 } // namespace |
108 | 122 |
109 bool BindingSecurity::ShouldAllowAccessTo( | 123 bool BindingSecurity::ShouldAllowAccessTo( |
110 const LocalDOMWindow* accessing_window, | 124 const LocalDOMWindow* accessing_window, |
111 const DOMWindow* target, | 125 const DOMWindow* target, |
112 ExceptionState& exception_state) { | 126 ExceptionState& exception_state) { |
113 DCHECK(target); | 127 DCHECK(target); |
114 const Frame* frame = target->GetFrame(); | 128 return CanAccessWindow(accessing_window, target, exception_state); |
115 if (!frame || !frame->GetSecurityContext()) | |
116 return false; | |
117 return CanAccessFrame(accessing_window, | |
118 frame->GetSecurityContext()->GetSecurityOrigin(), | |
119 target, exception_state); | |
120 } | 129 } |
121 | 130 |
122 bool BindingSecurity::ShouldAllowAccessTo( | 131 bool BindingSecurity::ShouldAllowAccessTo( |
123 const LocalDOMWindow* accessing_window, | 132 const LocalDOMWindow* accessing_window, |
124 const DOMWindow* target, | 133 const DOMWindow* target, |
125 ErrorReportOption reporting_option) { | 134 ErrorReportOption reporting_option) { |
126 DCHECK(target); | 135 DCHECK(target); |
127 const Frame* frame = target->GetFrame(); | 136 return CanAccessWindow(accessing_window, target, reporting_option); |
128 if (!frame || !frame->GetSecurityContext()) | |
129 return false; | |
130 return CanAccessFrame(accessing_window, | |
131 frame->GetSecurityContext()->GetSecurityOrigin(), | |
132 target, reporting_option); | |
133 } | 137 } |
134 | 138 |
135 bool BindingSecurity::ShouldAllowAccessTo( | 139 bool BindingSecurity::ShouldAllowAccessTo( |
136 const LocalDOMWindow* accessing_window, | |
137 const EventTarget* target, | |
138 ExceptionState& exception_state) { | |
139 DCHECK(target); | |
140 const DOMWindow* window = target->ToDOMWindow(); | |
141 if (!window) { | |
142 // We only need to check the access to Window objects which are | |
143 // cross-origin accessible. If it's not a Window, the object's | |
144 // origin must always be the same origin (or it already leaked). | |
145 return true; | |
146 } | |
147 const Frame* frame = window->GetFrame(); | |
148 if (!frame || !frame->GetSecurityContext()) | |
149 return false; | |
150 return CanAccessFrame(accessing_window, | |
151 frame->GetSecurityContext()->GetSecurityOrigin(), | |
152 window, exception_state); | |
153 } | |
154 | |
155 bool BindingSecurity::ShouldAllowAccessTo( | |
156 const LocalDOMWindow* accessing_window, | 140 const LocalDOMWindow* accessing_window, |
157 const Location* target, | 141 const Location* target, |
158 ExceptionState& exception_state) { | 142 ExceptionState& exception_state) { |
159 DCHECK(target); | 143 DCHECK(target); |
160 const Frame* frame = target->GetFrame(); | 144 return CanAccessWindow(accessing_window, target->DomWindow(), |
161 if (!frame || !frame->GetSecurityContext()) | 145 exception_state); |
162 return false; | |
163 return CanAccessFrame(accessing_window, | |
164 frame->GetSecurityContext()->GetSecurityOrigin(), | |
165 frame->DomWindow(), exception_state); | |
166 } | 146 } |
167 | 147 |
168 bool BindingSecurity::ShouldAllowAccessTo( | 148 bool BindingSecurity::ShouldAllowAccessTo( |
169 const LocalDOMWindow* accessing_window, | 149 const LocalDOMWindow* accessing_window, |
170 const Location* target, | 150 const Location* target, |
171 ErrorReportOption reporting_option) { | 151 ErrorReportOption reporting_option) { |
172 DCHECK(target); | 152 DCHECK(target); |
173 const Frame* frame = target->GetFrame(); | 153 return CanAccessWindow(accessing_window, target->DomWindow(), |
174 if (!frame || !frame->GetSecurityContext()) | 154 reporting_option); |
175 return false; | |
176 return CanAccessFrame(accessing_window, | |
177 frame->GetSecurityContext()->GetSecurityOrigin(), | |
178 frame->DomWindow(), reporting_option); | |
179 } | 155 } |
180 | 156 |
181 bool BindingSecurity::ShouldAllowAccessTo( | 157 bool BindingSecurity::ShouldAllowAccessTo( |
182 const LocalDOMWindow* accessing_window, | 158 const LocalDOMWindow* accessing_window, |
183 const Node* target, | 159 const Node* target, |
184 ExceptionState& exception_state) { | 160 ExceptionState& exception_state) { |
185 if (!target) | 161 if (!target) |
186 return false; | 162 return false; |
187 return CanAccessFrame(accessing_window, | 163 return CanAccessWindow(accessing_window, target->GetDocument().domWindow(), |
188 target->GetDocument().GetSecurityOrigin(), | 164 exception_state); |
189 target->GetDocument().domWindow(), exception_state); | |
190 } | 165 } |
191 | 166 |
192 bool BindingSecurity::ShouldAllowAccessTo( | 167 bool BindingSecurity::ShouldAllowAccessTo( |
193 const LocalDOMWindow* accessing_window, | 168 const LocalDOMWindow* accessing_window, |
194 const Node* target, | 169 const Node* target, |
195 ErrorReportOption reporting_option) { | 170 ErrorReportOption reporting_option) { |
196 if (!target) | 171 if (!target) |
197 return false; | 172 return false; |
198 return CanAccessFrame(accessing_window, | 173 return CanAccessWindow(accessing_window, target->GetDocument().domWindow(), |
199 target->GetDocument().GetSecurityOrigin(), | 174 reporting_option); |
200 target->GetDocument().domWindow(), reporting_option); | |
201 } | 175 } |
202 | 176 |
203 bool BindingSecurity::ShouldAllowAccessToFrame( | 177 bool BindingSecurity::ShouldAllowAccessToFrame( |
204 const LocalDOMWindow* accessing_window, | 178 const LocalDOMWindow* accessing_window, |
205 const Frame* target, | 179 const Frame* target, |
206 ExceptionState& exception_state) { | 180 ExceptionState& exception_state) { |
207 if (!target || !target->GetSecurityContext()) | 181 if (!target || !target->GetSecurityContext()) |
208 return false; | 182 return false; |
209 return CanAccessFrame(accessing_window, | 183 return CanAccessWindow(accessing_window, target->DomWindow(), |
210 target->GetSecurityContext()->GetSecurityOrigin(), | 184 exception_state); |
211 target->DomWindow(), exception_state); | |
212 } | 185 } |
213 | 186 |
214 bool BindingSecurity::ShouldAllowAccessToFrame( | 187 bool BindingSecurity::ShouldAllowAccessToFrame( |
215 const LocalDOMWindow* accessing_window, | 188 const LocalDOMWindow* accessing_window, |
216 const Frame* target, | 189 const Frame* target, |
217 ErrorReportOption reporting_option) { | 190 ErrorReportOption reporting_option) { |
218 if (!target || !target->GetSecurityContext()) | 191 if (!target || !target->GetSecurityContext()) |
219 return false; | 192 return false; |
220 return CanAccessFrame(accessing_window, | 193 return CanAccessWindow(accessing_window, target->DomWindow(), |
221 target->GetSecurityContext()->GetSecurityOrigin(), | 194 reporting_option); |
222 target->DomWindow(), reporting_option); | |
223 } | |
224 | |
225 bool BindingSecurity::ShouldAllowAccessToDetachedWindow( | |
226 const LocalDOMWindow* accessing_window, | |
227 const DOMWindow* target, | |
228 ExceptionState& exception_state) { | |
229 CHECK(target && !target->GetFrame()) | |
230 << "This version of shouldAllowAccessToFrame() must be used only for " | |
231 << "detached windows."; | |
232 if (!target->IsLocalDOMWindow()) | |
233 return false; | |
234 Document* document = ToLocalDOMWindow(target)->document(); | |
235 if (!document) | |
236 return false; | |
237 return CanAccessFrame(accessing_window, document->GetSecurityOrigin(), target, | |
238 exception_state); | |
239 } | 195 } |
240 | 196 |
241 bool BindingSecurity::ShouldAllowNamedAccessTo( | 197 bool BindingSecurity::ShouldAllowNamedAccessTo( |
242 const DOMWindow* accessing_window, | 198 const DOMWindow* accessing_window, |
243 const DOMWindow* target_window) { | 199 const DOMWindow* target_window) { |
244 const Frame* accessing_frame = accessing_window->GetFrame(); | 200 const Frame* accessing_frame = accessing_window->GetFrame(); |
245 DCHECK(accessing_frame); | 201 DCHECK(accessing_frame); |
246 DCHECK(accessing_frame->GetSecurityContext()); | 202 DCHECK(accessing_frame->GetSecurityContext()); |
247 const SecurityOrigin* accessing_origin = | 203 const SecurityOrigin* accessing_origin = |
248 accessing_frame->GetSecurityContext()->GetSecurityOrigin(); | 204 accessing_frame->GetSecurityContext()->GetSecurityOrigin(); |
(...skipping 29 matching lines...) Expand all Loading... |
278 | 234 |
279 v8::Isolate* isolate = creation_context->GetIsolate(); | 235 v8::Isolate* isolate = creation_context->GetIsolate(); |
280 LocalFrame* frame = ToLocalFrameIfNotDetached(creation_context); | 236 LocalFrame* frame = ToLocalFrameIfNotDetached(creation_context); |
281 ExceptionState exception_state(isolate, ExceptionState::kConstructionContext, | 237 ExceptionState exception_state(isolate, ExceptionState::kConstructionContext, |
282 type->interface_name); | 238 type->interface_name); |
283 if (!frame) { | 239 if (!frame) { |
284 // Sandbox detached frames - they can't create cross origin objects. | 240 // Sandbox detached frames - they can't create cross origin objects. |
285 LocalDOMWindow* calling_window = CurrentDOMWindow(isolate); | 241 LocalDOMWindow* calling_window = CurrentDOMWindow(isolate); |
286 LocalDOMWindow* target_window = ToLocalDOMWindow(creation_context); | 242 LocalDOMWindow* target_window = ToLocalDOMWindow(creation_context); |
287 | 243 |
288 return ShouldAllowAccessToDetachedWindow(calling_window, target_window, | 244 return ShouldAllowAccessTo(calling_window, target_window, exception_state); |
289 exception_state); | |
290 } | 245 } |
291 const DOMWrapperWorld& current_world = | 246 const DOMWrapperWorld& current_world = |
292 DOMWrapperWorld::World(isolate->GetCurrentContext()); | 247 DOMWrapperWorld::World(isolate->GetCurrentContext()); |
293 CHECK_EQ(current_world.GetWorldId(), | 248 CHECK_EQ(current_world.GetWorldId(), |
294 DOMWrapperWorld::World(creation_context).GetWorldId()); | 249 DOMWrapperWorld::World(creation_context).GetWorldId()); |
295 | 250 |
296 return !current_world.IsMainWorld() || | 251 return !current_world.IsMainWorld() || |
297 ShouldAllowAccessToFrame(CurrentDOMWindow(isolate), frame, | 252 ShouldAllowAccessToFrame(CurrentDOMWindow(isolate), frame, |
298 exception_state); | 253 exception_state); |
299 } | 254 } |
(...skipping 19 matching lines...) Expand all Loading... |
319 } | 274 } |
320 | 275 |
321 void BindingSecurity::InitWrapperCreationSecurityCheck() { | 276 void BindingSecurity::InitWrapperCreationSecurityCheck() { |
322 WrapperCreationSecurityCheck::SetSecurityCheckFunction( | 277 WrapperCreationSecurityCheck::SetSecurityCheckFunction( |
323 &ShouldAllowAccessToCreationContext); | 278 &ShouldAllowAccessToCreationContext); |
324 WrapperCreationSecurityCheck::SetRethrowExceptionFunction( | 279 WrapperCreationSecurityCheck::SetRethrowExceptionFunction( |
325 &RethrowCrossContextException); | 280 &RethrowCrossContextException); |
326 } | 281 } |
327 | 282 |
328 void BindingSecurity::FailedAccessCheckFor(v8::Isolate* isolate, | 283 void BindingSecurity::FailedAccessCheckFor(v8::Isolate* isolate, |
329 const Frame* target) { | 284 const WrapperTypeInfo* type, |
330 // TODO(dcheng): See if this null check can be removed or hoisted to a | 285 v8::Local<v8::Object> holder) { |
331 // different location. | 286 DOMWindow* target = FindWindow(isolate, type, holder); |
332 if (!target) | 287 // Failing to find a target means something is wrong. Failing to throw an |
333 return; | 288 // exception could be a security issue, so just crash. |
334 | 289 CHECK(target); |
335 DOMWindow* target_window = target->DomWindow(); | |
336 | 290 |
337 // TODO(dcheng): Add ContextType, interface name, and property name as | 291 // TODO(dcheng): Add ContextType, interface name, and property name as |
338 // arguments, so the generated exception can be more descriptive. | 292 // arguments, so the generated exception can be more descriptive. |
339 ExceptionState exception_state(isolate, ExceptionState::kUnknownContext, | 293 ExceptionState exception_state(isolate, ExceptionState::kUnknownContext, |
340 nullptr, nullptr); | 294 nullptr, nullptr); |
341 exception_state.ThrowSecurityError( | 295 exception_state.ThrowSecurityError( |
342 target_window->SanitizedCrossDomainAccessErrorMessage( | 296 target->SanitizedCrossDomainAccessErrorMessage(CurrentDOMWindow(isolate)), |
343 CurrentDOMWindow(isolate)), | 297 target->CrossDomainAccessErrorMessage(CurrentDOMWindow(isolate))); |
344 target_window->CrossDomainAccessErrorMessage(CurrentDOMWindow(isolate))); | |
345 } | 298 } |
346 | 299 |
347 } // namespace blink | 300 } // namespace blink |
OLD | NEW |