Source code

Revision control

Other Tools

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
11
#include "ExpandedPrincipal.h"
12
#include "nsNetUtil.h"
13
#include "nsContentUtils.h"
14
#include "nsIOService.h"
15
#include "nsIURIWithSpecialOrigin.h"
16
#include "nsScriptSecurityManager.h"
17
#include "nsServiceManagerUtils.h"
18
#include "nsAboutProtocolUtils.h"
19
#include "ThirdPartyUtil.h"
20
#include "mozilla/ContentPrincipal.h"
21
#include "mozilla/NullPrincipal.h"
22
#include "mozilla/dom/BlobURLProtocolHandler.h"
23
#include "mozilla/dom/ChromeUtils.h"
24
#include "mozilla/dom/ToJSValue.h"
25
#include "mozilla/dom/nsMixedContentBlocker.h"
26
#include "mozilla/Components.h"
27
#include "mozilla/dom/StorageUtils.h"
28
#include "mozilla/dom/StorageUtils.h"
29
#include "nsIURL.h"
30
#include "prnetdb.h"
31
32
#include "json/json.h"
33
#include "nsSerializationHelper.h"
34
35
namespace mozilla {
36
37
BasePrincipal::BasePrincipal(PrincipalKind aKind)
38
: mKind(aKind), mHasExplicitDomain(false), mInitialized(false) {}
39
40
BasePrincipal::~BasePrincipal() {}
41
42
NS_IMETHODIMP
43
BasePrincipal::GetOrigin(nsACString& aOrigin) {
44
MOZ_ASSERT(mInitialized);
45
46
nsresult rv = GetOriginNoSuffix(aOrigin);
47
NS_ENSURE_SUCCESS(rv, rv);
48
49
nsAutoCString suffix;
50
rv = GetOriginSuffix(suffix);
51
NS_ENSURE_SUCCESS(rv, rv);
52
aOrigin.Append(suffix);
53
return NS_OK;
54
}
55
56
NS_IMETHODIMP
57
BasePrincipal::GetAsciiOrigin(nsACString& aOrigin) {
58
aOrigin.Truncate();
59
nsCOMPtr<nsIURI> prinURI;
60
nsresult rv = GetURI(getter_AddRefs(prinURI));
61
if (NS_FAILED(rv) || !prinURI) {
62
return NS_ERROR_NOT_AVAILABLE;
63
}
64
return nsContentUtils::GetASCIIOrigin(prinURI, aOrigin);
65
}
66
67
NS_IMETHODIMP
68
BasePrincipal::GetHostPort(nsACString& aRes) {
69
aRes.Truncate();
70
nsCOMPtr<nsIURI> prinURI;
71
nsresult rv = GetURI(getter_AddRefs(prinURI));
72
if (NS_FAILED(rv) || !prinURI) {
73
return NS_OK;
74
}
75
return prinURI->GetHostPort(aRes);
76
}
77
78
NS_IMETHODIMP
79
BasePrincipal::GetHost(nsACString& aRes) {
80
aRes.Truncate();
81
nsCOMPtr<nsIURI> prinURI;
82
nsresult rv = GetURI(getter_AddRefs(prinURI));
83
if (NS_FAILED(rv) || !prinURI) {
84
return NS_OK;
85
}
86
return prinURI->GetHost(aRes);
87
}
88
89
NS_IMETHODIMP
90
BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) {
91
MOZ_ASSERT(mInitialized);
92
mOriginNoSuffix->ToUTF8String(aOrigin);
93
return NS_OK;
94
}
95
96
NS_IMETHODIMP
97
BasePrincipal::GetSiteOrigin(nsACString& aSiteOrigin) {
98
MOZ_ASSERT(mInitialized);
99
return GetOrigin(aSiteOrigin);
100
}
101
102
// Returns the inner Json::value of the serialized principal
103
// Example input and return values:
104
// Null principal:
105
// {"0":{"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}} ->
106
// {"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}
107
//
108
// Content principal:
109
// {"1":{"0":"https://mozilla.com"}} -> {"0":"https://mozilla.com"}
110
//
111
// Expanded principal:
112
// {"2":{"0":"<base64principal1>,<base64principal2>"}} ->
113
// {"0":"<base64principal1>,<base64principal2>"}
114
//
115
// System principal:
116
// {"3":{}} -> {}
117
// The aKey passed in also returns the corresponding PrincipalKind enum
118
//
119
// Warning: The Json::Value* pointer is into the aRoot object
120
static const Json::Value* GetPrincipalObject(const Json::Value& aRoot,
121
int& aOutPrincipalKind) {
122
const Json::Value::Members members = aRoot.getMemberNames();
123
// We only support one top level key in the object
124
if (members.size() != 1) {
125
return nullptr;
126
}
127
// members[0] here is the "0", "1", "2", "3" principalKind
128
// that is the top level of the serialized JSON principal
129
const std::string stringPrincipalKind = members[0];
130
131
// Next we take the string value from the JSON
132
// and convert it into the int for the BasePrincipal::PrincipalKind enum
133
134
// Verify that the key is within the valid range
135
int principalKind = std::stoi(stringPrincipalKind);
136
MOZ_ASSERT(BasePrincipal::eNullPrincipal == 0,
137
"We need to rely on 0 being a bounds check for the first "
138
"principal kind.");
139
if (principalKind < 0 || principalKind > BasePrincipal::eKindMax) {
140
return nullptr;
141
}
142
MOZ_ASSERT(principalKind == BasePrincipal::eNullPrincipal ||
143
principalKind == BasePrincipal::eContentPrincipal ||
144
principalKind == BasePrincipal::eExpandedPrincipal ||
145
principalKind == BasePrincipal::eSystemPrincipal);
146
aOutPrincipalKind = principalKind;
147
148
if (!aRoot[stringPrincipalKind].isObject()) {
149
return nullptr;
150
}
151
152
// Return the inner value of the principal object
153
return &aRoot[stringPrincipalKind];
154
}
155
156
// Accepts the JSON inner object without the wrapping principalKind
157
// (See GetPrincipalObject for the inner object response examples)
158
// Creates an array of KeyVal objects that are all defined on the principal
159
// Each principal type (null, content, expanded) has a KeyVal that stores the
160
// fields of the JSON
161
//
162
// This simplifies deserializing elsewhere as we do the checking for presence
163
// and string values here for the complete set of serializable keys that the
164
// corresponding principal supports.
165
//
166
// The KeyVal object has the following fields:
167
// - valueWasSerialized: is true if the deserialized JSON contained a string
168
// value
169
// - value: The string that was serialized for this key
170
// - key: an SerializableKeys enum value specific to the principal.
171
// For example content principal is an enum of: eURI, eDomain,
172
// eSuffix, eCSP
173
//
174
//
175
// Given an inner content principal:
176
// {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}
177
// | | | |
178
// ----------------------------- |
179
// | | |
180
// Key ----------------------
181
// |
182
// Value
183
//
184
// They Key "0" corresponds to ContentPrincipal::eURI
185
// They Key "1" corresponds to ContentPrincipal::eSuffix
186
template <typename T>
187
static nsTArray<typename T::KeyVal> GetJSONKeys(const Json::Value* aInput) {
188
int size = T::eMax + 1;
189
nsTArray<typename T::KeyVal> fields;
190
for (int i = 0; i != size; i++) {
191
typename T::KeyVal* field = fields.AppendElement();
192
// field->valueWasSerialized returns if the field was found in the
193
// deserialized code. This simplifies the consumers from having to check
194
// length.
195
field->valueWasSerialized = false;
196
field->key = static_cast<typename T::SerializableKeys>(i);
197
const std::string key = std::to_string(field->key);
198
if (aInput->isMember(key)) {
199
const Json::Value& val = (*aInput)[key];
200
if (val.isString()) {
201
field->value.Append(nsDependentCString(val.asCString()));
202
field->valueWasSerialized = true;
203
}
204
}
205
}
206
return fields;
207
}
208
209
// Takes a JSON string and parses it turning it into a principal of the
210
// corresponding type
211
//
212
// Given a content principal:
213
//
214
// inner JSON object
215
// |
216
// ---------------------------------------------------------
217
// | |
218
// {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}}
219
// | | | | |
220
// | ----------------------------- |
221
// | | | |
222
// PrincipalKind | | |
223
// | ----------------------------
224
// SerializableKeys |
225
// Value
226
//
227
// The string is first deserialized with jsoncpp to get the Json::Value of the
228
// object. The inner JSON object is parsed with GetPrincipalObject which returns
229
// a KeyVal array of the inner object's fields. PrincipalKind is returned by
230
// GetPrincipalObject which is then used to decide which principal
231
// implementation of FromProperties to call. The corresponding FromProperties
232
// call takes the KeyVal fields and turns it into a principal.
233
already_AddRefed<BasePrincipal> BasePrincipal::FromJSON(
234
const nsACString& aJSON) {
235
Json::Value root;
236
Json::CharReaderBuilder builder;
237
std::unique_ptr<Json::CharReader> const reader(builder.newCharReader());
238
bool parseSuccess =
239
reader->parse(aJSON.BeginReading(), aJSON.EndReading(), &root, nullptr);
240
if (!parseSuccess) {
241
MOZ_ASSERT(false,
242
"Unable to parse string as JSON to deserialize as a principal");
243
return nullptr;
244
}
245
246
int principalKind = -1;
247
const Json::Value* value = GetPrincipalObject(root, principalKind);
248
if (!value) {
249
#ifdef DEBUG
250
fprintf(stderr, "Unexpected JSON principal %s\n",
251
root.toStyledString().c_str());
252
#endif
253
MOZ_ASSERT(false, "Unexpected JSON to deserialize as a principal");
254
255
return nullptr;
256
}
257
MOZ_ASSERT(principalKind != -1,
258
"PrincipalKind should always be >=0 by this point");
259
260
if (principalKind == eSystemPrincipal) {
261
RefPtr<BasePrincipal> principal =
262
BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal());
263
return principal.forget();
264
}
265
266
if (principalKind == eNullPrincipal) {
267
nsTArray<NullPrincipal::KeyVal> res = GetJSONKeys<NullPrincipal>(value);
268
return NullPrincipal::FromProperties(res);
269
}
270
271
if (principalKind == eContentPrincipal) {
272
nsTArray<ContentPrincipal::KeyVal> res =
273
GetJSONKeys<ContentPrincipal>(value);
274
return ContentPrincipal::FromProperties(res);
275
}
276
277
if (principalKind == eExpandedPrincipal) {
278
nsTArray<ExpandedPrincipal::KeyVal> res =
279
GetJSONKeys<ExpandedPrincipal>(value);
280
return ExpandedPrincipal::FromProperties(res);
281
}
282
283
MOZ_RELEASE_ASSERT(false, "Unexpected enum to deserialize as a principal");
284
}
285
286
nsresult BasePrincipal::PopulateJSONObject(Json::Value& aObject) {
287
return NS_OK;
288
}
289
290
// Returns a JSON representation of the principal.
291
// Calling BasePrincipal::FromJSON will deserialize the JSON into
292
// the corresponding principal type.
293
nsresult BasePrincipal::ToJSON(nsACString& aResult) {
294
MOZ_ASSERT(aResult.IsEmpty(), "ToJSON only supports an empty result input");
295
aResult.Truncate();
296
297
Json::StreamWriterBuilder builder;
298
builder["indentation"] = "";
299
Json::Value innerJSONObject = Json::objectValue;
300
301
nsresult rv = PopulateJSONObject(innerJSONObject);
302
NS_ENSURE_SUCCESS(rv, rv);
303
304
Json::Value root = Json::objectValue;
305
std::string key = std::to_string(Kind());
306
root[key] = innerJSONObject;
307
std::string result = Json::writeString(builder, root);
308
aResult.Append(result);
309
if (aResult.Length() == 0) {
310
MOZ_ASSERT(false, "JSON writer failed to output a principal serialization");
311
return NS_ERROR_UNEXPECTED;
312
}
313
return NS_OK;
314
}
315
316
bool BasePrincipal::Subsumes(nsIPrincipal* aOther,
317
DocumentDomainConsideration aConsideration) {
318
MOZ_ASSERT(aOther);
319
MOZ_ASSERT_IF(Kind() == eContentPrincipal, mOriginSuffix);
320
321
// Expanded principals handle origin attributes for each of their
322
// sub-principals individually, null principals do only simple checks for
323
// pointer equality, and system principals are immune to origin attributes
324
// checks, so only do this check for content principals.
325
if (Kind() == eContentPrincipal &&
326
mOriginSuffix != Cast(aOther)->mOriginSuffix) {
327
return false;
328
}
329
330
return SubsumesInternal(aOther, aConsideration);
331
}
332
333
NS_IMETHODIMP
334
BasePrincipal::Equals(nsIPrincipal* aOther, bool* aResult) {
335
NS_ENSURE_ARG_POINTER(aOther);
336
337
*aResult = FastEquals(aOther);
338
339
return NS_OK;
340
}
341
342
NS_IMETHODIMP
343
BasePrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
344
NS_ENSURE_ARG_POINTER(aOther);
345
346
*aResult = FastEqualsConsideringDomain(aOther);
347
348
return NS_OK;
349
}
350
351
NS_IMETHODIMP
352
BasePrincipal::EqualsURI(nsIURI* aOtherURI, bool* aResult) {
353
*aResult = false;
354
nsCOMPtr<nsIURI> prinURI;
355
nsresult rv = GetURI(getter_AddRefs(prinURI));
356
if (NS_FAILED(rv) || !prinURI) {
357
return NS_OK;
358
}
359
return prinURI->EqualsExceptRef(aOtherURI, aResult);
360
}
361
362
NS_IMETHODIMP
363
BasePrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) {
364
NS_ENSURE_ARG_POINTER(aOther);
365
366
*aResult = FastSubsumes(aOther);
367
368
return NS_OK;
369
}
370
371
NS_IMETHODIMP
372
BasePrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
373
NS_ENSURE_ARG_POINTER(aOther);
374
375
*aResult = FastSubsumesConsideringDomain(aOther);
376
377
return NS_OK;
378
}
379
380
NS_IMETHODIMP
381
BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther,
382
bool* aResult) {
383
NS_ENSURE_ARG_POINTER(aOther);
384
385
*aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
386
387
return NS_OK;
388
}
389
390
NS_IMETHODIMP
391
BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aAllowIfInheritsPrincipal) {
392
return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, false, 0);
393
}
394
395
NS_IMETHODIMP
396
BasePrincipal::CheckMayLoadWithReporting(nsIURI* aURI,
397
bool aAllowIfInheritsPrincipal,
398
uint64_t aInnerWindowID) {
399
return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, true,
400
aInnerWindowID);
401
}
402
403
nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
404
bool aAllowIfInheritsPrincipal,
405
bool aReport,
406
uint64_t aInnerWindowID) {
407
NS_ENSURE_ARG_POINTER(aURI);
408
MOZ_ASSERT(
409
aReport || aInnerWindowID == 0,
410
"Why do we have an inner window id if we're not supposed to report?");
411
412
// Check the internal method first, which allows us to quickly approve loads
413
// for the System Principal.
414
if (MayLoadInternal(aURI)) {
415
return NS_OK;
416
}
417
418
nsresult rv;
419
if (aAllowIfInheritsPrincipal) {
420
// If the caller specified to allow loads of URIs that inherit
421
// our principal, allow the load if this URI inherits its principal.
422
bool doesInheritSecurityContext;
423
rv = NS_URIChainHasFlags(aURI,
424
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
425
&doesInheritSecurityContext);
426
if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
427
return NS_OK;
428
}
429
}
430
431
bool fetchableByAnyone;
432
rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE,
433
&fetchableByAnyone);
434
if (NS_SUCCEEDED(rv) && fetchableByAnyone) {
435
return NS_OK;
436
}
437
438
if (aReport) {
439
nsCOMPtr<nsIURI> prinURI;
440
rv = GetURI(getter_AddRefs(prinURI));
441
if (NS_SUCCEEDED(rv) && prinURI) {
442
nsScriptSecurityManager::ReportError(
443
"CheckSameOriginError", prinURI, aURI,
444
mOriginAttributes.mPrivateBrowsingId > 0, aInnerWindowID);
445
}
446
}
447
448
return NS_ERROR_DOM_BAD_URI;
449
}
450
451
NS_IMETHODIMP
452
BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) {
453
*aRes = true;
454
// If we do not have a URI its always 3rd party.
455
nsCOMPtr<nsIURI> prinURI;
456
nsresult rv = GetURI(getter_AddRefs(prinURI));
457
if (NS_FAILED(rv) || !prinURI) {
458
return NS_OK;
459
}
460
ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
461
return thirdPartyUtil->IsThirdPartyURI(prinURI, aURI, aRes);
462
}
463
464
NS_IMETHODIMP
465
BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal* aPrin, bool* aRes) {
466
*aRes = true;
467
nsCOMPtr<nsIURI> prinURI;
468
nsresult rv = GetURI(getter_AddRefs(prinURI));
469
if (NS_FAILED(rv) || !prinURI) {
470
return NS_OK;
471
}
472
return aPrin->IsThirdPartyURI(prinURI, aRes);
473
}
474
475
NS_IMETHODIMP
476
BasePrincipal::IsSameOrigin(nsIURI* aURI, bool aIsPrivateWin, bool* aRes) {
477
*aRes = false;
478
nsCOMPtr<nsIURI> prinURI;
479
nsresult rv = GetURI(getter_AddRefs(prinURI));
480
if (NS_FAILED(rv) || !prinURI) {
481
return NS_OK;
482
}
483
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
484
if (!ssm) {
485
return NS_ERROR_UNEXPECTED;
486
}
487
*aRes = NS_SUCCEEDED(
488
ssm->CheckSameOriginURI(prinURI, aURI, false, aIsPrivateWin));
489
return NS_OK;
490
}
491
492
NS_IMETHODIMP
493
BasePrincipal::IsL10nAllowed(nsIURI* aURI, bool* aRes) {
494
*aRes = false;
495
496
if (nsContentUtils::IsErrorPage(aURI)) {
497
*aRes = true;
498
return NS_OK;
499
}
500
501
// The system principal is always allowed.
502
if (IsSystemPrincipal()) {
503
*aRes = true;
504
return NS_OK;
505
}
506
507
nsCOMPtr<nsIURI> uri;
508
nsresult rv = GetURI(getter_AddRefs(uri));
509
NS_ENSURE_SUCCESS(rv, NS_OK);
510
511
bool hasFlags;
512
513
// Allow access to uris that cannot be loaded by web content.
514
rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD,
515
&hasFlags);
516
NS_ENSURE_SUCCESS(rv, NS_OK);
517
if (hasFlags) {
518
*aRes = true;
519
return NS_OK;
520
}
521
522
// UI resources also get access.
523
rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
524
&hasFlags);
525
NS_ENSURE_SUCCESS(rv, NS_OK);
526
if (hasFlags) {
527
*aRes = true;
528
return NS_OK;
529
}
530
531
auto policy = AddonPolicy();
532
*aRes = (policy && policy->IsPrivileged());
533
return NS_OK;
534
}
535
536
NS_IMETHODIMP
537
BasePrincipal::AllowsRelaxStrictFileOriginPolicy(nsIURI* aURI, bool* aRes) {
538
*aRes = false;
539
nsCOMPtr<nsIURI> prinURI;
540
nsresult rv = GetURI(getter_AddRefs(prinURI));
541
if (NS_FAILED(rv) || !prinURI) {
542
return NS_OK;
543
}
544
*aRes = NS_RelaxStrictFileOriginPolicy(aURI, prinURI);
545
return NS_OK;
546
}
547
548
NS_IMETHODIMP
549
BasePrincipal::GetPrefLightCacheKey(nsIURI* aURI, bool aWithCredentials,
550
nsACString& _retval) {
551
_retval.Truncate();
552
NS_NAMED_LITERAL_CSTRING(space, " ");
553
554
nsCOMPtr<nsIURI> uri;
555
nsresult rv = GetURI(getter_AddRefs(uri));
556
NS_ENSURE_SUCCESS(rv, rv);
557
558
nsAutoCString scheme, host, port;
559
if (uri) {
560
uri->GetScheme(scheme);
561
uri->GetHost(host);
562
port.AppendInt(NS_GetRealPort(uri));
563
}
564
565
if (aWithCredentials) {
566
_retval.AssignLiteral("cred");
567
} else {
568
_retval.AssignLiteral("nocred");
569
}
570
571
nsAutoCString spec;
572
rv = aURI->GetSpec(spec);
573
NS_ENSURE_SUCCESS(rv, rv);
574
575
_retval.Append(space + scheme + space + host + space + port + space + spec);
576
577
return NS_OK;
578
}
579
580
NS_IMETHODIMP
581
BasePrincipal::GetIsNullPrincipal(bool* aResult) {
582
*aResult = Kind() == eNullPrincipal;
583
return NS_OK;
584
}
585
586
NS_IMETHODIMP
587
BasePrincipal::GetIsContentPrincipal(bool* aResult) {
588
*aResult = Kind() == eContentPrincipal;
589
return NS_OK;
590
}
591
592
NS_IMETHODIMP
593
BasePrincipal::GetIsExpandedPrincipal(bool* aResult) {
594
*aResult = Kind() == eExpandedPrincipal;
595
return NS_OK;
596
}
597
598
NS_IMETHODIMP
599
BasePrincipal::GetAsciiSpec(nsACString& aSpec) {
600
aSpec.Truncate();
601
nsCOMPtr<nsIURI> prinURI;
602
nsresult rv = GetURI(getter_AddRefs(prinURI));
603
if (NS_FAILED(rv) || !prinURI) {
604
return NS_OK;
605
}
606
return prinURI->GetAsciiSpec(aSpec);
607
}
608
609
NS_IMETHODIMP
610
BasePrincipal::GetAsciiHost(nsACString& aHost) {
611
aHost.Truncate();
612
nsCOMPtr<nsIURI> prinURI;
613
nsresult rv = GetURI(getter_AddRefs(prinURI));
614
if (NS_FAILED(rv) || !prinURI) {
615
return NS_OK;
616
}
617
return prinURI->GetAsciiHost(aHost);
618
}
619
620
NS_IMETHODIMP
621
BasePrincipal::GetExposablePrePath(nsACString& aPrepath) {
622
aPrepath.Truncate();
623
nsCOMPtr<nsIURI> prinURI;
624
nsresult rv = GetURI(getter_AddRefs(prinURI));
625
if (NS_FAILED(rv) || !prinURI) {
626
return NS_OK;
627
}
628
629
nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(prinURI);
630
return exposableURI->GetDisplayPrePath(aPrepath);
631
}
632
NS_IMETHODIMP
633
BasePrincipal::GetPrepath(nsACString& aPath) {
634
aPath.Truncate();
635
nsCOMPtr<nsIURI> prinURI;
636
nsresult rv = GetURI(getter_AddRefs(prinURI));
637
if (NS_FAILED(rv) || !prinURI) {
638
return NS_OK;
639
}
640
return prinURI->GetPrePath(aPath);
641
}
642
643
NS_IMETHODIMP
644
BasePrincipal::GetIsSystemPrincipal(bool* aResult) {
645
*aResult = IsSystemPrincipal();
646
return NS_OK;
647
}
648
649
NS_IMETHODIMP
650
BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) {
651
*aResult = AddonPolicy() || ContentScriptAddonPolicy();
652
return NS_OK;
653
}
654
655
NS_IMETHODIMP BasePrincipal::GetIsOnion(bool* aIsOnion) {
656
*aIsOnion = false;
657
nsCOMPtr<nsIURI> prinURI;
658
nsresult rv = GetURI(getter_AddRefs(prinURI));
659
if (NS_FAILED(rv) || !prinURI) {
660
return NS_OK;
661
}
662
663
nsAutoCString host;
664
rv = prinURI->GetHost(host);
665
if (NS_FAILED(rv)) {
666
return NS_OK;
667
}
668
*aIsOnion = StringEndsWith(host, NS_LITERAL_CSTRING(".onion"));
669
return NS_OK;
670
}
671
672
NS_IMETHODIMP BasePrincipal::GetIsIpAddress(bool* aIsIpAddress) {
673
*aIsIpAddress = false;
674
675
nsCOMPtr<nsIURI> prinURI;
676
nsresult rv = GetURI(getter_AddRefs(prinURI));
677
if (NS_FAILED(rv) || !prinURI) {
678
return NS_OK;
679
}
680
681
nsAutoCString host;
682
rv = prinURI->GetHost(host);
683
if (NS_FAILED(rv)) {
684
return NS_OK;
685
}
686
687
PRNetAddr prAddr;
688
memset(&prAddr, 0, sizeof(prAddr));
689
690
if (PR_StringToNetAddr(host.get(), &prAddr) == PR_SUCCESS) {
691
*aIsIpAddress = true;
692
}
693
694
return NS_OK;
695
}
696
697
NS_IMETHODIMP
698
BasePrincipal::SchemeIs(const char* aScheme, bool* aResult) {
699
*aResult = false;
700
nsCOMPtr<nsIURI> prinURI;
701
nsresult rv = GetURI(getter_AddRefs(prinURI));
702
if (NS_FAILED(rv) || !prinURI) {
703
return NS_OK;
704
}
705
*aResult = prinURI->SchemeIs(aScheme);
706
return NS_OK;
707
}
708
709
NS_IMETHODIMP
710
BasePrincipal::IsURIInPrefList(const char* aPref, bool* aResult) {
711
*aResult = false;
712
nsCOMPtr<nsIURI> prinURI;
713
nsresult rv = GetURI(getter_AddRefs(prinURI));
714
if (NS_FAILED(rv) || !prinURI) {
715
return NS_OK;
716
}
717
*aResult = nsContentUtils::IsURIInPrefList(prinURI, aPref);
718
return NS_OK;
719
}
720
721
NS_IMETHODIMP
722
BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult) {
723
MOZ_ASSERT(NS_IsMainThread());
724
*aResult = false;
725
726
nsCOMPtr<nsIURI> uri;
727
nsresult rv = GetURI(getter_AddRefs(uri));
728
if (NS_FAILED(rv) || !uri) {
729
return NS_OK;
730
}
731
732
*aResult = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
733
return NS_OK;
734
}
735
736
NS_IMETHODIMP
737
BasePrincipal::GetAboutModuleFlags(uint32_t* flags) {
738
*flags = 0;
739
nsCOMPtr<nsIURI> prinURI;
740
nsresult rv = GetURI(getter_AddRefs(prinURI));
741
if (NS_FAILED(rv) || !prinURI) {
742
return NS_ERROR_NOT_AVAILABLE;
743
}
744
if (!prinURI->SchemeIs("about")) {
745
return NS_OK;
746
}
747
748
nsCOMPtr<nsIAboutModule> aboutModule;
749
rv = NS_GetAboutModule(prinURI, getter_AddRefs(aboutModule));
750
if (NS_FAILED(rv) || !aboutModule) {
751
return rv;
752
}
753
return aboutModule->GetURIFlags(prinURI, flags);
754
}
755
756
NS_IMETHODIMP
757
BasePrincipal::GetOriginAttributes(JSContext* aCx,
758
JS::MutableHandle<JS::Value> aVal) {
759
if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
760
return NS_ERROR_FAILURE;
761
}
762
return NS_OK;
763
}
764
765
NS_IMETHODIMP
766
BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) {
767
MOZ_ASSERT(mOriginSuffix);
768
mOriginSuffix->ToUTF8String(aOriginAttributes);
769
return NS_OK;
770
}
771
772
NS_IMETHODIMP
773
BasePrincipal::GetUserContextId(uint32_t* aUserContextId) {
774
*aUserContextId = UserContextId();
775
return NS_OK;
776
}
777
778
NS_IMETHODIMP
779
BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) {
780
*aPrivateBrowsingId = PrivateBrowsingId();
781
return NS_OK;
782
}
783
784
NS_IMETHODIMP
785
BasePrincipal::GetIsInIsolatedMozBrowserElement(
786
bool* aIsInIsolatedMozBrowserElement) {
787
*aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
788
return NS_OK;
789
}
790
791
nsresult BasePrincipal::GetAddonPolicy(nsISupports** aResult) {
792
RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy());
793
policy.forget(aResult);
794
return NS_OK;
795
}
796
797
extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() {
798
if (Is<ContentPrincipal>()) {
799
return As<ContentPrincipal>()->AddonPolicy();
800
}
801
return nullptr;
802
}
803
804
bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) {
805
if (auto policy = AddonPolicy()) {
806
return policy->HasPermission(aPerm);
807
}
808
return false;
809
}
810
811
nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
812
if (Is<ExpandedPrincipal>()) {
813
return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
814
}
815
return this;
816
}
817
818
already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
819
nsIURI* aURI, const OriginAttributes& aAttrs) {
820
MOZ_ASSERT(aURI);
821
822
nsAutoCString originNoSuffix;
823
nsresult rv =
824
ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
825
if (NS_FAILED(rv)) {
826
// If the generation of the origin fails, we still want to have a valid
827
// principal. Better to return a null principal here.
828
return NullPrincipal::Create(aAttrs);
829
}
830
831
return CreateContentPrincipal(aURI, aAttrs, originNoSuffix);
832
}
833
834
already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
835
nsIURI* aURI, const OriginAttributes& aAttrs,
836
const nsACString& aOriginNoSuffix) {
837
MOZ_ASSERT(aURI);
838
MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
839
840
// If the URI is supposed to inherit the security context of whoever loads it,
841
// we shouldn't make a content principal for it.
842
bool inheritsPrincipal;
843
nsresult rv = NS_URIChainHasFlags(
844
aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
845
&inheritsPrincipal);
846
if (NS_FAILED(rv) || inheritsPrincipal) {
847
return NullPrincipal::Create(aAttrs);
848
}
849
850
// Check whether the URI knows what its principal is supposed to be.
851
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
852
nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
853
do_QueryInterface(aURI);
854
if (uriWithSpecialOrigin) {
855
nsCOMPtr<nsIURI> origin;
856
rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
857
if (NS_WARN_IF(NS_FAILED(rv))) {
858
return nullptr;
859
}
860
MOZ_ASSERT(origin);
861
OriginAttributes attrs;
862
RefPtr<BasePrincipal> principal = CreateContentPrincipal(origin, attrs);
863
return principal.forget();
864
}
865
#endif
866
867
nsCOMPtr<nsIPrincipal> blobPrincipal;
868
if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
869
aURI, getter_AddRefs(blobPrincipal))) {
870
MOZ_ASSERT(blobPrincipal);
871
RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
872
return principal.forget();
873
}
874
875
// Mint a content principal.
876
RefPtr<ContentPrincipal> principal = new ContentPrincipal();
877
rv = principal->Init(aURI, aAttrs, aOriginNoSuffix);
878
NS_ENSURE_SUCCESS(rv, nullptr);
879
return principal.forget();
880
}
881
882
already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
883
const nsACString& aOrigin) {
884
MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")),
885
"CreateContentPrincipal does not support System and Expanded "
886
"principals");
887
888
MOZ_ASSERT(!StringBeginsWith(aOrigin,
889
NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")),
890
"CreateContentPrincipal does not support NullPrincipal");
891
892
nsAutoCString originNoSuffix;
893
OriginAttributes attrs;
894
if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
895
return nullptr;
896
}
897
898
nsCOMPtr<nsIURI> uri;
899
nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
900
NS_ENSURE_SUCCESS(rv, nullptr);
901
902
return BasePrincipal::CreateContentPrincipal(uri, attrs);
903
}
904
905
already_AddRefed<BasePrincipal> BasePrincipal::CloneForcingOriginAttributes(
906
const OriginAttributes& aOriginAttributes) {
907
if (NS_WARN_IF(!IsContentPrincipal())) {
908
return nullptr;
909
}
910
911
nsAutoCString originNoSuffix;
912
nsresult rv = GetOriginNoSuffix(originNoSuffix);
913
NS_ENSURE_SUCCESS(rv, nullptr);
914
915
nsIURI* uri = static_cast<ContentPrincipal*>(this)->mURI;
916
RefPtr<ContentPrincipal> copy = new ContentPrincipal();
917
rv = copy->Init(uri, aOriginAttributes, originNoSuffix);
918
NS_ENSURE_SUCCESS(rv, nullptr);
919
920
return copy.forget();
921
}
922
923
extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() {
924
if (!Is<ExpandedPrincipal>()) {
925
return nullptr;
926
}
927
928
auto expanded = As<ExpandedPrincipal>();
929
for (auto& prin : expanded->AllowList()) {
930
if (auto policy = BasePrincipal::Cast(prin)->AddonPolicy()) {
931
return policy;
932
}
933
}
934
935
return nullptr;
936
}
937
938
bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI,
939
bool aExplicit /* = false */) {
940
if (Is<ExpandedPrincipal>()) {
941
return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
942
}
943
if (auto policy = AddonPolicy()) {
944
return policy->CanAccessURI(aURI, aExplicit);
945
}
946
return false;
947
}
948
949
void BasePrincipal::FinishInit(const nsACString& aOriginNoSuffix,
950
const OriginAttributes& aOriginAttributes) {
951
mInitialized = true;
952
mOriginAttributes = aOriginAttributes;
953
954
// First compute the origin suffix since it's infallible.
955
nsAutoCString originSuffix;
956
mOriginAttributes.CreateSuffix(originSuffix);
957
mOriginSuffix = NS_Atomize(originSuffix);
958
959
MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
960
mOriginNoSuffix = NS_Atomize(aOriginNoSuffix);
961
}
962
963
void BasePrincipal::FinishInit(BasePrincipal* aOther,
964
const OriginAttributes& aOriginAttributes) {
965
mInitialized = true;
966
mOriginAttributes = aOriginAttributes;
967
968
// First compute the origin suffix since it's infallible.
969
nsAutoCString originSuffix;
970
mOriginAttributes.CreateSuffix(originSuffix);
971
mOriginSuffix = NS_Atomize(originSuffix);
972
973
mOriginNoSuffix = aOther->mOriginNoSuffix;
974
mHasExplicitDomain = aOther->mHasExplicitDomain;
975
}
976
977
NS_IMETHODIMP
978
BasePrincipal::GetLocalStorageQuotaKey(nsACString& aKey) {
979
aKey.Truncate();
980
nsresult rv;
981
nsCOMPtr<nsIEffectiveTLDService> eTLDService(
982
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv));
983
NS_ENSURE_SUCCESS(rv, rv);
984
985
nsCOMPtr<nsIURI> uri;
986
rv = GetURI(getter_AddRefs(uri));
987
NS_ENSURE_SUCCESS(rv, rv);
988
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
989
990
nsAutoCString eTLDplusOne;
991
rv = eTLDService->GetBaseDomain(uri, 0, eTLDplusOne);
992
if (NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS == rv) {
993
// XXX bug 357323 - what to do for localhost/file exactly?
994
rv = uri->GetAsciiHost(eTLDplusOne);
995
}
996
NS_ENSURE_SUCCESS(rv, rv);
997
998
OriginAttributesRef().CreateSuffix(aKey);
999
1000
nsAutoCString subdomainsDBKey;
1001
dom::StorageUtils::CreateReversedDomain(eTLDplusOne, subdomainsDBKey);
1002
1003
aKey.Append(':');
1004
aKey.Append(subdomainsDBKey);
1005
1006
return NS_OK;
1007
}
1008
1009
NS_IMETHODIMP
1010
BasePrincipal::GetStorageOriginKey(nsACString& aOriginKey) {
1011
aOriginKey.Truncate();
1012
nsCOMPtr<nsIURI> uri;
1013
nsresult rv = GetURI(getter_AddRefs(uri));
1014
NS_ENSURE_SUCCESS(rv, rv);
1015
if (!uri) {
1016
return NS_ERROR_UNEXPECTED;
1017
}
1018
1019
nsAutoCString domainOrigin;
1020
rv = uri->GetAsciiHost(domainOrigin);
1021
NS_ENSURE_SUCCESS(rv, rv);
1022
1023
if (domainOrigin.IsEmpty()) {
1024
// For the file:/// protocol use the exact directory as domain.
1025
if (uri->SchemeIs("file")) {
1026
nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
1027
NS_ENSURE_SUCCESS(rv, rv);
1028
rv = url->GetDirectory(domainOrigin);
1029
NS_ENSURE_SUCCESS(rv, rv);
1030
}
1031
}
1032
1033
// Append reversed domain
1034
nsAutoCString reverseDomain;
1035
rv = dom::StorageUtils::CreateReversedDomain(domainOrigin, reverseDomain);
1036
if (NS_FAILED(rv)) {
1037
return rv;
1038
}
1039
1040
aOriginKey.Append(reverseDomain);
1041
1042
// Append scheme
1043
nsAutoCString scheme;
1044
rv = uri->GetScheme(scheme);
1045
NS_ENSURE_SUCCESS(rv, rv);
1046
1047
aOriginKey.Append(':');
1048
aOriginKey.Append(scheme);
1049
1050
// Append port if any
1051
int32_t port = NS_GetRealPort(uri);
1052
if (port != -1) {
1053
aOriginKey.Append(nsPrintfCString(":%d", port));
1054
}
1055
return NS_OK;
1056
}
1057
1058
NS_IMETHODIMP
1059
BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy) {
1060
*aIsScriptAllowedByPolicy = false;
1061
nsCOMPtr<nsIURI> prinURI;
1062
nsresult rv = GetURI(getter_AddRefs(prinURI));
1063
if (NS_FAILED(rv) || !prinURI) {
1064
return NS_OK;
1065
}
1066
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
1067
if (!ssm) {
1068
return NS_ERROR_UNEXPECTED;
1069
}
1070
return ssm->PolicyAllowsScript(prinURI, aIsScriptAllowedByPolicy);
1071
}
1072
1073
bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
1074
MOZ_ASSERT(IsInitialized());
1075
MOZ_ASSERT(aOther.IsInitialized());
1076
return mPrincipal->FastEquals(aOther.mPrincipal);
1077
}
1078
1079
NS_IMETHODIMP
1080
BasePrincipal::CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy,
1081
nsIReferrerInfo** _retval) {
1082
nsCOMPtr<nsIURI> prinURI;
1083
RefPtr<dom::ReferrerInfo> info;
1084
nsresult rv = GetURI(getter_AddRefs(prinURI));
1085
if (NS_FAILED(rv) || !prinURI) {
1086
info = new dom::ReferrerInfo(nullptr);
1087
info.forget(_retval);
1088
return NS_OK;
1089
}
1090
info = new dom::ReferrerInfo(prinURI, aReferrerPolicy);
1091
info.forget(_retval);
1092
return NS_OK;
1093
}
1094
1095
} // namespace mozilla