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_file.h"
27 #include "dlp_zip.h"
28 #include "securec.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 DLP_RAW_HEAD_OFFSET = 8;
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
GetAuthPolicyWithType(const std::string & cfgFile,const std::string & type,std::vector<std::string> & authPolicy)67 bool DlpUtils::GetAuthPolicyWithType(const std::string &cfgFile, const std::string &type,
68 std::vector<std::string> &authPolicy)
69 {
70 std::string content;
71 (void)FileOperator().GetFileContentByPath(cfgFile, content);
72 if (content.empty()) {
73 return false;
74 }
75 auto jsonObj = nlohmann::json::parse(content, nullptr, false);
76 if (jsonObj.is_discarded() || (!jsonObj.is_object())) {
77 DLP_LOG_WARN(LABEL, "JsonObj is discarded");
78 return false;
79 }
80 auto result = jsonObj.find(type);
81 if (result != jsonObj.end() && result->is_array() && !result->empty() && (*result)[0].is_string()) {
82 authPolicy = result->get<std::vector<std::string>>();
83 }
84 if (authPolicy.size() != 0) {
85 return true;
86 }
87 return false;
88 }
89
ToLowerString(const std::string & str)90 std::string DlpUtils::ToLowerString(const std::string& str)
91 {
92 std::string lower;
93 for (char c : str) {
94 lower += std::tolower(c);
95 }
96 return lower;
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 isFromUriName = true;
154 return realFileName.substr(escapeLocate + 1);
155 }
156
GetFileNameWithDlpFd(const int32_t & fd,std::string & srcFileName)157 int32_t DlpUtils::GetFileNameWithDlpFd(const int32_t &fd, std::string &srcFileName)
158 {
159 char *fileName = new (std::nothrow) char[MAX_DLP_FILE_SIZE + 1];
160 if (fileName == nullptr) {
161 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
162 }
163 (void)memset_s(fileName, MAX_DLP_FILE_SIZE + 1, 0, MAX_DLP_FILE_SIZE + 1);
164
165 std::string path = DESCRIPTOR_MAP_PATH + std::to_string(fd);
166
167 int readLinkRes = readlink(path.c_str(), fileName, MAX_DLP_FILE_SIZE);
168 if (readLinkRes < 0) {
169 DLP_LOG_ERROR(LABEL, "fail to readlink uri, errno = %{public}d", errno);
170 delete[] fileName;
171 return DLP_PARSE_ERROR_FD_ERROR;
172 }
173 std::string tmp(fileName);
174 delete[] fileName;
175 std::size_t pos = tmp.find_last_of(".");
176 if (std::string::npos == pos) {
177 return DLP_PARSE_ERROR_FD_ERROR;
178 }
179 srcFileName = tmp.substr(0, pos);
180 return DLP_OK;
181 }
182
GetFileNameWithFd(const int32_t & fd,std::string & srcFileName)183 int32_t DlpUtils::GetFileNameWithFd(const int32_t &fd, std::string &srcFileName)
184 {
185 char *fileName = new (std::nothrow) char[MAX_DLP_FILE_SIZE + 1];
186 if (fileName == nullptr) {
187 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
188 }
189 (void)memset_s(fileName, MAX_DLP_FILE_SIZE + 1, 0, MAX_DLP_FILE_SIZE + 1);
190
191 std::string path = DESCRIPTOR_MAP_PATH + std::to_string(fd);
192
193 int readLinkRes = readlink(path.c_str(), fileName, MAX_DLP_FILE_SIZE);
194 if (readLinkRes < 0) {
195 DLP_LOG_ERROR(LABEL, "fail to readlink uri");
196 delete[] fileName;
197 return DLP_PARSE_ERROR_FD_ERROR;
198 }
199 fileName[readLinkRes] = '\0';
200
201 srcFileName = std::string(fileName);
202 delete[] fileName;
203 return DLP_OK;
204 }
205
GetFilePathWithFd(const int32_t & fd,std::string & srcFilePath)206 int32_t DlpUtils::GetFilePathWithFd(const int32_t &fd, std::string &srcFilePath)
207 {
208 char *fileName = new (std::nothrow) char[MAX_DLP_FILE_SIZE + 1];
209 if (fileName == nullptr) {
210 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
211 }
212 (void)memset_s(fileName, MAX_DLP_FILE_SIZE + 1, 0, MAX_DLP_FILE_SIZE + 1);
213
214 std::string path = DESCRIPTOR_MAP_PATH + std::to_string(fd);
215
216 int readLinkRes = readlink(path.c_str(), fileName, MAX_DLP_FILE_SIZE);
217 if (readLinkRes < 0) {
218 DLP_LOG_ERROR(LABEL, "fail to readlink uri, errno = %{public}d", errno);
219 delete[] fileName;
220 return DLP_PARSE_ERROR_FD_ERROR;
221 }
222 std::string tmp(fileName);
223 std::size_t pos = tmp.find_last_of(PATH_SEPARATOR);
224 srcFilePath = tmp.substr(0, pos + 1);
225 delete[] fileName;
226 return DLP_OK;
227 }
228
IsExistFile(const std::string & path)229 static bool IsExistFile(const std::string& path)
230 {
231 if (path.empty()) {
232 return false;
233 }
234
235 struct stat buf = {};
236 if (stat(path.c_str(), &buf) != 0) {
237 return false;
238 }
239
240 return S_ISREG(buf.st_mode);
241 }
242
GetFileContent(const std::string & path)243 static std::string GetFileContent(const std::string& path)
244 {
245 if (!IsExistFile(path)) {
246 DLP_LOG_DEBUG(LABEL, "cannot find file, path = %{public}s", path.c_str());
247 return DEFAULT_STRINGS;
248 }
249 std::stringstream buffer;
250 std::ifstream i(path);
251 if (!i.is_open()) {
252 DLP_LOG_DEBUG(LABEL, "cannot open file %{public}s, errno %{public}d.", path.c_str(), errno);
253 return DEFAULT_STRINGS;
254 }
255 buffer << i.rdbuf();
256 std::string content = buffer.str();
257 i.close();
258 return content;
259 }
260
RemoveCachePath(const std::string & path)261 static void RemoveCachePath(const std::string& path)
262 {
263 if (remove(DLP_GENERAL_INFO.c_str()) != 0) {
264 DLP_LOG_ERROR(LABEL, "remove dlp_general_info file fail, error %{public}s", strerror(errno));
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
GetRealTypeWithRawFile(const int32_t & fd)318 std::string DlpUtils::GetRealTypeWithRawFile(const int32_t& fd)
319 {
320 if (lseek(fd, DLP_RAW_HEAD_OFFSET, SEEK_SET) == static_cast<off_t>(-1)) {
321 DLP_LOG_ERROR(LABEL, "file head is error: %{public}s", strerror(errno));
322 return DEFAULT_STRINGS;
323 }
324 struct DlpHeader head;
325 if (read(fd, &head, sizeof(head)) != sizeof(head)) {
326 DLP_LOG_ERROR(LABEL, "can not read file head : %{public}s", strerror(errno));
327 return DEFAULT_STRINGS;
328 }
329 auto iter = NUM_TO_TYPE_MAP.find(head.fileType);
330 if (iter != NUM_TO_TYPE_MAP.end()) {
331 return iter->second;
332 }
333 DLP_LOG_DEBUG(LABEL, "find file type of raw is error");
334 return DEFAULT_STRINGS;
335 }
336
GetRealTypeWithFd(const int32_t & fd,bool & isFromUriName)337 std::string DlpUtils::GetRealTypeWithFd(const int32_t& fd, bool& isFromUriName)
338 {
339 std::string realType = DEFAULT_STRINGS;
340 do {
341 if (IsZipFile(fd)) {
342 std::string generateInfoStr = GetGenerateInfoStr(fd);
343 if (generateInfoStr == DEFAULT_STRINGS) {
344 break;
345 }
346 GenerateInfoParams params;
347 if (ParseDlpGeneralInfo(generateInfoStr, params) != DLP_OK) {
348 DLP_LOG_ERROR(LABEL, "ParseDlpGeneralInfo error: %{public}s", generateInfoStr.c_str());
349 break;
350 }
351 realType = params.realType;
352 } else {
353 return GetRealTypeWithRawFile(fd);
354 }
355 } while (0);
356
357 if (realType.size() >= MIN_REALY_TYPE_LENGTH && realType.size() <= MAX_REALY_TYPE_LENGTH) {
358 return realType;
359 }
360 DLP_LOG_DEBUG(LABEL, "not get real file type in dlp_general_info, will get to file name.");
361
362 std::string fileName;
363 if (DlpUtils::GetFileNameWithFd(fd, fileName) != DLP_OK) {
364 DLP_LOG_ERROR(LABEL, "Get file name with fd error");
365 return DEFAULT_STRINGS;
366 }
367 return DlpUtils::GetDlpFileRealSuffix(fileName, isFromUriName);
368 }
369
GetBundleInfoWithBundleName(const std::string & bundleName,int32_t flag,AppExecFwk::BundleInfo & bundleInfo,int32_t userId)370 bool DlpUtils::GetBundleInfoWithBundleName(const std::string &bundleName, int32_t flag,
371 AppExecFwk::BundleInfo &bundleInfo, int32_t userId)
372 {
373 auto bundleMgrProxy = DlpUtils::GetBundleMgrProxy();
374 if (bundleMgrProxy == nullptr) {
375 return false;
376 }
377 return bundleMgrProxy->GetBundleInfo(bundleName, flag, bundleInfo, userId);
378 }
379
GetUserIdByForegroundAccount(int32_t & userId)380 bool DlpUtils::GetUserIdByForegroundAccount(int32_t &userId)
381 {
382 int32_t ret = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
383 if (ret != ERR_OK) {
384 DLP_LOG_ERROR(LABEL, "GetForegroundOsAccountLocalId failed %{public}d", ret);
385 return false;
386 }
387 return true;
388 }
389
GetRealTypeForEnterpriseWithFd(const int32_t & fd,bool & isFromUriName)390 std::string DlpUtils::GetRealTypeForEnterpriseWithFd(const int32_t& fd, bool& isFromUriName)
391 {
392 std::string realType = DEFAULT_STRINGS;
393 do {
394 if (IsZipFile(fd)) {
395 std::string generateInfoStr = GetGenerateInfoStr(fd);
396 if (generateInfoStr == DEFAULT_STRINGS) {
397 break;
398 }
399 GenerateInfoParams params;
400 if (ParseDlpGeneralInfo(generateInfoStr, params) != DLP_OK) {
401 DLP_LOG_ERROR(LABEL, "ParseDlpGeneralInfo error: %{public}s", generateInfoStr.c_str());
402 break;
403 }
404 realType = params.realType;
405 } else {
406 realType = GetRealTypeWithRawFile(fd);
407 }
408 } while (0);
409
410 if (realType.size() >= MIN_REALY_TYPE_LENGTH && realType.size() <= MAX_REALY_TYPE_LENGTH) {
411 return realType;
412 }
413 DLP_LOG_DEBUG(LABEL, "not get real file type in dlp_general_info, will get to file name.");
414
415 std::string fileName;
416 if (DlpUtils::GetFileNameWithFd(fd, fileName) != DLP_OK) {
417 DLP_LOG_ERROR(LABEL, "Get file name with fd error");
418 return DEFAULT_STRINGS;
419 }
420 return DlpUtils::GetDlpFileRealSuffix(fileName, isFromUriName);
421 }
422 } // namespace DlpPermission
423 } // namespace Security
424 } // namespace OHOS
425