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