Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/caps/ExpandedPrincipal.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 "ExpandedPrincipal.h"
8
#include "nsIClassInfoImpl.h"
9
10
using namespace mozilla;
11
12
NS_IMPL_CLASSINFO(ExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
13
                  NS_EXPANDEDPRINCIPAL_CID)
14
NS_IMPL_QUERY_INTERFACE_CI(ExpandedPrincipal,
15
                           nsIPrincipal,
16
                           nsIExpandedPrincipal,
17
                           nsISerializable)
18
NS_IMPL_CI_INTERFACE_GETTER(ExpandedPrincipal,
19
                            nsIPrincipal,
20
                            nsIExpandedPrincipal,
21
                            nsISerializable)
22
23
struct OriginComparator
24
{
25
  bool LessThan(nsIPrincipal* a, nsIPrincipal* b) const
26
0
  {
27
0
    nsAutoCString originA;
28
0
    DebugOnly<nsresult> rv = a->GetOrigin(originA);
29
0
    MOZ_ASSERT(NS_SUCCEEDED(rv));
30
0
    nsAutoCString originB;
31
0
    rv = b->GetOrigin(originB);
32
0
    MOZ_ASSERT(NS_SUCCEEDED(rv));
33
0
    return originA < originB;
34
0
  }
35
36
  bool Equals(nsIPrincipal* a, nsIPrincipal* b) const
37
0
  {
38
0
    nsAutoCString originA;
39
0
    DebugOnly<nsresult> rv = a->GetOrigin(originA);
40
0
    MOZ_ASSERT(NS_SUCCEEDED(rv));
41
0
    nsAutoCString originB;
42
0
    rv = b->GetOrigin(originB);
43
0
    MOZ_ASSERT(NS_SUCCEEDED(rv));
44
0
    return a == b;
45
0
  }
46
};
47
48
ExpandedPrincipal::ExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList)
49
  : BasePrincipal(eExpandedPrincipal)
50
0
{
51
0
  // We force the principals to be sorted by origin so that ExpandedPrincipal
52
0
  // origins can have a canonical form.
53
0
  OriginComparator c;
54
0
  for (size_t i = 0; i < aWhiteList.Length(); ++i) {
55
0
    mPrincipals.InsertElementSorted(aWhiteList[i], c);
56
0
  }
57
0
}
58
59
ExpandedPrincipal::ExpandedPrincipal()
60
  : BasePrincipal(eExpandedPrincipal)
61
0
{
62
0
}
63
64
ExpandedPrincipal::~ExpandedPrincipal()
65
0
{ }
66
67
already_AddRefed<ExpandedPrincipal>
68
ExpandedPrincipal::Create(nsTArray<nsCOMPtr<nsIPrincipal>>& aWhiteList,
69
                          const OriginAttributes& aAttrs)
70
0
{
71
0
  RefPtr<ExpandedPrincipal> ep = new ExpandedPrincipal(aWhiteList);
72
0
73
0
  nsAutoCString origin;
74
0
  origin.AssignLiteral("[Expanded Principal [");
75
0
  for (size_t i = 0; i < ep->mPrincipals.Length(); ++i) {
76
0
    if (i != 0) {
77
0
      origin.AppendLiteral(", ");
78
0
    }
79
0
80
0
    nsAutoCString subOrigin;
81
0
    DebugOnly<nsresult> rv = ep->mPrincipals.ElementAt(i)->GetOrigin(subOrigin);
82
0
    MOZ_ASSERT(NS_SUCCEEDED(rv));
83
0
    origin.Append(subOrigin);
84
0
  }
85
0
  origin.AppendLiteral("]]");
86
0
87
0
  ep->FinishInit(origin, aAttrs);
88
0
  return ep.forget();
89
0
}
90
91
NS_IMETHODIMP
92
ExpandedPrincipal::GetDomain(nsIURI** aDomain)
93
0
{
94
0
  *aDomain = nullptr;
95
0
  return NS_OK;
96
0
}
97
98
NS_IMETHODIMP
99
ExpandedPrincipal::SetDomain(nsIURI* aDomain)
100
0
{
101
0
  return NS_OK;
102
0
}
103
104
bool
105
ExpandedPrincipal::SubsumesInternal(nsIPrincipal* aOther,
106
                                    BasePrincipal::DocumentDomainConsideration aConsideration)
