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 #include "file_permission.h"
16 #include "log.h"
17 #include "parameter.h"
18 #include "uri.h"
19 #include <unistd.h>
20 #include <unordered_set>
21 #ifdef SANDBOX_MANAGER
22 #include "uri_permission_manager_client.h"
23 #include "accesstoken_kit.h"
24 #include "bundle_constants.h"
25 #include "hap_token_info.h"
26 #include "ipc_skeleton.h"
27 #include "n_error.h"
28 #include "sandbox_helper.h"
29 #include "sandbox_manager_err_code.h"
30 #include "tokenid_kit.h"
31 #endif
32 
33 namespace OHOS {
34 namespace AppFileService {
35 const std::string MEDIA_AUTHORITY = "media";
36 const std::string NETWORK_PARA = "?networkid=";
37 const std::string PERSISTENCE_FORBIDDEN_MESSAGE = "URI forbid to be persisted!";
38 const std::string INVALID_MODE_MESSAGE = "Invalid operation mode!";
39 const std::string INVALID_PATH_MESSAGE = "Invalid path!";
40 const std::string PERMISSION_NOT_PERSISTED_MESSAGE = "The policy is no persistent capability!";
41 const std::string FILE_SCHEME_PREFIX = "file://";
42 const std::string FILE_MANAGER_AUTHORITY = "docs";
43 const std::string SANDBOX_STORAGE_PATH = "/storage/Users/currentUser/";
44 const std::string DOWNLOAD_PATH = "/storage/Users/currentUser/Download";
45 const std::string DESKTOP_PATH = "/storage/Users/currentUser/Desktop";
46 const std::string DOCUMENTS_PATH = "/storage/Users/currentUser/Documents";
47 const std::string READ_WRITE_DOWNLOAD_PERMISSION = "ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY";
48 const std::string READ_WRITE_DESKTOP_PERMISSION = "ohos.permission.READ_WRITE_DESKTOP_DIRECTORY";
49 const std::string READ_WRITE_DOCUMENTS_PERMISSION = "ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY";
50 const std::string FILE_ACCESS_MANAGER_PERMISSION = "ohos.permission.FILE_ACCESS_MANAGER";
51 const std::unordered_map<std::string, std::string> permissionPathMap = {
52     {READ_WRITE_DOWNLOAD_PERMISSION, DOWNLOAD_PATH},
53     {READ_WRITE_DESKTOP_PERMISSION, DESKTOP_PATH},
54     {READ_WRITE_DOCUMENTS_PERMISSION, DOCUMENTS_PATH}};
55 #ifdef SANDBOX_MANAGER
56 namespace {
CheckValidUri(const string & uriStr)57 bool CheckValidUri(const string &uriStr)
58 {
59     if (uriStr.find(FILE_SCHEME_PREFIX) != 0) {
60         LOGE("Incorrect URI format!");
61         return false;
62     }
63     Uri uri(uriStr);
64     std::string bundleName = uri.GetAuthority();
65     if (bundleName == MEDIA_AUTHORITY) {
66         LOGE("the URI is media URI");
67         return false;
68     }
69     if (uriStr.find(NETWORK_PARA) != string::npos) {
70         LOGE("the URI is not the current device URI");
71         return false;
72     }
73     return true;
74 }
ErrorCodeConversion(int32_t sandboxManagerErrorCode,const deque<struct PolicyErrorResult> & errorResults,const vector<uint32_t> & resultCodes)75 int32_t ErrorCodeConversion(int32_t sandboxManagerErrorCode,
76                             const deque<struct PolicyErrorResult> &errorResults,
77                             const vector<uint32_t> &resultCodes)
78 {
79     if (sandboxManagerErrorCode == PERMISSION_DENIED) {
80         LOGE("The app does not have the authorization URI permission");
81         return FileManagement::LibN::E_PERMISSION;
82     }
83     if (sandboxManagerErrorCode == INVALID_PARAMTER) {
84         if (resultCodes.size() != 0) {
85             LOGE("The number of incoming URIs is too many");
86             return FileManagement::LibN::E_PARAMS;
87         } else {
88             LOGE("The incoming URI is invalid");
89             return EPERM;
90         }
91     }
92     if (!errorResults.empty()) {
93         LOGE("Some of the incoming URIs failed");
94         return EPERM;
95     }
96     for (size_t i = 0; i < resultCodes.size(); i++) {
97         if (resultCodes[i] != 0) {
98             LOGE("Reason for URI authorization failure");
99             return EPERM;
100         }
101     }
102     if (sandboxManagerErrorCode == SANDBOX_MANAGER_OK) {
103         return 0;
104     }
105     return FileManagement::LibN::E_UNKNOWN_ERROR;
106 }
107 
ErrorCodeConversion(int32_t sandboxManagerErrorCode)108 int32_t ErrorCodeConversion(int32_t sandboxManagerErrorCode)
109 {
110     if (sandboxManagerErrorCode == SANDBOX_MANAGER_OK) {
111         return 0;
112     }
113     if (sandboxManagerErrorCode == PERMISSION_DENIED) {
114         LOGE("The app does not have the authorization URI permission");
115         return FileManagement::LibN::E_PERMISSION;
116     }
117     return FileManagement::LibN::E_UNKNOWN_ERROR;
118 }
119 } // namespace
ParseErrorResults(const vector<uint32_t> & resultCodes,const vector<PolicyInfo> & pathPolicies,deque<struct PolicyErrorResult> & errorResults)120 void FilePermission::ParseErrorResults(const vector<uint32_t> &resultCodes,
121                                        const vector<PolicyInfo> &pathPolicies,
122                                        deque<struct PolicyErrorResult> &errorResults)
123 {
124     if (resultCodes.size() != pathPolicies.size()) {
125         LOGE("resultCodes size is not equals pathPolicies size");
126         return;
127     }
128     for (size_t i = 0; i < resultCodes.size(); i++) {
129         PolicyErrorResult result;
130         Uri uri(pathPolicies[i].path);
131         switch (resultCodes[i]) {
132             case static_cast<PolicyErrorCode>(PolicyErrorCode::PERSISTENCE_FORBIDDEN):
133                 result = {uri.ToString(), PolicyErrorCode::PERSISTENCE_FORBIDDEN, PERSISTENCE_FORBIDDEN_MESSAGE};
134                 errorResults.emplace_back(result);
135                 break;
136             case static_cast<PolicyErrorCode>(PolicyErrorCode::INVALID_MODE):
137                 result = {uri.ToString(), PolicyErrorCode::INVALID_MODE, INVALID_MODE_MESSAGE};
138                 errorResults.emplace_back(result);
139                 break;
140             case static_cast<PolicyErrorCode>(PolicyErrorCode::INVALID_PATH):
141                 result = {uri.ToString(), PolicyErrorCode::INVALID_PATH, INVALID_PATH_MESSAGE};
142                 errorResults.emplace_back(result);
143                 break;
144             case static_cast<PolicyErrorCode>(PolicyErrorCode::PERMISSION_NOT_PERSISTED):
145                 result = {uri.ToString(), PolicyErrorCode::PERMISSION_NOT_PERSISTED, PERMISSION_NOT_PERSISTED_MESSAGE};
146                 errorResults.emplace_back(result);
147                 break;
148             default:
149                 break;
150         }
151     }
152 }
153 
ParseErrorResults(const vector<bool> & resultCodes,vector<bool> & errorResults)154 void FilePermission::ParseErrorResults(const vector<bool> &resultCodes, vector<bool> &errorResults)
155 {
156     auto resultCodeSize = resultCodes.size();
157     if (resultCodeSize == 0) {
158         return;
159     }
160     auto errorResultSize = errorResults.size();
161     for (size_t i = 0, j = 0; i < errorResultSize && j < resultCodeSize; i++) {
162         if (errorResults[i]) {
163             errorResults[i] = resultCodes[j++];
164         }
165     }
166 }
167 
GetPathPolicyInfoFromUriPolicyInfo(const vector<UriPolicyInfo> & uriPolicies,deque<struct PolicyErrorResult> & errorResults)168 vector<PolicyInfo> FilePermission::GetPathPolicyInfoFromUriPolicyInfo(const vector<UriPolicyInfo> &uriPolicies,
169                                                                       deque<struct PolicyErrorResult> &errorResults)
170 {
171     vector<PolicyInfo> pathPolicies;
172     for (auto uriPolicy : uriPolicies) {
173         Uri uri(uriPolicy.uri);
174         string path = SandboxHelper::Decode(uri.GetPath());
175         if (!CheckValidUri(uriPolicy.uri) || access(path.c_str(), F_OK) != 0) {
176             LOGE("Not correct uri!");
177             PolicyErrorResult result = {uriPolicy.uri, PolicyErrorCode::INVALID_PATH, INVALID_PATH_MESSAGE};
178             errorResults.emplace_back(result);
179         } else {
180             PolicyInfo policyInfo = {path, uriPolicy.mode};
181             pathPolicies.emplace_back(policyInfo);
182         }
183     }
184     return pathPolicies;
185 }
186 
GetPathPolicyInfoFromUriPolicyInfo(const vector<UriPolicyInfo> & uriPolicies,vector<bool> & errorResults)187 vector<PolicyInfo> FilePermission::GetPathPolicyInfoFromUriPolicyInfo(const vector<UriPolicyInfo> &uriPolicies,
188                                                                       vector<bool> &errorResults)
189 {
190     vector<PolicyInfo> pathPolicies;
191     for (const auto &uriPolicy : uriPolicies) {
192         Uri uri(uriPolicy.uri);
193         string path = SandboxHelper::Decode(uri.GetPath());
194         if (!CheckValidUri(uriPolicy.uri) || access(path.c_str(), F_OK) != 0) {
195             LOGE("Not correct uri!");
196             errorResults.emplace_back(false);
197         } else {
198             PolicyInfo policyInfo = {path, uriPolicy.mode};
199             pathPolicies.emplace_back(policyInfo);
200             errorResults.emplace_back(true);
201         }
202     }
203     return pathPolicies;
204 }
205 
CheckPermission(uint64_t tokenCaller,const string & permission)206 static bool CheckPermission(uint64_t tokenCaller, const string &permission)
207 {
208     return Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, permission) ==
209            Security::AccessToken::PermissionState::PERMISSION_GRANTED;
210 }
211 
IsFileManagerUri(const string & pathStr)212 static bool IsFileManagerUri(const string &pathStr)
213 {
214     return pathStr.find(DOWNLOAD_PATH) == 0 || pathStr.find(DESKTOP_PATH) == 0 || pathStr.find(DOCUMENTS_PATH) == 0;
215 }
216 
CheckFileManagerUriPermission(uint32_t providerTokenId,const string & pathStr)217 static bool CheckFileManagerUriPermission(uint32_t providerTokenId, const string &pathStr)
218 {
219     return (IsFileManagerUri(pathStr) && CheckPermission(providerTokenId, FILE_ACCESS_MANAGER_PERMISSION)) ||
220            (pathStr.find(DOWNLOAD_PATH) == 0 && CheckPermission(providerTokenId, READ_WRITE_DOWNLOAD_PERMISSION)) ||
221            (pathStr.find(DESKTOP_PATH) == 0 && CheckPermission(providerTokenId, READ_WRITE_DESKTOP_PERMISSION)) ||
222            (pathStr.find(DOCUMENTS_PATH) == 0 && CheckPermission(providerTokenId, READ_WRITE_DOCUMENTS_PERMISSION));
223 }
224 
CheckUriPersistentPermission(uint32_t tokenId,const vector<UriPolicyInfo> & uriPolicies,vector<bool> & errorResults)225 int32_t FilePermission::CheckUriPersistentPermission(uint32_t tokenId,
226                                                      const vector<UriPolicyInfo> &uriPolicies,
227                                                      vector<bool> &errorResults)
228 {
229     int errorCode = 0;
230     vector<PolicyInfo> pathPolicies = GetPathPolicyInfoFromUriPolicyInfo(uriPolicies, errorResults);
231     if (pathPolicies.size() == 0) {
232         return EPERM;
233     }
234 
235     vector<bool> resultCodes;
236     int32_t sandboxManagerErrorCode = SandboxManagerKit::CheckPersistPolicy(tokenId, pathPolicies, resultCodes);
237     for (size_t i = resultCodes.size(); i < pathPolicies.size(); i++) {
238         resultCodes.emplace_back(false);
239     }
240     for (size_t i = 0; i < pathPolicies.size(); i++) {
241         if (!resultCodes[i]) {
242             resultCodes[i] = CheckFileManagerUriPermission(tokenId, pathPolicies[i].path);
243         }
244     }
245 
246     errorCode = ErrorCodeConversion(sandboxManagerErrorCode);
247     ParseErrorResults(resultCodes, errorResults);
248     return errorCode;
249 }
250 #endif
251 
PersistPermission(const vector<UriPolicyInfo> & uriPolicies,deque<struct PolicyErrorResult> & errorResults)252 int32_t FilePermission::PersistPermission(const vector<UriPolicyInfo> &uriPolicies,
253                                           deque<struct PolicyErrorResult> &errorResults)
254 {
255     int errorCode = 0;
256 #ifdef SANDBOX_MANAGER
257     vector<PolicyInfo> pathPolicies = GetPathPolicyInfoFromUriPolicyInfo(uriPolicies, errorResults);
258     vector<uint32_t> resultCodes;
259     int32_t sandboxManagerErrorCode = SandboxManagerKit::PersistPolicy(pathPolicies, resultCodes);
260     errorCode = ErrorCodeConversion(sandboxManagerErrorCode, errorResults, resultCodes);
261     if (resultCodes.size() > MAX_ARRAY_SIZE) {
262         LOGE("The number of result codes exceeds the maximum");
263         return FileManagement::LibN::E_PARAMS;
264     }
265     if (errorCode == EPERM) {
266         ParseErrorResults(resultCodes, pathPolicies, errorResults);
267     }
268 #endif
269     return errorCode;
270 }
271 
RevokePermission(const vector<UriPolicyInfo> & uriPolicies,deque<struct PolicyErrorResult> & errorResults)272 int32_t FilePermission::RevokePermission(const vector<UriPolicyInfo> &uriPolicies,
273                                          deque<struct PolicyErrorResult> &errorResults)
274 {
275     int errorCode = 0;
276 #ifdef SANDBOX_MANAGER
277     vector<PolicyInfo> pathPolicies = GetPathPolicyInfoFromUriPolicyInfo(uriPolicies, errorResults);
278     vector<uint32_t> resultCodes;
279     int32_t sandboxManagerErrorCode = SandboxManagerKit::UnPersistPolicy(pathPolicies, resultCodes);
280     errorCode = ErrorCodeConversion(sandboxManagerErrorCode, errorResults, resultCodes);
281     if (resultCodes.size() > MAX_ARRAY_SIZE) {
282         LOGE("The number of result codes exceeds the maximum");
283         return FileManagement::LibN::E_PARAMS;
284     }
285     if (errorCode == EPERM) {
286         ParseErrorResults(resultCodes, pathPolicies, errorResults);
287     }
288 #endif
289     return errorCode;
290 }
291 
ActivatePermission(const vector<UriPolicyInfo> & uriPolicies,deque<struct PolicyErrorResult> & errorResults)292 int32_t FilePermission::ActivatePermission(const vector<UriPolicyInfo> &uriPolicies,
293                                            deque<struct PolicyErrorResult> &errorResults)
294 {
295     int errorCode = 0;
296 #ifdef SANDBOX_MANAGER
297     vector<PolicyInfo> pathPolicies = GetPathPolicyInfoFromUriPolicyInfo(uriPolicies, errorResults);
298     vector<uint32_t> resultCodes;
299     auto &uriPermissionClient = AAFwk::UriPermissionManagerClient::GetInstance();
300     int32_t sandboxManagerErrorCode = uriPermissionClient.Active(pathPolicies, resultCodes);
301     errorCode = ErrorCodeConversion(sandboxManagerErrorCode, errorResults, resultCodes);
302     if (resultCodes.size() > MAX_ARRAY_SIZE) {
303         LOGE("The number of result codes exceeds the maximum");
304         return FileManagement::LibN::E_PARAMS;
305     }
306     if (errorCode == EPERM) {
307         ParseErrorResults(resultCodes, pathPolicies, errorResults);
308     }
309 #endif
310     return errorCode;
311 }
312 
DeactivatePermission(const vector<UriPolicyInfo> & uriPolicies,deque<struct PolicyErrorResult> & errorResults)313 int32_t FilePermission::DeactivatePermission(const vector<UriPolicyInfo> &uriPolicies,
314                                              deque<struct PolicyErrorResult> &errorResults)
315 {
316     int errorCode = 0;
317 #ifdef SANDBOX_MANAGER
318     vector<PolicyInfo> pathPolicies = GetPathPolicyInfoFromUriPolicyInfo(uriPolicies, errorResults);
319     vector<uint32_t> resultCodes;
320     int32_t sandboxManagerErrorCode = SandboxManagerKit::StopAccessingPolicy(pathPolicies, resultCodes);
321     errorCode = ErrorCodeConversion(sandboxManagerErrorCode, errorResults, resultCodes);
322     if (resultCodes.size() > MAX_ARRAY_SIZE) {
323         LOGE("The number of result codes exceeds the maximum");
324         return FileManagement::LibN::E_PARAMS;
325     }
326     if (errorCode == EPERM) {
327         ParseErrorResults(resultCodes, pathPolicies, errorResults);
328     }
329 #endif
330     return errorCode;
331 }
332 
CheckPersistentPermission(const vector<UriPolicyInfo> & uriPolicies,vector<bool> & errorResults)333 int32_t FilePermission::CheckPersistentPermission(const vector<UriPolicyInfo> &uriPolicies, vector<bool> &errorResults)
334 {
335     int errorCode = 0;
336 #ifdef SANDBOX_MANAGER
337     auto tokenId = IPCSkeleton::GetCallingTokenID();
338     errorCode = CheckUriPersistentPermission(tokenId, uriPolicies, errorResults);
339 #endif
340     return errorCode;
341 }
342 
GetPathByPermission(const std::string & permission)343 string FilePermission::GetPathByPermission(const std::string &permission)
344 {
345 #ifdef SANDBOX_MANAGER
346     if (permissionPathMap.find(permission) != permissionPathMap.end()) {
347         return permissionPathMap.at(permission);
348     }
349 #endif
350     return "";
351 }
352 } // namespace AppFileService
353 } // namespace OHOS