1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "permission_utils.h"
16 
17 #include <unordered_set>
18 
19 #include "access_token.h"
20 #include "accesstoken_kit.h"
21 #include "el5_filekey_manager_kit.h"
22 #include "ipc_skeleton.h"
23 #include "iservice_registry.h"
24 #include "media_file_utils.h"
25 #include "media_log.h"
26 #include "medialibrary_db_const.h"
27 #include "medialibrary_errno.h"
28 #include "medialibrary_tracer.h"
29 #include "privacy_kit.h"
30 #include "system_ability_definition.h"
31 #include "tokenid_kit.h"
32 
33 namespace OHOS {
34 namespace Media {
35 using namespace std;
36 using namespace OHOS::Security::AccessToken;
37 using namespace OHOS::AppExecFwk::Constants;
38 
39 const int32_t CAPACITY = 50;
40 const int32_t HDC_SHELL_UID = 2000;
41 const int32_t BASE_USER_RANGE = 200000;
42 
43 std::mutex PermissionUtils::uninstallMutex_;
44 std::list<std::pair<int32_t, BundleInfo>> PermissionUtils::bundleInfoList_ = {};
45 std::unordered_map<int32_t, std::list<std::pair<int32_t, BundleInfo>>::iterator> PermissionUtils::bundleInfoMap_ = {};
46 
47 bool g_isDelayTask;
48 std::mutex addPhotoPermissionRecordLock_;
49 std::thread delayTask_;
50 std::vector<Security::AccessToken::AddPermParamInfo> infos_;
51 
52 sptr<AppExecFwk::IBundleMgr> PermissionUtils::bundleMgr_ = nullptr;
53 mutex PermissionUtils::bundleMgrMutex_;
GetSysBundleManager()54 sptr<AppExecFwk::IBundleMgr> PermissionUtils::GetSysBundleManager()
55 {
56     if (bundleMgr_ != nullptr) {
57         return bundleMgr_;
58     }
59 
60     lock_guard<mutex> lock(bundleMgrMutex_);
61     if (bundleMgr_ != nullptr) {
62         return bundleMgr_;
63     }
64 
65     auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
66     if (systemAbilityMgr == nullptr) {
67         MEDIA_ERR_LOG("Failed to get SystemAbilityManager.");
68         return nullptr;
69     }
70 
71     auto bundleObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
72     if (bundleObj == nullptr) {
73         MEDIA_ERR_LOG("Remote object is nullptr.");
74         return nullptr;
75     }
76 
77     auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
78     if (bundleMgr == nullptr) {
79         MEDIA_ERR_LOG("Failed to iface_cast");
80         return nullptr;
81     }
82     bundleMgr_ = bundleMgr;
83 
84     return bundleMgr_;
85 }
86 
GetBundleNameFromCache(int uid, string &bundleName)87 void PermissionUtils::GetBundleNameFromCache(int uid, string &bundleName)
88 {
89     lock_guard<mutex> lock(uninstallMutex_);
90     auto iter = bundleInfoMap_.find(uid);
91     if (iter != bundleInfoMap_.end() && !iter->second->second.bundleName.empty()) {
92         bundleInfoList_.splice(bundleInfoList_.begin(), bundleInfoList_, iter->second);
93         bundleName = iter->second->second.bundleName;
94         return;
95     }
96     bundleMgr_ = GetSysBundleManager();
97     if (bundleMgr_ == nullptr) {
98         bundleName = "";
99         return;
100     }
101     auto result = bundleMgr_->GetBundleNameForUid(uid, bundleName);
102     if (!result) {
103         bundleName = "";
104         return;
105     }
106 
107     UpdateBundleNameInCache(uid, bundleName);
108 }
109 
GetPackageNameFromCache(int uid, const string &bundleName, string &packageName)110 void PermissionUtils::GetPackageNameFromCache(int uid, const string &bundleName, string &packageName)
111 {
112     lock_guard<mutex> lock(uninstallMutex_);
113     auto iter = bundleInfoMap_.find(uid);
114     if (iter != bundleInfoMap_.end() && !iter->second->second.packageName.empty()) {
115         bundleInfoList_.splice(bundleInfoList_.begin(), bundleInfoList_, iter->second);
116         packageName = iter->second->second.packageName;
117         return;
118     }
119 
120     int32_t userId = uid / BASE_USER_RANGE;
121     MEDIA_DEBUG_LOG("uid:%{private}d, userId:%{private}d", uid, userId);
122 
123     AAFwk::Want want;
124     auto bundleMgr = GetSysBundleManager();
125     if (bundleMgr == nullptr) {
126         MEDIA_ERR_LOG("Get BundleManager failed");
127         packageName = "";
128         return;
129     }
130     int ret = bundleMgr->GetLaunchWantForBundle(bundleName, want, userId);
131     if (ret != ERR_OK) {
132         MEDIA_ERR_LOG("Can not get bundleName by want, err=%{public}d, userId=%{private}d", ret, userId);
133         packageName = "";
134         return;
135     }
136     string abilityName = want.GetOperation().GetAbilityName();
137     packageName = bundleMgr->GetAbilityLabel(bundleName, abilityName);
138 
139     UpdatePackageNameInCache(uid, packageName);
140 }
141 
GetAppIdFromCache(int uid, const string &bundleName, string &appId)142 void PermissionUtils::GetAppIdFromCache(int uid, const string &bundleName, string &appId)
143 {
144     lock_guard<mutex> lock(uninstallMutex_);
145     auto iter = bundleInfoMap_.find(uid);
146     if (iter != bundleInfoMap_.end() && !iter->second->second.appId.empty()) {
147         bundleInfoList_.splice(bundleInfoList_.begin(), bundleInfoList_, iter->second);
148         appId = iter->second->second.appId;
149         return;
150     }
151     int32_t userId = uid / BASE_USER_RANGE;
152     MEDIA_DEBUG_LOG("uid:%{private}d, userId:%{private}d", uid, userId);
153 
154     auto bundleMgr_ = GetSysBundleManager();
155     if (bundleMgr_ == nullptr) {
156         MEDIA_ERR_LOG("Get BundleManager failed");
157         return;
158     }
159 
160     appId = bundleMgr_->GetAppIdByBundleName(bundleName, userId);
161 
162     UpdateAppIdInCache(uid, appId);
163 }
164 
UpdateLatestBundleInfo(int uid, const BundleInfo &bundleInfo)165 void PermissionUtils::UpdateLatestBundleInfo(int uid, const BundleInfo &bundleInfo)
166 {
167     auto iter = bundleInfoMap_.find(uid);
168     if (iter != bundleInfoMap_.end()) {
169         bundleInfoList_.erase(iter->second);
170     }
171     bundleInfoList_.push_front(make_pair(uid, bundleInfo));
172     bundleInfoMap_[uid] = bundleInfoList_.begin();
173     if (bundleInfoMap_.size() > CAPACITY) {
174         int32_t deleteKey = bundleInfoList_.back().first;
175         bundleInfoMap_.erase(deleteKey);
176         bundleInfoList_.pop_back();
177     }
178 }
179 
UpdateBundleNameInCache(int uid, const string &bundleName)180 void PermissionUtils::UpdateBundleNameInCache(int uid, const string &bundleName)
181 {
182     auto iter = bundleInfoMap_.find(uid);
183     if (iter != bundleInfoMap_.end()) {
184         BundleInfo bundleInfo = bundleInfoMap_[uid]->second;
185         bundleInfo.bundleName = bundleName;
186         UpdateLatestBundleInfo(uid, bundleInfo);
187         return;
188     }
189     BundleInfo bundleInfo { bundleName, "", "" };
190     UpdateLatestBundleInfo(uid, bundleInfo);
191 }
192 
UpdatePackageNameInCache(int uid, const string &packageName)193 void PermissionUtils::UpdatePackageNameInCache(int uid, const string &packageName)
194 {
195     auto iter = bundleInfoMap_.find(uid);
196     if (iter != bundleInfoMap_.end()) {
197         BundleInfo bundleInfo = bundleInfoMap_[uid]->second;
198         bundleInfo.packageName = packageName;
199         UpdateLatestBundleInfo(uid, bundleInfo);
200         return;
201     }
202     BundleInfo bundleInfo { "", packageName, "" };
203     UpdateLatestBundleInfo(uid, bundleInfo);
204 }
205 
UpdateAppIdInCache(int uid, const string &appId)206 void PermissionUtils::UpdateAppIdInCache(int uid, const string &appId)
207 {
208     BundleInfo bundleInfo { "", "", appId };
209     auto iter = bundleInfoMap_.find(uid);
210     if (iter != bundleInfoMap_.end()) {
211         bundleInfo = bundleInfoMap_[uid]->second;
212         bundleInfo.appId = appId;
213     }
214     UpdateLatestBundleInfo(uid, bundleInfo);
215 }
216 
ClearBundleInfoInCache()217 void PermissionUtils::ClearBundleInfoInCache()
218 {
219     lock_guard<mutex> lock(uninstallMutex_);
220     bundleInfoMap_.clear();
221     bundleInfoList_.clear();
222     MEDIA_INFO_LOG("clear all info from cache");
223 }
224 
GetClientBundle(const int uid, string &bundleName)225 void PermissionUtils::GetClientBundle(const int uid, string &bundleName)
226 {
227     GetBundleNameFromCache(uid, bundleName);
228 }
229 
GetPackageName(const int uid, std::string &packageName)230 void PermissionUtils::GetPackageName(const int uid, std::string &packageName)
231 {
232     packageName = "";
233     string bundleName;
234     GetClientBundle(uid, bundleName);
235     if (bundleName.empty()) {
236         MEDIA_ERR_LOG("Get bundle name failed");
237         return;
238     }
239 
240     GetPackageNameFromCache(uid, bundleName, packageName);
241 }
242 
ShouldAddPermissionRecord(const AccessTokenID &token)243 bool inline ShouldAddPermissionRecord(const AccessTokenID &token)
244 {
245     return (AccessTokenKit::GetTokenTypeFlag(token) == TOKEN_HAP);
246 }
247 
AddPermissionRecord(const AccessTokenID &token, const string &perm, const bool permGranted)248 void AddPermissionRecord(const AccessTokenID &token, const string &perm, const bool permGranted)
249 {
250     if (!ShouldAddPermissionRecord(token)) {
251         return;
252     }
253 
254     int res = PrivacyKit::AddPermissionUsedRecord(token, perm, !!permGranted, !permGranted, true);
255     if (res != 0) {
256         /* Failed to add permission used record, not fatal */
257         MEDIA_WARN_LOG("Failed to add permission used record: %{public}s, permGranted: %{public}d, err: %{public}d",
258             perm.c_str(), permGranted, res);
259     }
260 }
261 
GetPermissionRecord()262 vector<AddPermParamInfo> GetPermissionRecord()
263 {
264     lock_guard<mutex> lock(addPhotoPermissionRecordLock_);
265     vector<AddPermParamInfo> result = infos_;
266     infos_.clear();
267     return result;
268 }
269 
AddPermissionRecord()270 void AddPermissionRecord()
271 {
272     vector<AddPermParamInfo> infos = GetPermissionRecord();
273     for (const auto &info : infos) {
274         int32_t ret = PrivacyKit::AddPermissionUsedRecord(info, true);
275         if (ret != 0) {
276             /* Failed to add permission used record, not fatal */
277             MEDIA_WARN_LOG("Failed to add permission used record: %{public}s, permGranted: %{public}d, err: %{public}d",
278                 info.permissionName.c_str(), info.successCount, ret);
279         }
280         MEDIA_DEBUG_LOG("Info: token = %{private}d, perm = %{private}s, permGranted = %{private}d, \
281             !permGranted = %{private}d, type = %{public}d", info.tokenId, info.permissionName.c_str(),
282             info.successCount, info.failCount, info.type);
283     }
284     infos.clear();
285 }
286 
DelayAddPermissionRecord()287 void DelayAddPermissionRecord()
288 {
289     string name("DelayAddPermissionRecord");
290     pthread_setname_np(pthread_self(), name.c_str());
291     MEDIA_INFO_LOG("DelayTask start");
292     std::this_thread::sleep_for(std::chrono::seconds(1));
293     AddPermissionRecord();
294     g_isDelayTask = false;
295     MEDIA_INFO_LOG("DelayTask end");
296 }
297 
DelayTaskInit()298 void DelayTaskInit()
299 {
300     if (!g_isDelayTask) {
301         MEDIA_INFO_LOG("DelayTaskInit");
302         delayTask_ = thread(DelayAddPermissionRecord);
303         delayTask_.detach();
304         g_isDelayTask = true;
305     }
306 }
307 
CollectPermissionRecord(const AccessTokenID &token, const string &perm, const bool permGranted, const PermissionUsedType type)308 void CollectPermissionRecord(const AccessTokenID &token, const string &perm,
309     const bool permGranted, const PermissionUsedType type)
310 {
311     lock_guard<mutex> lock(addPhotoPermissionRecordLock_);
312     DelayTaskInit();
313 
314     if (!ShouldAddPermissionRecord(token)) {
315         return;
316     }
317 
318     AddPermParamInfo info = {token, perm, permGranted, !permGranted, type};
319     auto iter = find_if(infos_.begin(), infos_.end(), [&token, &perm, type](auto &info) {
320         return info.tokenId == token && info.permissionName == perm && info.type == type;
321     });
322     if (iter == infos_.end()) {
323         infos_.push_back(info);
324     } else if (permGranted) {
325         iter->successCount += 1;
326     } else if (!permGranted) {
327         iter->failCount += 1;
328     }
329 }
330 
CollectPermissionInfo(const string &permission, const bool permGranted, const PermissionUsedType type)331 void PermissionUtils::CollectPermissionInfo(const string &permission,
332     const bool permGranted, const PermissionUsedType type)
333 {
334     AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
335     CollectPermissionRecord(tokenCaller, permission, permGranted, type);
336 }
337 
CheckPhotoCallerPermission(const string &permission)338 bool PermissionUtils::CheckPhotoCallerPermission(const string &permission)
339 {
340     PermissionUsedType type = PermissionUsedTypeValue::NORMAL_TYPE;
341     AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
342     int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
343     if (res != PermissionState::PERMISSION_GRANTED) {
344         MEDIA_ERR_LOG("Have no media permission: %{public}s", permission.c_str());
345         CollectPermissionRecord(tokenCaller, permission, false, type);
346         return false;
347     }
348     CollectPermissionRecord(tokenCaller, permission, true, type);
349     return true;
350 }
351 
CheckPhotoCallerPermission(const vector<string> &perms)352 bool PermissionUtils::CheckPhotoCallerPermission(const vector<string> &perms)
353 {
354     if (perms.empty()) {
355         return false;
356     }
357 
358     for (const auto &perm : perms) {
359         if (!CheckPhotoCallerPermission(perm)) {
360             return false;
361         }
362     }
363     return true;
364 }
365 
CheckCallerPermission(const string &permission)366 bool PermissionUtils::CheckCallerPermission(const string &permission)
367 {
368     MediaLibraryTracer tracer;
369     tracer.Start("CheckCallerPermission");
370 
371     AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
372     int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
373     if (res != PermissionState::PERMISSION_GRANTED) {
374         MEDIA_ERR_LOG("Have no media permission: %{public}s", permission.c_str());
375         AddPermissionRecord(tokenCaller, permission, false);
376         return false;
377     }
378     AddPermissionRecord(tokenCaller, permission, true);
379 
380     return true;
381 }
382 
383 /* Check whether caller has at least one of @perms */
CheckHasPermission(const vector<string> &perms)384 bool PermissionUtils::CheckHasPermission(const vector<string> &perms)
385 {
386     if (perms.empty()) {
387         return false;
388     }
389 
390     for (const auto &perm : perms) {
391         if (CheckCallerPermission(perm)) {
392             return true;
393         }
394     }
395 
396     return false;
397 }
398 
399 /* Check whether caller has all the @perms */
CheckCallerPermission(const vector<string> &perms)400 bool PermissionUtils::CheckCallerPermission(const vector<string> &perms)
401 {
402     if (perms.empty()) {
403         return false;
404     }
405 
406     for (const auto &perm : perms) {
407         if (!CheckCallerPermission(perm)) {
408             return false;
409         }
410     }
411     return true;
412 }
413 
GetTokenId()414 uint32_t PermissionUtils::GetTokenId()
415 {
416     return IPCSkeleton::GetCallingTokenID();
417 }
418 
IsSystemApp()419 bool PermissionUtils::IsSystemApp()
420 {
421     uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
422     return TokenIdKit::IsSystemAppByFullTokenID(tokenId);
423 }
424 
CheckIsSystemAppByUid()425 bool PermissionUtils::CheckIsSystemAppByUid()
426 {
427     int uid = IPCSkeleton::GetCallingUid();
428     bundleMgr_ = GetSysBundleManager();
429     if (bundleMgr_ == nullptr) {
430         MEDIA_ERR_LOG("Can not get bundleMgr");
431         return false;
432     }
433     return bundleMgr_->CheckIsSystemAppByUid(uid);
434 }
435 
IsNativeSAApp()436 bool PermissionUtils::IsNativeSAApp()
437 {
438     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
439     ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
440     MEDIA_DEBUG_LOG("check if native sa token, tokenId:%{public}d, tokenType:%{public}d",
441         tokenId, tokenType);
442     if (tokenType == ATokenTypeEnum::TOKEN_NATIVE) {
443         return true;
444     }
445     return false;
446 }
447 
IsRootShell()448 bool PermissionUtils::IsRootShell()
449 {
450     return IPCSkeleton::GetCallingUid() == 0;
451 }
452 
IsHdcShell()453 bool PermissionUtils::IsHdcShell()
454 {
455     return IPCSkeleton::GetCallingUid() == HDC_SHELL_UID;
456 }
457 
GetPackageNameByBundleName(const string &bundleName)458 string PermissionUtils::GetPackageNameByBundleName(const string &bundleName)
459 {
460     const static int32_t INVALID_UID = -1;
461 
462     string packageName = "";
463     int uid = IPCSkeleton::GetCallingUid();
464     if (uid <= INVALID_UID) {
465         MEDIA_ERR_LOG("Get INVALID_UID UID %{public}d", uid);
466         return packageName;
467     }
468     GetPackageNameFromCache(uid, bundleName, packageName);
469 
470     return packageName;
471 }
472 
GetAppIdByBundleName(const string &bundleName)473 string PermissionUtils::GetAppIdByBundleName(const string &bundleName)
474 {
475     int uid = IPCSkeleton::GetCallingUid();
476     return GetAppIdByBundleName(bundleName, uid);
477 }
478 
GetAppIdByBundleName(const string &bundleName, int32_t uid)479 string PermissionUtils::GetAppIdByBundleName(const string &bundleName, int32_t uid)
480 {
481     if (uid <= INVALID_UID) {
482         MEDIA_ERR_LOG("Get INVALID_UID UID %{public}d", uid);
483         return "";
484     }
485     string appId = "";
486     GetAppIdFromCache(uid, bundleName, appId);
487 
488     return appId;
489 }
490 
SetEPolicy()491 bool PermissionUtils::SetEPolicy()
492 {
493     MEDIA_INFO_LOG("SetEPolicy for directory");
494     int ret = Security::AccessToken::El5FilekeyManagerKit::SetFilePathPolicy();
495     if (ret != 0) {
496         MEDIA_ERR_LOG("SetEPolicy fail of %{public}d", ret);
497         return false;
498     }
499     return true;
500 }
501 }  // namespace Media
502 }  // namespace OHOS
503