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

Side by Side Diff: Source/core/loader/MixedContentChecker.cpp

Issue 842783002: Mixed Content: Add a static check for WebSockets. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@lax
Patch Set: Rebase. Created 5 years, 11 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) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 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 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. 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 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 bool MixedContentChecker::isMixedContent(SecurityOrigin* securityOrigin, const K URL& url) 74 bool MixedContentChecker::isMixedContent(SecurityOrigin* securityOrigin, const K URL& url)
75 { 75 {
76 if (!SchemeRegistry::shouldTreatURLSchemeAsRestrictingMixedContent(securityO rigin->protocol())) 76 if (!SchemeRegistry::shouldTreatURLSchemeAsRestrictingMixedContent(securityO rigin->protocol()))
77 return false; 77 return false;
78 78
79 // We're in a secure context, so |url| is mixed content if it's insecure. 79 // We're in a secure context, so |url| is mixed content if it's insecure.
80 return !SecurityOrigin::isSecure(url); 80 return !SecurityOrigin::isSecure(url);
81 } 81 }
82 82
83 // static 83 // static
84 LocalFrame* MixedContentChecker::inWhichFrameIsContentMixed(LocalFrame* frame, W ebURLRequest::FrameType frameType, const KURL& url)
85 {
86 // We only care about subresource loads; top-level navigations cannot be mix ed content. Neither can frameless requests.
87 if (frameType == WebURLRequest::FrameTypeTopLevel || !frame)
88 return nullptr;
89
90 // Check the top frame first.
91 if (Frame* top = frame->tree().top()) {
92 // FIXME: We need a way to access the top-level frame's SecurityOrigin w hen that frame
93 // is in a different process from the current frame. Until that is done, we bail out.
94 if (!top->isLocalFrame())
95 return nullptr;
96
97 LocalFrame* localTop = toLocalFrame(top);
98 measureStricterVersionOfIsMixedContent(localTop, url);
99 if (isMixedContent(localTop->document()->securityOrigin(), url))
100 return localTop;
101 }
102
103 measureStricterVersionOfIsMixedContent(frame, url);
104 if (isMixedContent(frame->document()->securityOrigin(), url))
105 return frame;
106
107 // No mixed content, no problem.
108 return nullptr;
109 }
110
111 // static
84 MixedContentChecker::ContextType MixedContentChecker::contextTypeFromContext(Web URLRequest::RequestContext context) 112 MixedContentChecker::ContextType MixedContentChecker::contextTypeFromContext(Web URLRequest::RequestContext context)
85 { 113 {
86 switch (context) { 114 switch (context) {
87 // "Optionally-blockable" mixed content 115 // "Optionally-blockable" mixed content
88 case WebURLRequest::RequestContextAudio: 116 case WebURLRequest::RequestContextAudio:
89 case WebURLRequest::RequestContextFavicon: 117 case WebURLRequest::RequestContextFavicon:
90 case WebURLRequest::RequestContextImage: 118 case WebURLRequest::RequestContextImage:
91 case WebURLRequest::RequestContextVideo: 119 case WebURLRequest::RequestContextVideo:
92 return ContextTypeOptionallyBlockable; 120 return ContextTypeOptionallyBlockable;
93 121
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 default: 292 default:
265 ASSERT_NOT_REACHED(); 293 ASSERT_NOT_REACHED();
266 return; 294 return;
267 } 295 }
268 UseCounter::count(frame, feature); 296 UseCounter::count(frame, feature);
269 } 297 }
270 298
271 // static 299 // static
272 bool MixedContentChecker::shouldBlockFetch(LocalFrame* frame, WebURLRequest::Req uestContext requestContext, WebURLRequest::FrameType frameType, const KURL& url, MixedContentChecker::ReportingStatus reportingStatus) 300 bool MixedContentChecker::shouldBlockFetch(LocalFrame* frame, WebURLRequest::Req uestContext requestContext, WebURLRequest::FrameType frameType, const KURL& url, MixedContentChecker::ReportingStatus reportingStatus)
273 { 301 {
274 // No frame, no mixed content: 302 LocalFrame* mixedFrame = inWhichFrameIsContentMixed(frame, frameType, url);
275 if (!frame) 303 if (!mixedFrame)
276 return false; 304 return false;
277 305
278 // Check the top frame first. 306 MixedContentChecker::count(mixedFrame, requestContext);
279 if (Frame* top = frame->tree().top()) {
280 // FIXME: We need a way to access the top-level frame's SecurityOrigin w hen that frame
281 // is in a different process from the current frame. Until that is done, we bail out
282 // early and allow the load.
283 if (!top->isLocalFrame())
284 return false;
285 307
286 LocalFrame* localTop = toLocalFrame(top); 308 Settings* settings = mixedFrame->settings();
287 if (frame != localTop && shouldBlockFetch(localTop, requestContext, fram eType, url, reportingStatus)) 309 FrameLoaderClient* client = mixedFrame->loader().client();
288 return true; 310 SecurityOrigin* securityOrigin = mixedFrame->document()->securityOrigin();
289 }
290
291 // We only care about subresource loads; top-level navigations cannot be mix ed content.
292 if (frameType == WebURLRequest::FrameTypeTopLevel)
293 return false;
294
295 // No mixed content, no problem.
296 measureStricterVersionOfIsMixedContent(frame, url);
297 if (!isMixedContent(frame->document()->securityOrigin(), url))
298 return false;
299
300 MixedContentChecker::count(frame, requestContext);
301
302 Settings* settings = frame->settings();
303 FrameLoaderClient* client = frame->loader().client();
304 SecurityOrigin* securityOrigin = frame->document()->securityOrigin();
305 bool allowed = false; 311 bool allowed = false;
306 312
307 // If we're in strict mode, we'll automagically fail everything, and intenti onally skip 313 // If we're in strict mode, we'll automagically fail everything, and intenti onally skip
308 // the client checks in order to prevent degrading the site's security UI. 314 // the client checks in order to prevent degrading the site's security UI.
309 bool strictMode = frame->document()->shouldEnforceStrictMixedContentChecking () || settings->strictMixedContentChecking(); 315 bool strictMode = mixedFrame->document()->shouldEnforceStrictMixedContentChe cking() || settings->strictMixedContentChecking();
310 316
311 ContextType contextType = contextTypeFromContext(requestContext); 317 ContextType contextType = contextTypeFromContext(requestContext);
312 318
313 // If we're loading the main resource of a subframe, we need to take a close look at the loaded URL. 319 // If we're loading the main resource of a subframe, we need to take a close look at the loaded URL.
314 // If we're dealing with a CORS-enabled scheme, then block mixed frames as a ctive content. Otherwise, 320 // If we're dealing with a CORS-enabled scheme, then block mixed frames as a ctive content. Otherwise,
315 // treat frames as passive content. 321 // treat frames as passive content.
316 // 322 //
317 // FIXME: Remove this temporary hack once we have a reasonable API for launc hing external applications 323 // FIXME: Remove this temporary hack once we have a reasonable API for launc hing external applications
318 // via URLs. http://crbug.com/318788 and https://crbug.com/393481 324 // via URLs. http://crbug.com/318788 and https://crbug.com/393481
319 if (frameType == WebURLRequest::FrameTypeNested && !SchemeRegistry::shouldTr eatURLSchemeAsCORSEnabled(url.protocol())) 325 if (frameType == WebURLRequest::FrameTypeNested && !SchemeRegistry::shouldTr eatURLSchemeAsCORSEnabled(url.protocol()))
(...skipping 16 matching lines...) Expand all
336 allowed = true; 342 allowed = true;
337 client->didDisplayInsecureContent(); 343 client->didDisplayInsecureContent();
338 break; 344 break;
339 }; 345 };
340 346
341 if (reportingStatus == SendReport) 347 if (reportingStatus == SendReport)
342 logToConsole(frame, url, requestContext, allowed); 348 logToConsole(frame, url, requestContext, allowed);
343 return !allowed; 349 return !allowed;
344 } 350 }
345 351
352 // static
353 bool MixedContentChecker::shouldBlockConnection(LocalFrame* frame, const KURL& u rl, MixedContentChecker::ReportingStatus reportingStatus)
354 {
355 LocalFrame* mixedFrame = inWhichFrameIsContentMixed(frame, WebURLRequest::Fr ameTypeNone, url);
356 if (!mixedFrame)
357 return false;
358
359 UseCounter::count(mixedFrame, UseCounter::MixedContentPresent);
360 UseCounter::count(mixedFrame, UseCounter::MixedContentWebSocket);
361
362 // If we're in strict mode, we'll automagically fail everything, and intenti onally skip
363 // the client checks in order to prevent degrading the site's security UI.
364 bool strictMode = mixedFrame->document()->shouldEnforceStrictMixedContentChe cking();
365
366 Settings* settings = mixedFrame->settings();
367 FrameLoaderClient* client = mixedFrame->loader().client();
368 SecurityOrigin* securityOrigin = mixedFrame->document()->securityOrigin();
369 bool allowedPerSettings = settings && (settings->allowRunningOfInsecureConte nt() || settings->allowConnectingInsecureWebSocket());
370 bool allowed = !strictMode && client->allowRunningInsecureContent(allowedPer Settings, securityOrigin, url);
371
372 if (reportingStatus == SendReport) {
373 String message = String::format(
374 "Mixed Content: The page at '%s' was loaded over HTTPS, but attempte d to connect to the insecure WebSocket endpoint '%s'. %s",
375 frame->document()->url().elidedString().utf8().data(), url.elidedStr ing().utf8().data(),
376 allowed ? "This endpoint should be available via WSS. Insecure acces s is deprecated." : "This request has been blocked; this endpoint must be availa ble over WSS.");
377 MessageLevel messageLevel = allowed ? WarningMessageLevel : ErrorMessage Level;
378 mixedFrame->document()->addConsoleMessage(ConsoleMessage::create(Securit yMessageSource, messageLevel, message));
379 }
380
381 return !allowed;
382 }
383
346 bool MixedContentChecker::canDisplayInsecureContent(SecurityOrigin* securityOrig in, const KURL& url, const MixedContentType type) const 384 bool MixedContentChecker::canDisplayInsecureContent(SecurityOrigin* securityOrig in, const KURL& url, const MixedContentType type) const
347 { 385 {
348 // Check the top frame if it differs from MixedContentChecker's m_frame. 386 // Check the top frame if it differs from MixedContentChecker's m_frame.
349 if (!m_frame->tree().top()->isLocalFrame()) { 387 if (!m_frame->tree().top()->isLocalFrame()) {
350 // FIXME: We need a way to access the top-level frame's MixedContentChec ker when that frame 388 // FIXME: We need a way to access the top-level frame's MixedContentChec ker when that frame
351 // is in a different process from the current frame. Until that is done, we always allow 389 // is in a different process from the current frame. Until that is done, we always allow
352 // loads in remote frames. 390 // loads in remote frames.
353 return false; 391 return false;
354 } 392 }
355 Frame* top = m_frame->tree().top(); 393 Frame* top = m_frame->tree().top();
(...skipping 11 matching lines...) Expand all
367 Settings* settings = m_frame->settings(); 405 Settings* settings = m_frame->settings();
368 bool allowed = client()->allowDisplayingInsecureContent(settings && settings ->allowDisplayOfInsecureContent(), securityOrigin, url); 406 bool allowed = client()->allowDisplayingInsecureContent(settings && settings ->allowDisplayOfInsecureContent(), securityOrigin, url);
369 logWarning(allowed, url, type); 407 logWarning(allowed, url, type);
370 408
371 if (allowed) 409 if (allowed)
372 client()->didDisplayInsecureContent(); 410 client()->didDisplayInsecureContent();
373 411
374 return allowed; 412 return allowed;
375 } 413 }
376 414
377 bool MixedContentChecker::canRunInsecureContent(SecurityOrigin* securityOrigin, const KURL& url, const MixedContentType type) const
378 {
379 // Check the top frame if it differs from MixedContentChecker's m_frame.
380 if (!m_frame->tree().top()->isLocalFrame()) {
381 // FIXME: We need a way to access the top-level frame's MixedContentChec ker when that frame
382 // is in a different process from the current frame. Until that is done, we always allow
383 // loads in remote frames.
384 return true;
385 }
386 Frame* top = m_frame->tree().top();
387 if (top != m_frame && !toLocalFrame(top)->loader().mixedContentChecker()->ca nRunInsecureContent(toLocalFrame(top)->document()->securityOrigin(), url, type))
388 return false;
389
390 // Just count these for the moment, don't block them.
391 if (Platform::current()->isReservedIPAddress(url) && !Platform::current()->i sReservedIPAddress(KURL(ParsedURLString, securityOrigin->toString())))
392 UseCounter::count(m_frame->document(), UseCounter::MixedContentPrivateIP InPublicWebsiteActive);
393
394 // Then check the current frame:
395 if (!isMixedContent(securityOrigin, url))
396 return true;
397
398 Settings* settings = m_frame->settings();
399 bool allowedPerSettings = settings && (settings->allowRunningOfInsecureConte nt() || ((type == WebSocket) && settings->allowConnectingInsecureWebSocket()));
400 bool allowed = client()->allowRunningInsecureContent(allowedPerSettings, sec urityOrigin, url);
401 logWarning(allowed, url, type);
402
403 if (allowed)
404 client()->didRunInsecureContent(securityOrigin, url);
405
406 return allowed;
407 }
408
409 bool MixedContentChecker::canConnectInsecureWebSocket(SecurityOrigin* securityOr igin, const KURL& url) const
410 {
411 return canRunInsecureContent(securityOrigin, url, MixedContentChecker::WebSo cket);
412 }
413
414 bool MixedContentChecker::canSubmitToInsecureForm(SecurityOrigin* securityOrigin , const KURL& url) const 415 bool MixedContentChecker::canSubmitToInsecureForm(SecurityOrigin* securityOrigin , const KURL& url) const
415 { 416 {
416 // For whatever reason, some folks handle forms via JavaScript, and submit t o `javascript:void(0)` 417 // For whatever reason, some folks handle forms via JavaScript, and submit t o `javascript:void(0)`
417 // rather than calling `preventDefault()`. We special-case `javascript:` URL s here, as they don't 418 // rather than calling `preventDefault()`. We special-case `javascript:` URL s here, as they don't
418 // introduce MixedContent for form submissions. 419 // introduce MixedContent for form submissions.
419 if (url.protocolIs("javascript")) 420 if (url.protocolIs("javascript"))
420 return true; 421 return true;
421 422
422 return canDisplayInsecureContent(securityOrigin, url, MixedContentChecker::S ubmission); 423 return canDisplayInsecureContent(securityOrigin, url, MixedContentChecker::S ubmission);
423 } 424 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 if (Platform::current()->isReservedIPAddress(resourceIP) && !Platform::curre nt()->isReservedIPAddress(documentIP)) 458 if (Platform::current()->isReservedIPAddress(resourceIP) && !Platform::curre nt()->isReservedIPAddress(documentIP))
458 UseCounter::count(frame->document(), UseCounter::MixedContentPrivateHost nameInPublicHostname); 459 UseCounter::count(frame->document(), UseCounter::MixedContentPrivateHost nameInPublicHostname);
459 } 460 }
460 461
461 void MixedContentChecker::trace(Visitor* visitor) 462 void MixedContentChecker::trace(Visitor* visitor)
462 { 463 {
463 visitor->trace(m_frame); 464 visitor->trace(m_frame);
464 } 465 }
465 466
466 } // namespace blink 467 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698