Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* |
michael@0 | 7 | * Content policy implementation that prevents all loads of images, |
michael@0 | 8 | * subframes, etc from documents loaded as data (eg documents loaded |
michael@0 | 9 | * via XMLHttpRequest). |
michael@0 | 10 | */ |
michael@0 | 11 | |
michael@0 | 12 | #include "nsDataDocumentContentPolicy.h" |
michael@0 | 13 | #include "nsNetUtil.h" |
michael@0 | 14 | #include "nsScriptSecurityManager.h" |
michael@0 | 15 | #include "nsIDocument.h" |
michael@0 | 16 | #include "nsINode.h" |
michael@0 | 17 | #include "nsIDOMWindow.h" |
michael@0 | 18 | |
michael@0 | 19 | NS_IMPL_ISUPPORTS(nsDataDocumentContentPolicy, nsIContentPolicy) |
michael@0 | 20 | |
michael@0 | 21 | // Helper method for ShouldLoad() |
michael@0 | 22 | // Checks a URI for the given flags. Returns true if the URI has the flags, |
michael@0 | 23 | // and false if not (or if we weren't able to tell). |
michael@0 | 24 | static bool |
michael@0 | 25 | HasFlags(nsIURI* aURI, uint32_t aURIFlags) |
michael@0 | 26 | { |
michael@0 | 27 | bool hasFlags; |
michael@0 | 28 | nsresult rv = NS_URIChainHasFlags(aURI, aURIFlags, &hasFlags); |
michael@0 | 29 | return NS_SUCCEEDED(rv) && hasFlags; |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | // If you change DataDocumentContentPolicy, make sure to check that |
michael@0 | 33 | // CHECK_PRINCIPAL_AND_DATA in nsContentPolicyUtils is still valid. |
michael@0 | 34 | // nsContentPolicyUtils may not pass all the parameters to ShouldLoad. |
michael@0 | 35 | NS_IMETHODIMP |
michael@0 | 36 | nsDataDocumentContentPolicy::ShouldLoad(uint32_t aContentType, |
michael@0 | 37 | nsIURI *aContentLocation, |
michael@0 | 38 | nsIURI *aRequestingLocation, |
michael@0 | 39 | nsISupports *aRequestingContext, |
michael@0 | 40 | const nsACString &aMimeGuess, |
michael@0 | 41 | nsISupports *aExtra, |
michael@0 | 42 | nsIPrincipal *aRequestPrincipal, |
michael@0 | 43 | int16_t *aDecision) |
michael@0 | 44 | { |
michael@0 | 45 | *aDecision = nsIContentPolicy::ACCEPT; |
michael@0 | 46 | // Look for the document. In most cases, aRequestingContext is a node. |
michael@0 | 47 | nsCOMPtr<nsIDocument> doc; |
michael@0 | 48 | nsCOMPtr<nsINode> node = do_QueryInterface(aRequestingContext); |
michael@0 | 49 | if (node) { |
michael@0 | 50 | doc = node->OwnerDoc(); |
michael@0 | 51 | } else { |
michael@0 | 52 | nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aRequestingContext); |
michael@0 | 53 | if (window) { |
michael@0 | 54 | doc = window->GetDoc(); |
michael@0 | 55 | } |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | // DTDs are always OK to load |
michael@0 | 59 | if (!doc || aContentType == nsIContentPolicy::TYPE_DTD) { |
michael@0 | 60 | return NS_OK; |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | // Nothing else is OK to load for data documents |
michael@0 | 64 | if (doc->IsLoadedAsData()) { |
michael@0 | 65 | // ...but let static (print/print preview) documents to load fonts. |
michael@0 | 66 | if (!doc->IsStaticDocument() || aContentType != nsIContentPolicy::TYPE_FONT) { |
michael@0 | 67 | *aDecision = nsIContentPolicy::REJECT_TYPE; |
michael@0 | 68 | return NS_OK; |
michael@0 | 69 | } |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | if (doc->IsBeingUsedAsImage()) { |
michael@0 | 73 | // We only allow SVG images to load content from URIs that are local and |
michael@0 | 74 | // also satisfy one of the following conditions: |
michael@0 | 75 | // - URI inherits security context, e.g. data URIs |
michael@0 | 76 | // OR |
michael@0 | 77 | // - URI loadable by subsumers, e.g. blob URIs |
michael@0 | 78 | // Any URI that doesn't meet these requirements will be rejected below. |
michael@0 | 79 | if (!HasFlags(aContentLocation, |
michael@0 | 80 | nsIProtocolHandler::URI_IS_LOCAL_RESOURCE) || |
michael@0 | 81 | (!HasFlags(aContentLocation, |
michael@0 | 82 | nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT) && |
michael@0 | 83 | !HasFlags(aContentLocation, |
michael@0 | 84 | nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS))) { |
michael@0 | 85 | *aDecision = nsIContentPolicy::REJECT_TYPE; |
michael@0 | 86 | |
michael@0 | 87 | // Report error, if we can. |
michael@0 | 88 | if (node) { |
michael@0 | 89 | nsIPrincipal* requestingPrincipal = node->NodePrincipal(); |
michael@0 | 90 | nsRefPtr<nsIURI> principalURI; |
michael@0 | 91 | nsresult rv = |
michael@0 | 92 | requestingPrincipal->GetURI(getter_AddRefs(principalURI)); |
michael@0 | 93 | if (NS_SUCCEEDED(rv) && principalURI) { |
michael@0 | 94 | nsScriptSecurityManager::ReportError( |
michael@0 | 95 | nullptr, NS_LITERAL_STRING("CheckSameOriginError"), principalURI, |
michael@0 | 96 | aContentLocation); |
michael@0 | 97 | } |
michael@0 | 98 | } |
michael@0 | 99 | } else if (aContentType == nsIContentPolicy::TYPE_IMAGE && |
michael@0 | 100 | doc->GetDocumentURI()) { |
michael@0 | 101 | // Check for (& disallow) recursive image-loads |
michael@0 | 102 | bool isRecursiveLoad; |
michael@0 | 103 | nsresult rv = aContentLocation->EqualsExceptRef(doc->GetDocumentURI(), |
michael@0 | 104 | &isRecursiveLoad); |
michael@0 | 105 | if (NS_FAILED(rv) || isRecursiveLoad) { |
michael@0 | 106 | NS_WARNING("Refusing to recursively load image"); |
michael@0 | 107 | *aDecision = nsIContentPolicy::REJECT_TYPE; |
michael@0 | 108 | } |
michael@0 | 109 | } |
michael@0 | 110 | return NS_OK; |
michael@0 | 111 | } |
michael@0 | 112 | |
michael@0 | 113 | // Allow all loads for non-resource documents |
michael@0 | 114 | if (!doc->IsResourceDoc()) { |
michael@0 | 115 | return NS_OK; |
michael@0 | 116 | } |
michael@0 | 117 | |
michael@0 | 118 | // For resource documents, blacklist some load types |
michael@0 | 119 | if (aContentType == nsIContentPolicy::TYPE_OBJECT || |
michael@0 | 120 | aContentType == nsIContentPolicy::TYPE_DOCUMENT || |
michael@0 | 121 | aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT || |
michael@0 | 122 | aContentType == nsIContentPolicy::TYPE_SCRIPT || |
michael@0 | 123 | aContentType == nsIContentPolicy::TYPE_XSLT) { |
michael@0 | 124 | *aDecision = nsIContentPolicy::REJECT_TYPE; |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | // If you add more restrictions here, make sure to check that |
michael@0 | 128 | // CHECK_PRINCIPAL_AND_DATA in nsContentPolicyUtils is still valid. |
michael@0 | 129 | // nsContentPolicyUtils may not pass all the parameters to ShouldLoad |
michael@0 | 130 | |
michael@0 | 131 | return NS_OK; |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | NS_IMETHODIMP |
michael@0 | 135 | nsDataDocumentContentPolicy::ShouldProcess(uint32_t aContentType, |
michael@0 | 136 | nsIURI *aContentLocation, |
michael@0 | 137 | nsIURI *aRequestingLocation, |
michael@0 | 138 | nsISupports *aRequestingContext, |
michael@0 | 139 | const nsACString &aMimeGuess, |
michael@0 | 140 | nsISupports *aExtra, |
michael@0 | 141 | nsIPrincipal *aRequestPrincipal, |
michael@0 | 142 | int16_t *aDecision) |
michael@0 | 143 | { |
michael@0 | 144 | return ShouldLoad(aContentType, aContentLocation, aRequestingLocation, |
michael@0 | 145 | aRequestingContext, aMimeGuess, aExtra, aRequestPrincipal, |
michael@0 | 146 | aDecision); |
michael@0 | 147 | } |