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 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 void MixedContentChecker::logToConsole(LocalFrame* frame, const KURL& url, WebUR
LRequest::RequestContext requestContext, bool allowed) | 205 void MixedContentChecker::logToConsole(LocalFrame* frame, const KURL& url, WebUR
LRequest::RequestContext requestContext, bool allowed) |
206 { | 206 { |
207 String message = String::format( | 207 String message = String::format( |
208 "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an
insecure %s '%s'. %s", | 208 "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an
insecure %s '%s'. %s", |
209 frame->document()->url().elidedString().utf8().data(), typeNameFromConte
xt(requestContext), url.elidedString().utf8().data(), | 209 frame->document()->url().elidedString().utf8().data(), typeNameFromConte
xt(requestContext), url.elidedString().utf8().data(), |
210 allowed ? "This content should also be served over HTTPS." : "This reque
st has been blocked; the content must be served over HTTPS."); | 210 allowed ? "This content should also be served over HTTPS." : "This reque
st has been blocked; the content must be served over HTTPS."); |
211 MessageLevel messageLevel = allowed ? WarningMessageLevel : ErrorMessageLeve
l; | 211 MessageLevel messageLevel = allowed ? WarningMessageLevel : ErrorMessageLeve
l; |
212 frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageS
ource, messageLevel, message)); | 212 frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageS
ource, messageLevel, message)); |
213 } | 213 } |
214 | 214 |
215 LocalFrame* MixedContentChecker::inWhichFrameIsThisContentMixed(LocalFrame* fram
e, WebURLRequest::RequestContext requestContext, WebURLRequest::FrameType frameT
ype, const KURL& url) | 215 // static |
| 216 bool MixedContentChecker::shouldBlockFetch(LocalFrame* frame, const ResourceRequ
est& resourceRequest, const KURL& url) |
216 { | 217 { |
217 // No frame, no mixed content: | 218 // No frame, no mixed content: |
218 if (!frame) | 219 if (!frame) |
219 return nullptr; | 220 return false; |
220 | |
221 // We only care about subresource loads; top-level navigations cannot be mix
ed content. | |
222 if (frameType == WebURLRequest::FrameTypeTopLevel) | |
223 return nullptr; | |
224 | 221 |
225 // Check the top frame first. | 222 // Check the top frame first. |
226 if (Frame* top = frame->tree().top()) { | 223 if (Frame* top = frame->tree().top()) { |
227 // FIXME: We need a way to access the top-level frame's SecurityOrigin w
hen that frame | 224 // FIXME: We need a way to access the top-level frame's SecurityOrigin w
hen that frame |
228 // is in a different process from the current frame. Until that is done,
we bail out | 225 // is in a different process from the current frame. Until that is done,
we bail out |
229 // early and allow the load. | 226 // early and allow the load. |
230 if (!top->isLocalFrame()) | 227 if (!top->isLocalFrame()) |
231 return nullptr; | 228 return false; |
232 | 229 |
233 LocalFrame* localTop = toLocalFrame(top); | 230 LocalFrame* localTop = toLocalFrame(top); |
234 if (frame != localTop && inWhichFrameIsThisContentMixed(localTop, reques
tContext, frameType, url)) | 231 if (frame != localTop && shouldBlockFetch(localTop, resourceRequest, url
)) |
235 return localTop; | 232 return true; |
236 } | 233 } |
237 | 234 |
238 // Just count these for the moment, don't block them. | 235 // We only care about subresource loads; top-level navigations cannot be mix
ed content. |
239 if (Platform::current()->isReservedIPAddress(url) && !Platform::current()->i
sReservedIPAddress(KURL(ParsedURLString, frame->document()->securityOrigin()->to
String()))) | 236 if (resourceRequest.frameType() == WebURLRequest::FrameTypeTopLevel) |
240 UseCounter::count(frame->document(), contextTypeFromContext(requestConte
xt) == ContextTypeBlockable ? UseCounter::MixedContentPrivateIPInPublicWebsiteAc
tive : UseCounter::MixedContentPrivateIPInPublicWebsitePassive); | 237 return false; |
241 | 238 |
242 // No mixed content, no problem. | 239 // No mixed content, no problem. |
243 if (!isMixedContent(frame->document()->securityOrigin(), url)) | 240 if (!isMixedContent(frame->document()->securityOrigin(), url)) |
244 return nullptr; | |
245 | |
246 return frame; | |
247 } | |
248 | |
249 // static | |
250 bool MixedContentChecker::shouldBlockFetch(LocalFrame* frame, WebURLRequest::Req
uestContext requestContext, WebURLRequest::FrameType frameType, const KURL& url) | |
251 { | |
252 LocalFrame* effectiveFrame = inWhichFrameIsThisContentMixed(frame, requestCo
ntext, frameType, url); | |
253 if (!effectiveFrame) | |
254 return false; | 241 return false; |
255 | 242 |
256 // We grab the settings and client from the frame in which the content was m
ixed, as it might be | 243 Settings* settings = frame->settings(); |
257 // configured to allow mixed content in a different way than the frame in wh
ich the content | 244 FrameLoaderClient* client = frame->loader().client(); |
258 // loads (e.g. if Frame A is allowed to frame an insecure Frame B, we defer
to Frame A's settings | 245 SecurityOrigin* securityOrigin = frame->document()->securityOrigin(); |
259 // when evaluating Frame B's subresource loads). Yes, this is confusing. | |
260 Settings* settings = effectiveFrame->settings(); | |
261 FrameLoaderClient* client = effectiveFrame->loader().client(); | |
262 SecurityOrigin* securityOrigin = effectiveFrame->document()->securityOrigin(
); | |
263 bool allowed = false; | 246 bool allowed = false; |
264 | 247 |
265 ContextType contextType = contextTypeFromContext(requestContext); | 248 ContextType contextType = contextTypeFromContext(resourceRequest.requestCont
ext()); |
266 if (contextType == ContextTypeBlockableUnlessLax) | 249 if (contextType == ContextTypeBlockableUnlessLax) |
267 contextType = RuntimeEnabledFeatures::laxMixedContentCheckingEnabled() ?
ContextTypeOptionallyBlockable : ContextTypeBlockable; | 250 contextType = RuntimeEnabledFeatures::laxMixedContentCheckingEnabled() ?
ContextTypeOptionallyBlockable : ContextTypeBlockable; |
268 | 251 |
269 switch (contextType) { | 252 switch (contextType) { |
270 case ContextTypeOptionallyBlockable: | 253 case ContextTypeOptionallyBlockable: |
271 allowed = client->allowDisplayingInsecureContent(settings && settings->a
llowDisplayOfInsecureContent(), securityOrigin, url); | 254 allowed = client->allowDisplayingInsecureContent(settings && settings->a
llowDisplayOfInsecureContent(), securityOrigin, url); |
272 if (allowed) | 255 if (allowed) |
273 client->didDisplayInsecureContent(); | 256 client->didDisplayInsecureContent(); |
274 break; | 257 break; |
275 | 258 |
276 case ContextTypeBlockable: | 259 case ContextTypeBlockable: |
277 allowed = client->allowRunningInsecureContent(settings && settings->allo
wRunningOfInsecureContent(), securityOrigin, url); | 260 allowed = client->allowRunningInsecureContent(settings && settings->allo
wRunningOfInsecureContent(), securityOrigin, url); |
278 if (allowed) | 261 if (allowed) |
279 client->didRunInsecureContent(securityOrigin, url); | 262 client->didRunInsecureContent(securityOrigin, url); |
280 break; | 263 break; |
281 | 264 |
282 case ContextTypeShouldBeBlockable: | 265 case ContextTypeShouldBeBlockable: |
283 return false; | 266 return false; |
284 | 267 |
285 case ContextTypeBlockableUnlessLax: | 268 case ContextTypeBlockableUnlessLax: |
286 // We map this to either OptionallyBlockable or Blockable above. | 269 // We map this to either OptionallyBlockable or Blockable above. |
287 ASSERT_NOT_REACHED(); | 270 ASSERT_NOT_REACHED(); |
288 return true; | 271 return true; |
289 }; | 272 }; |
290 | 273 |
291 // While we use the |effectiveFrame| to grab the settings object, we log the
console error in | 274 logToConsole(frame, url, resourceRequest.requestContext(), allowed); |
292 // |frame|, where the violation actually happened. | |
293 String message = String::format( | |
294 "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an
insecure %s '%s'. %s", | |
295 frame->document()->url().elidedString().utf8().data(), typeNameFromConte
xt(requestContext), url.elidedString().utf8().data(), | |
296 allowed ? "This content should also be served over HTTPS." : "This reque
st has been blocked; the content must be served over HTTPS."); | |
297 MessageLevel messageLevel = allowed ? WarningMessageLevel : ErrorMessageLeve
l; | |
298 frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageS
ource, messageLevel, message)); | |
299 | |
300 return !allowed; | 275 return !allowed; |
301 } | 276 } |
302 | 277 |
303 // static | |
304 bool MixedContentChecker::checkFormAction(LocalFrame* frame, const KURL& url) | |
305 { | |
306 // For whatever reason, some folks handle forms via JavaScript, and submit t
o `javascript:void(0)` | |
307 // rather than calling `preventDefault()`. We special-case `javascript:` URL
s here, as they don't | |
308 // introduce MixedContent for form submissions. | |
309 if (url.protocolIs("javascript")) | |
310 return false; | |
311 | |
312 // If lax mixed content checking is enabled (noooo!), skip this check entire
ly. | |
313 if (RuntimeEnabledFeatures::laxMixedContentCheckingEnabled()) | |
314 return false; | |
315 | |
316 LocalFrame* effectiveFrame = inWhichFrameIsThisContentMixed(frame, WebURLReq
uest::RequestContextForm, WebURLRequest::FrameTypeNone, url); | |
317 if (!effectiveFrame) | |
318 return false; | |
319 | |
320 // No "allowed" check here; we're not yet exposing anything which would bloc
k form submission. | |
321 FrameLoaderClient* client = effectiveFrame->loader().client(); | |
322 client->didDisplayInsecureContent(); | |
323 | |
324 String message = String::format( | |
325 "Mixed Content: The page at '%s' was loaded over HTTPS, but contains a f
orm whose 'action' attribute is '%s'. This form should not submit data to insecu
re endpoints.", | |
326 effectiveFrame->document()->url().elidedString().utf8().data(), url.elid
edString().utf8().data()); | |
327 effectiveFrame->document()->addConsoleMessage(ConsoleMessage::create(Securit
yMessageSource, WarningMessageLevel, message)); | |
328 return true; | |
329 } | |
330 | |
331 bool MixedContentChecker::canDisplayInsecureContentInternal(SecurityOrigin* secu
rityOrigin, const KURL& url, const MixedContentType type) const | 278 bool MixedContentChecker::canDisplayInsecureContentInternal(SecurityOrigin* secu
rityOrigin, const KURL& url, const MixedContentType type) const |
332 { | 279 { |
333 // Check the top frame if it differs from MixedContentChecker's m_frame. | 280 // Check the top frame if it differs from MixedContentChecker's m_frame. |
334 if (!m_frame->tree().top()->isLocalFrame()) { | 281 if (!m_frame->tree().top()->isLocalFrame()) { |
335 // FIXME: We need a way to access the top-level frame's MixedContentChec
ker when that frame | 282 // FIXME: We need a way to access the top-level frame's MixedContentChec
ker when that frame |
336 // is in a different process from the current frame. Until that is done,
we always allow | 283 // is in a different process from the current frame. Until that is done,
we always allow |
337 // loads in remote frames. | 284 // loads in remote frames. |
338 return false; | 285 return false; |
339 } | 286 } |
340 Frame* top = m_frame->tree().top(); | 287 Frame* top = m_frame->tree().top(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 return canDisplayInsecureContentInternal(securityOrigin, url, MixedContentCh
ecker::Display); | 350 return canDisplayInsecureContentInternal(securityOrigin, url, MixedContentCh
ecker::Display); |
404 } | 351 } |
405 | 352 |
406 bool MixedContentChecker::canConnectInsecureWebSocket(SecurityOrigin* securityOr
igin, const KURL& url) const | 353 bool MixedContentChecker::canConnectInsecureWebSocket(SecurityOrigin* securityOr
igin, const KURL& url) const |
407 { | 354 { |
408 if (RuntimeEnabledFeatures::laxMixedContentCheckingEnabled()) | 355 if (RuntimeEnabledFeatures::laxMixedContentCheckingEnabled()) |
409 return canDisplayInsecureContentInternal(securityOrigin, url, MixedConte
ntChecker::WebSocket); | 356 return canDisplayInsecureContentInternal(securityOrigin, url, MixedConte
ntChecker::WebSocket); |
410 return canRunInsecureContentInternal(securityOrigin, url, MixedContentChecke
r::WebSocket); | 357 return canRunInsecureContentInternal(securityOrigin, url, MixedContentChecke
r::WebSocket); |
411 } | 358 } |
412 | 359 |
| 360 bool MixedContentChecker::canSubmitToInsecureForm(SecurityOrigin* securityOrigin
, const KURL& url) const |
| 361 { |
| 362 // For whatever reason, some folks handle forms via JavaScript, and submit t
o `javascript:void(0)` |
| 363 // rather than calling `preventDefault()`. We special-case `javascript:` URL
s here, as they don't |
| 364 // introduce MixedContent for form submissions. |
| 365 if (url.protocolIs("javascript")) |
| 366 return true; |
| 367 |
| 368 // If lax mixed content checking is enabled (noooo!), skip this check entire
ly. |
| 369 if (RuntimeEnabledFeatures::laxMixedContentCheckingEnabled()) |
| 370 return true; |
| 371 return canDisplayInsecureContentInternal(securityOrigin, url, MixedContentCh
ecker::Submission); |
| 372 } |
| 373 |
413 void MixedContentChecker::logWarning(bool allowed, const KURL& target, const Mix
edContentType type) const | 374 void MixedContentChecker::logWarning(bool allowed, const KURL& target, const Mix
edContentType type) const |
414 { | 375 { |
415 StringBuilder message; | 376 StringBuilder message; |
416 message.append((allowed ? "" : "[blocked] ")); | 377 message.append((allowed ? "" : "[blocked] ")); |
417 message.append("The page at '" + m_frame->document()->url().elidedString() +
"' was loaded over HTTPS, but "); | 378 message.append("The page at '" + m_frame->document()->url().elidedString() +
"' was loaded over HTTPS, but "); |
418 switch (type) { | 379 switch (type) { |
419 case Display: | 380 case Display: |
420 message.append("displayed insecure content from '" + target.elidedString
() + "': this content should also be loaded over HTTPS.\n"); | 381 message.append("displayed insecure content from '" + target.elidedString
() + "': this content should also be loaded over HTTPS.\n"); |
421 break; | 382 break; |
422 case Execution: | 383 case Execution: |
(...skipping 22 matching lines...) Expand all Loading... |
445 if (Platform::current()->isReservedIPAddress(resourceIP) && !Platform::curre
nt()->isReservedIPAddress(documentIP)) | 406 if (Platform::current()->isReservedIPAddress(resourceIP) && !Platform::curre
nt()->isReservedIPAddress(documentIP)) |
446 UseCounter::count(frame->document(), UseCounter::MixedContentPrivateHost
nameInPublicHostname); | 407 UseCounter::count(frame->document(), UseCounter::MixedContentPrivateHost
nameInPublicHostname); |
447 } | 408 } |
448 | 409 |
449 void MixedContentChecker::trace(Visitor* visitor) | 410 void MixedContentChecker::trace(Visitor* visitor) |
450 { | 411 { |
451 visitor->trace(m_frame); | 412 visitor->trace(m_frame); |
452 } | 413 } |
453 | 414 |
454 } // namespace blink | 415 } // namespace blink |
OLD | NEW |