/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "dlp_utils.h" #include #include #include #include #include #include #include "dlp_permission.h" #include "dlp_permission_log.h" #include "dlp_permission_public_interface.h" #include "dlp_zip.h" #include "securec.h" #include "system_ability_definition.h" namespace OHOS { namespace Security { namespace DlpPermission { using Defer = std::shared_ptr; namespace { static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpUtils"}; static constexpr uint32_t MAX_DLP_FILE_SIZE = 1000; static const std::string DLP_FILE_SUFFIXS = ".dlp"; static const std::string DEFAULT_STRINGS = ""; static const std::string PATH_SEPARATOR = "/"; static const std::string DESCRIPTOR_MAP_PATH = "/proc/self/fd/"; const std::string DLP_GENERAL_INFO = "dlp_general_info"; const std::string CACHE_PATH = "/data/storage/el2/base/files/cache/"; const uint32_t DLP_CWD_MAX = 256; const uint32_t OS_ACCOUNT = 100; std::mutex g_fileOpLock; } sptr DlpUtils::GetBundleMgrProxy(void) { sptr systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (systemAbilityManager == nullptr) { DLP_LOG_ERROR(LABEL, "failed to get system ability manager"); return nullptr; } sptr remoteObj = systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); if (remoteObj == nullptr) { DLP_LOG_ERROR(LABEL, "Fail to connect bundle manager service."); return nullptr; } return iface_cast(remoteObj); } std::string DlpUtils::ToLowerString(const std::string& str) { std::string lower; for (char c : str) { lower += std::tolower(c); } return lower; } bool DlpUtils::GetAuthPolicyWithType(const std::string &cfgFile, const std::string &type, std::vector &authPolicy) { std::string content; (void)FileOperator().GetFileContentByPath(cfgFile, content); if (content.empty()) { return false; } auto jsonObj = nlohmann::json::parse(content, nullptr, false); if (jsonObj.is_discarded() || (!jsonObj.is_object())) { DLP_LOG_WARN(LABEL, "JsonObj is discarded"); return false; } auto result = jsonObj.find(type); if (result != jsonObj.end() && result->is_array() && !result->empty() && (*result)[0].is_string()) { authPolicy = result->get>(); } if (authPolicy.size() != 0) { return true; } return false; } std::string DlpUtils::GetFileTypeBySuffix(const std::string& suffix, const bool isFromUriName) { std::string lower = DlpUtils::ToLowerString(suffix); if (isFromUriName) { for (size_t len = MAX_REALY_TYPE_LENGTH; len >= MIN_REALY_TYPE_LENGTH; len--) { if (len > lower.size()) { continue; } std::string newStr = lower.substr(0, len); auto iter = FILE_TYPE_MAP.find(newStr); if (iter != FILE_TYPE_MAP.end()) { return iter->second; } } } else { auto iter = FILE_TYPE_MAP.find(lower); if (iter != FILE_TYPE_MAP.end()) { return iter->second; } } return DEFAULT_STRINGS; } bool DlpUtils::GetFileType(const std::string& realFileType) { std::string lower = DlpUtils::ToLowerString(realFileType); for (size_t len = MAX_REALY_TYPE_LENGTH; len >= MIN_REALY_TYPE_LENGTH; len--) { if (len > lower.size()) { continue; } std::string newStr = lower.substr(0, len); if (newStr == DLP_HIAE_TYPE) { DLP_LOG_DEBUG(LABEL, "the file supports the HIAE."); return true; } } return false; } std::string DlpUtils::GetDlpFileRealSuffix(const std::string& dlpFileName, bool& isFromUriName) { uint32_t dlpSuffixLen = DLP_FILE_SUFFIXS.size(); if (dlpFileName.size() <= dlpSuffixLen) { DLP_LOG_ERROR(LABEL, "invalid fileName!"); return DEFAULT_STRINGS; } std::string realFileName = dlpFileName.substr(0, dlpFileName.size() - dlpSuffixLen); char escape = '.'; std::size_t escapeLocate = realFileName.find_last_of(escape); if (escapeLocate >= realFileName.size()) { DLP_LOG_ERROR(LABEL, "Get file suffix fail, no '.' in file name"); return DEFAULT_STRINGS; } return realFileName.substr(escapeLocate + 1); } int32_t DlpUtils::GetFileNameWithDlpFd(const int32_t &fd, std::string &srcFileName) { char *fileName = new (std::nothrow) char[MAX_DLP_FILE_SIZE + 1]; if (fileName == nullptr) { return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL; } (void)memset_s(fileName, MAX_DLP_FILE_SIZE + 1, 0, MAX_DLP_FILE_SIZE + 1); std::string path = DESCRIPTOR_MAP_PATH + std::to_string(fd); int readLinkRes = readlink(path.c_str(), fileName, MAX_DLP_FILE_SIZE); if (readLinkRes < 0) { DLP_LOG_ERROR(LABEL, "fail to readlink uri, errno = %{public}d", errno); delete[] fileName; return DLP_PARSE_ERROR_FD_ERROR; } std::string tmp(fileName); delete[] fileName; std::size_t pos = tmp.find_last_of("."); if (std::string::npos == pos) { return DLP_PARSE_ERROR_FD_ERROR; } srcFileName = tmp.substr(0, pos); return DLP_OK; } int32_t DlpUtils::GetFileNameWithFd(const int32_t &fd, std::string &srcFileName) { char *fileName = new (std::nothrow) char[MAX_DLP_FILE_SIZE + 1]; if (fileName == nullptr) { return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL; } (void)memset_s(fileName, MAX_DLP_FILE_SIZE + 1, 0, MAX_DLP_FILE_SIZE + 1); std::string path = DESCRIPTOR_MAP_PATH + std::to_string(fd); int readLinkRes = readlink(path.c_str(), fileName, MAX_DLP_FILE_SIZE); if (readLinkRes < 0) { DLP_LOG_ERROR(LABEL, "fail to readlink uri"); delete[] fileName; return DLP_PARSE_ERROR_FD_ERROR; } fileName[readLinkRes] = '\0'; srcFileName = std::string(fileName); delete[] fileName; return DLP_OK; } int32_t DlpUtils::GetFilePathWithFd(const int32_t &fd, std::string &srcFilePath) { char *fileName = new (std::nothrow) char[MAX_DLP_FILE_SIZE + 1]; if (fileName == nullptr) { return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL; } (void)memset_s(fileName, MAX_DLP_FILE_SIZE + 1, 0, MAX_DLP_FILE_SIZE + 1); std::string path = DESCRIPTOR_MAP_PATH + std::to_string(fd); int readLinkRes = readlink(path.c_str(), fileName, MAX_DLP_FILE_SIZE); if (readLinkRes < 0) { DLP_LOG_ERROR(LABEL, "fail to readlink uri, errno = %{public}d", errno); delete[] fileName; return DLP_PARSE_ERROR_FD_ERROR; } std::string tmp(fileName); std::size_t pos = tmp.find_last_of(PATH_SEPARATOR); srcFilePath = tmp.substr(0, pos + 1); delete[] fileName; return DLP_OK; } static bool IsExistFile(const std::string& path) { if (path.empty()) { return false; } struct stat buf = {}; if (stat(path.c_str(), &buf) != 0) { return false; } return S_ISREG(buf.st_mode); } static std::string GetFileContent(const std::string& path) { if (!IsExistFile(path)) { DLP_LOG_DEBUG(LABEL, "cannot find file, path = %{public}s", path.c_str()); return DEFAULT_STRINGS; } std::stringstream buffer; std::ifstream i(path); if (!i.is_open()) { DLP_LOG_DEBUG(LABEL, "cannot open file %{public}s, errno %{public}d.", path.c_str(), errno); return DEFAULT_STRINGS; } buffer << i.rdbuf(); std::string content = buffer.str(); i.close(); return content; } static void RemoveCachePath(const std::string& path) { if (remove(DLP_GENERAL_INFO.c_str()) != 0) { DLP_LOG_ERROR(LABEL, "remove dlp_general_info file fail, error %{public}s", strerror(errno)); return; } if (rmdir(path.c_str()) != 0) { DLP_LOG_ERROR(LABEL, "remove cache path fail, error %{public}s", strerror(errno)); } } static std::string GetGenerateInfoStr(const int32_t& fd) { std::lock_guard lock(g_fileOpLock); char cwd[DLP_CWD_MAX] = {0}; if (getcwd(cwd, DLP_CWD_MAX) == nullptr) { DLP_LOG_ERROR(LABEL, "getcwd fail error %{public}s", strerror(errno)); return DEFAULT_STRINGS; } Defer p(nullptr, [&](...) { if (chdir(cwd) != 0) { DLP_LOG_ERROR(LABEL, "chdir failed, %{public}s", strerror(errno)); } }); std::filesystem::path cachePath = CACHE_PATH; if (!std::filesystem::exists(cachePath) || !std::filesystem::is_directory(cachePath)) { if (mkdir(cachePath.c_str(), S_IRWXU) != 0) { DLP_LOG_ERROR(LABEL, "mkdir cache path failed, errorno is %{public}s", strerror(errno)); return DEFAULT_STRINGS; } } int64_t timeStamp = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) .count(); std::string path = CACHE_PATH + std::to_string(timeStamp); if (mkdir(path.c_str(), S_IRWXU) != 0) { DLP_LOG_ERROR(LABEL, "mkdir timeStamp path failed, errorno is %{public}s", strerror(errno)); return DEFAULT_STRINGS; } if (chdir(path.c_str()) != 0) { DLP_LOG_ERROR(LABEL, "chdir cache err, errno is %{public}d", errno); RemoveCachePath(path); return DEFAULT_STRINGS; } if (!CheckUnzipFileInfo(fd) || UnzipSpecificFile(fd, DLP_GENERAL_INFO.c_str(), DLP_GENERAL_INFO.c_str()) != ZIP_OK) { RemoveCachePath(path); return DEFAULT_STRINGS; } std::string generateInfoStr = GetFileContent(DLP_GENERAL_INFO); RemoveCachePath(path); return generateInfoStr; } std::string DlpUtils::GetRealTypeWithFd(const int32_t& fd, bool& isFromUriName) { std::string realType = DEFAULT_STRINGS; do { std::string generateInfoStr = GetGenerateInfoStr(fd); if (generateInfoStr == DEFAULT_STRINGS) { break; } GenerateInfoParams params; if (ParseDlpGeneralInfo(generateInfoStr, params) != DLP_OK) { DLP_LOG_ERROR(LABEL, "ParseDlpGeneralInfo error: %{public}s", generateInfoStr.c_str()); break; } realType = params.realType; if (realType.size() >= MIN_REALY_TYPE_LENGTH && realType.size() <= MAX_REALY_TYPE_LENGTH) { return realType; } } while (0); DLP_LOG_DEBUG(LABEL, "not get real file type in dlp_general_info, will get to file name."); std::string fileName; if (DlpUtils::GetFileNameWithFd(fd, fileName) != DLP_OK) { DLP_LOG_ERROR(LABEL, "Get file name with fd error"); return DEFAULT_STRINGS; } return DlpUtils::GetDlpFileRealSuffix(fileName, isFromUriName); } bool DlpUtils::GetBundleInfoWithBundleName(const std::string &bundleName, int32_t flag, AppExecFwk::BundleInfo &bundleInfo, int32_t userId) { bundleInfo.appId = "test_appId_passed"; return true; } bool DlpUtils::GetUserIdByForegroundAccount(int32_t &userId) { userId = OS_ACCOUNT; return true; } std::string DlpUtils::GetRealTypeForEnterpriseWithFd(const int32_t& fd, bool& isFromUriName) { return DlpUtils::GetRealTypeWithFd(fd, isFromUriName); } } // namespace DlpPermission } // namespace Security } // namespace OHOS