1 /*
2  * Copyright (c) 2023 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 "accesstoken_kit.h"
17 #include "dfs_daemon_event_dfx.h"
18 #include "dfs_error.h"
19 #include "dfsu_access_token_helper.h"
20 #include "ipc_skeleton.h"
21 #include "tokenid_kit.h"
22 #include "uri_permission_manager_client.h"
23 #include "uri.h"
24 #include "utils_log.h"
25 #include "want.h"
26 
27 namespace OHOS::FileManagement {
28 using namespace std;
29 using namespace Security::AccessToken;
30 using namespace Storage::DistributedFile;
31 constexpr int32_t ROOT_UID = 0;
32 constexpr int32_t BASE_USER_RANGE = 200000;
CheckCallerPermission(const std::string & permissionName)33 bool DfsuAccessTokenHelper::CheckCallerPermission(const std::string &permissionName)
34 {
35     auto tokenId = IPCSkeleton::GetCallingTokenID();
36     auto uid = IPCSkeleton::GetCallingUid();
37     auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
38     if (tokenType == TOKEN_HAP || tokenType == TOKEN_NATIVE) {
39         bool isGranted = CheckPermission(tokenId, permissionName);
40         if (!isGranted) {
41             LOGE("Token Type is %{public}d", tokenType);
42         }
43         return isGranted;
44     } else if ((tokenType == TOKEN_SHELL) && (uid == ROOT_UID)) {
45         LOGI("Token type is shell");
46         return false;
47     } else {
48         LOGE("Unsupported token type:%{public}d", tokenType);
49         return false;
50     }
51 }
52 
CheckPermission(uint32_t tokenId,const std::string & permissionName)53 bool DfsuAccessTokenHelper::CheckPermission(uint32_t tokenId, const std::string &permissionName)
54 {
55     int32_t ret = AccessTokenKit::VerifyAccessToken(tokenId, permissionName);
56     if (ret == PermissionState::PERMISSION_DENIED) {
57         LOGE("permission %{private}s: PERMISSION_DENIED", permissionName.c_str());
58         return false;
59     }
60     return true;
61 }
62 
GetCallerBundleName(std::string & bundleName)63 int32_t DfsuAccessTokenHelper::GetCallerBundleName(std::string &bundleName)
64 {
65     auto tokenId = IPCSkeleton::GetCallingTokenID();
66     return GetBundleNameByToken(tokenId, bundleName);
67 }
68 
GetBundleNameByToken(uint32_t tokenId,std::string & bundleName)69 int32_t DfsuAccessTokenHelper::GetBundleNameByToken(uint32_t tokenId, std::string &bundleName)
70 {
71     int32_t tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
72     switch (tokenType) {
73         case TOKEN_HAP: {
74             HapTokenInfo hapInfo;
75             if (AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != 0) {
76                 LOGE("[Permission Check] get hap token info fail");
77                 return E_GET_TOKEN_INFO_ERROR;
78             }
79             if (hapInfo.instIndex != 0) {
80                 LOGE("[Permission Check] APP twin is not supported.");
81                 break;
82             }
83             bundleName = hapInfo.bundleName;
84             break;
85         }
86         case TOKEN_NATIVE:
87         // fall-through
88         case TOKEN_SHELL: {
89             NativeTokenInfo tokenInfo;
90             if (AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) != 0) {
91                 LOGE("[Permission Check] get native token info fail");
92                 return E_GET_TOKEN_INFO_ERROR;
93             }
94             bundleName = tokenInfo.processName;
95             break;
96         }
97         default: {
98             LOGE("[Permission Check] token type not match");
99             return E_GET_TOKEN_INFO_ERROR;
100         }
101     }
102     if (bundleName.empty()) {
103         LOGE("[Permission Check] package name is empty");
104         return E_INVAL_ARG;
105     }
106     return E_OK;
107 }
IsSystemApp()108 bool DfsuAccessTokenHelper::IsSystemApp()
109 {
110     auto tokenId = IPCSkeleton::GetCallingTokenID();
111     auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
112     if (tokenType == TOKEN_HAP) {
113         uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
114         return TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
115     }
116     return true;
117 }
118 
GetUserId()119 int32_t DfsuAccessTokenHelper::GetUserId()
120 {
121     auto uid = IPCSkeleton::GetCallingUid();
122     return uid / BASE_USER_RANGE;
123 }
124 
GetPid()125 int32_t DfsuAccessTokenHelper::GetPid()
126 {
127     auto pid = IPCSkeleton::GetCallingPid();
128     return pid;
129 }
130 
CheckUriPermission(const std::string & uriStr)131 bool DfsuAccessTokenHelper::CheckUriPermission(const std::string &uriStr)
132 {
133     auto tokenId = IPCSkeleton::GetCallingTokenID();
134     string bundleName;
135     if (GetBundleNameByToken(tokenId, bundleName) != E_OK) {
136         LOGE("get caller bundle name failed");
137         return false;
138     }
139     Uri uri(uriStr);
140     auto &uriPermissionClient = AAFwk::UriPermissionManagerClient::GetInstance();
141     if (bundleName != uri.GetAuthority() &&
142         !uriPermissionClient.VerifyUriPermission(uri, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, tokenId)) {
143         RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED,
144             RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE,
145             RadarReporter::CHECK_URI_PREMISSION_ERROR, RadarReporter::PACKAGE_NAME, RadarReporter::uriPermMgr);
146         LOGE("uri permission denied");
147         return false;
148     }
149     return true;
150 }
151 } // namespace OHOS::FileManagement