• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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