* Copyright (c) 2024-2025 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 "file_uri_distribution_utils.h"
#include "ability_manager_errors.h"
#include "accesstoken_kit.h"
#include "bundle_mgr_client.h"
#include "bundle_mgr_helper.h"
#include "global_constant.h"
#include "hilog_tag_wrapper.h"
#include "in_process_call_wrapper.h"
#include "ipc_skeleton.h"
#include "os_account_manager_wrapper.h"
#include "permission_constants.h"
#include "permission_verification.h"
#include "tokenid_kit.h"
#include "fud_constants.h"
namespace OHOS {
namespace AAFwk {
namespace {
constexpr int32_t DEFAULT_USER_ID = 0;
constexpr int32_t API_VERSION_MOD = 100;
constexpr int32_t COLLABORATION_FWK_UID = 5520;
constexpr int32_t FOUNDATION_UID = 5523;
constexpr int32_t UDMF_UID = 3012;
constexpr int32_t PASTEBOARD_UID = 3816;
constexpr int32_t BROKER_PASTEBOARD_UID = 5557;
constexpr int32_t DFS_UID = 1009;
constexpr const char *NET_WORK_ID_MARK = "?networkid=";
}
bool FUDUtils::SendShareUnPrivilegeUriEvent(uint32_t callerTokenId, uint32_t targetTokenId)
{
std::string callerBundleName;
if (!GetBundleNameByTokenId(callerTokenId, callerBundleName)) {
return false;
}
std::string targetBundleName;
if (!GetBundleNameByTokenId(targetTokenId, targetBundleName)) {
return false;
}
AAFwk::EventInfo eventInfo;
eventInfo.callerBundleName = callerBundleName;
eventInfo.bundleName = targetBundleName;
TAG_LOGD(AAFwkTag::URIPERMMGR, "Send SHARE_UNPRIVILEGED_FILE_URI Event");
AAFwk::EventReport::SendGrantUriPermissionEvent(AAFwk::EventName::SHARE_UNPRIVILEGED_FILE_URI, eventInfo);
return true;
}
bool FUDUtils::SendSystemAppGrantUriPermissionEvent(uint32_t callerTokenId, uint32_t targetTokenId,
const std::vector<std::string> &uriVec,
const std::vector<CheckResult> &resVec)
{
TAG_LOGD(AAFwkTag::URIPERMMGR, "send grant uri permission event start.");
EventInfo eventInfo;
if (!CheckAndCreateEventInfo(callerTokenId, targetTokenId, eventInfo)) {
return false;
}
for (size_t i = 0; i < resVec.size(); i++) {
if (resVec[i].result) {
Uri uri(uriVec[i]);
eventInfo.uri = uri.GetScheme() + ":" + uri.GetAuthority();
EventReport::SendGrantUriPermissionEvent(EventName::GRANT_URI_PERMISSION, eventInfo);
return true;
}
}
TAG_LOGD(AAFwkTag::URIPERMMGR, "send grant uri permission event end.");
return false;
}
bool FUDUtils::CheckAndCreateEventInfo(uint32_t callerTokenId, uint32_t targetTokenId, EventInfo &eventInfo)
{
std::string callerBundleName;
if (!GetBundleNameByTokenId(callerTokenId, callerBundleName)) {
TAG_LOGD(AAFwkTag::URIPERMMGR, "get callerBundleName failed");
return false;
}
if (!CheckIsSystemAppByBundleName(callerBundleName)) {
TAG_LOGD(AAFwkTag::URIPERMMGR, "caller not system");
return false;
}
std::string targetBundleName;
if (!GetBundleNameByTokenId(targetTokenId, targetBundleName)) {
TAG_LOGD(AAFwkTag::URIPERMMGR, "get targetBundleName failed");
return false;
}
if (CheckIsSystemAppByBundleName(targetBundleName)) {
TAG_LOGD(AAFwkTag::URIPERMMGR, "target is systemApp");
return false;
}
eventInfo.callerBundleName = callerBundleName;
eventInfo.bundleName = targetBundleName;
return true;
}
int32_t FUDUtils::GetCurrentAccountId()
{
std::vector<int32_t> osActiveAccountIds;
auto ret = AppExecFwk::OsAccountManagerWrapper::QueryActiveOsAccountIds(
osActiveAccountIds);
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "QueryActiveOsAccountIds error. ret: %{public}d", ret);
return DEFAULT_USER_ID;
}
if (osActiveAccountIds.empty()) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "QueryActiveOsAccountIds empty");
return DEFAULT_USER_ID;
}
TAG_LOGD(AAFwkTag::URIPERMMGR, "osActiveAccountId: %{public}d", osActiveAccountIds.front());
return osActiveAccountIds.front();
}
bool FUDUtils::IsFoundationCall()
{
return IPCSkeleton::GetCallingUid() == FOUNDATION_UID;
}
bool FUDUtils::IsSAOrSystemAppCall()
{
return PermissionVerification::GetInstance()->IsSystemAppCall() ||
PermissionVerification::GetInstance()->IsSACall();
}
bool FUDUtils::IsSystemAppCall()
{
return PermissionVerification::GetInstance()->IsSystemAppCall();
}
bool FUDUtils::IsPrivilegedSACall()
{
uint32_t callerTokenId = IPCSkeleton::GetCallingTokenID();
auto permissionName = PermissionConstants::PERMISSION_GRANT_URI_PERMISSION_PRIVILEGED;
if (PermissionVerification::GetInstance()->VerifyPermissionByTokenId(callerTokenId, permissionName)) {
return true;
}
int32_t callerUId = IPCSkeleton::GetCallingUid();
return callerUId == COLLABORATION_FWK_UID;
}
bool FUDUtils::CheckIsSystemAppByBundleName(std::string &bundleName)
{
auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
if (bundleMgrHelper == nullptr) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "bundleMgrHelper null");
return false;
}
AppExecFwk::ApplicationInfo appInfo;
if (!IN_PROCESS_CALL(bundleMgrHelper->GetApplicationInfo(bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT,
GetCurrentAccountId(), appInfo))) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "GetApplicationInfo failed");
return false;
}
auto isSystemApp = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(appInfo.accessTokenIdEx);
TAG_LOGD(AAFwkTag::URIPERMMGR, "BundleName:%{public}s, isSystemApp:%{public}d", bundleName.c_str(),
static_cast<int32_t>(isSystemApp));
return isSystemApp;
}
bool FUDUtils::GetBundleApiTargetVersion(const std::string &bundleName, int32_t &targetApiVersion)
{
auto bundleMgrHelper = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
if (bundleMgrHelper == nullptr) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "The bundleMgrHelper is nullptr.");
return false;
}
AppExecFwk::ApplicationInfo appInfo;
if (!IN_PROCESS_CALL(bundleMgrHelper->GetApplicationInfo(bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT,
GetCurrentAccountId(), appInfo))) {
TAG_LOGI(AAFwkTag::URIPERMMGR, "Get application info failed.");
return false;
}
targetApiVersion = (appInfo.apiTargetVersion % API_VERSION_MOD);
return true;
}
bool FUDUtils::CheckIsSystemAppByTokenId(uint32_t tokenId)
{
std::string bundleName;
if (GetBundleNameByTokenId(tokenId, bundleName)) {
return CheckIsSystemAppByBundleName(bundleName);
}
return false;
}
bool FUDUtils::GetDirByBundleNameAndAppIndex(const std::string &bundleName, int32_t appIndex, std::string &dirName)
{
dirName = bundleName;
auto bmsClient = DelayedSingleton<AppExecFwk::BundleMgrClient>::GetInstance();
if (bmsClient == nullptr) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "bundleMgrClient is nullptr.");
return false;
}
auto bmsRet = IN_PROCESS_CALL(bmsClient->GetDirByBundleNameAndAppIndex(bundleName, appIndex, dirName));
if (bmsRet != ERR_OK) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "GetDirByBundleNameAndAppIndex failed, ret:%{public}d", bmsRet);
return false;
}
return true;
}
bool FUDUtils::GetAlterableBundleNameByTokenId(uint32_t tokenId, std::string &bundleName)
{
auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
Security::AccessToken::HapTokenInfo hapInfo;
auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo);
if (ret != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "GetHapTokenInfo failed, ret:%{public}d", ret);
return false;
}
return GetDirByBundleNameAndAppIndex(hapInfo.bundleName, hapInfo.instIndex, bundleName);
}
return false;
}
bool FUDUtils::GetBundleNameByTokenId(uint32_t tokenId, std::string &bundleName)
{
auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
Security::AccessToken::HapTokenInfo hapInfo;
auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo);
if (ret != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "GetHapTokenInfo failed, ret:%{public}d", ret);
return false;
}
bundleName = hapInfo.bundleName;
return true;
}
return false;
}
int32_t FUDUtils::GetAppIdByBundleName(const std::string &bundleName, std::string &appId)
{
TAG_LOGD(AAFwkTag::URIPERMMGR, "BundleName is %{public}s.", bundleName.c_str());
auto bms = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
if (bms == nullptr) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "The bundleMgrHelper is nullptr.");
return GET_BUNDLE_MANAGER_SERVICE_FAILED;
}
auto userId = GetCurrentAccountId();
appId = IN_PROCESS_CALL(bms->GetAppIdByBundleName(bundleName, userId));
if (appId.empty()) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "Get appId by bundle name failed, userId is %{private}d", userId);
return INNER_ERR;
}
return ERR_OK;
}
int32_t FUDUtils::GetTokenIdByBundleName(const std::string &bundleName, int32_t appIndex, int32_t userId,
uint32_t &tokenId)
{
TAG_LOGD(AAFwkTag::URIPERMMGR, "BundleName:%{public}s, appIndex:%{public}d, userId:%{public}d",
bundleName.c_str(), appIndex, userId);
auto bms = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
if (bms == nullptr) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "null bms");
return GET_BUNDLE_MANAGER_SERVICE_FAILED;
}
AppExecFwk::BundleInfo bundleInfo;
if (appIndex == 0) {
auto bundleFlag = AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO;
if (!IN_PROCESS_CALL(bms->GetBundleInfo(bundleName, bundleFlag, bundleInfo, userId))) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "Failed GetBundleInfo");
return ERR_GET_TARGET_BUNDLE_INFO_FAILED;
}
tokenId = bundleInfo.applicationInfo.accessTokenId;
return ERR_OK;
}
if (AbilityRuntime::GlobalConstant::IsAppCloneIndex(appIndex) ||
AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(appIndex)) {
auto bundleFlag = static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION);
if (IN_PROCESS_CALL(bms->GetCloneBundleInfo(bundleName, bundleFlag, appIndex, bundleInfo, userId)) != ERR_OK) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "Failed GetCloneBundleInfo");
return ERR_GET_TARGET_BUNDLE_INFO_FAILED;
}
tokenId = bundleInfo.applicationInfo.accessTokenId;
return ERR_OK;
}
if (IN_PROCESS_CALL(bms->GetSandboxBundleInfo(bundleName, appIndex, userId, bundleInfo) != ERR_OK)) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "Failed GetSandboxBundleInfo");
return ERR_GET_TARGET_BUNDLE_INFO_FAILED;
}
tokenId = bundleInfo.applicationInfo.accessTokenId;
return ERR_OK;
}
bool FUDUtils::GenerateFUDAppInfo(FUDAppInfo &info, bool supportSA)
{
auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(info.tokenId);
if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
Security::AccessToken::HapTokenInfo hapInfo;
auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(info.tokenId, hapInfo);
if (ret != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "GetHapTokenInfo failed, ret:%{public}d", ret);
return false;
}
info.userId = hapInfo.userID;
info.bundleName = hapInfo.bundleName;
return GetDirByBundleNameAndAppIndex(hapInfo.bundleName, hapInfo.instIndex, info.alterBundleName);
}
if (supportSA && tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
info.isSA = true;
info.userId = DEFAULT_USER_ID;
return true;
}
return false;
}
bool FUDUtils::IsSandboxApp(uint32_t tokenId)
{
auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
Security::AccessToken::HapTokenInfo hapInfo;
auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo);
if (ret != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "GetHapTokenInfo failed, ret:%{public}d", ret);
return false;
}
return AbilityRuntime::GlobalConstant::IsDlpIndex(hapInfo.instIndex);
}
return false;
}
bool FUDUtils::CheckUriTypeIsValid(Uri &uri)
{
auto &&scheme = uri.GetScheme();
if (scheme != FUDConstants::FILE_SCHEME && scheme != FUDConstants::ANCO_SCHEME) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "uri invalid: %{public}s-%{private}s", scheme.c_str(), uri.ToString().c_str());
return false;
}
return true;
}
bool FUDUtils::IsDocsCloudUri(Uri &uri)
{
return (uri.GetAuthority() == FUDConstants::DOCS_AUTHORITY &&
uri.ToString().find(NET_WORK_ID_MARK) != std::string::npos);
}
bool FUDUtils::IsUdmfOrPasteboardCall()
{
auto uid = IPCSkeleton::GetCallingUid();
return uid == UDMF_UID || uid == PASTEBOARD_UID || uid == BROKER_PASTEBOARD_UID;
}
bool FUDUtils::IsBrokerCaller()
{
auto uid = IPCSkeleton::GetCallingUid();
return uid == BROKER_PASTEBOARD_UID;
}
bool FUDUtils::IsDFSCall()
{
return IPCSkeleton::GetCallingUid() == DFS_UID;
}
}
}