1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "extensions/common/permissions/api_permission_set.h"
6 
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/values.h"
11 #include "extensions/common/error_utils.h"
12 #include "extensions/common/manifest_constants.h"
13 #include "extensions/common/permissions/permissions_info.h"
14 
15 namespace extensions {
16 
17 namespace errors = manifest_errors;
18 
19 namespace {
20 
21 // Helper object that is implicitly constructible from both a PermissionID and
22 // from an APIPermission::ID.
23 struct PermissionIDCompareHelper {
PermissionIDCompareHelperextensions::__anona76ac7830111::PermissionIDCompareHelper24   PermissionIDCompareHelper(const PermissionID& id) : id(id.id()) {}
PermissionIDCompareHelperextensions::__anona76ac7830111::PermissionIDCompareHelper25   PermissionIDCompareHelper(const APIPermission::ID id) : id(id) {}
26 
27   APIPermission::ID id;
28 };
29 
CreateAPIPermission(const std::string & permission_str,const base::Value * permission_value,APIPermissionSet::ParseSource source,APIPermissionSet * api_permissions,base::string16 * error,std::vector<std::string> * unhandled_permissions)30 bool CreateAPIPermission(
31     const std::string& permission_str,
32     const base::Value* permission_value,
33     APIPermissionSet::ParseSource source,
34     APIPermissionSet* api_permissions,
35     base::string16* error,
36     std::vector<std::string>* unhandled_permissions) {
37 
38   const APIPermissionInfo* permission_info =
39       PermissionsInfo::GetInstance()->GetByName(permission_str);
40   if (permission_info) {
41     std::unique_ptr<APIPermission> permission(
42         permission_info->CreateAPIPermission());
43     if (source != APIPermissionSet::kAllowInternalPermissions &&
44         permission_info->is_internal()) {
45       // An internal permission specified in permissions list is an error.
46       if (error) {
47         *error = ErrorUtils::FormatErrorMessageUTF16(
48             errors::kPermissionNotAllowedInManifest, permission_str);
49       }
50       return false;
51     }
52 
53     std::string error_details;
54     if (!permission->FromValue(permission_value, &error_details,
55                                unhandled_permissions)) {
56       if (error) {
57         if (error_details.empty()) {
58           *error = ErrorUtils::FormatErrorMessageUTF16(
59               errors::kInvalidPermission,
60               permission_info->name());
61         } else {
62           *error = ErrorUtils::FormatErrorMessageUTF16(
63               errors::kInvalidPermissionWithDetail,
64               permission_info->name(),
65               error_details);
66         }
67         return false;
68       }
69       LOG(WARNING) << "Parse permission failed.";
70     } else {
71       api_permissions->insert(std::move(permission));
72     }
73     return true;
74   }
75 
76   if (unhandled_permissions)
77     unhandled_permissions->push_back(permission_str);
78   else
79     LOG(WARNING) << "Unknown permission[" << permission_str << "].";
80 
81   return true;
82 }
83 
ParseChildPermissions(const std::string & base_name,const base::Value * permission_value,APIPermissionSet::ParseSource source,APIPermissionSet * api_permissions,base::string16 * error,std::vector<std::string> * unhandled_permissions)84 bool ParseChildPermissions(const std::string& base_name,
85                            const base::Value* permission_value,
86                            APIPermissionSet::ParseSource source,
87                            APIPermissionSet* api_permissions,
88                            base::string16* error,
89                            std::vector<std::string>* unhandled_permissions) {
90   if (permission_value) {
91     if (!permission_value->is_list()) {
92       if (error) {
93         *error = ErrorUtils::FormatErrorMessageUTF16(
94             errors::kInvalidPermission, base_name);
95         return false;
96       }
97       LOG(WARNING) << "Permission value is not a list.";
98       // Failed to parse, but since error is NULL, failures are not fatal so
99       // return true here anyway.
100       return true;
101     }
102 
103     base::Value::ConstListView list_view = permission_value->GetList();
104     for (size_t i = 0; i < list_view.size(); ++i) {
105       std::string permission_str;
106       if (!list_view[i].is_string()) {
107         // permission should be a string
108         if (error) {
109           *error = ErrorUtils::FormatErrorMessageUTF16(
110               errors::kInvalidPermission,
111               base_name + '.' + base::NumberToString(i));
112           return false;
113         }
114         LOG(WARNING) << "Permission is not a string.";
115         continue;
116       }
117 
118       if (!CreateAPIPermission(base_name + '.' + list_view[i].GetString(),
119                                nullptr, source, api_permissions, error,
120                                unhandled_permissions))
121         return false;
122     }
123   }
124 
125   return CreateAPIPermission(base_name, nullptr, source, api_permissions, error,
126                              nullptr);
127 }
128 
129 }  // namespace
130 
insert(APIPermission::ID id)131 void APIPermissionSet::insert(APIPermission::ID id) {
132   const APIPermissionInfo* permission_info =
133       PermissionsInfo::GetInstance()->GetByID(id);
134   DCHECK(permission_info);
135   insert(permission_info->CreateAPIPermission());
136 }
137 
insert(std::unique_ptr<APIPermission> permission)138 void APIPermissionSet::insert(std::unique_ptr<APIPermission> permission) {
139   BaseSetOperators<APIPermissionSet>::insert(std::move(permission));
140 }
141 
142 // static
ParseFromJSON(const base::Value * permissions,APIPermissionSet::ParseSource source,APIPermissionSet * api_permissions,base::string16 * error,std::vector<std::string> * unhandled_permissions)143 bool APIPermissionSet::ParseFromJSON(
144     const base::Value* permissions,
145     APIPermissionSet::ParseSource source,
146     APIPermissionSet* api_permissions,
147     base::string16* error,
148     std::vector<std::string>* unhandled_permissions) {
149   if (!permissions->is_list()) {
150     if (error) {
151       *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermission,
152                                                    "<root>");
153       return false;
154     }
155     LOG(WARNING) << "Root Permissions value is not a list.";
156     // Failed to parse, but since error is NULL, failures are not fatal so
157     // return true here anyway.
158     return true;
159   }
160   base::Value::ConstListView list_view = permissions->GetList();
161   for (size_t i = 0; i < list_view.size(); ++i) {
162     std::string permission_str;
163     const base::Value* permission_value = nullptr;
164     // permission should be a string or a single key dict.
165     if (list_view[i].is_string()) {
166       permission_str = list_view[i].GetString();
167     } else if (list_view[i].is_dict() && list_view[i].DictSize() == 1) {
168       auto dict_iter = list_view[i].DictItems().begin();
169       permission_str = dict_iter->first;
170       permission_value = &dict_iter->second;
171     } else {
172       if (error) {
173         *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermission,
174                                                      base::NumberToString(i));
175         return false;
176       }
177       LOG(WARNING) << "Permission is not a string or single key dict.";
178       continue;
179     }
180 
181     // Check if this permission is a special case where its value should
182     // be treated as a list of child permissions.
183     if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) {
184       if (!ParseChildPermissions(permission_str, permission_value, source,
185                                  api_permissions, error, unhandled_permissions))
186         return false;
187       continue;
188     }
189 
190     if (!CreateAPIPermission(permission_str, permission_value, source,
191                              api_permissions, error, unhandled_permissions))
192       return false;
193   }
194   return true;
195 }
196 
PermissionID(APIPermission::ID id)197 PermissionID::PermissionID(APIPermission::ID id)
198     : std::pair<APIPermission::ID, base::string16>(id, base::string16()) {
199 }
200 
PermissionID(APIPermission::ID id,const base::string16 & parameter)201 PermissionID::PermissionID(APIPermission::ID id,
202                            const base::string16& parameter)
203     : std::pair<APIPermission::ID, base::string16>(id, parameter) {
204 }
205 
~PermissionID()206 PermissionID::~PermissionID() {
207 }
208 
PermissionIDSet()209 PermissionIDSet::PermissionIDSet() {
210 }
211 
PermissionIDSet(std::initializer_list<APIPermission::ID> permissions)212 PermissionIDSet::PermissionIDSet(
213     std::initializer_list<APIPermission::ID> permissions) {
214   for (auto permission : permissions) {
215     permissions_.insert(PermissionID(permission));
216   }
217 }
218 
219 PermissionIDSet::PermissionIDSet(const PermissionIDSet& other) = default;
220 
~PermissionIDSet()221 PermissionIDSet::~PermissionIDSet() {
222 }
223 
insert(APIPermission::ID permission_id)224 void PermissionIDSet::insert(APIPermission::ID permission_id) {
225   insert(permission_id, base::string16());
226 }
227 
insert(APIPermission::ID permission_id,const base::string16 & permission_detail)228 void PermissionIDSet::insert(APIPermission::ID permission_id,
229                              const base::string16& permission_detail) {
230   permissions_.insert(PermissionID(permission_id, permission_detail));
231 }
232 
InsertAll(const PermissionIDSet & permission_set)233 void PermissionIDSet::InsertAll(const PermissionIDSet& permission_set) {
234   for (const auto& permission : permission_set.permissions_) {
235     permissions_.insert(permission);
236   }
237 }
238 
erase(APIPermission::ID permission_id)239 void PermissionIDSet::erase(APIPermission::ID permission_id) {
240   auto lower_bound = permissions_.lower_bound(PermissionID(permission_id));
241   auto upper_bound = lower_bound;
242   while (upper_bound != permissions_.end() &&
243          upper_bound->id() == permission_id) {
244     ++upper_bound;
245   }
246   permissions_.erase(lower_bound, upper_bound);
247 }
248 
GetAllPermissionParameters() const249 std::vector<base::string16> PermissionIDSet::GetAllPermissionParameters()
250     const {
251   std::vector<base::string16> params;
252   for (const auto& permission : permissions_) {
253     params.push_back(permission.parameter());
254   }
255   return params;
256 }
257 
ContainsID(PermissionID permission_id) const258 bool PermissionIDSet::ContainsID(PermissionID permission_id) const {
259   auto it = permissions_.lower_bound(permission_id);
260   return it != permissions_.end() && it->id() == permission_id.id();
261 }
262 
ContainsID(APIPermission::ID permission_id) const263 bool PermissionIDSet::ContainsID(APIPermission::ID permission_id) const {
264   return ContainsID(PermissionID(permission_id));
265 }
266 
ContainsAllIDs(const std::set<APIPermission::ID> & permission_ids) const267 bool PermissionIDSet::ContainsAllIDs(
268     const std::set<APIPermission::ID>& permission_ids) const {
269   return std::includes(permissions_.begin(), permissions_.end(),
270                        permission_ids.begin(), permission_ids.end(),
271                        [] (const PermissionIDCompareHelper& lhs,
272                            const PermissionIDCompareHelper& rhs) {
273                          return lhs.id < rhs.id;
274                        });
275 }
276 
ContainsAnyID(const std::set<APIPermission::ID> & permission_ids) const277 bool PermissionIDSet::ContainsAnyID(
278     const std::set<APIPermission::ID>& permission_ids) const {
279   for (APIPermission::ID id : permission_ids) {
280     if (ContainsID(id))
281       return true;
282   }
283   return false;
284 }
285 
ContainsAnyID(const PermissionIDSet & other) const286 bool PermissionIDSet::ContainsAnyID(const PermissionIDSet& other) const {
287   for (const auto& id : other) {
288     if (ContainsID(id))
289       return true;
290   }
291   return false;
292 }
293 
GetAllPermissionsWithID(APIPermission::ID permission_id) const294 PermissionIDSet PermissionIDSet::GetAllPermissionsWithID(
295     APIPermission::ID permission_id) const {
296   PermissionIDSet subset;
297   auto it = permissions_.lower_bound(PermissionID(permission_id));
298   while (it != permissions_.end() && it->id() == permission_id) {
299     subset.permissions_.insert(*it);
300     ++it;
301   }
302   return subset;
303 }
304 
GetAllPermissionsWithIDs(const std::set<APIPermission::ID> & permission_ids) const305 PermissionIDSet PermissionIDSet::GetAllPermissionsWithIDs(
306     const std::set<APIPermission::ID>& permission_ids) const {
307   PermissionIDSet subset;
308   for (const auto& permission : permissions_) {
309     if (base::Contains(permission_ids, permission.id())) {
310       subset.permissions_.insert(permission);
311     }
312   }
313   return subset;
314 }
315 
Includes(const PermissionIDSet & subset) const316 bool PermissionIDSet::Includes(const PermissionIDSet& subset) const {
317   return base::STLIncludes(permissions_, subset.permissions_);
318 }
319 
Equals(const PermissionIDSet & set) const320 bool PermissionIDSet::Equals(const PermissionIDSet& set) const {
321   return permissions_ == set.permissions_;
322 }
323 
324 // static
Difference(const PermissionIDSet & set_1,const PermissionIDSet & set_2)325 PermissionIDSet PermissionIDSet::Difference(const PermissionIDSet& set_1,
326                                             const PermissionIDSet& set_2) {
327   return PermissionIDSet(base::STLSetDifference<std::set<PermissionID>>(
328       set_1.permissions_, set_2.permissions_));
329 }
330 
size() const331 size_t PermissionIDSet::size() const {
332   return permissions_.size();
333 }
334 
empty() const335 bool PermissionIDSet::empty() const {
336   return permissions_.empty();
337 }
338 
PermissionIDSet(const std::set<PermissionID> & permissions)339 PermissionIDSet::PermissionIDSet(const std::set<PermissionID>& permissions)
340     : permissions_(permissions) {
341 }
342 
343 }  // namespace extensions
344