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 "uri_permission_utils.h"
17
18#include "ability_manager_errors.h"
19#include "accesstoken_kit.h"
20#include "bundle_mgr_client.h"
21#include "global_constant.h"
22#include "hilog_tag_wrapper.h"
23#include "in_process_call_wrapper.h"
24#include "ipc_skeleton.h"
25#include "os_account_manager_wrapper.h"
26#include "permission_verification.h"
27#include "tokenid_kit.h"
28
29namespace OHOS {
30namespace AAFwk {
31namespace {
32constexpr int32_t DEFAULT_USER_ID = 0;
33constexpr const char* FOUNDATION_PROCESS_NAME = "foundation";
34constexpr const char* NET_WORK_ID_MARK = "?networkid=";
35}
36
37std::shared_ptr<AppExecFwk::BundleMgrHelper> UPMSUtils::ConnectManagerHelper()
38{
39    if (bundleMgrHelper_ == nullptr) {
40        bundleMgrHelper_ = DelayedSingleton<AppExecFwk::BundleMgrHelper>::GetInstance();
41    }
42    return bundleMgrHelper_;
43}
44
45bool UPMSUtils::SendShareUnPrivilegeUriEvent(uint32_t callerTokenId, uint32_t targetTokenId)
46{
47    std::string callerBundleName;
48    if (!GetBundleNameByTokenId(callerTokenId, callerBundleName)) {
49        return false;
50    }
51    std::string targetBundleName;
52    if (!GetBundleNameByTokenId(targetTokenId, targetBundleName)) {
53        return false;
54    }
55    AAFwk::EventInfo eventInfo;
56    eventInfo.callerBundleName = callerBundleName;
57    eventInfo.bundleName = targetBundleName;
58    TAG_LOGD(AAFwkTag::URIPERMMGR, "Send SHARE_UNPRIVILEGED_FILE_URI Event");
59    AAFwk::EventReport::SendGrantUriPermissionEvent(AAFwk::EventName::SHARE_UNPRIVILEGED_FILE_URI, eventInfo);
60    return true;
61}
62
63bool UPMSUtils::SendSystemAppGrantUriPermissionEvent(uint32_t callerTokenId, uint32_t targetTokenId,
64    const std::vector<std::string> &uriVec, const std::vector<int32_t> &resVec)
65{
66    EventInfo eventInfo;
67    if (!CheckAndCreateEventInfo(callerTokenId, targetTokenId, eventInfo)) {
68        return false;
69    }
70    for (size_t i = 0; i < resVec.size(); i++) {
71        if (resVec[i] == 0 || resVec[i] == -EEXIST) {
72            eventInfo.uri = uriVec[i];
73            EventReport::SendGrantUriPermissionEvent(EventName::GRANT_URI_PERMISSION, eventInfo);
74        }
75    }
76    TAG_LOGD(AAFwkTag::URIPERMMGR, "Send GRANT_URI_PERMISSION Event");
77    return true;
78}
79
80bool UPMSUtils::CheckAndCreateEventInfo(uint32_t callerTokenId, uint32_t targetTokenId,
81    EventInfo &eventInfo)
82{
83    std::string callerBundleName;
84    if (!GetBundleNameByTokenId(callerTokenId, callerBundleName)) {
85        TAG_LOGD(AAFwkTag::URIPERMMGR, "get callerBundleName failed");
86        return false;
87    }
88    if (!CheckIsSystemAppByBundleName(callerBundleName)) {
89        TAG_LOGD(AAFwkTag::URIPERMMGR, "caller not system");
90        return false;
91    }
92    std::string targetBundleName;
93    if (!GetBundleNameByTokenId(targetTokenId, targetBundleName)) {
94        TAG_LOGD(AAFwkTag::URIPERMMGR, "get targetBundleName failed");
95        return false;
96    }
97    if (CheckIsSystemAppByBundleName(targetBundleName)) {
98        TAG_LOGD(AAFwkTag::URIPERMMGR, "target is systemApp");
99        return false;
100    }
101    eventInfo.callerBundleName = callerBundleName;
102    eventInfo.bundleName = targetBundleName;
103    return true;
104}
105
106int32_t UPMSUtils::GetCurrentAccountId()
107{
108    std::vector<int32_t> osActiveAccountIds;
109    auto ret = DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
110        QueryActiveOsAccountIds(osActiveAccountIds);
111    if (ret != ERR_OK) {
112        TAG_LOGE(AAFwkTag::URIPERMMGR, "QueryActiveOsAccountIds error");
113        return DEFAULT_USER_ID;
114    }
115    if (osActiveAccountIds.empty()) {
116        TAG_LOGE(AAFwkTag::URIPERMMGR, "QueryActiveOsAccountIds empty");
117        return DEFAULT_USER_ID;
118    }
119    return osActiveAccountIds.front();
120}
121
122bool UPMSUtils::IsFoundationCall()
123{
124    auto callerTokenId = IPCSkeleton::GetCallingTokenID();
125    TAG_LOGD(AAFwkTag::ABILITYMGR, "callerTokenId is %{public}u", callerTokenId);
126    auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerTokenId);
127    if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
128        TAG_LOGI(AAFwkTag::ABILITYMGR, "not native call");
129        return false;
130    }
131    Security::AccessToken::NativeTokenInfo nativeInfo;
132    auto result = Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(callerTokenId, nativeInfo);
133    if (result != ERR_OK) {
134        TAG_LOGE(AAFwkTag::URIPERMMGR, "GetNativeTokenInfo failed, callerTokenId:%{public}u", callerTokenId);
135        return false;
136    }
137    TAG_LOGD(AAFwkTag::URIPERMMGR, "Caller processName:%{public}s", nativeInfo.processName.c_str());
138    return nativeInfo.processName == FOUNDATION_PROCESS_NAME;
139}
140
141bool UPMSUtils::IsSAOrSystemAppCall()
142{
143    return PermissionVerification::GetInstance()->IsSystemAppCall() ||
144        PermissionVerification::GetInstance()->IsSACall();
145}
146
147bool UPMSUtils::IsSystemAppCall(uint32_t tokenId)
148{
149    if (UPMSUtils::IsFoundationCall()) {
150        return UPMSUtils::CheckIsSystemAppByTokenId(tokenId);
151    }
152    return PermissionVerification::GetInstance()->IsSystemAppCall();
153}
154
155bool UPMSUtils::CheckIsSystemAppByBundleName(std::string &bundleName)
156{
157    auto bundleMgrHelper = ConnectManagerHelper();
158    if (bundleMgrHelper == nullptr) {
159        TAG_LOGW(AAFwkTag::URIPERMMGR, "bundleMgrHelper null");
160        return false;
161    }
162    AppExecFwk::ApplicationInfo appInfo;
163    if (!IN_PROCESS_CALL(bundleMgrHelper->GetApplicationInfo(bundleName,
164        AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, GetCurrentAccountId(), appInfo))) {
165        TAG_LOGW(AAFwkTag::URIPERMMGR, "GetApplicationInfo failed");
166        return false;
167    }
168    auto isSystemApp = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(appInfo.accessTokenIdEx);
169    TAG_LOGD(AAFwkTag::URIPERMMGR, "BundleName:%{public}s, isSystemApp:%{public}d", bundleName.c_str(),
170        static_cast<int32_t>(isSystemApp));
171    return isSystemApp;
172}
173
174bool UPMSUtils::CheckIsSystemAppByTokenId(uint32_t tokenId)
175{
176    std::string bundleName;
177    if (GetBundleNameByTokenId(tokenId, bundleName)) {
178        return CheckIsSystemAppByBundleName(bundleName);
179    }
180    return false;
181}
182
183bool UPMSUtils::GetDirByBundleNameAndAppIndex(const std::string &bundleName, int32_t appIndex, std::string &dirName)
184{
185    auto bmsClient = DelayedSingleton<AppExecFwk::BundleMgrClient>::GetInstance();
186    if (bmsClient == nullptr) {
187        TAG_LOGE(AAFwkTag::URIPERMMGR, "bundleMgrClient is nullptr.");
188        return false;
189    }
190    auto bmsRet = bmsClient->GetDirByBundleNameAndAppIndex(bundleName, appIndex, dirName);
191    if (bmsRet != ERR_OK) {
192        TAG_LOGE(AAFwkTag::URIPERMMGR, "GetDirByBundleNameAndAppIndex failed, ret:%{public}d", bmsRet);
193        return false;
194    }
195    return true;
196}
197
198bool UPMSUtils::GetAlterableBundleNameByTokenId(uint32_t tokenId, std::string &bundleName)
199{
200    auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
201    if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
202        Security::AccessToken::HapTokenInfo hapInfo;
203        auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo);
204        if (ret != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
205            TAG_LOGE(AAFwkTag::URIPERMMGR, "GetHapTokenInfo failed, ret:%{public}d", ret);
206            return false;
207        }
208        return GetDirByBundleNameAndAppIndex(hapInfo.bundleName, hapInfo.instIndex, bundleName);
209    }
210    return false;
211}
212
213bool UPMSUtils::GetBundleNameByTokenId(uint32_t tokenId, std::string &bundleName)
214{
215    auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
216    if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
217        Security::AccessToken::HapTokenInfo hapInfo;
218        auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo);
219        if (ret != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
220            TAG_LOGE(AAFwkTag::URIPERMMGR, "GetHapTokenInfo failed, ret:%{public}d", ret);
221            return false;
222        }
223        bundleName = hapInfo.bundleName;
224        return true;
225    }
226    return false;
227}
228
229int32_t UPMSUtils::GetAppIdByBundleName(const std::string &bundleName, std::string &appId)
230{
231    TAG_LOGD(AAFwkTag::URIPERMMGR, "BundleName is %{public}s.", bundleName.c_str());
232    auto bms = ConnectManagerHelper();
233    if (bms == nullptr) {
234        TAG_LOGW(AAFwkTag::URIPERMMGR, "The bundleMgrHelper is nullptr.");
235        return GET_BUNDLE_MANAGER_SERVICE_FAILED;
236    }
237    auto userId = GetCurrentAccountId();
238    appId = IN_PROCESS_CALL(bms->GetAppIdByBundleName(bundleName, userId));
239    if (appId.empty()) {
240        TAG_LOGW(AAFwkTag::URIPERMMGR, "Get appId by bundle name failed, userId is %{private}d", userId);
241        return INNER_ERR;
242    }
243    return ERR_OK;
244}
245
246int32_t UPMSUtils::GetTokenIdByBundleName(const std::string &bundleName, int32_t appIndex, uint32_t &tokenId)
247{
248    TAG_LOGD(AAFwkTag::URIPERMMGR, "BundleName:%{public}s, appIndex:%{public}d", bundleName.c_str(), appIndex);
249    auto bms = ConnectManagerHelper();
250    if (bms == nullptr) {
251        TAG_LOGW(AAFwkTag::URIPERMMGR, "null bms");
252        return GET_BUNDLE_MANAGER_SERVICE_FAILED;
253    }
254    AppExecFwk::BundleInfo bundleInfo;
255    auto userId = GetCurrentAccountId();
256    if (appIndex == 0) {
257        auto bundleFlag = AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO;
258        if (!IN_PROCESS_CALL(bms->GetBundleInfo(bundleName, bundleFlag, bundleInfo, userId))) {
259            TAG_LOGW(AAFwkTag::URIPERMMGR, "Failed GetBundleInfo");
260            return GET_BUNDLE_INFO_FAILED;
261        }
262        tokenId = bundleInfo.applicationInfo.accessTokenId;
263        return ERR_OK;
264    }
265    if (appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) {
266        auto bundleFlag = static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION);
267        if (IN_PROCESS_CALL(bms->GetCloneBundleInfo(bundleName, bundleFlag, appIndex, bundleInfo, userId)) != ERR_OK) {
268            TAG_LOGW(AAFwkTag::URIPERMMGR, "Failed GetCloneBundleInfo");
269            return GET_BUNDLE_INFO_FAILED;
270        }
271        tokenId = bundleInfo.applicationInfo.accessTokenId;
272        return ERR_OK;
273    }
274    if (IN_PROCESS_CALL(bms->GetSandboxBundleInfo(bundleName, appIndex, userId, bundleInfo) != ERR_OK)) {
275        TAG_LOGW(AAFwkTag::URIPERMMGR, "Failed GetSandboxBundleInfo");
276        return GET_BUNDLE_INFO_FAILED;
277    }
278    tokenId = bundleInfo.applicationInfo.accessTokenId;
279    return ERR_OK;
280}
281
282bool UPMSUtils::IsDocsCloudUri(Uri &uri)
283{
284    return (uri.GetAuthority() == "docs" && uri.ToString().find(NET_WORK_ID_MARK) != std::string::npos);
285}
286
287std::shared_ptr<AppExecFwk::BundleMgrHelper> UPMSUtils::bundleMgrHelper_ = nullptr;
288}  // namespace AAFwk
289}  // namespace OHOS
290