Coverage Report

Created: 2018-09-25 14:53

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