OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |