* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "permission_utils.h"
#include <unordered_set>
#include "access_token.h"
#include "accesstoken_kit.h"
#include "el5_filekey_manager_kit.h"
#include "ipc_skeleton.h"
#include "iservice_registry.h"
#include "media_file_utils.h"
#include "media_log.h"
#include "medialibrary_db_const.h"
#include "medialibrary_errno.h"
#include "medialibrary_tracer.h"
#include "privacy_kit.h"
#include "system_ability_definition.h"
#include "tokenid_kit.h"
#include "bundle_mgr_proxy.h"
#include "bundle_info.h"
#include "parameters.h"
#include "permission_whitelist_utils.h"
#include <nlohmann/json.hpp>
namespace OHOS {
namespace Media {
using namespace std;
using namespace OHOS::Security::AccessToken;
using namespace OHOS::AppExecFwk::Constants;
using namespace OHOS::AppExecFwk;
const int32_t CAPACITY = 50;
const int32_t HDC_SHELL_UID = 2000;
std::mutex PermissionUtils::uninstallMutex_;
std::list<std::pair<int32_t, BundleInfo>> PermissionUtils::bundleInfoList_ = {};
std::unordered_map<int32_t, std::list<std::pair<int32_t, BundleInfo>>::iterator> PermissionUtils::bundleInfoMap_ = {};
SafeMap<uint64_t, bool> PermissionUtils::systemAppCache_;
vector<AddPermParamInfo> PermissionUtils::infos_ {};
vector<OpenPermissionInfo> PermissionUtils::pendingOpenPermissionInfos_ {};
bool g_isDelayTask;
std::mutex addPhotoPermissionRecordLock_;
std::thread delayTask_;
std::mutex pendingOpenDataInfosLock_;
constexpr size_t URI_NUMBER_THRESHOLD = 50;
constexpr size_t EXTRA_SIZE_LIMIT = 10000;
sptr<AppExecFwk::IBundleMgr> PermissionUtils::bundleMgr_ = nullptr;
mutex PermissionUtils::bundleMgrMutex_;
sptr<AppExecFwk::IBundleMgr> PermissionUtils::GetSysBundleManager()
{
if (bundleMgr_ != nullptr) {
return bundleMgr_;
}
lock_guard<mutex> lock(bundleMgrMutex_);
if (bundleMgr_ != nullptr) {
return bundleMgr_;
}
auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (systemAbilityMgr == nullptr) {
MEDIA_ERR_LOG("Failed to get SystemAbilityManager.");
return nullptr;
}
auto bundleObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
if (bundleObj == nullptr) {
MEDIA_ERR_LOG("Remote object is nullptr.");
return nullptr;
}
auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
if (bundleMgr == nullptr) {
MEDIA_ERR_LOG("Failed to iface_cast");
return nullptr;
}
bundleMgr_ = bundleMgr;
return bundleMgr_;
}
void PermissionUtils::GetBundleNameFromCache(int uid, string &bundleName)
{
lock_guard<mutex> lock(uninstallMutex_);
auto iter = bundleInfoMap_.find(uid);
if (iter != bundleInfoMap_.end() && !iter->second->second.bundleName.empty()) {
bundleInfoList_.splice(bundleInfoList_.begin(), bundleInfoList_, iter->second);
bundleName = iter->second->second.bundleName;
return;
}
bundleMgr_ = GetSysBundleManager();
if (bundleMgr_ == nullptr) {
bundleName = "";
return;
}
auto result = bundleMgr_->GetBundleNameForUid(uid, bundleName);
if (!result) {
bundleName = "";
return;
}
UpdateBundleNameInCache(uid, bundleName);
}
void PermissionUtils::GetPackageNameFromCache(int uid, const string &bundleName, string &packageName)
{
lock_guard<mutex> lock(uninstallMutex_);
auto iter = bundleInfoMap_.find(uid);
if (iter != bundleInfoMap_.end() && !iter->second->second.packageName.empty()) {
bundleInfoList_.splice(bundleInfoList_.begin(), bundleInfoList_, iter->second);
packageName = iter->second->second.packageName;
return;
}
int32_t userId = uid / BASE_USER_RANGE;
MEDIA_DEBUG_LOG("uid:%{private}d, userId:%{private}d", uid, userId);
AAFwk::Want want;
auto bundleMgr = GetSysBundleManager();
if (bundleMgr == nullptr) {
MEDIA_ERR_LOG("Get BundleManager failed");
packageName = "";
return;
}
int ret = bundleMgr->GetLaunchWantForBundle(bundleName, want, userId);
if (ret != ERR_OK) {
MEDIA_ERR_LOG("Can not get bundleName by want, err=%{public}d, userId=%{private}d", ret, userId);
packageName = "";
return;
}
string abilityName = want.GetOperation().GetAbilityName();
packageName = bundleMgr->GetAbilityLabel(bundleName, abilityName);
UpdatePackageNameInCache(uid, packageName);
}
void PermissionUtils::GetAppIdFromCache(int uid, const string &bundleName, string &appId)
{
lock_guard<mutex> lock(uninstallMutex_);
auto iter = bundleInfoMap_.find(uid);
if (iter != bundleInfoMap_.end() && !iter->second->second.appId.empty()) {
bundleInfoList_.splice(bundleInfoList_.begin(), bundleInfoList_, iter->second);
appId = iter->second->second.appId;
return;
}
int32_t userId = uid / BASE_USER_RANGE;
MEDIA_DEBUG_LOG("uid:%{private}d, userId:%{private}d", uid, userId);
auto bundleMgr_ = GetSysBundleManager();
if (bundleMgr_ == nullptr) {
MEDIA_ERR_LOG("Get BundleManager failed");
return;
}
appId = bundleMgr_->GetAppIdByBundleName(bundleName, userId);
UpdateAppIdInCache(uid, appId);
}
void PermissionUtils::UpdateLatestBundleInfo(int uid, const BundleInfo &bundleInfo)
{
auto iter = bundleInfoMap_.find(uid);
if (iter != bundleInfoMap_.end()) {
bundleInfoList_.erase(iter->second);
}
bundleInfoList_.push_front(make_pair(uid, bundleInfo));
bundleInfoMap_[uid] = bundleInfoList_.begin();
if (bundleInfoMap_.size() > CAPACITY) {
int32_t deleteKey = bundleInfoList_.back().first;
bundleInfoMap_.erase(deleteKey);
bundleInfoList_.pop_back();
}
}
void PermissionUtils::UpdateBundleNameInCache(int uid, const string &bundleName)
{
auto iter = bundleInfoMap_.find(uid);
if (iter != bundleInfoMap_.end()) {
BundleInfo bundleInfo = bundleInfoMap_[uid]->second;
bundleInfo.bundleName = bundleName;
UpdateLatestBundleInfo(uid, bundleInfo);
return;
}
BundleInfo bundleInfo { bundleName, "", "" };
UpdateLatestBundleInfo(uid, bundleInfo);
}
void PermissionUtils::UpdatePackageNameInCache(int uid, const string &packageName)
{
auto iter = bundleInfoMap_.find(uid);
if (iter != bundleInfoMap_.end()) {
BundleInfo bundleInfo = bundleInfoMap_[uid]->second;
bundleInfo.packageName = packageName;
UpdateLatestBundleInfo(uid, bundleInfo);
return;
}
BundleInfo bundleInfo { "", packageName, "" };
UpdateLatestBundleInfo(uid, bundleInfo);
}
void PermissionUtils::UpdateAppIdInCache(int uid, const string &appId)
{
BundleInfo bundleInfo { "", "", appId };
auto iter = bundleInfoMap_.find(uid);
if (iter != bundleInfoMap_.end()) {
bundleInfo = bundleInfoMap_[uid]->second;
bundleInfo.appId = appId;
}
UpdateLatestBundleInfo(uid, bundleInfo);
}
void PermissionUtils::ClearBundleInfoInCache()
{
lock_guard<mutex> lock(uninstallMutex_);
bundleInfoMap_.clear();
bundleInfoList_.clear();
bundleMgr_ = nullptr;
systemAppCache_.Clear();
infos_.clear();
pendingOpenPermissionInfos_.clear();
MEDIA_INFO_LOG("clear all info from cache");
}
void PermissionUtils::GetClientBundle(const int uid, string &bundleName)
{
GetBundleNameFromCache(uid, bundleName);
}
void PermissionUtils::GetPackageName(const int uid, std::string &packageName)
{
packageName = "";
string bundleName;
GetClientBundle(uid, bundleName);
if (bundleName.empty()) {
MEDIA_ERR_LOG("Get bundle name failed");
return;
}
GetPackageNameFromCache(uid, bundleName, packageName);
}
int64_t PermissionUtils::GetMainTokenId(const string &appId, int64_t &tokenId)
{
bundleMgr_ = GetSysBundleManager();
if (bundleMgr_ == nullptr) {
MEDIA_ERR_LOG("Get bundleMgr failed");
return E_ERR;
}
string bundleName;
int32_t err = bundleMgr_->GetBundleNameByAppId(appId, bundleName);
if (err != E_OK) {
MEDIA_ERR_LOG("Get bundle name failed");
return err;
}
int32_t uid = static_cast<int32_t>(getuid());
int32_t userId = uid / BASE_USER_RANGE;
OHOS::AppExecFwk::BundleInfo bundleInfo;
err = bundleMgr_->GetBundleInfoV9(bundleName,
static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION), bundleInfo, userId);
CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "main app tokenid from appId fail");
tokenId = static_cast<int64_t>(bundleInfo.applicationInfo.accessTokenId);
return E_OK;
}
bool inline ShouldAddPermissionRecord(const AccessTokenID &token)
{
return (AccessTokenKit::GetTokenTypeFlag(token) == TOKEN_HAP);
}
void PermissionUtils::AddPermissionRecord(const AccessTokenID &token, const string &perm, const bool permGranted)
{
if (!ShouldAddPermissionRecord(token)) {
return;
}
int res = PrivacyKit::AddPermissionUsedRecord(token, perm, !!permGranted, !permGranted, true);
if (res != 0) {
MEDIA_WARN_LOG("Failed to add permission used record: %{public}s, permGranted: %{public}d, err: %{public}d",
perm.c_str(), permGranted, res);
}
}
vector<AddPermParamInfo> PermissionUtils::GetPermissionRecord()
{
lock_guard<mutex> lock(addPhotoPermissionRecordLock_);
vector<AddPermParamInfo> result = infos_;
infos_.clear();
return result;
}
void PermissionUtils::AddPermissionRecord()
{
vector<AddPermParamInfo> infos = GetPermissionRecord();
for (const auto &info : infos) {
int32_t ret = PrivacyKit::AddPermissionUsedRecord(info, true);
if (ret != 0) {
MEDIA_WARN_LOG("Failed to add permission used record: %{public}s, permGranted: %{public}d, err: %{public}d",
info.permissionName.c_str(), info.successCount, ret);
}
MEDIA_DEBUG_LOG("Info: token = %{private}d, perm = %{private}s, permGranted = %{private}d, \
!permGranted = %{private}d, type = %{public}d, extra = %{private}s", info.tokenId,
info.permissionName.c_str(), info.successCount, info.failCount, info.type,
info.extra.c_str());
}
}
void PermissionUtils::CollectPermissionRecord(const AccessTokenID &token, const string &perm,
const bool permGranted, const PermissionUsedType type)
{
lock_guard<mutex> lock(addPhotoPermissionRecordLock_);
PermissionUtils::DelayTaskInit();
if (!ShouldAddPermissionRecord(token)) {
return;
}
AddPermParamInfo info = {token, perm, permGranted, !permGranted, type};
auto iter = find_if(infos_.begin(), infos_.end(), [&token, &perm, type](auto &info) {
return info.tokenId == token && info.permissionName == perm && info.type == type;
});
if (iter == infos_.end()) {
infos_.push_back(info);
} else if (permGranted) {
iter->successCount += 1;
} else if (!permGranted) {
iter->failCount += 1;
}
}
bool PermissionUtils::HandleEmptyOpenDataInfo(const AccessTokenID &token, const string &perm,
const bool permGranted, const PermissionUsedType type, const OpenDataInfo &openDataInfo)
{
if (openDataInfo.uri.empty()) {
CollectPermissionRecord(token, perm, permGranted, type);
return true;
}
return false;
}
static std::vector<AddPermParamInfo>::iterator FindMatchingPermissionInfo(
std::vector<AddPermParamInfo> &infos, const AccessTokenID &token,
const string &perm, const PermissionUsedType type)
{
return find_if(infos.begin(), infos.end(), [&token, &perm, type](auto &info) {
return info.tokenId == token && info.permissionName == perm && info.type == type;
});
}
void PermissionUtils::AddToPendingOpenPermissionInfo(const AccessTokenID &token, const string &perm,
const bool permGranted, const PermissionUsedType type, const OpenDataInfo &openDataInfo)
{
lock_guard<mutex> lock(pendingOpenDataInfosLock_);
OpenPermissionInfo openInfo;
openInfo.token = token;
openInfo.perm = perm;
openInfo.permGranted = permGranted;
openInfo.type = type;
openInfo.openDataInfo = openDataInfo;
pendingOpenPermissionInfos_.push_back(openInfo);
}
static nlohmann::json BuildUriItem(const std::string &uri, int64_t timestamp)
{
nlohmann::json uriItem = nlohmann::json::object();
uriItem["uri"] = uri;
if (timestamp <= 0) {
timestamp = MediaFileUtils::UTCTimeMilliSeconds();
}
uriItem["timestamp"] = timestamp;
return uriItem;
}
static bool ParseExtraJson(const std::string &extra, nlohmann::json &extraJson)
{
extraJson = nlohmann::json::object();
if (extra.empty()) {
return true;
}
extraJson = nlohmann::json::parse(extra, nullptr, false);
if (extraJson.is_discarded()) {
MEDIA_ERR_LOG("Parse extra JSON failed");
extraJson = nlohmann::json::object();
return false;
}
return true;
}
static bool DumpExtraWithSizeCheck(const nlohmann::json &extraJson, std::string &extra)
{
std::string newExtra = extraJson.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
if (newExtra.size() > EXTRA_SIZE_LIMIT) {
MEDIA_DEBUG_LOG("Extra size %{public}zu exceeds limit %{public}zu", newExtra.size(), EXTRA_SIZE_LIMIT);
return false;
}
extra = newExtra;
return true;
}
static bool CreateNewExtraForOpenData(AddPermParamInfo &info, const OpenDataInfo &openDataInfo)
{
nlohmann::json newItem;
newItem["type"] = openDataInfo.type;
newItem["uid"] = openDataInfo.uid;
newItem["userId"] = openDataInfo.userId;
newItem["uris"] = nlohmann::json::array({ BuildUriItem(openDataInfo.uri, openDataInfo.timestamp) });
return DumpExtraWithSizeCheck(newItem, info.extra);
}
static bool AppendUriToExistingExtra(AddPermParamInfo &info, const OpenDataInfo &openDataInfo)
{
nlohmann::json extraJson = nlohmann::json::object();
if (!ParseExtraJson(info.extra, extraJson) || !extraJson.is_object()) {
return false;
}
const auto typeIt = extraJson.find("type");
const auto uidIt = extraJson.find("uid");
const auto userIdIt = extraJson.find("userId");
if (typeIt == extraJson.end() || !typeIt->is_string() ||
uidIt == extraJson.end() || !uidIt->is_number_integer() ||
userIdIt == extraJson.end() || !userIdIt->is_number_integer()) {
return false;
}
if (typeIt->get_ref<const std::string&>() != openDataInfo.type ||
uidIt->get<int32_t>() != openDataInfo.uid ||
userIdIt->get<int32_t>() != openDataInfo.userId) {
return false;
}
auto urisIt = extraJson.find("uris");
if (urisIt == extraJson.end() || !urisIt->is_array()) {
extraJson["uris"] = nlohmann::json::array();
urisIt = extraJson.find("uris");
}
if (urisIt->size() >= URI_NUMBER_THRESHOLD) {
MEDIA_DEBUG_LOG("Uri size %{public}zu exceeds limit %{public}zu", urisIt->size(), URI_NUMBER_THRESHOLD);
return false;
}
urisIt->push_back(BuildUriItem(openDataInfo.uri, openDataInfo.timestamp));
return DumpExtraWithSizeCheck(extraJson, info.extra);
}
static bool UpdatePermissionInfoWithOpenData(AddPermParamInfo &info, const OpenDataInfo &openDataInfo)
{
if (openDataInfo.uri.empty()) {
return true;
}
if (info.extra.empty()) {
return CreateNewExtraForOpenData(info, openDataInfo);
}
return AppendUriToExistingExtra(info, openDataInfo);
}
void PermissionUtils::CollectPermissionRecord(const AccessTokenID &token, const string &perm,
const bool permGranted, const PermissionUsedType type, const OpenDataInfo &openDataInfo)
{
if (HandleEmptyOpenDataInfo(token, perm, permGranted, type, openDataInfo)) {
return;
}
lock_guard<mutex> lock(addPhotoPermissionRecordLock_);
if (!ShouldAddPermissionRecord(token)) {
return;
}
PermissionUtils::DelayTaskInit();
auto iter = FindMatchingPermissionInfo(infos_, token, perm, type);
if (iter != infos_.end()) {
if (UpdatePermissionInfoWithOpenData(*iter, openDataInfo)) {
iter->successCount += permGranted;
iter->failCount += !permGranted;
} else {
AddToPendingOpenPermissionInfo(token, perm, permGranted, type, openDataInfo);
}
} else {
AddPermParamInfo info {};
info.tokenId = token;
info.permissionName = perm;
info.successCount = permGranted;
info.failCount = !permGranted;
info.type = type;
if (UpdatePermissionInfoWithOpenData(info, openDataInfo)) {
infos_.push_back(info);
} else {
MEDIA_ERR_LOG("Failed to update permission info with open data with a single uri, skip this record");
}
}
}
void PermissionUtils::HandlePendingOpenDataInfos()
{
std::vector<OpenPermissionInfo> pendingInfosTmp {};
{
lock_guard<mutex> lock(pendingOpenDataInfosLock_);
if (!pendingOpenPermissionInfos_.empty()) {
pendingInfosTmp.swap(pendingOpenPermissionInfos_);
}
}
for (const auto& info : pendingInfosTmp) {
CollectPermissionRecord(info.token, info.perm, info.permGranted, info.type, info.openDataInfo);
}
}
void PermissionUtils::DelayAddPermissionRecord()
{
string name("DelayAddPermissionRecord");
pthread_setname_np(pthread_self(), name.c_str());
MEDIA_INFO_LOG("DelayTask start");
std::this_thread::sleep_for(std::chrono::seconds(1));
AddPermissionRecord();
{
std::lock_guard<std::mutex> lock(addPhotoPermissionRecordLock_);
g_isDelayTask = false;
if (!infos_.empty()) {
delayTask_ = thread(DelayAddPermissionRecord);
delayTask_.detach();
g_isDelayTask = true;
}
}
HandlePendingOpenDataInfos();
MEDIA_INFO_LOG("DelayTask end");
}
void PermissionUtils::DelayTaskInit()
{
if (!g_isDelayTask) {
MEDIA_INFO_LOG("DelayTaskInit");
delayTask_ = thread(DelayAddPermissionRecord);
delayTask_.detach();
g_isDelayTask = true;
}
}
void PermissionUtils::CollectPermissionInfo(const std::string &permission, const bool permGranted,
const PermissionUsedType type, const OpenDataInfo &openDataInfo)
{
AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
CollectPermissionRecord(tokenCaller, permission, permGranted, type, openDataInfo);
}
void PermissionUtils::CollectPermissionInfo(const string &permission,
const bool permGranted, const PermissionUsedType type)
{
AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
CollectPermissionRecord(tokenCaller, permission, permGranted, type);
}
bool PermissionUtils::CheckPhotoCallerPermission(const string &permission, OpenDataInfo info)
{
PermissionUsedType type = PermissionUsedTypeValue::NORMAL_TYPE;
AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
if (res != PermissionState::PERMISSION_GRANTED) {
MEDIA_ERR_LOG("Have no media permission: %{public}s", permission.c_str());
CollectPermissionRecord(tokenCaller, permission, false, type, info);
return false;
}
CollectPermissionRecord(tokenCaller, permission, true, type, info);
return true;
}
bool PermissionUtils::CheckPhotoCallerPermission(const vector<string> &perms, OpenDataInfo info)
{
if (perms.empty()) {
return false;
}
for (const auto &perm : perms) {
if (!CheckPhotoCallerPermission(perm, info)) {
return false;
}
}
return true;
}
bool PermissionUtils::CheckPhotoCallerPermission(const string &permission, const AccessTokenID &tokenCaller,
OpenDataInfo info)
{
PermissionUsedType type = PermissionUsedTypeValue::NORMAL_TYPE;
int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
if (res != PermissionState::PERMISSION_GRANTED) {
CollectPermissionRecord(tokenCaller, permission, false, type, info);
return false;
}
CollectPermissionRecord(tokenCaller, permission, true, type, info);
return true;
}
bool PermissionUtils::CheckPhotoCallerPermissionNoRecord(const string &permission, const AccessTokenID &tokenCaller)
{
int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
return res == PermissionState::PERMISSION_GRANTED;
}
bool PermissionUtils::GetTokenCallerForUid(const int &uid, AccessTokenID &tokenCaller)
{
string bundleName;
int32_t appIndex;
bundleMgr_ = GetSysBundleManager();
if (bundleMgr_ == nullptr) {
MEDIA_ERR_LOG("Get BundleManager failed");
return false;
}
auto err = bundleMgr_->GetNameAndIndexForUid(uid, bundleName, appIndex);
if (err != E_OK) {
MEDIA_ERR_LOG("Get bundleName failed");
return false;
}
OHOS::AppExecFwk::BundleInfo bundleInfo;
int32_t userId = uid / BASE_USER_RANGE;
if (appIndex == 0) {
err = bundleMgr_->GetBundleInfoV9(bundleName,
static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION), bundleInfo, userId);
CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "main app tokenid from uid fail");
} else {
err = bundleMgr_->GetCloneBundleInfo(bundleName,
static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION), appIndex, bundleInfo, userId);
CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "clone app get tokenid from uid fail");
}
tokenCaller = bundleInfo.applicationInfo.accessTokenId;
return true;
}
void PermissionUtils::CollectPermissionInfo(const string &permission,
const bool permGranted, const PermissionUsedType type, const int &uid, const OpenDataInfo &openDataInfo)
{
AccessTokenID tokenCaller = INVALID_TOKENID;
GetTokenCallerForUid(uid, tokenCaller);
CollectPermissionRecord(tokenCaller, permission, permGranted, type, openDataInfo);
}
void PermissionUtils::CollectPermissionInfo(const string &permission,
const bool permGranted, const PermissionUsedType type, const int &uid)
{
AccessTokenID tokenCaller = INVALID_TOKENID;
GetTokenCallerForUid(uid, tokenCaller);
CollectPermissionRecord(tokenCaller, permission, permGranted, type);
}
bool PermissionUtils::CheckPhotoCallerPermission(const vector<string> &perms, const int &uid,
AccessTokenID &tokenCaller, OpenDataInfo info)
{
bool err = GetTokenCallerForUid(uid, tokenCaller);
CHECK_AND_RETURN_RET(!perms.empty(), false);
CHECK_AND_RETURN_RET(err != false, false);
for (const auto &perm : perms) {
CHECK_AND_RETURN_RET(CheckPhotoCallerPermission(perm, tokenCaller, info), false);
}
return true;
}
bool PermissionUtils::CheckPhotoCallerPermissionNoRecord(const vector<string> &perms, const int &uid,
AccessTokenID &tokenCaller)
{
bool err = GetTokenCallerForUid(uid, tokenCaller);
CHECK_AND_RETURN_RET(!perms.empty(), false);
CHECK_AND_RETURN_RET(err, false);
for (const auto &perm : perms) {
CHECK_AND_RETURN_RET(CheckPhotoCallerPermissionNoRecord(perm, tokenCaller), false);
}
return true;
}
bool PermissionUtils::CheckCloudPermission()
{
AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
auto ret = AccessTokenKit::VerifyAccessToken(tokenCaller, CLOUD_READ_ALL_PHOTO_PERMISSION);
CHECK_AND_RETURN_RET(ret != PermissionState::PERMISSION_GRANTED, true);
ret = AccessTokenKit::VerifyAccessToken(tokenCaller, PERM_READ_CLOUD_IMAGEVIDEO);
return ret == PermissionState::PERMISSION_GRANTED;
}
bool PermissionUtils::CheckCallerPermission(const string &permission)
{
MediaLibraryTracer tracer;
tracer.Start("CheckCallerPermission");
bool isInWhitelist = true;
if (permission == PERMISSION_NAME_READ_MEDIA || permission == PERMISSION_NAME_WRITE_MEDIA) {
isInWhitelist = PermissionWhitelistUtils::CheckWhiteList() == E_SUCCESS;
}
AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
if (res != PermissionState::PERMISSION_GRANTED || !isInWhitelist) {
MEDIA_ERR_LOG("Have no media permission: %{public}s", permission.c_str());
AddPermissionRecord(tokenCaller, permission, false);
return false;
}
AddPermissionRecord(tokenCaller, permission, true);
return true;
}
bool PermissionUtils::CheckCallerPermission(const string &permission, const int &uid)
{
AccessTokenID tokenCaller;
bool err = GetTokenCallerForUid(uid, tokenCaller);
if (err == false) {
MEDIA_ERR_LOG("get tokenid fail");
return false;
}
int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
if (res != PermissionState::PERMISSION_GRANTED) {
MEDIA_ERR_LOG("Have no media permission: %{public}s", permission.c_str());
AddPermissionRecord(tokenCaller, permission, false);
return false;
}
AddPermissionRecord(tokenCaller, permission, true);
return true;
}
bool PermissionUtils::CheckHasPermission(const vector<string> &perms)
{
CHECK_AND_RETURN_RET(!perms.empty(), false);
for (const auto &perm : perms) {
CHECK_AND_RETURN_RET(!CheckCallerPermission(perm), true);
}
return false;
}
bool PermissionUtils::CheckCallerPermission(const vector<string> &perms)
{
if (perms.empty()) {
return false;
}
for (const auto &perm : perms) {
if (!CheckCallerPermission(perm)) {
return false;
}
}
return true;
}
uint32_t PermissionUtils::GetTokenId()
{
return IPCSkeleton::GetCallingTokenID();
}
bool PermissionUtils::IsBetaVersion()
{
std::string versionType = system::GetParameter(CONST_LOGSYSTEM_VERSIONTYPE, "unknown");
return versionType == "beta";
}
bool PermissionUtils::IsSystemAppByCache(const uint64_t tokenId)
{
bool isSystemApp = false;
if (systemAppCache_.Find(tokenId, isSystemApp)) {
return isSystemApp;
} else {
isSystemApp = TokenIdKit::IsSystemAppByFullTokenID(tokenId);
systemAppCache_.EnsureInsert(tokenId, isSystemApp);
return isSystemApp;
}
}
bool PermissionUtils::IsSystemApp()
{
uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
return IsSystemAppByCache(tokenId);
}
bool PermissionUtils::CheckIsSystemAppByUid()
{
int uid = IPCSkeleton::GetCallingUid();
bundleMgr_ = GetSysBundleManager();
if (bundleMgr_ == nullptr) {
MEDIA_ERR_LOG("Can not get bundleMgr");
return false;
}
return bundleMgr_->CheckIsSystemAppByUid(uid);
}
bool PermissionUtils::IsNativeSAApp()
{
uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
MEDIA_DEBUG_LOG("check if native sa token, tokenId:%{public}d, tokenType:%{public}d",
tokenId, tokenType);
if (tokenType == ATokenTypeEnum::TOKEN_NATIVE) {
return true;
}
return false;
}
bool PermissionUtils::IsRootShell()
{
return IPCSkeleton::GetCallingUid() == 0;
}
bool PermissionUtils::IsHdcShell()
{
return IPCSkeleton::GetCallingUid() == HDC_SHELL_UID;
}
string PermissionUtils::GetPackageNameByBundleName(const string &bundleName)
{
const static int32_t INVALID_UID = -1;
string packageName = "";
int uid = IPCSkeleton::GetCallingUid();
if (uid <= INVALID_UID) {
MEDIA_ERR_LOG("Get INVALID_UID UID %{public}d", uid);
return packageName;
}
GetPackageNameFromCache(uid, bundleName, packageName);
return packageName;
}
string PermissionUtils::GetAppIdByBundleName(const string &bundleName)
{
int uid = IPCSkeleton::GetCallingUid();
return GetAppIdByBundleName(bundleName, uid);
}
string PermissionUtils::GetAppIdByBundleName(const string &bundleName, int32_t uid)
{
if (uid <= INVALID_UID) {
MEDIA_ERR_LOG("Get INVALID_UID UID %{public}d", uid);
return "";
}
string appId = "";
GetAppIdFromCache(uid, bundleName, appId);
return appId;
}
bool PermissionUtils::SetEPolicy()
{
MEDIA_INFO_LOG("SetEPolicy for directory");
int ret = Security::AccessToken::El5FilekeyManagerKit::SetFilePathPolicy();
CHECK_AND_RETURN_RET_LOG(ret == 0, false, "SetEPolicy fail of %{public}d", ret);
return true;
}
bool PermissionUtils::IsSystemAppByBundleName(const std::string &bundleName)
{
AppExecFwk::BundleInfo bundleInfo;
auto bundleMgr = GetSysBundleManager();
if (bundleMgr == nullptr) {
return false;
}
ErrCode state = bundleMgr->GetBundleInfoV9(
bundleName, static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION),
bundleInfo, OHOS::AppExecFwk::Constants::START_USERID);
if (state != 0) {
MEDIA_ERR_LOG("Failed to get bundle info for %{public}s, Error: %{public}d", bundleName.c_str(), state);
return false;
}
return bundleInfo.applicationInfo.isSystemApp;
}
}
}