Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/BasePrincipal.h
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
#ifndef mozilla_BasePrincipal_h
8
#define mozilla_BasePrincipal_h
9
10
#include "nsJSPrincipals.h"
11
12
#include "mozilla/Attributes.h"
13
#include "mozilla/OriginAttributes.h"
14
15
class nsAtom;
16
class nsIContentSecurityPolicy;
17
class nsIObjectOutputStream;
18
class nsIObjectInputStream;
19
class nsIURI;
20
21
class ExpandedPrincipal;
22
23
namespace mozilla {
24
namespace extensions {
25
  class WebExtensionPolicy;
26
}
27
28
class BasePrincipal;
29
30
// Codebase principals (and codebase principals embedded within expanded
31
// principals) stored in SiteIdentifier are guaranteed to contain only the
32
// eTLD+1 part of the original domain. This is used to determine whether two
33
// origins are same-site: if it's possible for two origins to access each other
34
// (maybe after mutating document.domain), then they must have the same site
35
// identifier.
36
class SiteIdentifier
37
{
38
public:
39
  void Init(BasePrincipal* aPrincipal)
40
6
  {
41
6
    MOZ_ASSERT(aPrincipal);
42
6
    mPrincipal = aPrincipal;
43
6
  }
44
45
0
  bool IsInitialized() const { return !!mPrincipal; }
46
47
  bool Equals(const SiteIdentifier& aOther) const;
48
49
private:
50
  friend class ::ExpandedPrincipal;
51
52
  BasePrincipal* GetPrincipal() const
53
0
  {
54
0
    MOZ_ASSERT(IsInitialized());
55
0
    return mPrincipal;
56
0
  }
57
58
  RefPtr<BasePrincipal> mPrincipal;
59
};
60
61
/*
62
 * Base class from which all nsIPrincipal implementations inherit. Use this for
63
 * default implementations and other commonalities between principal
64
 * implementations.
65
 *
66
 * We should merge nsJSPrincipals into this class at some point.
67
 */
68
class BasePrincipal : public nsJSPrincipals
69
{
70
public:
71
  enum PrincipalKind {
72
    eNullPrincipal,
73
    eCodebasePrincipal,
74
    eExpandedPrincipal,
75
    eSystemPrincipal
76
  };
77
78
  explicit BasePrincipal(PrincipalKind aKind);
79
80
  template<typename T>
81
  bool Is() const
82
6
  {
83
6
    return mKind == T::Kind();
84
6
  }
bool mozilla::BasePrincipal::Is<ExpandedPrincipal>() const
Line
Count
Source
82
3
  {
83
3
    return mKind == T::Kind();
84
3
  }
Unexecuted instantiation: bool mozilla::BasePrincipal::Is<mozilla::SystemPrincipal>() const
bool mozilla::BasePrincipal::Is<mozilla::ContentPrincipal>() const
Line
Count
Source
82
3
  {
83
3
    return mKind == T::Kind();
84
3
  }
85
86
  template<typename T>
87
  T* As()
88
0
  {
89
0
    MOZ_ASSERT(Is<T>());
90
0
    return static_cast<T*>(this);
91
0
  }
Unexecuted instantiation: ExpandedPrincipal* mozilla::BasePrincipal::As<ExpandedPrincipal>()
Unexecuted instantiation: mozilla::ContentPrincipal* mozilla::BasePrincipal::As<mozilla::ContentPrincipal>()
92
93
  enum DocumentDomainConsideration { DontConsiderDocumentDomain, ConsiderDocumentDomain};
94
  bool Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration);
95
96
  NS_IMETHOD GetOrigin(nsACString& aOrigin) final;
97
  NS_IMETHOD GetOriginNoSuffix(nsACString& aOrigin) final;
98
  NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval) final;
99
  NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval) final;
100
  NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) final;
101
  NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) final;
102
  NS_IMETHOD SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* other, bool* _retval) final;
103
  NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
104
  NS_IMETHOD GetAddonPolicy(nsISupports** aResult) final;
105
  NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
106
  NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
107
  NS_IMETHOD EnsureCSP(nsIDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
108
  NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
109
  NS_IMETHOD EnsurePreloadCSP(nsIDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
110
  NS_IMETHOD GetCspJSON(nsAString& outCSPinJSON) override;
111
  NS_IMETHOD GetIsNullPrincipal(bool* aResult) override;
112
  NS_IMETHOD GetIsCodebasePrincipal(bool* aResult) override;
113
  NS_IMETHOD GetIsExpandedPrincipal(bool* aResult) override;
114
  NS_IMETHOD GetIsSystemPrincipal(bool* aResult) override;
115
  NS_IMETHOD GetIsAddonOrExpandedAddonPrincipal(bool* aResult) override;
116
  NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final;
117
  NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
118
  NS_IMETHOD GetAppId(uint32_t* aAppId) final;
119
  NS_IMETHOD GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement) final;
120
  NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
121
  NS_IMETHOD GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) final;
