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