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 "oh_file_share.h"
17
18 #include <cstdint>
19 #include <cstdlib>
20 #include <iostream>
21
22 #include "access_token.h"
23 #include "accesstoken_kit.h"
24 #include "file_permission.h"
25 #include "ipc_skeleton.h"
26 #include "log.h"
27 #include "parameter.h"
28 #include "securec.h"
29 #include "tokenid_kit.h"
30
31 const int32_t FOO_MAX_LEN = sizeof(FileShare_PolicyErrorResult) * OHOS::AppFileService::MAX_ARRAY_SIZE;
32 const std::string FILE_ACCESS_PERSIST_PERMISSION = "ohos.permission.FILE_ACCESS_PERSIST";
33 const std::string FULL_MOUNT_ENABLE_PARAMETER = "const.filemanager.full_mount.enable";
34
35 using Exec = std::function<int(const std::vector<OHOS::AppFileService::UriPolicyInfo> &uriPolicies,
36 std::deque<struct OHOS::AppFileService::PolicyErrorResult> &errorResults)>;
CheckPermission(const std::string & permission)37 static bool CheckPermission(const std::string &permission)
38 {
39 OHOS::Security::AccessToken::AccessTokenID tokenCaller = OHOS::IPCSkeleton::GetCallingTokenID();
40 return OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, permission) ==
41 OHOS::Security::AccessToken::PermissionState::PERMISSION_GRANTED;
42 }
43
CheckFileManagerFullMountEnable()44 static bool CheckFileManagerFullMountEnable()
45 {
46 char value[] = "false";
47 int retSystem = GetParameter(FULL_MOUNT_ENABLE_PARAMETER.c_str(), "false", value, sizeof(value));
48 if (retSystem > 0 && !strcmp(value, "true")) {
49 LOGI("The full mount enable parameter is true");
50 return true;
51 }
52 LOGI("The full mount enable parameter is false");
53 return false;
54 }
55
ConvertPolicyInfo(const FileShare_PolicyInfo * policies,int policyNum,std::vector<OHOS::AppFileService::UriPolicyInfo> & uriPolicies)56 static bool ConvertPolicyInfo(const FileShare_PolicyInfo *policies,
57 int policyNum,
58 std::vector<OHOS::AppFileService::UriPolicyInfo> &uriPolicies)
59 {
60 for (int32_t i = 0; i < policyNum; i++) {
61 OHOS::AppFileService::UriPolicyInfo policyInfo;
62 if (policies[i].uri == nullptr || policies[i].length == 0) {
63 LOGE("The uri pointer is nullptr or length is 0");
64 return false;
65 }
66 auto uriLength = strnlen(policies[i].uri, policies[i].length);
67 if (uriLength != policies[i].length) {
68 LOGE("The uri length abnormal");
69 return false;
70 }
71 policyInfo.uri = std::string(policies[i].uri, policies[i].length);
72 policyInfo.mode = policies[i].operationMode;
73 uriPolicies.push_back(policyInfo);
74 }
75 return true;
76 }
77
ConvertPolicyErrorResult(const std::deque<OHOS::AppFileService::PolicyErrorResult> & errorResults,FileShare_PolicyErrorResult ** result,unsigned int & resultNum)78 static bool ConvertPolicyErrorResult(const std::deque<OHOS::AppFileService::PolicyErrorResult> &errorResults,
79 FileShare_PolicyErrorResult **result,
80 unsigned int &resultNum)
81 {
82 resultNum = 0;
83 auto count = errorResults.size();
84 auto memorySize = count * sizeof(FileShare_PolicyErrorResult);
85 if (memorySize == 0 || memorySize > FOO_MAX_LEN) {
86 LOGE("The size of the return value array is abnormal");
87 return false;
88 }
89 *result = static_cast<FileShare_PolicyErrorResult *>(malloc(memorySize));
90 if (*result == nullptr) {
91 LOGE("Failed to apply for FileShare_PolicyErrorResult array memory");
92 return false;
93 }
94 for (uint32_t i = 0; i < count; i++) {
95 size_t size = errorResults[i].uri.size() + 1;
96 (*result)[i].uri = static_cast<char *>(malloc(size));
97 if ((*result)[i].uri == nullptr) {
98 LOGE("Failed to apply for URI memory");
99 return false;
100 }
101 auto ret = strcpy_s((*result)[i].uri, size, errorResults[i].uri.c_str());
102 if (ret != 0) {
103 LOGE("Copy uri failed uri:%{public}s, errno:%{public}d", errorResults[i].uri.c_str(), ret);
104 free((*result)[i].uri);
105 return false;
106 }
107 (*result)[i].code = static_cast<FileShare_PolicyErrorCode>(errorResults[i].code);
108 size = errorResults[i].message.size() + 1;
109 (*result)[i].message = static_cast<char *>(malloc(size));
110 if ((*result)[i].message == nullptr) {
111 LOGE("Failed to apply for message memory");
112 free((*result)[i].uri);
113 return false;
114 }
115 ret = strcpy_s((*result)[i].message, size, errorResults[i].message.c_str());
116 if (ret != 0) {
117 LOGE("Copy message failed message:%{public}s, errno:%{public}d", errorResults[i].uri.c_str(), ret);
118 free((*result)[i].uri);
119 free((*result)[i].message);
120 return false;
121 }
122 resultNum++;
123 }
124 return true;
125 }
126
ConvertPolicyErrorResultBool(const std::vector<bool> & errorResults,bool ** result)127 static bool ConvertPolicyErrorResultBool(const std::vector<bool> &errorResults, bool **result)
128 {
129 auto count = errorResults.size();
130 auto memorySize = count * sizeof(bool);
131 if (memorySize == 0 || memorySize > FOO_MAX_LEN) {
132 LOGE("The size of the return value array is abnormal");
133 return false;
134 }
135 *result = (bool *)malloc(memorySize);
136 if (*result == nullptr) {
137 LOGE("Failed to apply for bool array memory");
138 return false;
139 }
140 for (uint32_t i = 0; i < count; i++) {
141 (*result)[i] = errorResults[i];
142 }
143 return true;
144 }
145
ErrorCodeConversion(int32_t errorCode)146 static FileManagement_ErrCode ErrorCodeConversion(int32_t errorCode)
147 {
148 FileManagement_ErrCode errCode = E_UNKNOWN_ERROR;
149 switch (errorCode) {
150 case static_cast<int32_t>(E_NO_ERROR):
151 errCode = E_NO_ERROR;
152 break;
153 case static_cast<int32_t>(E_PERMISSION):
154 errCode = E_PERMISSION;
155 break;
156 case static_cast<int32_t>(E_PARAMS):
157 errCode = E_PARAMS;
158 break;
159 case EPERM:
160 errCode = E_EPERM;
161 break;
162 default:
163 break;
164 }
165 return errCode;
166 }
167
168 void OH_FileShare_ReleasePolicyErrorResult(FileShare_PolicyErrorResult *result, unsigned int num);
ExecAction(const FileShare_PolicyInfo * policies,unsigned int policyNum,FileShare_PolicyErrorResult ** result,unsigned int * resultNum,Exec exec)169 static FileManagement_ErrCode ExecAction(const FileShare_PolicyInfo *policies,
170 unsigned int policyNum,
171 FileShare_PolicyErrorResult **result,
172 unsigned int *resultNum,
173 Exec exec)
174 {
175 (*resultNum) = 0;
176 if (!CheckFileManagerFullMountEnable()) {
177 return E_DEVICE_NOT_SUPPORT;
178 }
179 if (!CheckPermission(FILE_ACCESS_PERSIST_PERMISSION)) {
180 return E_PERMISSION;
181 }
182 std::vector<OHOS::AppFileService::UriPolicyInfo> uriPolicies;
183 if (!ConvertPolicyInfo(policies, policyNum, uriPolicies)) {
184 return E_PARAMS;
185 }
186 std::deque<OHOS::AppFileService::PolicyErrorResult> errorResults;
187 auto ret = ErrorCodeConversion(exec(uriPolicies, errorResults));
188 if (ret == E_NO_ERROR) {
189 return E_NO_ERROR;
190 }
191 if (!ConvertPolicyErrorResult(errorResults, result, *resultNum)) {
192 OH_FileShare_ReleasePolicyErrorResult(*result, *resultNum);
193 return E_ENOMEM;
194 }
195 return ret;
196 }
197
OH_FileShare_PersistPermission(const FileShare_PolicyInfo * policies,unsigned int policyNum,FileShare_PolicyErrorResult ** result,unsigned int * resultNum)198 FileManagement_ErrCode OH_FileShare_PersistPermission(const FileShare_PolicyInfo *policies,
199 unsigned int policyNum,
200 FileShare_PolicyErrorResult **result,
201 unsigned int *resultNum)
202 {
203 if (policies == nullptr || result == nullptr || resultNum == nullptr) {
204 LOGE("The external input pointer is abnormal");
205 return E_PARAMS;
206 }
207 if (policyNum == 0 || policyNum > OHOS::AppFileService::MAX_ARRAY_SIZE) {
208 LOGE("The policyNum is abnormal");
209 return E_PARAMS;
210 }
211 return ExecAction(policies, policyNum, result, resultNum, OHOS::AppFileService::FilePermission::PersistPermission);
212 }
213
OH_FileShare_RevokePermission(const FileShare_PolicyInfo * policies,unsigned int policyNum,FileShare_PolicyErrorResult ** result,unsigned int * resultNum)214 FileManagement_ErrCode OH_FileShare_RevokePermission(const FileShare_PolicyInfo *policies,
215 unsigned int policyNum,
216 FileShare_PolicyErrorResult **result,
217 unsigned int *resultNum)
218 {
219 if (policies == nullptr || result == nullptr || resultNum == nullptr) {
220 LOGE("The external input pointer is abnormal");
221 return E_PARAMS;
222 }
223 if (policyNum == 0 || policyNum > OHOS::AppFileService::MAX_ARRAY_SIZE) {
224 LOGE("The policyNum is abnormal");
225 return E_PARAMS;
226 }
227 return ExecAction(policies, policyNum, result, resultNum, OHOS::AppFileService::FilePermission::RevokePermission);
228 }
229
OH_FileShare_ActivatePermission(const FileShare_PolicyInfo * policies,unsigned int policyNum,FileShare_PolicyErrorResult ** result,unsigned int * resultNum)230 FileManagement_ErrCode OH_FileShare_ActivatePermission(const FileShare_PolicyInfo *policies,
231 unsigned int policyNum,
232 FileShare_PolicyErrorResult **result,
233 unsigned int *resultNum)
234 {
235 if (policies == nullptr || result == nullptr || resultNum == nullptr) {
236 LOGE("The external input pointer is abnormal");
237 return E_PARAMS;
238 }
239 if (policyNum == 0 || policyNum > OHOS::AppFileService::MAX_ARRAY_SIZE) {
240 LOGE("The policyNum is abnormal");
241 return E_PARAMS;
242 }
243 return ExecAction(policies, policyNum, result, resultNum, OHOS::AppFileService::FilePermission::ActivatePermission);
244 }
245
OH_FileShare_DeactivatePermission(const FileShare_PolicyInfo * policies,unsigned int policyNum,FileShare_PolicyErrorResult ** result,unsigned int * resultNum)246 FileManagement_ErrCode OH_FileShare_DeactivatePermission(const FileShare_PolicyInfo *policies,
247 unsigned int policyNum,
248 FileShare_PolicyErrorResult **result,
249 unsigned int *resultNum)
250 {
251 if (policies == nullptr || result == nullptr || resultNum == nullptr) {
252 LOGE("The external input pointer is abnormal");
253 return E_PARAMS;
254 }
255 if (policyNum == 0 || policyNum > OHOS::AppFileService::MAX_ARRAY_SIZE) {
256 LOGE("The policyNum is abnormal");
257 return E_PARAMS;
258 }
259 return ExecAction(policies, policyNum, result, resultNum,
260 OHOS::AppFileService::FilePermission::DeactivatePermission);
261 }
262
OH_FileShare_CheckPersistentPermission(const FileShare_PolicyInfo * policies,unsigned int policyNum,bool ** result,unsigned int * resultNum)263 FileManagement_ErrCode OH_FileShare_CheckPersistentPermission(const FileShare_PolicyInfo *policies,
264 unsigned int policyNum,
265 bool **result,
266 unsigned int *resultNum)
267 {
268 if (policies == nullptr || result == nullptr || resultNum == nullptr) {
269 LOGE("The external input pointer is abnormal");
270 return E_PARAMS;
271 }
272 if (policyNum == 0 || policyNum > OHOS::AppFileService::MAX_ARRAY_SIZE) {
273 LOGE("The policyNum is abnormal");
274 return E_PARAMS;
275 }
276 *resultNum = 0;
277 if (!CheckFileManagerFullMountEnable()) {
278 return E_DEVICE_NOT_SUPPORT;
279 }
280 if (!CheckPermission(FILE_ACCESS_PERSIST_PERMISSION)) {
281 return E_PERMISSION;
282 }
283 std::vector<OHOS::AppFileService::UriPolicyInfo> uriPolicies;
284 if (!ConvertPolicyInfo(policies, policyNum, uriPolicies)) {
285 return E_PARAMS;
286 }
287 std::vector<bool> errorResults;
288 auto ret = OHOS::AppFileService::FilePermission::CheckPersistentPermission(uriPolicies, errorResults);
289 if (ret != 0) {
290 return ErrorCodeConversion(ret);
291 }
292 if (!ConvertPolicyErrorResultBool(errorResults, result)) {
293 return E_ENOMEM;
294 }
295 *resultNum = errorResults.size();
296 return E_NO_ERROR;
297 }
298
OH_FileShare_ReleasePolicyErrorResult(FileShare_PolicyErrorResult * result,unsigned int num)299 void OH_FileShare_ReleasePolicyErrorResult(FileShare_PolicyErrorResult *result, unsigned int num)
300 {
301 if (result == nullptr) {
302 return;
303 }
304 for (unsigned i = 0; i < num; i++) {
305 if (result[i].uri != nullptr) {
306 free(result[i].uri);
307 }
308 if (result[i].message != nullptr) {
309 free(result[i].message);
310 }
311 }
312 free(result);
313 }