122
  NS_IMETHOD GetSiteOrigin(nsACString& aOrigin) override;
123
124
  virtual bool AddonHasPermission(const nsAtom* aPerm);
125
126
0
  virtual bool IsCodebasePrincipal() const { return false; };
127
128
15
  static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
129
130
  static already_AddRefed<BasePrincipal>
131
  CreateCodebasePrincipal(const nsACString& aOrigin);
132
133
  // These following method may not create a codebase principal in case it's
134
  // not possible to generate a correct origin from the passed URI. If this
135
  // happens, a NullPrincipal is returned.
136
137
  static already_AddRefed<BasePrincipal>
138
  CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs);
139
140
5
  const OriginAttributes& OriginAttributesRef() final { return mOriginAttributes; }
141
0
  uint32_t AppId() const { return mOriginAttributes.mAppId; }
142
  extensions::WebExtensionPolicy* AddonPolicy();
143
0
  uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; }
144
0
  uint32_t PrivateBrowsingId() const { return mOriginAttributes.mPrivateBrowsingId; }
145
0
  bool IsInIsolatedMozBrowserElement() const { return mOriginAttributes.mInIsolatedMozBrowser; }
146
147
5
  PrincipalKind Kind() const { return mKind; }
148
149
  already_AddRefed<BasePrincipal> CloneStrippingUserContextIdAndFirstPartyDomain();
150
151
  // If this is an add-on content script principal, returns its AddonPolicy.
152
  // Otherwise returns null.
153
  extensions::WebExtensionPolicy* ContentScriptAddonPolicy();
154
155
  // Helper to check whether this principal is associated with an addon that
156
  // allows unprivileged code to load aURI.  aExplicit == true will prevent
157
  // use of all_urls permission, requiring the domain in its permissions.
158
  bool AddonAllowsLoad(nsIURI* aURI, bool aExplicit = false);
159
160
  // Call these to avoid the cost of virtual dispatch.
161
  inline bool FastEquals(nsIPrincipal* aOther);
162
  inline bool FastEqualsConsideringDomain(nsIPrincipal* aOther);
163
  inline bool FastSubsumes(nsIPrincipal* aOther);
164
  inline bool FastSubsumesConsideringDomain(nsIPrincipal* aOther);
165
  inline bool FastSubsumesIgnoringFPD(nsIPrincipal* aOther);
166
  inline bool FastSubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther);
167
168
  // Returns the principal to inherit when a caller with this principal loads
169
  // the given URI.
170
  //
171
  // For most principal types, this returns the principal itself. For expanded
172
  // principals, it returns the first sub-principal which subsumes the given URI
173
  // (or, if no URI is given, the last whitelist principal).
174
  nsIPrincipal* PrincipalToInherit(nsIURI* aRequestedURI = nullptr);
175
176
  /**
177
   * Returns true if this principal's CSP should override a document's CSP for
178
   * loads that it triggers. Currently true for system principal, for expanded
179
   * principals which subsume the document principal, and add-on codebase
180
   * principals regardless of whether they subsume the document principal.
181
   */
182
  bool OverridesCSP(nsIPrincipal* aDocumentPrincipal)
183
0
  {
184
0
    // SystemPrincipal can override the page's CSP by definition.
185
0
    if (mKind == eSystemPrincipal) {
186
0
      return true;
187
0
    }
188
0
189
0
    // Expanded principals override CSP if and only if they subsume the document
190
0
    // principal.
191
0
    if (mKind == eExpandedPrincipal) {
192
0
      return FastSubsumes(aDocumentPrincipal);
193
0
    }
194
0
    // Extension principals always override the CSP non-extension principals.
195
0
    // This is primarily for the sake of their stylesheets, which are usually
196
0
    // loaded from channels and cannot have expanded principals.
197
0
    return (AddonPolicy() &&
198
0
            !BasePrincipal::Cast(aDocumentPrincipal)->AddonPolicy());
199
0
  }
200
201
0
  uint32_t GetOriginNoSuffixHash() const { return mOriginNoSuffix->hash(); }
202
203
  virtual nsresult GetSiteIdentifier(SiteIdentifier& aSite) = 0;
204
205
protected:
206
  virtual ~BasePrincipal();
207
208
  // Note that this does not check OriginAttributes. Callers that depend on
209
  // those must call Subsumes instead.
210
  virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0;
211
212
  // Internal, side-effect-free check to determine whether the concrete
213
  // principal would allow the load ignoring any common behavior implemented in
214
  // BasePrincipal::CheckMayLoad.
215
  virtual bool MayLoadInternal(nsIURI* aURI) = 0;
216
  friend class ::ExpandedPrincipal;
217
218
  void
219
  SetHasExplicitDomain()
220
0
  {
221
0
    mHasExplicitDomain = true;
222
0
  }
223
224
  // This function should be called as the last step of the initialization of the
225
  // principal objects.  It's typically called as the last step from the Init()
226
  // method of the child classes.
227
  void FinishInit(const nsACString& aOriginNoSuffix,
228
                  const OriginAttributes& aOriginAttributes);
