1 /*
2  * Copyright (c) 2021-2022 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 "environment_n_exporter.h"
17 #include "accesstoken_kit.h"
18 #include "account_error_no.h"
19 #include "filemgmt_libhilog.h"
20 #include "ipc_skeleton.h"
21 #include "os_account_manager.h"
22 #include "parameter.h"
23 #include "tokenid_kit.h"
24 #include <string>
25 #include <unistd.h>
26 namespace OHOS {
27 namespace FileManagement {
28 namespace ModuleEnvironment {
29 using namespace OHOS::FileManagement::LibN;
30 namespace {
31 const std::string STORAGE_DATA_PATH = "/data";
32 const std::string PC_STORAGE_PATH = "/storage/Users/";
33 const std::string EXTERNAL_STORAGE_PATH = "/storage/External";
34 const std::string USER_APP_DATA_PATH = "/appdata";
35 const std::string READ_WRITE_DOWNLOAD_PERMISSION = "ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY";
36 const std::string READ_WRITE_DESKTOP_PERMISSION = "ohos.permission.READ_WRITE_DESKTOP_DIRECTORY";
37 const std::string READ_WRITE_DOCUMENTS_PERMISSION = "ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY";
38 const std::string FILE_ACCESS_MANAGER_PERMISSION = "ohos.permission.FILE_ACCESS_MANAGER";
39 const std::string DOWNLOAD_PATH = "/Download";
40 const std::string DESKTOP_PATH = "/Desktop";
41 const std::string DOCUMENTS_PATH = "/Documents";
42 const std::string DEFAULT_USERNAME = "currentUser";
43 const char *g_fileManagerFullMountEnableParameter = "const.filemanager.full_mount.enable";
IsSystemApp()44 static bool IsSystemApp()
45 {
46     uint64_t fullTokenId = OHOS::IPCSkeleton::GetCallingFullTokenID();
47     return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
48 }
49 
CheckCallingPermission(const std::string & permission)50 static bool CheckCallingPermission(const std::string &permission)
51 {
52     Security::AccessToken::AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
53     int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
54     if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
55         HILOGE("ModuleUserDirectory::CheckCallingPermission have no fileAccess permission");
56         return false;
57     }
58     return true;
59 }
60 
GetUserName()61 static std::string GetUserName()
62 {
63     std::string userName;
64     ErrCode errCode = OHOS::AccountSA::OsAccountManager::GetOsAccountShortName(userName);
65     if (errCode != ERR_OK || userName.empty()) {
66         HILOGE("Get userName Failed");
67     }
68     userName = DEFAULT_USERNAME;
69     return userName;
70 }
71 
GetPublicPath(const std::string & directoryName)72 static std::string GetPublicPath(const std::string &directoryName)
73 {
74     return PC_STORAGE_PATH + GetUserName() + directoryName;
75 }
76 
CheckFileManagerFullMountEnable()77 static bool CheckFileManagerFullMountEnable()
78 {
79     char value[] = "false";
80     int retSystem = GetParameter(g_fileManagerFullMountEnableParameter, "false", value, sizeof(value));
81     if (retSystem > 0 && !std::strcmp(value, "true")) {
82         return true;
83     }
84     HILOGE("Not supporting all mounts");
85     return false;
86 }
87 
CheckInvalidAccess(const std::string & permission,napi_env env)88 static bool CheckInvalidAccess(const std::string &permission, napi_env env)
89 {
90     if (!CheckFileManagerFullMountEnable()) {
91         HILOGE("Capability not supported");
92         NError(E_DEVICENOTSUPPORT).ThrowErr(env);
93         return true;
94     }
95     if (permission == FILE_ACCESS_MANAGER_PERMISSION) {
96         if (!IsSystemApp()) {
97             NError(E_PERMISSION_SYS).ThrowErr(env);
98             return true;
99         }
100     }
101     if (!CheckCallingPermission(permission)) {
102         HILOGE("No Permission");
103         NError(E_PERMISSION).ThrowErr(env);
104         return true;
105     }
106     return false;
107 }
108 }
109 
GetStorageDataDir(napi_env env,napi_callback_info info)110 napi_value GetStorageDataDir(napi_env env, napi_callback_info info)
111 {
112     if (!IsSystemApp()) {
113         NError(E_PERMISSION_SYS).ThrowErr(env);
114         return nullptr;
115     }
116     NFuncArg funcArg(env, info);
117     if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
118         HILOGE("Number of arguments unmatched");
119         NError(EINVAL).ThrowErr(env);
120         return nullptr;
121     }
122 
123     auto cbExec = []() -> NError {
124         return NError(ERRNO_NOERR);
125     };
126     auto cbComplete = [](napi_env env, NError err) -> NVal {
127         if (err) {
128             return { env, err.GetNapiErr(env) };
129         }
130         return NVal::CreateUTF8String(env, STORAGE_DATA_PATH);
131     };
132 
133     static const std::string PROCEDURE_NAME = "GetStorageDataDir";
134     NVal thisVar(env, funcArg.GetThisVar());
135     if (funcArg.GetArgc() == NARG_CNT::ZERO) {
136         return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_NAME, cbExec, cbComplete).val_;
137     }
138 
139     NVal cb(env, funcArg[NARG_POS::FIRST]);
140     return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_NAME, cbExec, cbComplete).val_;
141 }
142 
GetUserId()143 int GetUserId()
144 {
145     return 0;
146 }
147 
GetUserDataDir(napi_env env,napi_callback_info info)148 napi_value GetUserDataDir(napi_env env, napi_callback_info info)
149 {
150     if (!IsSystemApp()) {
151         NError(E_PERMISSION_SYS).ThrowErr(env);
152         return nullptr;
153     }
154     NFuncArg funcArg(env, info);
155     if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
156         HILOGE("Number of arguments unmatched");
157         NError(EINVAL).ThrowErr(env);
158         return nullptr;
159     }
160 
161     auto userDataPath = std::make_shared<std::string>();
162     auto cbExec = [userDataPath]() -> NError {
163         (*userDataPath).append("/storage/media/").append(std::to_string(GetUserId())).append("/local");
164         return NError(ERRNO_NOERR);
165     };
166     auto cbComplete = [userDataPath](napi_env env, NError err) -> NVal {
167         if (err) {
168             return { env, err.GetNapiErr(env) };
169         }
170         return NVal::CreateUTF8String(env, *userDataPath);
171     };
172 
173     static const std::string PROCEDURE_NAME = "GetUserDataDir";
174     NVal thisVar(env, funcArg.GetThisVar());
175     if (funcArg.GetArgc() == NARG_CNT::ZERO) {
176         return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_NAME, cbExec, cbComplete).val_;
177     }
178 
179     NVal cb(env, funcArg[NARG_POS::FIRST]);
180     return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_NAME, cbExec, cbComplete).val_;
181 }
182 
GetUserDownloadDir(napi_env env,napi_callback_info info)183 napi_value GetUserDownloadDir(napi_env env, napi_callback_info info)
184 {
185     if (!CheckFileManagerFullMountEnable()) {
186         HILOGE("Capability not supported");
187         NError(E_DEVICENOTSUPPORT).ThrowErr(env);
188         return nullptr;
189     }
190     NFuncArg funcArg(env, info);
191     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
192         HILOGE("Number of arguments unmatched");
193         NError(E_PARAMS).ThrowErr(env);
194         return nullptr;
195     }
196     static std::string downloadPath = GetPublicPath(DOWNLOAD_PATH);
197     if (downloadPath.empty()) {
198         HILOGE("Unknown error");
199         NError(E_UNKNOWN_ERROR).ThrowErr(env);
200         return nullptr;
201     }
202     return NVal::CreateUTF8String(env, downloadPath).val_;
203 }
204 
GetUserDesktopDir(napi_env env,napi_callback_info info)205 napi_value GetUserDesktopDir(napi_env env, napi_callback_info info)
206 {
207     if (!CheckFileManagerFullMountEnable()) {
208         HILOGE("Capability not supported");
209         NError(E_DEVICENOTSUPPORT).ThrowErr(env);
210         return nullptr;
211     }
212     NFuncArg funcArg(env, info);
213     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
214         HILOGE("Number of arguments unmatched");
215         NError(E_PARAMS).ThrowErr(env);
216         return nullptr;
217     }
218     static std::string desktopPath = GetPublicPath(DESKTOP_PATH);
219     if (desktopPath.empty()) {
220         HILOGE("Unknown error");
221         NError(E_UNKNOWN_ERROR).ThrowErr(env);
222         return nullptr;
223     }
224     return NVal::CreateUTF8String(env, desktopPath).val_;
225 }
226 
GetUserDocumentDir(napi_env env,napi_callback_info info)227 napi_value GetUserDocumentDir(napi_env env, napi_callback_info info)
228 {
229     if (!CheckFileManagerFullMountEnable()) {
230         HILOGE("Capability not supported");
231         NError(E_DEVICENOTSUPPORT).ThrowErr(env);
232         return nullptr;
233     }
234     NFuncArg funcArg(env, info);
235     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
236         HILOGE("Number of arguments unmatched");
237         NError(E_PARAMS).ThrowErr(env);
238         return nullptr;
239     }
240     static std::string documentsPath = GetPublicPath(DOCUMENTS_PATH);
241     if (documentsPath.empty()) {
242         HILOGE("Unknown error");
243         NError(E_UNKNOWN_ERROR).ThrowErr(env);
244         return nullptr;
245     }
246     return NVal::CreateUTF8String(env, documentsPath).val_;
247 }
248 
GetExternalStorageDir(napi_env env,napi_callback_info info)249 napi_value GetExternalStorageDir(napi_env env, napi_callback_info info)
250 {
251     if (CheckInvalidAccess(FILE_ACCESS_MANAGER_PERMISSION, env)) {
252         return nullptr;
253     }
254     NFuncArg funcArg(env, info);
255     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
256         HILOGE("Number of arguments unmatched");
257         NError(E_PARAMS).ThrowErr(env);
258         return nullptr;
259     }
260     return NVal::CreateUTF8String(env, EXTERNAL_STORAGE_PATH).val_;
261 }
262 
GetUserHomeDir(napi_env env,napi_callback_info info)263 napi_value GetUserHomeDir(napi_env env, napi_callback_info info)
264 {
265     if (CheckInvalidAccess(FILE_ACCESS_MANAGER_PERMISSION, env)) {
266         return nullptr;
267     }
268     NFuncArg funcArg(env, info);
269     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
270         HILOGE("Number of arguments unmatched");
271         NError(E_PARAMS).ThrowErr(env);
272         return nullptr;
273     }
274     static std::string userName = GetUserName();
275     if (userName.empty()) {
276         HILOGE("Unknown error");
277         NError(E_UNKNOWN_ERROR).ThrowErr(env);
278         return nullptr;
279     }
280     return NVal::CreateUTF8String(env, PC_STORAGE_PATH + userName).val_;
281 }
282 } // namespace ModuleEnvironment
283 } // namespace FileManagement
284 } // namespace OHOS