107
0
{
108
0
  // If aOther is an ExpandedPrincipal too, we break it down into its component
109
0
  // nsIPrincipals, and check subsumes on each one.
110
0
  if (Cast(aOther)->Is<ExpandedPrincipal>()) {
111
0
    auto* expanded = Cast(aOther)->As<ExpandedPrincipal>();
112
0
113
0
    for (auto& other : expanded->WhiteList()) {
114
0
      // Use SubsumesInternal rather than Subsumes here, since OriginAttribute
115
0
      // checks are only done between non-expanded sub-principals, and we don't
116
0
      // need to incur the extra virtual call overhead.
117
0
      if (!SubsumesInternal(other, aConsideration)) {
118
0
        return false;
119
0
      }
120
0
    }
121
0
    return true;
122
0
  }
123
0
124
0
  // We're dealing with a regular principal. One of our principals must subsume
125
0
  // it.
126
0
  for (uint32_t i = 0; i < mPrincipals.Length(); ++i) {
127
0
    if (Cast(mPrincipals[i])->Subsumes(aOther, aConsideration)) {
128
0
      return true;
129
0
    }
130
0
  }
131
0
132
0
  return false;
133
0
}
134
135
bool
136
ExpandedPrincipal::MayLoadInternal(nsIURI* uri)
137
0
{
138
0
  for (uint32_t i = 0; i < mPrincipals.Length(); ++i){
139
0
    if (BasePrincipal::Cast(mPrincipals[i])->MayLoadInternal(uri)) {
140
0
      return true;
141
0
    }
142
0
  }
143
0
144
0
  return false;
145
0
}
146
147
NS_IMETHODIMP
148
ExpandedPrincipal::GetHashValue(uint32_t* result)
149
0
{
150
0
  MOZ_CRASH("extended principal should never be used as key in a hash map");
151
0
}
152
153
NS_IMETHODIMP
154
ExpandedPrincipal::GetURI(nsIURI** aURI)
155
0
{
156
0
  *aURI = nullptr;
157
0
  return NS_OK;
158
0
}
159
160
const nsTArray<nsCOMPtr<nsIPrincipal>>&
161
ExpandedPrincipal::WhiteList()
162
0
{
163
0
  return mPrincipals;
164
0
}
165
166
NS_IMETHODIMP
167
ExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
168
0
{
169
0
  return NS_ERROR_NOT_AVAILABLE;
170
0
}
171
172
NS_IMETHODIMP
173
ExpandedPrincipal::GetAddonId(nsAString& aAddonId)
174
0
{
175
0
  aAddonId.Truncate();
176
0
  return NS_OK;
177
0
};
178
179
bool
180
ExpandedPrincipal::AddonHasPermission(const nsAtom* aPerm)
181
0
{
182
0
  for (size_t i = 0; i < mPrincipals.Length(); ++i) {
183
0
    if (BasePrincipal::Cast(mPrincipals[i])->AddonHasPermission(aPerm)) {
184
0
      return true;
185
0
    }
186
0
  }
187
0
  return false;
188
0
}
189
190
bool
191
ExpandedPrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */)
192
0
{
193
0
  for (const auto& principal : mPrincipals) {
194
0
    if (Cast(principal)->AddonAllowsLoad(aURI, aExplicit)) {
195
0
      return true;
196
0
    }
197
0
  }
198
0
  return false;
199
0
}
200
201
nsIPrincipal*
202
ExpandedPrincipal::PrincipalToInherit(nsIURI* aRequestedURI)
203
0
{
204
0
  if (aRequestedURI) {
205
0
    // If a given sub-principal subsumes the given URI, use that principal for
206
0
    // inheritance. In general, this only happens with certain CORS modes, loads
207
0
    // with forced principal inheritance, and creation of XML documents from
208
0
    // XMLHttpRequests or fetch requests. For URIs that normally inherit a
209
0
    // principal (such as data: URIs), we fall back to the last principal in the
210
0
    // whitelist.
211
0
    for (const auto& principal : mPrincipals) {
212
0
      if (Cast(principal)->MayLoadInternal(aRequestedURI)) {
213
0
        return principal;
214
0
      }
215
0
    }
216
0
  }
217
0
  return mPrincipals.LastElement();
218
0
}
219
220
nsresult
221
ExpandedPrincipal::GetScriptLocation(nsACString& aStr)
222
0
{
223
0
  aStr.AssignLiteral("[Expanded Principal [");
224
0
  for (size_t i = 0; i < mPrincipals.Length(); ++i) {
225
0
    if (i != 0) {
226
0
      aStr.AppendLiteral(", ");
227
0
    }
228
0
229
0
    nsAutoCString spec;
230
0
    nsresult rv =
231
0
      nsJSPrincipals::get(mPrincipals.ElementAt(i))->GetScriptLocation(spec);
232
0
    NS_ENSURE_SUCCESS(rv, rv);
233
0
234
0
    aStr.Append(spec);
235
0
  }
236
0
  aStr.AppendLiteral("]]");
237
0
  return NS_OK;
238
0
}
239
240
//////////////////////////////////////////
241
// Methods implementing nsISerializable //
242
//////////////////////////////////////////
243
244
// We've had way too many issues with unversioned serializations, so
245
// explicitly version this one.
246
static const uint32_t kSerializationVersion = 1;
247
248
NS_IMETHODIMP
249
ExpandedPrincipal::Read(nsIObjectInputStream* aStream)
250
0
{
251
0
  uint32_t version;
252
0
  nsresult rv = aStream->Read32(&version);
253
0
  if (version != kSerializationVersion) {
254
0
    MOZ_ASSERT(false,
255
0
               "We really need to add handling of the old(?) version here");
256
0
    return NS_ERROR_UNEXPECTED;
257
0
  }
258
0
259
0
  uint32_t count;
260
0
  rv = aStream->Read32(&count);
261
0
  if (NS_FAILED(rv)) {
262
0
    return rv;
263
0
  }
264
0
265
0
  if (!mPrincipals.SetCapacity(count, fallible)) {
266
0
    return NS_ERROR_OUT_OF_MEMORY;
267
0
  }
268
0
269
0
  OriginComparator c;
270
0
  for (uint32_t i = 0; i < count; ++i) {
271
0
    nsCOMPtr<nsISupports> read;
272
0
    rv = aStream->ReadObject(true, getter_AddRefs(read));
273
0
    if (NS_FAILED(rv)) {
274
0
      return rv;
275
0
    }
276
0
277
0
    nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(read);
278
0
    if (!principal) {
279
0
      return NS_ERROR_UNEXPECTED;
280
0
    }
281
0
282
0
    // Play it safe and InsertElementSorted, in case the sort order
283
0
    // changed for some bizarre reason.
284
0
    mPrincipals.InsertElementSorted(std::move(principal), c);
285
0
  }
286
0
287
0
  return NS_OK;
288
0
}
289
290
NS_IMETHODIMP
291
ExpandedPrincipal::Write(nsIObjectOutputStream* aStream)
292
0
{
293
0
  nsresult rv = aStream->Write32(kSerializationVersion);
294
0
  if (NS_FAILED(rv)) {
295
0
    return rv;
296
0
  }
297
0
298
0
  rv = aStream->Write32(mPrincipals.Length());
299
0
  if (NS_FAILED(rv)) {
300
0
    return rv;
301
0
  }
302
0
303
0
  for (auto& principal : mPrincipals) {
304
0
    rv = aStream->WriteObject(principal, true);
305
0
    if (NS_FAILED(rv)) {
306
0
      return rv;
307
0
    }
308
0
  }
309
0
310
0
  return NS_OK;
311
0
}
312
313
nsresult
314
ExpandedPrincipal::GetSiteIdentifier(SiteIdentifier& aSite)
315
0
{
316
0
  // Call GetSiteIdentifier on each of our principals and return a new
317
0
  // ExpandedPrincipal.
318
0
319
0
  nsTArray<nsCOMPtr<nsIPrincipal>> whitelist;
320
0
  for (const auto& principal : mPrincipals) {
321
0
    SiteIdentifier site;
322
0
    nsresult rv = Cast(principal)->GetSiteIdentifier(site);
323
0
    NS_ENSURE_SUCCESS(rv, rv);
324
0
    whitelist.AppendElement(site.GetPrincipal());
325
0
  }
326
0
327
0
  RefPtr<ExpandedPrincipal> expandedPrincipal =
328
0
    ExpandedPrincipal::Create(whitelist, OriginAttributesRef());
329
0
  MOZ_ASSERT(expandedPrincipal, "ExpandedPrincipal::Create returned nullptr?");
330
0
331
0
  aSite.Init(expandedPrincipal);
332
0
  return NS_OK;
333
0
}