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 #include "nsPermission.h"
7 #include "nsContentUtils.h"
8 #include "nsIClassInfoImpl.h"
9 #include "nsIEffectiveTLDService.h"
10 #include "mozilla/BasePrincipal.h"
11
12 // nsPermission Implementation
13
14 NS_IMPL_CLASSINFO(nsPermission, nullptr, 0, {0})
NS_IMPL_ISUPPORTS_CI(nsPermission,nsIPermission)15 NS_IMPL_ISUPPORTS_CI(nsPermission, nsIPermission)
16
17 nsPermission::nsPermission(nsIPrincipal* aPrincipal, const nsACString& aType,
18 uint32_t aCapability, uint32_t aExpireType,
19 int64_t aExpireTime)
20 : mPrincipal(aPrincipal),
21 mType(aType),
22 mCapability(aCapability),
23 mExpireType(aExpireType),
24 mExpireTime(aExpireTime) {}
25
Create(nsIPrincipal * aPrincipal,const nsACString & aType,uint32_t aCapability,uint32_t aExpireType,int64_t aExpireTime)26 already_AddRefed<nsPermission> nsPermission::Create(nsIPrincipal* aPrincipal,
27 const nsACString& aType,
28 uint32_t aCapability,
29 uint32_t aExpireType,
30 int64_t aExpireTime) {
31 NS_ENSURE_TRUE(aPrincipal, nullptr);
32 nsCOMPtr<nsIPrincipal> principal =
33 mozilla::BasePrincipal::Cast(aPrincipal)
34 ->CloneStrippingUserContextIdAndFirstPartyDomain();
35
36 NS_ENSURE_TRUE(principal, nullptr);
37
38 RefPtr<nsPermission> permission =
39 new nsPermission(principal, aType, aCapability, aExpireType, aExpireTime);
40 return permission.forget();
41 }
42
43 NS_IMETHODIMP
GetPrincipal(nsIPrincipal ** aPrincipal)44 nsPermission::GetPrincipal(nsIPrincipal** aPrincipal) {
45 nsCOMPtr<nsIPrincipal> copy = mPrincipal;
46 copy.forget(aPrincipal);
47 return NS_OK;
48 }
49
50 NS_IMETHODIMP
GetType(nsACString & aType)51 nsPermission::GetType(nsACString& aType) {
52 aType = mType;
53 return NS_OK;
54 }
55
56 NS_IMETHODIMP
GetCapability(uint32_t * aCapability)57 nsPermission::GetCapability(uint32_t* aCapability) {
58 *aCapability = mCapability;
59 return NS_OK;
60 }
61
62 NS_IMETHODIMP
GetExpireType(uint32_t * aExpireType)63 nsPermission::GetExpireType(uint32_t* aExpireType) {
64 *aExpireType = mExpireType;
65 return NS_OK;
66 }
67
68 NS_IMETHODIMP
GetExpireTime(int64_t * aExpireTime)69 nsPermission::GetExpireTime(int64_t* aExpireTime) {
70 *aExpireTime = mExpireTime;
71 return NS_OK;
72 }
73
74 NS_IMETHODIMP
Matches(nsIPrincipal * aPrincipal,bool aExactHost,bool * aMatches)75 nsPermission::Matches(nsIPrincipal* aPrincipal, bool aExactHost,
76 bool* aMatches) {
77 NS_ENSURE_ARG_POINTER(aPrincipal);
78 NS_ENSURE_ARG_POINTER(aMatches);
79
80 *aMatches = false;
81
82 nsCOMPtr<nsIPrincipal> principal =
83 mozilla::BasePrincipal::Cast(aPrincipal)
84 ->CloneStrippingUserContextIdAndFirstPartyDomain();
85
86 if (!principal) {
87 *aMatches = false;
88 return NS_OK;
89 }
90
91 // If the principals are equal, then they match.
92 if (mPrincipal->Equals(principal)) {
93 *aMatches = true;
94 return NS_OK;
95 }
96
97 // If we are matching with an exact host, we're done now - the permissions
98 // don't match otherwise, we need to start comparing subdomains!
99 if (aExactHost) {
100 return NS_OK;
101 }
102
103 // Compare their OriginAttributes
104 const mozilla::OriginAttributes& theirAttrs =
105 principal->OriginAttributesRef();
106 const mozilla::OriginAttributes& ourAttrs = mPrincipal->OriginAttributesRef();
107
108 if (theirAttrs != ourAttrs) {
109 return NS_OK;
110 }
111
112 nsCOMPtr<nsIURI> theirURI;
113 nsresult rv = principal->GetURI(getter_AddRefs(theirURI));
114 NS_ENSURE_SUCCESS(rv, rv);
115
116 nsCOMPtr<nsIURI> ourURI;
117 rv = mPrincipal->GetURI(getter_AddRefs(ourURI));
118 NS_ENSURE_SUCCESS(rv, rv);
119
120 // Compare schemes
121 nsAutoCString theirScheme;
122 rv = theirURI->GetScheme(theirScheme);
123 NS_ENSURE_SUCCESS(rv, rv);
124
125 nsAutoCString ourScheme;
126 rv = ourURI->GetScheme(ourScheme);
127 NS_ENSURE_SUCCESS(rv, rv);
128
129 if (theirScheme != ourScheme) {
130 return NS_OK;
131 }
132
133 // Compare ports
134 int32_t theirPort;
135 rv = theirURI->GetPort(&theirPort);
136 NS_ENSURE_SUCCESS(rv, rv);
137
138 int32_t ourPort;
139 rv = ourURI->GetPort(&ourPort);
140 NS_ENSURE_SUCCESS(rv, rv);
141
142 if (theirPort != ourPort) {
143 return NS_OK;
144 }
145
146 // Check if the host or any subdomain of their host matches.
147 nsAutoCString theirHost;
148 rv = theirURI->GetHost(theirHost);
149 if (NS_FAILED(rv) || theirHost.IsEmpty()) {
150 return NS_OK;
151 }
152
153 nsAutoCString ourHost;
154 rv = ourURI->GetHost(ourHost);
155 if (NS_FAILED(rv) || ourHost.IsEmpty()) {
156 return NS_OK;
157 }
158
159 nsCOMPtr<nsIEffectiveTLDService> tldService =
160 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
161 if (!tldService) {
162 NS_ERROR("Should have a tld service!");
163 return NS_ERROR_FAILURE;
164 }
165
166 // This loop will not loop forever, as GetNextSubDomain will eventually fail
167 // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
168 while (theirHost != ourHost) {
169 rv = tldService->GetNextSubDomain(theirHost, theirHost);
170 if (NS_FAILED(rv)) {
171 if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
172 return NS_OK;
173 } else {
174 return rv;
175 }
176 }
177 }
178
179 *aMatches = true;
180 return NS_OK;
181 }
182
183 NS_IMETHODIMP
MatchesURI(nsIURI * aURI,bool aExactHost,bool * aMatches)184 nsPermission::MatchesURI(nsIURI* aURI, bool aExactHost, bool* aMatches) {
185 NS_ENSURE_ARG_POINTER(aURI);
186
187 mozilla::OriginAttributes attrs;
188 nsCOMPtr<nsIPrincipal> principal =
189 mozilla::BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
190 NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
191
192 return Matches(principal, aExactHost, aMatches);
193 }
194