Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=4 et sw=4 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 "DomainPolicy.h"
8 : #include "mozilla/dom/ContentParent.h"
9 : #include "mozilla/ipc/URIUtils.h"
10 : #include "mozilla/Unused.h"
11 : #include "nsIMessageManager.h"
12 : #include "nsScriptSecurityManager.h"
13 :
14 : namespace mozilla {
15 :
16 : using namespace ipc;
17 : using namespace dom;
18 :
19 0 : NS_IMPL_ISUPPORTS(DomainPolicy, nsIDomainPolicy)
20 :
21 : static nsresult
22 0 : BroadcastDomainSetChange(DomainSetType aSetType, DomainSetChangeType aChangeType,
23 : nsIURI* aDomain = nullptr)
24 : {
25 0 : MOZ_ASSERT(XRE_IsParentProcess(),
26 : "DomainPolicy should only be exposed to the chrome process.");
27 :
28 0 : nsTArray<ContentParent*> parents;
29 0 : ContentParent::GetAll(parents);
30 0 : if (!parents.Length()) {
31 0 : return NS_OK;
32 : }
33 :
34 0 : OptionalURIParams uri;
35 0 : SerializeURI(aDomain, uri);
36 :
37 0 : for (uint32_t i = 0; i < parents.Length(); i++) {
38 0 : Unused << parents[i]->SendDomainSetChanged(aSetType, aChangeType, uri);
39 : }
40 0 : return NS_OK;
41 : }
42 :
43 0 : DomainPolicy::DomainPolicy() : mBlacklist(new DomainSet(BLACKLIST))
44 0 : , mSuperBlacklist(new DomainSet(SUPER_BLACKLIST))
45 0 : , mWhitelist(new DomainSet(WHITELIST))
46 0 : , mSuperWhitelist(new DomainSet(SUPER_WHITELIST))
47 : {
48 0 : if (XRE_IsParentProcess()) {
49 0 : BroadcastDomainSetChange(NO_TYPE, ACTIVATE_POLICY);
50 : }
51 0 : }
52 :
53 0 : DomainPolicy::~DomainPolicy()
54 : {
55 : // The SSM holds a strong ref to the DomainPolicy until Deactivate() is
56 : // invoked, so we should never hit the destructor until that happens.
57 0 : MOZ_ASSERT(!mBlacklist && !mSuperBlacklist &&
58 : !mWhitelist && !mSuperWhitelist);
59 0 : }
60 :
61 :
62 : NS_IMETHODIMP
63 0 : DomainPolicy::GetBlacklist(nsIDomainSet** aSet)
64 : {
65 0 : nsCOMPtr<nsIDomainSet> set = mBlacklist.get();
66 0 : set.forget(aSet);
67 0 : return NS_OK;
68 : }
69 :
70 : NS_IMETHODIMP
71 0 : DomainPolicy::GetSuperBlacklist(nsIDomainSet** aSet)
72 : {
73 0 : nsCOMPtr<nsIDomainSet> set = mSuperBlacklist.get();
74 0 : set.forget(aSet);
75 0 : return NS_OK;
76 : }
77 :
78 : NS_IMETHODIMP
79 0 : DomainPolicy::GetWhitelist(nsIDomainSet** aSet)
80 : {
81 0 : nsCOMPtr<nsIDomainSet> set = mWhitelist.get();
82 0 : set.forget(aSet);
83 0 : return NS_OK;
84 : }
85 :
86 : NS_IMETHODIMP
87 0 : DomainPolicy::GetSuperWhitelist(nsIDomainSet** aSet)
88 : {
89 0 : nsCOMPtr<nsIDomainSet> set = mSuperWhitelist.get();
90 0 : set.forget(aSet);
91 0 : return NS_OK;
92 : }
93 :
94 : NS_IMETHODIMP
95 0 : DomainPolicy::Deactivate()
96 : {
97 : // Clear the hashtables first to free up memory, since script might
98 : // hold the doomed sets alive indefinitely.
99 0 : mBlacklist->Clear();
100 0 : mSuperBlacklist->Clear();
101 0 : mWhitelist->Clear();
102 0 : mSuperWhitelist->Clear();
103 :
104 : // Null them out.
105 0 : mBlacklist = nullptr;
106 0 : mSuperBlacklist = nullptr;
107 0 : mWhitelist = nullptr;
108 0 : mSuperWhitelist = nullptr;
109 :
110 : // Inform the SSM.
111 0 : nsScriptSecurityManager* ssm = nsScriptSecurityManager::GetScriptSecurityManager();
112 0 : if (ssm) {
113 0 : ssm->DeactivateDomainPolicy();
114 : }
115 0 : if (XRE_IsParentProcess()) {
116 0 : BroadcastDomainSetChange(NO_TYPE, DEACTIVATE_POLICY);
117 : }
118 0 : return NS_OK;
119 : }
120 :
121 : void
122 0 : DomainPolicy::CloneDomainPolicy(DomainPolicyClone* aClone)
123 : {
124 0 : aClone->active() = true;
125 0 : mBlacklist->CloneSet(&aClone->blacklist());
126 0 : mSuperBlacklist->CloneSet(&aClone->superBlacklist());
127 0 : mWhitelist->CloneSet(&aClone->whitelist());
128 0 : mSuperWhitelist->CloneSet(&aClone->superWhitelist());
129 0 : }
130 :
131 : static
132 : void
133 0 : CopyURIs(const InfallibleTArray<URIParams>& aDomains, nsIDomainSet* aSet)
134 : {
135 0 : for (uint32_t i = 0; i < aDomains.Length(); i++) {
136 0 : nsCOMPtr<nsIURI> uri = DeserializeURI(aDomains[i]);
137 0 : aSet->Add(uri);
138 : }
139 0 : }
140 :
141 : void
142 0 : DomainPolicy::ApplyClone(const DomainPolicyClone* aClone)
143 : {
144 0 : CopyURIs(aClone->blacklist(), mBlacklist);
145 0 : CopyURIs(aClone->whitelist(), mWhitelist);
146 0 : CopyURIs(aClone->superBlacklist(), mSuperBlacklist);
147 0 : CopyURIs(aClone->superWhitelist(), mSuperWhitelist);
148 0 : }
149 :
150 : static already_AddRefed<nsIURI>
151 0 : GetCanonicalClone(nsIURI* aURI)
152 : {
153 0 : nsCOMPtr<nsIURI> clone;
154 0 : nsresult rv = aURI->Clone(getter_AddRefs(clone));
155 0 : NS_ENSURE_SUCCESS(rv, nullptr);
156 0 : rv = clone->SetUserPass(EmptyCString());
157 0 : NS_ENSURE_SUCCESS(rv, nullptr);
158 0 : rv = clone->SetPath(EmptyCString());
159 0 : NS_ENSURE_SUCCESS(rv, nullptr);
160 0 : return clone.forget();
161 : }
162 :
163 0 : NS_IMPL_ISUPPORTS(DomainSet, nsIDomainSet)
164 :
165 : NS_IMETHODIMP
166 0 : DomainSet::Add(nsIURI* aDomain)
167 : {
168 0 : nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
169 0 : NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
170 0 : mHashTable.PutEntry(clone);
171 0 : if (XRE_IsParentProcess())
172 0 : return BroadcastDomainSetChange(mType, ADD_DOMAIN, aDomain);
173 :
174 0 : return NS_OK;
175 : }
176 :
177 : NS_IMETHODIMP
178 0 : DomainSet::Remove(nsIURI* aDomain)
179 : {
180 0 : nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
181 0 : NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
182 0 : mHashTable.RemoveEntry(clone);
183 0 : if (XRE_IsParentProcess())
184 0 : return BroadcastDomainSetChange(mType, REMOVE_DOMAIN, aDomain);
185 :
186 0 : return NS_OK;
187 : }
188 :
189 : NS_IMETHODIMP
190 0 : DomainSet::Clear()
191 : {
192 0 : mHashTable.Clear();
193 0 : if (XRE_IsParentProcess())
194 0 : return BroadcastDomainSetChange(mType, CLEAR_DOMAINS);
195 :
196 0 : return NS_OK;
197 : }
198 :
199 : NS_IMETHODIMP
200 0 : DomainSet::Contains(nsIURI* aDomain, bool* aContains)
201 : {
202 0 : *aContains = false;
203 0 : nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
204 0 : NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
205 0 : *aContains = mHashTable.Contains(clone);
206 0 : return NS_OK;
207 : }
208 :
209 : NS_IMETHODIMP
210 0 : DomainSet::ContainsSuperDomain(nsIURI* aDomain, bool* aContains)
211 : {
212 0 : *aContains = false;
213 0 : nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
214 0 : NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
215 0 : nsAutoCString domain;
216 0 : nsresult rv = clone->GetHost(domain);
217 0 : NS_ENSURE_SUCCESS(rv, rv);
218 : while (true) {
219 : // Check the current domain.
220 0 : if (mHashTable.Contains(clone)) {
221 0 : *aContains = true;
222 0 : return NS_OK;
223 : }
224 :
225 : // Chop off everything before the first dot, or break if there are no
226 : // dots left.
227 0 : int32_t index = domain.Find(".");
228 0 : if (index == kNotFound)
229 0 : break;
230 0 : domain.Assign(Substring(domain, index + 1));
231 0 : rv = clone->SetHost(domain);
232 0 : NS_ENSURE_SUCCESS(rv, rv);
233 0 : }
234 :
235 : // No match.
236 0 : return NS_OK;
237 :
238 : }
239 :
240 : NS_IMETHODIMP
241 0 : DomainSet::GetType(uint32_t* aType)
242 : {
243 0 : *aType = mType;
244 0 : return NS_OK;
245 : }
246 :
247 : void
248 0 : DomainSet::CloneSet(InfallibleTArray<URIParams>* aDomains)
249 : {
250 0 : for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
251 0 : nsIURI* key = iter.Get()->GetKey();
252 :
253 0 : URIParams uri;
254 0 : SerializeURI(key, uri);
255 :
256 0 : aDomains->AppendElement(uri);
257 : }
258 0 : }
259 :
260 : } /* namespace mozilla */
|