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