1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/nsDataDocumentContentPolicy.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,147 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * Content policy implementation that prevents all loads of images, 1.11 + * subframes, etc from documents loaded as data (eg documents loaded 1.12 + * via XMLHttpRequest). 1.13 + */ 1.14 + 1.15 +#include "nsDataDocumentContentPolicy.h" 1.16 +#include "nsNetUtil.h" 1.17 +#include "nsScriptSecurityManager.h" 1.18 +#include "nsIDocument.h" 1.19 +#include "nsINode.h" 1.20 +#include "nsIDOMWindow.h" 1.21 + 1.22 +NS_IMPL_ISUPPORTS(nsDataDocumentContentPolicy, nsIContentPolicy) 1.23 + 1.24 +// Helper method for ShouldLoad() 1.25 +// Checks a URI for the given flags. Returns true if the URI has the flags, 1.26 +// and false if not (or if we weren't able to tell). 1.27 +static bool 1.28 +HasFlags(nsIURI* aURI, uint32_t aURIFlags) 1.29 +{ 1.30 + bool hasFlags; 1.31 + nsresult rv = NS_URIChainHasFlags(aURI, aURIFlags, &hasFlags); 1.32 + return NS_SUCCEEDED(rv) && hasFlags; 1.33 +} 1.34 + 1.35 +// If you change DataDocumentContentPolicy, make sure to check that 1.36 +// CHECK_PRINCIPAL_AND_DATA in nsContentPolicyUtils is still valid. 1.37 +// nsContentPolicyUtils may not pass all the parameters to ShouldLoad. 1.38 +NS_IMETHODIMP 1.39 +nsDataDocumentContentPolicy::ShouldLoad(uint32_t aContentType, 1.40 + nsIURI *aContentLocation, 1.41 + nsIURI *aRequestingLocation, 1.42 + nsISupports *aRequestingContext, 1.43 + const nsACString &aMimeGuess, 1.44 + nsISupports *aExtra, 1.45 + nsIPrincipal *aRequestPrincipal, 1.46 + int16_t *aDecision) 1.47 +{ 1.48 + *aDecision = nsIContentPolicy::ACCEPT; 1.49 + // Look for the document. In most cases, aRequestingContext is a node. 1.50 + nsCOMPtr<nsIDocument> doc; 1.51 + nsCOMPtr<nsINode> node = do_QueryInterface(aRequestingContext); 1.52 + if (node) { 1.53 + doc = node->OwnerDoc(); 1.54 + } else { 1.55 + nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aRequestingContext); 1.56 + if (window) { 1.57 + doc = window->GetDoc(); 1.58 + } 1.59 + } 1.60 + 1.61 + // DTDs are always OK to load 1.62 + if (!doc || aContentType == nsIContentPolicy::TYPE_DTD) { 1.63 + return NS_OK; 1.64 + } 1.65 + 1.66 + // Nothing else is OK to load for data documents 1.67 + if (doc->IsLoadedAsData()) { 1.68 + // ...but let static (print/print preview) documents to load fonts. 1.69 + if (!doc->IsStaticDocument() || aContentType != nsIContentPolicy::TYPE_FONT) { 1.70 + *aDecision = nsIContentPolicy::REJECT_TYPE; 1.71 + return NS_OK; 1.72 + } 1.73 + } 1.74 + 1.75 + if (doc->IsBeingUsedAsImage()) { 1.76 + // We only allow SVG images to load content from URIs that are local and 1.77 + // also satisfy one of the following conditions: 1.78 + // - URI inherits security context, e.g. data URIs 1.79 + // OR 1.80 + // - URI loadable by subsumers, e.g. blob URIs 1.81 + // Any URI that doesn't meet these requirements will be rejected below. 1.82 + if (!HasFlags(aContentLocation, 1.83 + nsIProtocolHandler::URI_IS_LOCAL_RESOURCE) || 1.84 + (!HasFlags(aContentLocation, 1.85 + nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT) && 1.86 + !HasFlags(aContentLocation, 1.87 + nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS))) { 1.88 + *aDecision = nsIContentPolicy::REJECT_TYPE; 1.89 + 1.90 + // Report error, if we can. 1.91 + if (node) { 1.92 + nsIPrincipal* requestingPrincipal = node->NodePrincipal(); 1.93 + nsRefPtr<nsIURI> principalURI; 1.94 + nsresult rv = 1.95 + requestingPrincipal->GetURI(getter_AddRefs(principalURI)); 1.96 + if (NS_SUCCEEDED(rv) && principalURI) { 1.97 + nsScriptSecurityManager::ReportError( 1.98 + nullptr, NS_LITERAL_STRING("CheckSameOriginError"), principalURI, 1.99 + aContentLocation); 1.100 + } 1.101 + } 1.102 + } else if (aContentType == nsIContentPolicy::TYPE_IMAGE && 1.103 + doc->GetDocumentURI()) { 1.104 + // Check for (& disallow) recursive image-loads 1.105 + bool isRecursiveLoad; 1.106 + nsresult rv = aContentLocation->EqualsExceptRef(doc->GetDocumentURI(), 1.107 + &isRecursiveLoad); 1.108 + if (NS_FAILED(rv) || isRecursiveLoad) { 1.109 + NS_WARNING("Refusing to recursively load image"); 1.110 + *aDecision = nsIContentPolicy::REJECT_TYPE; 1.111 + } 1.112 + } 1.113 + return NS_OK; 1.114 + } 1.115 + 1.116 + // Allow all loads for non-resource documents 1.117 + if (!doc->IsResourceDoc()) { 1.118 + return NS_OK; 1.119 + } 1.120 + 1.121 + // For resource documents, blacklist some load types 1.122 + if (aContentType == nsIContentPolicy::TYPE_OBJECT || 1.123 + aContentType == nsIContentPolicy::TYPE_DOCUMENT || 1.124 + aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT || 1.125 + aContentType == nsIContentPolicy::TYPE_SCRIPT || 1.126 + aContentType == nsIContentPolicy::TYPE_XSLT) { 1.127 + *aDecision = nsIContentPolicy::REJECT_TYPE; 1.128 + } 1.129 + 1.130 + // If you add more restrictions here, make sure to check that 1.131 + // CHECK_PRINCIPAL_AND_DATA in nsContentPolicyUtils is still valid. 1.132 + // nsContentPolicyUtils may not pass all the parameters to ShouldLoad 1.133 + 1.134 + return NS_OK; 1.135 +} 1.136 + 1.137 +NS_IMETHODIMP 1.138 +nsDataDocumentContentPolicy::ShouldProcess(uint32_t aContentType, 1.139 + nsIURI *aContentLocation, 1.140 + nsIURI *aRequestingLocation, 1.141 + nsISupports *aRequestingContext, 1.142 + const nsACString &aMimeGuess, 1.143 + nsISupports *aExtra, 1.144 + nsIPrincipal *aRequestPrincipal, 1.145 + int16_t *aDecision) 1.146 +{ 1.147 + return ShouldLoad(aContentType, aContentLocation, aRequestingLocation, 1.148 + aRequestingContext, aMimeGuess, aExtra, aRequestPrincipal, 1.149 + aDecision); 1.150 +}