Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 sw=2 et 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 : #include "mozilla/BasePrincipal.h"
8 :
9 : #include "nsDocShell.h"
10 : #ifdef MOZ_CRASHREPORTER
11 : #include "nsExceptionHandler.h"
12 : #endif
13 : #include "nsIAddonPolicyService.h"
14 : #include "nsIContentSecurityPolicy.h"
15 : #include "nsIObjectInputStream.h"
16 : #include "nsIObjectOutputStream.h"
17 : #include "nsIStandardURL.h"
18 :
19 : #include "ContentPrincipal.h"
20 : #include "nsNetUtil.h"
21 : #include "nsIURIWithPrincipal.h"
22 : #include "NullPrincipal.h"
23 : #include "nsScriptSecurityManager.h"
24 : #include "nsServiceManagerUtils.h"
25 :
26 : #include "mozilla/dom/ChromeUtils.h"
27 : #include "mozilla/dom/CSPDictionariesBinding.h"
28 : #include "mozilla/dom/ToJSValue.h"
29 :
30 : namespace mozilla {
31 :
32 343 : BasePrincipal::BasePrincipal(PrincipalKind aKind)
33 : : mKind(aKind)
34 : , mHasExplicitDomain(false)
35 343 : , mInitialized(false)
36 343 : {}
37 :
38 177 : BasePrincipal::~BasePrincipal()
39 177 : {}
40 :
41 : NS_IMETHODIMP
42 29 : BasePrincipal::GetOrigin(nsACString& aOrigin)
43 : {
44 29 : MOZ_ASSERT(mInitialized);
45 :
46 29 : nsresult rv = GetOriginNoSuffix(aOrigin);
47 29 : NS_ENSURE_SUCCESS(rv, rv);
48 :
49 58 : nsAutoCString suffix;
50 29 : rv = GetOriginSuffix(suffix);
51 29 : NS_ENSURE_SUCCESS(rv, rv);
52 29 : aOrigin.Append(suffix);
53 29 : return NS_OK;
54 : }
55 :
56 : NS_IMETHODIMP
57 84 : BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin)
58 : {
59 84 : MOZ_ASSERT(mInitialized);
60 84 : return mOriginNoSuffix->ToUTF8String(aOrigin);
61 : }
62 :
63 : bool
64 2513 : BasePrincipal::Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration)
65 : {
66 2513 : MOZ_ASSERT(aOther);
67 2513 : MOZ_ASSERT_IF(Kind() == eCodebasePrincipal, mOriginSuffix);
68 :
69 : // Expanded principals handle origin attributes for each of their
70 : // sub-principals individually, null principals do only simple checks for
71 : // pointer equality, and system principals are immune to origin attributes
72 : // checks, so only do this check for codebase principals.
73 2597 : if (Kind() == eCodebasePrincipal &&
74 84 : mOriginSuffix != Cast(aOther)->mOriginSuffix) {
75 0 : return false;
76 : }
77 :
78 2513 : return SubsumesInternal(aOther, aConsideration);
79 : }
80 :
81 : NS_IMETHODIMP
82 85 : BasePrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
83 : {
84 85 : NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
85 :
86 85 : *aResult = FastEquals(aOther);
87 :
88 85 : return NS_OK;
89 : }
90 :
91 : NS_IMETHODIMP
92 0 : BasePrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult)
93 : {
94 0 : NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
95 :
96 0 : *aResult = FastEqualsConsideringDomain(aOther);
97 :
98 0 : return NS_OK;
99 : }
100 :
101 : NS_IMETHODIMP
102 112 : BasePrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
103 : {
104 112 : NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
105 :
106 112 : *aResult = FastSubsumes(aOther);
107 :
108 112 : return NS_OK;
109 : }
110 :
111 : NS_IMETHODIMP
112 636 : BasePrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult)
113 : {
114 636 : NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
115 :
116 636 : *aResult = FastSubsumesConsideringDomain(aOther);
117 :
118 636 : return NS_OK;
119 : }
120 :
121 : NS_IMETHODIMP
122 0 : BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal *aOther,
123 : bool *aResult)
124 : {
125 0 : NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
126 :
127 0 : *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
128 :
129 0 : return NS_OK;
130 : }
131 :
132 : NS_IMETHODIMP
133 48 : BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
134 : {
135 : // Check the internal method first, which allows us to quickly approve loads
136 : // for the System Principal.
137 48 : if (MayLoadInternal(aURI)) {
138 46 : return NS_OK;
139 : }
140 :
141 : nsresult rv;
142 2 : if (aAllowIfInheritsPrincipal) {
143 : // If the caller specified to allow loads of URIs that inherit
144 : // our principal, allow the load if this URI inherits its principal.
145 : bool doesInheritSecurityContext;
146 : rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
147 0 : &doesInheritSecurityContext);
148 0 : if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
149 0 : return NS_OK;
150 : }
151 : }
152 :
153 : bool fetchableByAnyone;
154 2 : rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE, &fetchableByAnyone);
155 2 : if (NS_SUCCEEDED(rv) && fetchableByAnyone) {
156 0 : return NS_OK;
157 : }
158 :
159 2 : if (aReport) {
160 0 : nsCOMPtr<nsIURI> prinURI;
161 0 : rv = GetURI(getter_AddRefs(prinURI));
162 0 : if (NS_SUCCEEDED(rv) && prinURI) {
163 0 : nsScriptSecurityManager::ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), prinURI, aURI);
164 : }
165 : }
166 :
167 2 : return NS_ERROR_DOM_BAD_URI;
168 : }
169 :
170 : NS_IMETHODIMP
171 42 : BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
172 : {
173 42 : NS_IF_ADDREF(*aCsp = mCSP);
174 42 : return NS_OK;
175 : }
176 :
177 : NS_IMETHODIMP
178 0 : BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
179 : {
180 : // Never destroy an existing CSP on the principal.
181 : // This method should only be called in rare cases.
182 :
183 0 : MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
184 0 : if (mCSP) {
185 0 : return NS_ERROR_ALREADY_INITIALIZED;
186 : }
187 :
188 0 : mCSP = aCsp;
189 0 : return NS_OK;
190 : }
191 :
192 : NS_IMETHODIMP
193 0 : BasePrincipal::EnsureCSP(nsIDOMDocument* aDocument,
194 : nsIContentSecurityPolicy** aCSP)
195 : {
196 0 : if (mCSP) {
197 : // if there is a CSP already associated with this principal
198 : // then just return that - do not overwrite it!!!
199 0 : NS_IF_ADDREF(*aCSP = mCSP);
200 0 : return NS_OK;
201 : }
202 :
203 0 : nsresult rv = NS_OK;
204 0 : mCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
205 0 : NS_ENSURE_SUCCESS(rv, rv);
206 :
207 : // Store the request context for violation reports
208 0 : rv = aDocument ? mCSP->SetRequestContext(aDocument, nullptr)
209 0 : : mCSP->SetRequestContext(nullptr, this);
210 0 : NS_ENSURE_SUCCESS(rv, rv);
211 0 : NS_IF_ADDREF(*aCSP = mCSP);
212 0 : return NS_OK;
213 : }
214 :
215 : NS_IMETHODIMP
216 6 : BasePrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
217 : {
218 6 : NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
219 6 : return NS_OK;
220 : }
221 :
222 : NS_IMETHODIMP
223 0 : BasePrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument,
224 : nsIContentSecurityPolicy** aPreloadCSP)
225 : {
226 0 : if (mPreloadCSP) {
227 : // if there is a speculative CSP already associated with this principal
228 : // then just return that - do not overwrite it!!!
229 0 : NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
230 0 : return NS_OK;
231 : }
232 :
233 0 : nsresult rv = NS_OK;
234 0 : mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
235 0 : NS_ENSURE_SUCCESS(rv, rv);
236 :
237 : // Store the request context for violation reports
238 0 : rv = aDocument ? mPreloadCSP->SetRequestContext(aDocument, nullptr)
239 0 : : mPreloadCSP->SetRequestContext(nullptr, this);
240 0 : NS_ENSURE_SUCCESS(rv, rv);
241 0 : NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
242 0 : return NS_OK;
243 : }
244 :
245 : NS_IMETHODIMP
246 0 : BasePrincipal::GetCspJSON(nsAString& outCSPinJSON)
247 : {
248 0 : outCSPinJSON.Truncate();
249 0 : dom::CSPPolicies jsonPolicies;
250 :
251 0 : if (!mCSP) {
252 0 : jsonPolicies.ToJSON(outCSPinJSON);
253 0 : return NS_OK;
254 : }
255 0 : return mCSP->ToJSON(outCSPinJSON);
256 : }
257 :
258 : NS_IMETHODIMP
259 139 : BasePrincipal::GetIsNullPrincipal(bool* aResult)
260 : {
261 139 : *aResult = Kind() == eNullPrincipal;
262 139 : return NS_OK;
263 : }
264 :
265 : NS_IMETHODIMP
266 8 : BasePrincipal::GetIsCodebasePrincipal(bool* aResult)
267 : {
268 8 : *aResult = Kind() == eCodebasePrincipal;
269 8 : return NS_OK;
270 : }
271 :
272 : NS_IMETHODIMP
273 0 : BasePrincipal::GetIsExpandedPrincipal(bool* aResult)
274 : {
275 0 : *aResult = Kind() == eExpandedPrincipal;
276 0 : return NS_OK;
277 : }
278 :
279 : NS_IMETHODIMP
280 116 : BasePrincipal::GetIsSystemPrincipal(bool* aResult)
281 : {
282 116 : *aResult = Kind() == eSystemPrincipal;
283 116 : return NS_OK;
284 : }
285 :
286 : NS_IMETHODIMP
287 0 : BasePrincipal::GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal)
288 : {
289 0 : if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
290 0 : return NS_ERROR_FAILURE;
291 : }
292 0 : return NS_OK;
293 : }
294 :
295 : NS_IMETHODIMP
296 59 : BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes)
297 : {
298 59 : MOZ_ASSERT(mOriginSuffix);
299 59 : return mOriginSuffix->ToUTF8String(aOriginAttributes);
300 : }
301 :
302 : NS_IMETHODIMP
303 25 : BasePrincipal::GetAppId(uint32_t* aAppId)
304 : {
305 25 : if (AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
306 0 : MOZ_ASSERT(false);
307 : *aAppId = nsIScriptSecurityManager::NO_APP_ID;
308 : return NS_OK;
309 : }
310 :
311 25 : *aAppId = AppId();
312 25 : return NS_OK;
313 : }
314 :
315 : NS_IMETHODIMP
316 0 : BasePrincipal::GetUserContextId(uint32_t* aUserContextId)
317 : {
318 0 : *aUserContextId = UserContextId();
319 0 : return NS_OK;
320 : }
321 :
322 : NS_IMETHODIMP
323 4 : BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId)
324 : {
325 4 : *aPrivateBrowsingId = PrivateBrowsingId();
326 4 : return NS_OK;
327 : }
328 :
329 : NS_IMETHODIMP
330 23 : BasePrincipal::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
331 : {
332 23 : *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
333 23 : return NS_OK;
334 : }
335 :
336 : bool
337 0 : BasePrincipal::AddonHasPermission(const nsAString& aPerm)
338 : {
339 0 : nsAutoString addonId;
340 0 : NS_ENSURE_SUCCESS(GetAddonId(addonId), false);
341 :
342 0 : if (addonId.IsEmpty()) {
343 0 : return false;
344 : }
345 :
346 : nsCOMPtr<nsIAddonPolicyService> aps =
347 0 : do_GetService("@mozilla.org/addons/policy-service;1");
348 0 : NS_ENSURE_TRUE(aps, false);
349 :
350 0 : bool retval = false;
351 0 : nsresult rv = aps->AddonHasPermission(addonId, aPerm, &retval);
352 0 : NS_ENSURE_SUCCESS(rv, false);
353 0 : return retval;
354 : }
355 :
356 : already_AddRefed<BasePrincipal>
357 205 : BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI,
358 : const OriginAttributes& aAttrs)
359 : {
360 205 : MOZ_ASSERT(aURI);
361 :
362 410 : nsAutoCString originNoSuffix;
363 : nsresult rv =
364 205 : ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
365 205 : if (NS_FAILED(rv)) {
366 : // If the generation of the origin fails, we still want to have a valid
367 : // principal. Better to return a null principal here.
368 7 : return NullPrincipal::Create(aAttrs);
369 : }
370 :
371 198 : return CreateCodebasePrincipal(aURI, aAttrs, originNoSuffix);
372 : }
373 :
374 : already_AddRefed<BasePrincipal>
375 198 : BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI,
376 : const OriginAttributes& aAttrs,
377 : const nsACString& aOriginNoSuffix)
378 : {
379 198 : MOZ_ASSERT(aURI);
380 198 : MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
381 :
382 : // If the URI is supposed to inherit the security context of whoever loads it,
383 : // we shouldn't make a codebase principal for it.
384 : bool inheritsPrincipal;
385 : nsresult rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
386 198 : &inheritsPrincipal);
387 198 : if (NS_FAILED(rv) || inheritsPrincipal) {
388 0 : return NullPrincipal::Create(aAttrs);
389 : }
390 :
391 : // Check whether the URI knows what its principal is supposed to be.
392 396 : nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
393 198 : if (uriPrinc) {
394 0 : nsCOMPtr<nsIPrincipal> principal;
395 0 : uriPrinc->GetPrincipal(getter_AddRefs(principal));
396 0 : if (!principal) {
397 0 : return NullPrincipal::Create(aAttrs);
398 : }
399 0 : RefPtr<BasePrincipal> concrete = Cast(principal);
400 0 : return concrete.forget();
401 : }
402 :
403 : // Mint a codebase principal.
404 396 : RefPtr<ContentPrincipal> codebase = new ContentPrincipal();
405 198 : rv = codebase->Init(aURI, aAttrs, aOriginNoSuffix);
406 198 : NS_ENSURE_SUCCESS(rv, nullptr);
407 198 : return codebase.forget();
408 : }
409 :
410 : already_AddRefed<BasePrincipal>
411 0 : BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin)
412 : {
413 0 : MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")),
414 : "CreateCodebasePrincipal does not support System and Expanded principals");
415 :
416 0 : MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")),
417 : "CreateCodebasePrincipal does not support NullPrincipal");
418 :
419 0 : nsAutoCString originNoSuffix;
420 0 : mozilla::OriginAttributes attrs;
421 0 : if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
422 0 : return nullptr;
423 : }
424 :
425 0 : nsCOMPtr<nsIURI> uri;
426 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
427 0 : NS_ENSURE_SUCCESS(rv, nullptr);
428 :
429 0 : return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
430 : }
431 :
432 : already_AddRefed<BasePrincipal>
433 14 : BasePrincipal::CloneStrippingUserContextIdAndFirstPartyDomain()
434 : {
435 28 : OriginAttributes attrs = OriginAttributesRef();
436 : attrs.StripAttributes(OriginAttributes::STRIP_USER_CONTEXT_ID |
437 14 : OriginAttributes::STRIP_FIRST_PARTY_DOMAIN);
438 :
439 28 : nsAutoCString originNoSuffix;
440 14 : nsresult rv = GetOriginNoSuffix(originNoSuffix);
441 14 : NS_ENSURE_SUCCESS(rv, nullptr);
442 :
443 28 : nsCOMPtr<nsIURI> uri;
444 14 : rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
445 14 : NS_ENSURE_SUCCESS(rv, nullptr);
446 :
447 14 : return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
448 : }
449 :
450 : bool
451 5 : BasePrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */)
452 : {
453 10 : nsAutoString addonId;
454 5 : NS_ENSURE_SUCCESS(GetAddonId(addonId), false);
455 :
456 5 : if (addonId.IsEmpty()) {
457 5 : return false;
458 : }
459 :
460 0 : nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1");
461 0 : NS_ENSURE_TRUE(aps, false);
462 :
463 0 : bool allowed = false;
464 0 : nsresult rv = aps->AddonMayLoadURI(addonId, aURI, aExplicit, &allowed);
465 0 : return NS_SUCCEEDED(rv) && allowed;
466 : }
467 :
468 : void
469 343 : BasePrincipal::FinishInit(const nsACString& aOriginNoSuffix,
470 : const OriginAttributes& aOriginAttributes)
471 : {
472 343 : mInitialized = true;
473 343 : mOriginAttributes = aOriginAttributes;
474 :
475 : // First compute the origin suffix since it's infallible.
476 686 : nsAutoCString originSuffix;
477 343 : mOriginAttributes.CreateSuffix(originSuffix);
478 343 : mOriginSuffix = NS_Atomize(originSuffix);
479 :
480 343 : MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
481 343 : mOriginNoSuffix = NS_Atomize(aOriginNoSuffix);
482 343 : }
483 :
484 : } // namespace mozilla
|