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