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