* Copyright (c) 2023 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 "accesstoken_kit.h"
#include "dfs_daemon_event_dfx.h"
#include "dfs_error.h"
#include "dfsu_access_token_helper.h"
#include "ipc_skeleton.h"
#include "os_account_manager.h"
#include "tokenid_kit.h"
#include "uri_permission_manager_client.h"
#include "uri.h"
#include "utils_log.h"
#include "want.h"
namespace OHOS::FileManagement {
using namespace std;
using namespace Security::AccessToken;
using namespace Storage::DistributedFile;
constexpr int32_t ROOT_UID = 0;
constexpr int32_t BASE_USER_RANGE = 200000;
bool DfsuAccessTokenHelper::CheckCallerPermission(const std::string &permissionName)
{
auto tokenId = IPCSkeleton::GetCallingTokenID();
auto uid = IPCSkeleton::GetCallingUid();
auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
if (tokenType == TOKEN_HAP || tokenType == TOKEN_NATIVE) {
bool isGranted = CheckPermission(tokenId, permissionName);
if (!isGranted) {
LOGE("Token Type is %{public}d", tokenType);
}
return isGranted;
} else if ((tokenType == TOKEN_SHELL) && (uid == ROOT_UID)) {
LOGI("Token type is shell");
return false;
} else {
LOGE("Unsupported token type:%{public}d", tokenType);
return false;
}
}
bool DfsuAccessTokenHelper::CheckPermission(uint32_t tokenId, const std::string &permissionName)
{
int32_t ret = AccessTokenKit::VerifyAccessToken(tokenId, permissionName);
if (ret == PermissionState::PERMISSION_DENIED) {
LOGE("permission %{private}s: PERMISSION_DENIED", permissionName.c_str());
return false;
}
return true;
}
int32_t DfsuAccessTokenHelper::GetCallerBundleName(std::string &bundleName)
{
auto tokenId = IPCSkeleton::GetCallingTokenID();
return GetBundleNameByToken(tokenId, bundleName);
}
int32_t DfsuAccessTokenHelper::GetBundleNameByToken(uint32_t tokenId, std::string &bundleName)
{
int32_t tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
switch (tokenType) {
case TOKEN_HAP: {
HapTokenInfo hapInfo;
if (AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != 0) {
LOGE("[Permission Check] get hap token info fail");
return E_GET_TOKEN_INFO_ERROR;
}
if (hapInfo.instIndex != 0) {
LOGE("[Permission Check] APP twin is not supported.");
break;
}
bundleName = hapInfo.bundleName;
break;
}
case TOKEN_NATIVE:
case TOKEN_SHELL: {
NativeTokenInfo tokenInfo;
if (AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) != 0) {
LOGE("[Permission Check] get native token info fail");
return E_GET_TOKEN_INFO_ERROR;
}
bundleName = tokenInfo.processName;
break;
}
default: {
LOGE("[Permission Check] token type not match");
return E_GET_TOKEN_INFO_ERROR;
}
}
if (bundleName.empty()) {
LOGE("[Permission Check] package name is empty");
return E_INVAL_ARG;
}
return E_OK;
}
bool DfsuAccessTokenHelper::IsSystemApp()
{
auto tokenId = IPCSkeleton::GetCallingTokenID();
auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
if (tokenType == TOKEN_HAP) {
uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
return TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
}
return true;
}
int32_t DfsuAccessTokenHelper::GetUserId()
{
auto uid = IPCSkeleton::GetCallingUid();
return uid / BASE_USER_RANGE;
}
bool DfsuAccessTokenHelper::IsUserVerifyed(const int32_t userId)
{
bool isVerified = false;
if (AccountSA::OsAccountManager::IsOsAccountVerified(userId, isVerified) != E_OK) {
LOGE("check user verified failed");
return false;
}
return isVerified;
}
int32_t DfsuAccessTokenHelper::GetAccountId(int32_t &userId)
{
vector<int32_t> activeUsers;
if (AccountSA::OsAccountManager::QueryActiveOsAccountIds(activeUsers) != E_OK || activeUsers.empty()) {
LOGE("query active user failed");
return E_OSACCOUNT;
}
userId = activeUsers.front();
if (!IsUserVerifyed(userId)) {
LOGE("userId is invalid");
return E_INVAL_ARG;
}
LOGI("GetAccountId ok, UserId: %{public}d", userId);
return E_OK;
}
int32_t DfsuAccessTokenHelper::GetPid()
{
auto pid = IPCSkeleton::GetCallingPid();
return pid;
}
bool DfsuAccessTokenHelper::CheckUriPermission(const std::string &uriStr)
{
auto tokenId = IPCSkeleton::GetCallingTokenID();
string bundleName;
if (GetBundleNameByToken(tokenId, bundleName) != E_OK) {
LOGE("get caller bundle name failed");
return false;
}
Uri uri(uriStr);
auto &uriPermissionClient = AAFwk::UriPermissionManagerClient::GetInstance();
if (bundleName != uri.GetAuthority() &&
!uriPermissionClient.VerifyUriPermission(uri, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, tokenId)) {
RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED,
RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE,
RadarReporter::CHECK_URI_PREMISSION_ERROR, RadarReporter::PACKAGE_NAME, RadarReporter::uriPermMgr);
LOGE("uri permission denied");
return false;
}
return true;
}
}