|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /** |
|
7 * This is the principal that has no rights and can't be accessed by |
|
8 * anything other than itself and chrome; null principals are not |
|
9 * same-origin with anything but themselves. |
|
10 */ |
|
11 |
|
12 #include "mozilla/ArrayUtils.h" |
|
13 |
|
14 #include "nsNullPrincipal.h" |
|
15 #include "nsNullPrincipalURI.h" |
|
16 #include "nsMemory.h" |
|
17 #include "nsIUUIDGenerator.h" |
|
18 #include "nsID.h" |
|
19 #include "nsNetUtil.h" |
|
20 #include "nsIClassInfoImpl.h" |
|
21 #include "nsNetCID.h" |
|
22 #include "nsError.h" |
|
23 #include "nsIScriptSecurityManager.h" |
|
24 #include "nsPrincipal.h" |
|
25 #include "nsScriptSecurityManager.h" |
|
26 #include "pratom.h" |
|
27 |
|
28 using namespace mozilla; |
|
29 |
|
30 NS_IMPL_CLASSINFO(nsNullPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, |
|
31 NS_NULLPRINCIPAL_CID) |
|
32 NS_IMPL_QUERY_INTERFACE_CI(nsNullPrincipal, |
|
33 nsIPrincipal, |
|
34 nsISerializable) |
|
35 NS_IMPL_CI_INTERFACE_GETTER(nsNullPrincipal, |
|
36 nsIPrincipal, |
|
37 nsISerializable) |
|
38 |
|
39 NS_IMETHODIMP_(MozExternalRefCountType) |
|
40 nsNullPrincipal::AddRef() |
|
41 { |
|
42 NS_PRECONDITION(int32_t(refcount) >= 0, "illegal refcnt"); |
|
43 nsrefcnt count = ++refcount; |
|
44 NS_LOG_ADDREF(this, count, "nsNullPrincipal", sizeof(*this)); |
|
45 return count; |
|
46 } |
|
47 |
|
48 NS_IMETHODIMP_(MozExternalRefCountType) |
|
49 nsNullPrincipal::Release() |
|
50 { |
|
51 NS_PRECONDITION(0 != refcount, "dup release"); |
|
52 nsrefcnt count = --refcount; |
|
53 NS_LOG_RELEASE(this, count, "nsNullPrincipal"); |
|
54 if (count == 0) { |
|
55 delete this; |
|
56 } |
|
57 |
|
58 return count; |
|
59 } |
|
60 |
|
61 nsNullPrincipal::nsNullPrincipal() |
|
62 { |
|
63 } |
|
64 |
|
65 nsNullPrincipal::~nsNullPrincipal() |
|
66 { |
|
67 } |
|
68 |
|
69 #define NS_NULLPRINCIPAL_PREFIX NS_NULLPRINCIPAL_SCHEME ":" |
|
70 |
|
71 nsresult |
|
72 nsNullPrincipal::Init() |
|
73 { |
|
74 // FIXME: bug 327161 -- make sure the uuid generator is reseeding-resistant. |
|
75 nsresult rv; |
|
76 nsCOMPtr<nsIUUIDGenerator> uuidgen = |
|
77 do_GetService("@mozilla.org/uuid-generator;1", &rv); |
|
78 NS_ENSURE_SUCCESS(rv, rv); |
|
79 |
|
80 nsID id; |
|
81 rv = uuidgen->GenerateUUIDInPlace(&id); |
|
82 NS_ENSURE_SUCCESS(rv, rv); |
|
83 |
|
84 char chars[NSID_LENGTH]; |
|
85 id.ToProvidedString(chars); |
|
86 |
|
87 uint32_t suffixLen = NSID_LENGTH - 1; |
|
88 uint32_t prefixLen = ArrayLength(NS_NULLPRINCIPAL_PREFIX) - 1; |
|
89 |
|
90 // Use an nsCString so we only do the allocation once here and then share |
|
91 // with nsJSPrincipals |
|
92 nsCString str; |
|
93 str.SetCapacity(prefixLen + suffixLen); |
|
94 |
|
95 str.Append(NS_NULLPRINCIPAL_PREFIX); |
|
96 str.Append(chars); |
|
97 |
|
98 if (str.Length() != prefixLen + suffixLen) { |
|
99 NS_WARNING("Out of memory allocating null-principal URI"); |
|
100 return NS_ERROR_OUT_OF_MEMORY; |
|
101 } |
|
102 |
|
103 mURI = new nsNullPrincipalURI(str); |
|
104 NS_ENSURE_TRUE(mURI, NS_ERROR_OUT_OF_MEMORY); |
|
105 |
|
106 return NS_OK; |
|
107 } |
|
108 |
|
109 void |
|
110 nsNullPrincipal::GetScriptLocation(nsACString &aStr) |
|
111 { |
|
112 mURI->GetSpec(aStr); |
|
113 } |
|
114 |
|
115 #ifdef DEBUG |
|
116 void nsNullPrincipal::dumpImpl() |
|
117 { |
|
118 nsAutoCString str; |
|
119 mURI->GetSpec(str); |
|
120 fprintf(stderr, "nsNullPrincipal (%p) = %s\n", this, str.get()); |
|
121 } |
|
122 #endif |
|
123 |
|
124 /** |
|
125 * nsIPrincipal implementation |
|
126 */ |
|
127 |
|
128 NS_IMETHODIMP |
|
129 nsNullPrincipal::Equals(nsIPrincipal *aOther, bool *aResult) |
|
130 { |
|
131 // Just equal to ourselves. Note that nsPrincipal::Equals will return false |
|
132 // for us since we have a unique domain/origin/etc. |
|
133 *aResult = (aOther == this); |
|
134 return NS_OK; |
|
135 } |
|
136 |
|
137 NS_IMETHODIMP |
|
138 nsNullPrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult) |
|
139 { |
|
140 return Equals(aOther, aResult); |
|
141 } |
|
142 |
|
143 NS_IMETHODIMP |
|
144 nsNullPrincipal::GetHashValue(uint32_t *aResult) |
|
145 { |
|
146 *aResult = (NS_PTR_TO_INT32(this) >> 2); |
|
147 return NS_OK; |
|
148 } |
|
149 |
|
150 NS_IMETHODIMP |
|
151 nsNullPrincipal::GetURI(nsIURI** aURI) |
|
152 { |
|
153 return NS_EnsureSafeToReturn(mURI, aURI); |
|
154 } |
|
155 |
|
156 NS_IMETHODIMP |
|
157 nsNullPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) |
|
158 { |
|
159 NS_IF_ADDREF(*aCsp = mCSP); |
|
160 return NS_OK; |
|
161 } |
|
162 |
|
163 NS_IMETHODIMP |
|
164 nsNullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) |
|
165 { |
|
166 // If CSP was already set, it should not be destroyed! Instead, it should |
|
167 // get set anew when a new principal is created. |
|
168 if (mCSP) |
|
169 return NS_ERROR_ALREADY_INITIALIZED; |
|
170 |
|
171 mCSP = aCsp; |
|
172 return NS_OK; |
|
173 } |
|
174 |
|
175 NS_IMETHODIMP |
|
176 nsNullPrincipal::GetDomain(nsIURI** aDomain) |
|
177 { |
|
178 return NS_EnsureSafeToReturn(mURI, aDomain); |
|
179 } |
|
180 |
|
181 NS_IMETHODIMP |
|
182 nsNullPrincipal::SetDomain(nsIURI* aDomain) |
|
183 { |
|
184 // I think the right thing to do here is to just throw... Silently failing |
|
185 // seems counterproductive. |
|
186 return NS_ERROR_NOT_AVAILABLE; |
|
187 } |
|
188 |
|
189 NS_IMETHODIMP |
|
190 nsNullPrincipal::GetOrigin(char** aOrigin) |
|
191 { |
|
192 *aOrigin = nullptr; |
|
193 |
|
194 nsAutoCString str; |
|
195 nsresult rv = mURI->GetSpec(str); |
|
196 NS_ENSURE_SUCCESS(rv, rv); |
|
197 |
|
198 *aOrigin = ToNewCString(str); |
|
199 NS_ENSURE_TRUE(*aOrigin, NS_ERROR_OUT_OF_MEMORY); |
|
200 |
|
201 return NS_OK; |
|
202 } |
|
203 |
|
204 NS_IMETHODIMP |
|
205 nsNullPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult) |
|
206 { |
|
207 // We don't subsume anything except ourselves. Note that nsPrincipal::Equals |
|
208 // will return false for us, since we're not about:blank and not Equals to |
|
209 // reasonable nsPrincipals. |
|
210 *aResult = (aOther == this); |
|
211 return NS_OK; |
|
212 } |
|
213 |
|
214 NS_IMETHODIMP |
|
215 nsNullPrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult) |
|
216 { |
|
217 return Subsumes(aOther, aResult); |
|
218 } |
|
219 |
|
220 NS_IMETHODIMP |
|
221 nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal) |
|
222 { |
|
223 if (aAllowIfInheritsPrincipal) { |
|
224 if (nsPrincipal::IsPrincipalInherited(aURI)) { |
|
225 return NS_OK; |
|
226 } |
|
227 |
|
228 // Also allow the load if the principal of the URI being checked is exactly |
|
229 // us ie this. |
|
230 nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI); |
|
231 if (uriPrinc) { |
|
232 nsCOMPtr<nsIPrincipal> principal; |
|
233 uriPrinc->GetPrincipal(getter_AddRefs(principal)); |
|
234 |
|
235 if (principal && principal == this) { |
|
236 return NS_OK; |
|
237 } |
|
238 } |
|
239 } |
|
240 |
|
241 if (aReport) { |
|
242 nsScriptSecurityManager::ReportError( |
|
243 nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mURI, aURI); |
|
244 } |
|
245 |
|
246 return NS_ERROR_DOM_BAD_URI; |
|
247 } |
|
248 |
|
249 NS_IMETHODIMP |
|
250 nsNullPrincipal::GetJarPrefix(nsACString& aJarPrefix) |
|
251 { |
|
252 aJarPrefix.Truncate(); |
|
253 return NS_OK; |
|
254 } |
|
255 |
|
256 NS_IMETHODIMP |
|
257 nsNullPrincipal::GetAppStatus(uint16_t* aAppStatus) |
|
258 { |
|
259 *aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED; |
|
260 return NS_OK; |
|
261 } |
|
262 |
|
263 NS_IMETHODIMP |
|
264 nsNullPrincipal::GetAppId(uint32_t* aAppId) |
|
265 { |
|
266 *aAppId = nsIScriptSecurityManager::NO_APP_ID; |
|
267 return NS_OK; |
|
268 } |
|
269 |
|
270 NS_IMETHODIMP |
|
271 nsNullPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement) |
|
272 { |
|
273 *aIsInBrowserElement = false; |
|
274 return NS_OK; |
|
275 } |
|
276 |
|
277 NS_IMETHODIMP |
|
278 nsNullPrincipal::GetUnknownAppId(bool* aUnknownAppId) |
|
279 { |
|
280 *aUnknownAppId = false; |
|
281 return NS_OK; |
|
282 } |
|
283 |
|
284 NS_IMETHODIMP |
|
285 nsNullPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal) |
|
286 { |
|
287 *aIsNullPrincipal = true; |
|
288 return NS_OK; |
|
289 } |
|
290 |
|
291 NS_IMETHODIMP |
|
292 nsNullPrincipal::GetBaseDomain(nsACString& aBaseDomain) |
|
293 { |
|
294 // For a null principal, we use our unique uuid as the base domain. |
|
295 return mURI->GetPath(aBaseDomain); |
|
296 } |
|
297 |
|
298 /** |
|
299 * nsISerializable implementation |
|
300 */ |
|
301 NS_IMETHODIMP |
|
302 nsNullPrincipal::Read(nsIObjectInputStream* aStream) |
|
303 { |
|
304 // no-op: CID is sufficient to create a useful nsNullPrincipal, since the URI |
|
305 // is not really relevant. |
|
306 return NS_OK; |
|
307 } |
|
308 |
|
309 NS_IMETHODIMP |
|
310 nsNullPrincipal::Write(nsIObjectOutputStream* aStream) |
|
311 { |
|
312 // no-op: CID is sufficient to create a useful nsNullPrincipal, since the URI |
|
313 // is not really relevant. |
|
314 return NS_OK; |
|
315 } |
|
316 |