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