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
33namespace OHOS {
34namespace Media {
35using namespace std;
36using namespace OHOS::Security::AccessToken;
37using namespace OHOS::AppExecFwk::Constants;
38
39const int32_t CAPACITY = 50;
40const int32_t HDC_SHELL_UID = 2000;
41const int32_t BASE_USER_RANGE = 200000;
42
43std::mutex PermissionUtils::uninstallMutex_;
44std::list<std::pair<int32_t, BundleInfo>> PermissionUtils::bundleInfoList_ = {};
45std::unordered_map<int32_t, std::list<std::pair<int32_t, BundleInfo>>::iterator> PermissionUtils::bundleInfoMap_ = {};
46
47bool g_isDelayTask;
48std::mutex addPhotoPermissionRecordLock_;
49std::thread delayTask_;
50std::vector<Security::AccessToken::AddPermParamInfo> infos_;
51
52sptr<AppExecFwk::IBundleMgr> PermissionUtils::bundleMgr_ = nullptr;
53mutex PermissionUtils::bundleMgrMutex_;
54sptr<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
87void 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
110void 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
142void 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
165void 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
180void 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
193void 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
206void 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
217void 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
225void PermissionUtils::GetClientBundle(const int uid, string &bundleName)
226{
227    GetBundleNameFromCache(uid, bundleName);
228}
229
230void 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
243bool inline ShouldAddPermissionRecord(const AccessTokenID &token)
244{
245    return (AccessTokenKit::GetTokenTypeFlag(token) == TOKEN_HAP);
246}
247
248void 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
262vector<AddPermParamInfo> GetPermissionRecord()
263{
264    lock_guard<mutex> lock(addPhotoPermissionRecordLock_);
265    vector<AddPermParamInfo> result = infos_;
266    infos_.clear();
267    return result;
268}
269
270void 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
287void 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
298void 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
308void 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
331void 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
338bool 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
352bool 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
366bool 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 */
384bool 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 */
400bool 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
414uint32_t PermissionUtils::GetTokenId()
415{
416    return IPCSkeleton::GetCallingTokenID();
417}
418
419bool PermissionUtils::IsSystemApp()
420{
421    uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
422    return TokenIdKit::IsSystemAppByFullTokenID(tokenId);
423}
424
425bool 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
436bool 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
448bool PermissionUtils::IsRootShell()
449{
450    return IPCSkeleton::GetCallingUid() == 0;
451}
452
453bool PermissionUtils::IsHdcShell()
454{
455    return IPCSkeleton::GetCallingUid() == HDC_SHELL_UID;
456}
457
458string 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
473string PermissionUtils::GetAppIdByBundleName(const string &bundleName)
474{
475    int uid = IPCSkeleton::GetCallingUid();
476    return GetAppIdByBundleName(bundleName, uid);
477}
478
479string 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
491bool 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