Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp

Issue 2706923002: Rework security checks to be based on Window rather than Frame. (Closed)
Patch Set: Meh Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698