Line data Source code
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 24 : 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 0 : HasFlags(nsIURI* aURI, uint32_t aURIFlags)
30 : {
31 : bool hasFlags;
32 0 : nsresult rv = NS_URIChainHasFlags(aURI, aURIFlags, &hasFlags);
33 0 : return NS_SUCCEEDED(rv) && hasFlags;
34 : }
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 23 : nsDataDocumentContentPolicy::ShouldLoad(uint32_t aContentType,
41 : nsIURI *aContentLocation,
42 : nsIURI *aRequestingLocation,
43 : nsISupports *aRequestingContext,
44 : const nsACString &aMimeGuess,
45 : nsISupports *aExtra,
46 : nsIPrincipal *aRequestPrincipal,
47 : int16_t *aDecision)
48 : {
49 23 : MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
50 : "We should only see external content policy types here.");
51 :
52 23 : *aDecision = nsIContentPolicy::ACCEPT;
53 : // Look for the document. In most cases, aRequestingContext is a node.
54 46 : nsCOMPtr<nsIDocument> doc;
55 46 : nsCOMPtr<nsINode> node = do_QueryInterface(aRequestingContext);
56 23 : if (node) {
57 13 : doc = node->OwnerDoc();
58 : } else {
59 20 : if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(aRequestingContext)) {
60 2 : doc = window->GetDoc();
61 : }
62 : }
63 :
64 : // DTDs are always OK to load
65 23 : if (!doc || aContentType == nsIContentPolicy::TYPE_DTD) {
66 8 : return NS_OK;
67 : }
68 :
69 : // Nothing else is OK to load for data documents
70 15 : if (doc->IsLoadedAsData()) {
71 : // ...but let static (print/print preview) documents to load fonts.
72 0 : if (!doc->IsStaticDocument() || aContentType != nsIContentPolicy::TYPE_FONT) {
73 0 : *aDecision = nsIContentPolicy::REJECT_TYPE;
74 0 : return NS_OK;
75 : }
76 : }
77 :
78 15 : nsIDocument* docToCheckForImage = doc->GetDisplayDocument();
79 15 : if (!docToCheckForImage) {
80 15 : docToCheckForImage = doc;
81 : }
82 :
83 15 : if (docToCheckForImage->IsBeingUsedAsImage()) {
84 : // We only allow SVG images to load content from URIs that are local and
85 : // also satisfy one of the following conditions:
86 : // - URI inherits security context, e.g. data URIs
87 : // OR
88 : // - URI loadable by subsumers, e.g. blob URIs
89 : // Any URI that doesn't meet these requirements will be rejected below.
90 0 : if (!(HasFlags(aContentLocation,
91 : nsIProtocolHandler::URI_IS_LOCAL_RESOURCE) &&
92 0 : (HasFlags(aContentLocation,
93 0 : nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT) ||
94 0 : HasFlags(aContentLocation,
95 : nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS)))) {
96 0 : *aDecision = nsIContentPolicy::REJECT_TYPE;
97 :
98 : // Report error, if we can.
99 0 : if (node) {
100 0 : nsIPrincipal* requestingPrincipal = node->NodePrincipal();
101 0 : RefPtr<nsIURI> principalURI;
102 : nsresult rv =
103 0 : requestingPrincipal->GetURI(getter_AddRefs(principalURI));
104 0 : if (NS_SUCCEEDED(rv) && principalURI) {
105 0 : nsScriptSecurityManager::ReportError(
106 0 : nullptr, NS_LITERAL_STRING("ExternalDataError"), principalURI,
107 0 : aContentLocation);
108 : }
109 : }
110 0 : } else if ((aContentType == nsIContentPolicy::TYPE_IMAGE ||
111 0 : aContentType == nsIContentPolicy::TYPE_IMAGESET) &&
112 0 : doc->GetDocumentURI()) {
113 : // Check for (& disallow) recursive image-loads
114 : bool isRecursiveLoad;
115 0 : nsresult rv = aContentLocation->EqualsExceptRef(doc->GetDocumentURI(),
116 0 : &isRecursiveLoad);
117 0 : if (NS_FAILED(rv) || isRecursiveLoad) {
118 0 : NS_WARNING("Refusing to recursively load image");
119 0 : *aDecision = nsIContentPolicy::REJECT_TYPE;
120 : }
121 : }
122 0 : return NS_OK;
123 : }
124 :
125 : // Allow all loads for non-resource documents
126 15 : if (!doc->IsResourceDoc()) {
127 15 : return NS_OK;
128 : }
129 :
130 : // For resource documents, blacklist some load types
131 0 : if (aContentType == nsIContentPolicy::TYPE_OBJECT ||
132 0 : aContentType == nsIContentPolicy::TYPE_DOCUMENT ||
133 0 : aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
134 0 : aContentType == nsIContentPolicy::TYPE_SCRIPT ||
135 0 : aContentType == nsIContentPolicy::TYPE_XSLT ||
136 0 : aContentType == nsIContentPolicy::TYPE_FETCH ||
137 : aContentType == nsIContentPolicy::TYPE_WEB_MANIFEST) {
138 0 : *aDecision = nsIContentPolicy::REJECT_TYPE;
139 : }
140 :
141 : // If you add more restrictions here, make sure to check that
142 : // CHECK_PRINCIPAL_AND_DATA in nsContentPolicyUtils is still valid.
143 : // nsContentPolicyUtils may not pass all the parameters to ShouldLoad
144 :
145 0 : return NS_OK;
146 : }
147 :
148 : NS_IMETHODIMP
149 0 : nsDataDocumentContentPolicy::ShouldProcess(uint32_t aContentType,
150 : nsIURI *aContentLocation,
151 : nsIURI *aRequestingLocation,
152 : nsISupports *aRequestingContext,
153 : const nsACString &aMimeGuess,
154 : nsISupports *aExtra,
155 : nsIPrincipal *aRequestPrincipal,
156 : int16_t *aDecision)
157 : {
158 : return ShouldLoad(aContentType, aContentLocation, aRequestingLocation,
159 : aRequestingContext, aMimeGuess, aExtra, aRequestPrincipal,
160 0 : aDecision);
161 : }
|