229
230
  nsCOMPtr<nsIContentSecurityPolicy> mCSP;
231
  nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
232
233
private:
234
  static already_AddRefed<BasePrincipal>
235
  CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs,
236
                          const nsACString& aOriginNoSuffix);
237
238
  inline bool FastSubsumesIgnoringFPD(nsIPrincipal* aOther,
239
                                      DocumentDomainConsideration aConsideration);
240
241
  RefPtr<nsAtom> mOriginNoSuffix;
242
  RefPtr<nsAtom> mOriginSuffix;
243
244
  OriginAttributes mOriginAttributes;
245
  PrincipalKind mKind;
246
  bool mHasExplicitDomain;
247
  bool mInitialized;
248
};
249
250
inline bool
251
BasePrincipal::FastEquals(nsIPrincipal* aOther)
252
0
{
253
0
  auto other = Cast(aOther);
254
0
  if (Kind() != other->Kind()) {
255
0
    // Principals of different kinds can't be equal.
256
0
    return false;
257
0
  }
258
0
259
0
  // Two principals are considered to be equal if their origins are the same.
260
0
  // If the two principals are codebase principals, their origin attributes
261
0
  // (aka the origin suffix) must also match.
262
0
  // If the two principals are null principals, they're only equal if they're
263
0
  // the same object.
264
0
  if (Kind() == eNullPrincipal || Kind() == eSystemPrincipal) {
265
0
    return this == other;
266
0
  }
267
0
268
0
  if (Kind() == eCodebasePrincipal) {
269
0
    return mOriginNoSuffix == other->mOriginNoSuffix &&
270
0
           mOriginSuffix == other->mOriginSuffix;
271
0
  }
272
0
273
0
  MOZ_ASSERT(Kind() == eExpandedPrincipal);
274
0
  return mOriginNoSuffix == other->mOriginNoSuffix;
275
0
}
276
277
inline bool
278
BasePrincipal::FastEqualsConsideringDomain(nsIPrincipal* aOther)
279
0
{
280
0
  // If neither of the principals have document.domain set, we use the fast path
281
0
  // in Equals().  Otherwise, we fall back to the slow path below.
282
0
  auto other = Cast(aOther);
283
0
  if (!mHasExplicitDomain && !other->mHasExplicitDomain) {
284
0
    return FastEquals(aOther);
285
0
  }
286
0
287
0
  return Subsumes(aOther, ConsiderDocumentDomain) &&
288
0
         other->Subsumes(this, ConsiderDocumentDomain);
289
0
}
290
291
inline bool
292
BasePrincipal::FastSubsumes(nsIPrincipal* aOther)
293
0
{
294
0
  // If two principals are equal, then they both subsume each other.
295
0
  // We deal with two special cases first:
296
0
  // Null principals only subsume each other if they are equal, and are only
297
0
  // equal if they're the same object.
298
0
  auto other = Cast(aOther);
299
0
  if (Kind() == eNullPrincipal && other->Kind() == eNullPrincipal) {
300
0
    return this == other;
301
0
  }
302
0
  if (FastEquals(aOther)) {
303
0
    return true;
304
0
  }
305
0
306
0
  // Otherwise, fall back to the slow path.
307
0
  return Subsumes(aOther, DontConsiderDocumentDomain);
308
0
}
309
310
inline bool
311
BasePrincipal::FastSubsumesConsideringDomain(nsIPrincipal* aOther)
312
0
{
313
0
  // If neither of the principals have document.domain set, we hand off to
314
0
  // FastSubsumes() which has fast paths for some special cases. Otherwise, we fall
315
0
  // back to the slow path below.
316
0
  if (!mHasExplicitDomain && !Cast(aOther)->mHasExplicitDomain) {
317
0
    return FastSubsumes(aOther);
318
0
  }
319
0
320
0
  return Subsumes(aOther, ConsiderDocumentDomain);
321
0
}
322
323
inline bool
324
BasePrincipal::FastSubsumesIgnoringFPD(nsIPrincipal* aOther,
325
                                       DocumentDomainConsideration aConsideration)
326
0
{
327
0
  if (Kind() == eCodebasePrincipal &&
328
0
      !dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
329
0
            mOriginAttributes, Cast(aOther)->mOriginAttributes)) {
330
0
    return false;
331
0
  }
332
0
333
0
  return SubsumesInternal(aOther, aConsideration);
334
0
}
335
336
inline bool
337
BasePrincipal::FastSubsumesIgnoringFPD(nsIPrincipal* aOther)
338
0
{
339
0
  return FastSubsumesIgnoringFPD(aOther, DontConsiderDocumentDomain);
340
0
}
341
342
inline bool
343
BasePrincipal::FastSubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther)
344
0
{
345
0
  return FastSubsumesIgnoringFPD(aOther, ConsiderDocumentDomain);
346
0
}
347
348
} // namespace mozilla
349
350
#endif /* mozilla_BasePrincipal_h */