1/*
2 * Copyright (C) 2024 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
16#include "permission_utils.h"
17
18#include "accesstoken_kit.h"
19#include "ipc_skeleton.h"
20#include "iservice_registry.h"
21#include "privacy_kit.h"
22#include "ringtone_log.h"
23#include "ringtone_tracer.h"
24#include "system_ability_definition.h"
25#include "tokenid_kit.h"
26
27namespace OHOS {
28namespace Media {
29using namespace std;
30using namespace OHOS::Security::AccessToken;
31using namespace OHOS::AppExecFwk::Constants;
32
33sptr<AppExecFwk::IBundleMgr> RingtonePermissionUtils::bundleManager_ = nullptr;
34mutex RingtonePermissionUtils::bundleManagerMutex_;
35sptr<AppExecFwk::IBundleMgr> RingtonePermissionUtils::GetSysBundleManager()
36{
37    if (bundleManager_ != nullptr) {
38        return bundleManager_;
39    }
40
41    lock_guard<mutex> lock(bundleManagerMutex_);
42    if (bundleManager_ != nullptr) {
43        return bundleManager_;
44    }
45
46    auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
47    if (systemAbilityManager == nullptr) {
48        RINGTONE_ERR_LOG("Failed to get SystemAbilityManager.");
49        return nullptr;
50    }
51
52    auto bundleObj = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
53    if (bundleObj == nullptr) {
54        RINGTONE_ERR_LOG("Remote object is nullptr.");
55        return nullptr;
56    }
57
58    auto bundleManager = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
59    if (bundleManager == nullptr) {
60        RINGTONE_ERR_LOG("Failed to iface_cast");
61        return nullptr;
62    }
63    bundleManager_ = bundleManager;
64
65    return bundleManager_;
66}
67
68void RingtonePermissionUtils::GetClientBundle(const int uid, string &bundleName)
69{
70    bundleManager_ = GetSysBundleManager();
71    if (bundleManager_ == nullptr) {
72        bundleName = "";
73        return;
74    }
75    auto result = bundleManager_->GetBundleNameForUid(uid, bundleName);
76    if (!result) {
77        RINGTONE_ERR_LOG("GetBundleNameForUid fail");
78        bundleName = "";
79    }
80}
81
82bool RingtonePermissionUtils::CheckCallerPermission(const string &permission)
83{
84    RingtoneTracer tracer;
85    tracer.Start("CheckCallerPermission");
86
87    AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
88    int result = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
89    if (result != PermissionState::PERMISSION_GRANTED) {
90        RINGTONE_ERR_LOG("Have no media permission: %{public}s", permission.c_str());
91        return false;
92    }
93    return true;
94}
95
96/* Check whether caller has at least one of @permsVec */
97bool RingtonePermissionUtils::CheckHasPermission(const vector<string> &permsVec)
98{
99    if (permsVec.empty()) {
100        return false;
101    }
102
103    for (const auto &perm : permsVec) {
104        if (CheckCallerPermission(perm)) {
105            return true;
106        }
107    }
108
109    return false;
110}
111
112string RingtonePermissionUtils::GetPackageNameByBundleName(const string &bundleName)
113{
114    const static int32_t  invalidUid = -1;
115    const static int32_t baseUserRange = 200000;
116
117    int uid = IPCSkeleton::GetCallingUid();
118    if (uid <= invalidUid) {
119        RINGTONE_ERR_LOG("Get invalidUid UID %{public}d", uid);
120        return "";
121    }
122    int32_t userId = uid / baseUserRange;
123    RINGTONE_DEBUG_LOG("uid:%{private}d, userId:%{private}d", uid, userId);
124
125    AAFwk::Want want;
126    auto bundleManager_ = GetSysBundleManager();
127    if (bundleManager_ == nullptr) {
128        RINGTONE_ERR_LOG("Get BundleManager failed");
129        return "";
130    }
131    int ret = bundleManager_->GetLaunchWantForBundle(bundleName, want, userId);
132    if (ret != ERR_OK) {
133        RINGTONE_ERR_LOG("Can not get bundleName by want, err=%{public}d, userId=%{private}d",
134            ret, userId);
135        return "";
136    }
137    string abilityName = want.GetOperation().GetAbilityName();
138    return bundleManager_->GetAbilityLabel(bundleName, abilityName);
139}
140
141/* Check whether caller has all the @permsVec */
142bool RingtonePermissionUtils::CheckCallerPermission(const vector<string> &permsVec)
143{
144    if (permsVec.empty()) {
145        return false;
146    }
147
148    for (const auto &perm : permsVec) {
149        if (!CheckCallerPermission(perm)) {
150            return false;
151        }
152    }
153    return true;
154}
155
156uint32_t RingtonePermissionUtils::GetTokenId()
157{
158    return IPCSkeleton::GetCallingTokenID();
159}
160
161bool RingtonePermissionUtils::IsSystemApp()
162{
163    uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
164    return TokenIdKit::IsSystemAppByFullTokenID(tokenId);
165}
166
167bool RingtonePermissionUtils::CheckIsSystemAppByUid()
168{
169    int uid = IPCSkeleton::GetCallingUid();
170    bundleManager_ = GetSysBundleManager();
171    if (bundleManager_ == nullptr) {
172        RINGTONE_ERR_LOG("Can not get bundleMgr");
173        return false;
174    }
175    return bundleManager_->CheckIsSystemAppByUid(uid);
176}
177
178bool RingtonePermissionUtils::IsNativeSAApp()
179{
180    uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
181    ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
182    RINGTONE_DEBUG_LOG("check if native sa token, tokenId:%{public}d, tokenType:%{public}d", tokenId, tokenType);
183    if (tokenType == ATokenTypeEnum::TOKEN_NATIVE) {
184        return true;
185    }
186    return false;
187}
188}  // namespace Media
189}  // namespace OHOS
190