/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 */ |