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 }