1 /*
2 * Copyright (c) 2024 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 "dlp_utils.h"
17 #include <cctype>
18 #include <unistd.h>
19 #include <sys/stat.h>
20 #include <fstream>
21 #include <sstream>
22 #include <filesystem>
23 #include "dlp_permission.h"
24 #include "dlp_permission_log.h"
25 #include "dlp_permission_public_interface.h"
26 #include "dlp_zip.h"
27 #include "securec.h"
28 #include "system_ability_definition.h"
29
30 namespace OHOS {
31 namespace Security {
32 namespace DlpPermission {
33 using Defer = std::shared_ptr<void>;
34 namespace {
35 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpUtils"};
36 static constexpr uint32_t MAX_DLP_FILE_SIZE = 1000;
37 static const std::string DLP_FILE_SUFFIXS = ".dlp";
38 static const std::string DEFAULT_STRINGS = "";
39 static const std::string PATH_SEPARATOR = "/";
40 static const std::string DESCRIPTOR_MAP_PATH = "/proc/self/fd/";
41 const std::string DLP_GENERAL_INFO = "dlp_general_info";
42 const std::string CACHE_PATH = "/data/storage/el2/base/files/cache/";
43 const uint32_t DLP_CWD_MAX = 256;
44 const uint32_t OS_ACCOUNT = 100;
45 std::mutex g_fileOpLock;
46 }
47
48
GetBundleMgrProxy(void)49 sptr<AppExecFwk::IBundleMgr> DlpUtils::GetBundleMgrProxy(void)
50 {
51 sptr<ISystemAbilityManager> systemAbilityManager =
52 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
53 if (systemAbilityManager == nullptr) {
54 DLP_LOG_ERROR(LABEL, "failed to get system ability manager");
55 return nullptr;
56 }
57
58 sptr<IRemoteObject> remoteObj = systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
59 if (remoteObj == nullptr) {
60 DLP_LOG_ERROR(LABEL, "Fail to connect bundle manager service.");
61 return nullptr;
62 }
63
64 return iface_cast<AppExecFwk::IBundleMgr>(remoteObj);
65 }
66
ToLowerString(const std::string & str)67 std::string DlpUtils::ToLowerString(const std::string& str)
68 {
69 std::string lower;
70 for (char c : str) {
71 lower += std::tolower(c);
72 }
73 return lower;
74 }
75
GetAuthPolicyWithType(const std::string & cfgFile,const std::string & type,std::vector<std::string> & authPolicy)76 bool DlpUtils::GetAuthPolicyWithType(const std::string &cfgFile, const std::string &type,
77 std::vector<std::string> &authPolicy)
78 {
79 std::string content;
80 (void)FileOperator().GetFileContentByPath(cfgFile, content);
81 if (content.empty()) {
82 return false;
83 }
84 auto jsonObj = nlohmann::json::parse(content, nullptr, false);
85 if (jsonObj.is_discarded() || (!jsonObj.is_object())) {
86 DLP_LOG_WARN(LABEL, "JsonObj is discarded");
87 return false;
88 }
89 auto result = jsonObj.find(type);
90 if (result != jsonObj.end() && result->is_array() && !result->empty() && (*result)[0].is_string()) {
91 authPolicy = result->get<std::vector<std::string>>();
92 }
93 if (authPolicy.size() != 0) {
94 return true;
95 }
96 return false;
97 }
98
GetFileTypeBySuffix(const std::string & suffix,const bool isFromUriName)99 std::string DlpUtils::GetFileTypeBySuffix(const std::string& suffix, const bool isFromUriName)
100 {
101 std::string lower = DlpUtils::ToLowerString(suffix);
102 if (isFromUriName) {
103 for (size_t len = MAX_REALY_TYPE_LENGTH; len >= MIN_REALY_TYPE_LENGTH; len--) {
104 if (len > lower.size()) {
105 continue;
106 }
107 std::string newStr = lower.substr(0, len);
108 auto iter = FILE_TYPE_MAP.find(newStr);
109 if (iter != FILE_TYPE_MAP.end()) {
110 return iter->second;
111 }
112 }
113 } else {
114 auto iter = FILE_TYPE_MAP.find(lower);
115 if (iter != FILE_TYPE_MAP.end()) {
116 return iter->second;
117 }
118 }
119 return DEFAULT_STRINGS;
120 }
121
GetFileType(const std::string & realFileType)122 bool DlpUtils::GetFileType(const std::string& realFileType)
123 {
124 std::string lower = DlpUtils::ToLowerString(realFileType);
125 for (size_t len = MAX_REALY_TYPE_LENGTH; len >= MIN_REALY_TYPE_LENGTH; len--) {
126 if (len > lower.size()) {
127 continue;
128 }
129 std::string newStr = lower.substr(0, len);
130 if (newStr == DLP_HIAE_TYPE) {
131 DLP_LOG_DEBUG(LABEL, "the file supports the HIAE.");
132 return true;
133 }
134 }
135 return false;
136 }
137
GetDlpFileRealSuffix(const std::string & dlpFileName,bool & isFromUriName)138 std::string DlpUtils::GetDlpFileRealSuffix(const std::string& dlpFileName, bool& isFromUriName)
139 {
140 uint32_t dlpSuffixLen = DLP_FILE_SUFFIXS.size();
141 if (dlpFileName.size() <= dlpSuffixLen) {
142 DLP_LOG_ERROR(LABEL, "invalid fileName!");
143 return DEFAULT_STRINGS;
144 }
145 std::string realFileName = dlpFileName.substr(0, dlpFileName.size() - dlpSuffixLen);
146 char escape = '.';
147 std::size_t escapeLocate = realFileName.find_last_of(escape);
148 if (escapeLocate >= realFileName.size()) {
149 DLP_LOG_ERROR(LABEL, "Get file suffix fail, no '.' in file name");
150 return DEFAULT_STRINGS;
151 }
152
153 return realFileName.substr(escapeLocate + 1);
154 }
155
GetFileNameWithDlpFd(const int32_t & fd,std::string & srcFileName)156 int32_t DlpUtils::GetFileNameWithDlpFd(const int32_t &fd, std::string &srcFileName)
157 {
158 char *fileName = new (std::nothrow) char[MAX_DLP_FILE_SIZE + 1];
159 if (fileName == nullptr) {
160 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
161 }
162 (void)memset_s(fileName, MAX_DLP_FILE_SIZE + 1, 0, MAX_DLP_FILE_SIZE + 1);
163
164 std::string path = DESCRIPTOR_MAP_PATH + std::to_string(fd);
165
166 int readLinkRes = readlink(path.c_str(), fileName, MAX_DLP_FILE_SIZE);
167 if (readLinkRes < 0) {
168 DLP_LOG_ERROR(LABEL, "fail to readlink uri, errno = %{public}d", errno);
169 delete[] fileName;
170 return DLP_PARSE_ERROR_FD_ERROR;
171 }
172 std::string tmp(fileName);
173 delete[] fileName;
174 std::size_t pos = tmp.find_last_of(".");
175 if (std::string::npos == pos) {
176 return DLP_PARSE_ERROR_FD_ERROR;
177 }
178 srcFileName = tmp.substr(0, pos);
179 return DLP_OK;
180 }
181
GetFileNameWithFd(const int32_t & fd,std::string & srcFileName)182 int32_t DlpUtils::GetFileNameWithFd(const int32_t &fd, std::string &srcFileName)
183 {
184 char *fileName = new (std::nothrow) char[MAX_DLP_FILE_SIZE + 1];
185 if (fileName == nullptr) {
186 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
187 }
188 (void)memset_s(fileName, MAX_DLP_FILE_SIZE + 1, 0, MAX_DLP_FILE_SIZE + 1);
189
190 std::string path = DESCRIPTOR_MAP_PATH + std::to_string(fd);
191
192 int readLinkRes = readlink(path.c_str(), fileName, MAX_DLP_FILE_SIZE);
193 if (readLinkRes < 0) {
194 DLP_LOG_ERROR(LABEL, "fail to readlink uri");
195 delete[] fileName;
196 return DLP_PARSE_ERROR_FD_ERROR;
197 }
198 fileName[readLinkRes] = '\0';
199
200 srcFileName = std::string(fileName);
201 delete[] fileName;
202 return DLP_OK;
203 }
204
GetFilePathWithFd(const int32_t & fd,std::string & srcFilePath)205 int32_t DlpUtils::GetFilePathWithFd(const int32_t &fd, std::string &srcFilePath)
206 {
207 char *fileName = new (std::nothrow) char[MAX_DLP_FILE_SIZE + 1];
208 if (fileName == nullptr) {
209 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
210 }
211 (void)memset_s(fileName, MAX_DLP_FILE_SIZE + 1, 0, MAX_DLP_FILE_SIZE + 1);
212
213 std::string path = DESCRIPTOR_MAP_PATH + std::to_string(fd);
214
215 int readLinkRes = readlink(path.c_str(), fileName, MAX_DLP_FILE_SIZE);
216 if (readLinkRes < 0) {
217 DLP_LOG_ERROR(LABEL, "fail to readlink uri, errno = %{public}d", errno);
218 delete[] fileName;
219 return DLP_PARSE_ERROR_FD_ERROR;
220 }
221 std::string tmp(fileName);
222 std::size_t pos = tmp.find_last_of(PATH_SEPARATOR);
223 srcFilePath = tmp.substr(0, pos + 1);
224 delete[] fileName;
225 return DLP_OK;
226 }
227
IsExistFile(const std::string & path)228 static bool IsExistFile(const std::string& path)
229 {
230 if (path.empty()) {
231 return false;
232 }
233
234 struct stat buf = {};
235 if (stat(path.c_str(), &buf) != 0) {
236 return false;
237 }
238
239 return S_ISREG(buf.st_mode);
240 }
241
GetFileContent(const std::string & path)242 static std::string GetFileContent(const std::string& path)
243 {
244 if (!IsExistFile(path)) {
245 DLP_LOG_DEBUG(LABEL, "cannot find file, path = %{public}s", path.c_str());
246 return DEFAULT_STRINGS;
247 }
248 std::stringstream buffer;
249 std::ifstream i(path);
250 if (!i.is_open()) {
251 DLP_LOG_DEBUG(LABEL, "cannot open file %{public}s, errno %{public}d.", path.c_str(), errno);
252 return DEFAULT_STRINGS;
253 }
254 buffer << i.rdbuf();
255 std::string content = buffer.str();
256 i.close();
257 return content;
258 }
259
RemoveCachePath(const std::string & path)260 static void RemoveCachePath(const std::string& path)
261 {
262 if (remove(DLP_GENERAL_INFO.c_str()) != 0) {
263 DLP_LOG_ERROR(LABEL, "remove dlp_general_info file fail, error %{public}s", strerror(errno));
264 return;
265 }
266 if (rmdir(path.c_str()) != 0) {
267 DLP_LOG_ERROR(LABEL, "remove cache path fail, error %{public}s", strerror(errno));
268 }
269 }
270
GetGenerateInfoStr(const int32_t & fd)271 static std::string GetGenerateInfoStr(const int32_t& fd)
272 {
273 std::lock_guard<std::mutex> lock(g_fileOpLock);
274 char cwd[DLP_CWD_MAX] = {0};
275 if (getcwd(cwd, DLP_CWD_MAX) == nullptr) {
276 DLP_LOG_ERROR(LABEL, "getcwd fail error %{public}s", strerror(errno));
277 return DEFAULT_STRINGS;
278 }
279 Defer p(nullptr, [&](...) {
280 if (chdir(cwd) != 0) {
281 DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno));
282 }
283 });
284
285 std::filesystem::path cachePath = CACHE_PATH;
286 if (!std::filesystem::exists(cachePath) || !std::filesystem::is_directory(cachePath)) {
287 if (mkdir(cachePath.c_str(), S_IRWXU) != 0) {
288 DLP_LOG_ERROR(LABEL, "mkdir cache path failed, errorno is %{public}s", strerror(errno));
289 return DEFAULT_STRINGS;
290 }
291 }
292
293 int64_t timeStamp =
294 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
295 .count();
296 std::string path = CACHE_PATH + std::to_string(timeStamp);
297 if (mkdir(path.c_str(), S_IRWXU) != 0) {
298 DLP_LOG_ERROR(LABEL, "mkdir timeStamp path failed, errorno is %{public}s", strerror(errno));
299 return DEFAULT_STRINGS;
300 }
301
302 if (chdir(path.c_str()) != 0) {
303 DLP_LOG_ERROR(LABEL, "chdir cache err, errno is %{public}d", errno);
304 RemoveCachePath(path);
305 return DEFAULT_STRINGS;
306 }
307 if (!CheckUnzipFileInfo(fd) ||
308 UnzipSpecificFile(fd, DLP_GENERAL_INFO.c_str(), DLP_GENERAL_INFO.c_str()) != ZIP_OK) {
309 RemoveCachePath(path);
310 return DEFAULT_STRINGS;
311 }
312
313 std::string generateInfoStr = GetFileContent(DLP_GENERAL_INFO);
314 RemoveCachePath(path);
315 return generateInfoStr;
316 }
317
GetRealTypeWithFd(const int32_t & fd,bool & isFromUriName)318 std::string DlpUtils::GetRealTypeWithFd(const int32_t& fd, bool& isFromUriName)
319 {
320 std::string realType = DEFAULT_STRINGS;
321 do {
322 std::string generateInfoStr = GetGenerateInfoStr(fd);
323 if (generateInfoStr == DEFAULT_STRINGS) {
324 break;
325 }
326 GenerateInfoParams params;
327 if (ParseDlpGeneralInfo(generateInfoStr, params) != DLP_OK) {
328 DLP_LOG_ERROR(LABEL, "ParseDlpGeneralInfo error: %{public}s", generateInfoStr.c_str());
329 break;
330 }
331 realType = params.realType;
332 if (realType.size() >= MIN_REALY_TYPE_LENGTH && realType.size() <= MAX_REALY_TYPE_LENGTH) {
333 return realType;
334 }
335 } while (0);
336 DLP_LOG_DEBUG(LABEL, "not get real file type in dlp_general_info, will get to file name.");
337
338 std::string fileName;
339 if (DlpUtils::GetFileNameWithFd(fd, fileName) != DLP_OK) {
340 DLP_LOG_ERROR(LABEL, "Get file name with fd error");
341 return DEFAULT_STRINGS;
342 }
343 return DlpUtils::GetDlpFileRealSuffix(fileName, isFromUriName);
344 }
345
GetBundleInfoWithBundleName(const std::string & bundleName,int32_t flag,AppExecFwk::BundleInfo & bundleInfo,int32_t userId)346 bool DlpUtils::GetBundleInfoWithBundleName(const std::string &bundleName, int32_t flag,
347 AppExecFwk::BundleInfo &bundleInfo, int32_t userId)
348 {
349 bundleInfo.appId = "test_appId_passed";
350 return true;
351 }
352
GetUserIdByForegroundAccount(int32_t & userId)353 bool DlpUtils::GetUserIdByForegroundAccount(int32_t &userId)
354 {
355 userId = OS_ACCOUNT;
356 return true;
357 }
358
GetRealTypeForEnterpriseWithFd(const int32_t & fd,bool & isFromUriName)359 std::string DlpUtils::GetRealTypeForEnterpriseWithFd(const int32_t& fd, bool& isFromUriName)
360 {
361 return DlpUtils::GetRealTypeWithFd(fd, isFromUriName);
362 }
363 } // namespace DlpPermission
364 } // namespace Security
365 } // namespace OHOS
366