• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "dlp_file_operator.h"
16 
17 #include <cstdio>
18 #include <dirent.h>
19 #include <memory>
20 #include <openssl/rand.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 
25 #include "nlohmann/json.hpp"
26 
27 #include "cert_parcel.h"
28 #include "dlp_crypt.h"
29 #include "dlp_file_manager.h"
30 #include "dlp_permission.h"
31 #include "dlp_permission_kit.h"
32 #include "dlp_permission_log.h"
33 #include "dlp_utils.h"
34 #include "permission_policy.h"
35 
36 namespace OHOS {
37 namespace Security {
38 namespace DlpPermission {
39 
40 namespace {
41 static const std::string ACCOUNT_INDEX = "account";
42 static const std::string ACCOUNT_TYPE = "accountType";
43 static const std::string EDIT_INDEX = "edit";
44 static const std::string ENC_ACCOUNT_TYPE = "accountType";
45 static const std::string EVERYONE_INDEX = "everyone";
46 static const std::string FC_INDEX = "fullCtrl";
47 static const std::string NEED_ONLINE = "needOnline";
48 static const std::string OWNER_ACCOUNT_NAME = "ownerAccountName";
49 static const std::string OWNER_ACCOUNT = "ownerAccount";
50 static const std::string OWNER_ACCOUNT_ID = "ownerAccountId";
51 static const std::string OWNER_ACCOUNT_TYPE = "ownerAccountType";
52 static const std::string AUTHUSER_LIST = "authUserList";
53 static const std::string CONTACT_ACCOUNT = "contactAccount";
54 static const std::string OFFLINE_ACCESS = "offlineAccess";
55 static const std::string EVERYONE_ACCESS_LIST = "everyoneAccessList";
56 static const std::string PERM_EXPIRY_TIME = "expireTime";
57 static const std::string ACTION_UPON_EXPIRY = "actionUponExpiry";
58 static const std::string POLICY_INDEX = "policy";
59 static const std::string READ_INDEX = "read";
60 static const std::string RIGHT_INDEX = "right";
61 static const std::string CUSTOM_PROPERTY = "customProperty";
62 const std::string PATH_CACHE = "cache";
63 
64 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
65     LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "EnterpriseDlpPermissionKit"
66 };
67 using Defer = std::shared_ptr<void>;
68 using json = nlohmann::ordered_json;
69 std::mutex g_dirCleanLock;
70 std::mutex g_missionMutex;
71 std::shared_ptr<std::thread> g_missionThread = nullptr;
72 const std::string APPID = "com.ohos.dlpmanager_BAurHtxID8irkrB1VYVHLCWnMGKeOwaGNcJymGCMdhIpP+"
73     "PyVFlFnmikA0NIVqmvB+TnZpjup0qT4D0nEdTM/soy4Ab/wzCdSyoJYPNjl6IR/lW/IktytZ7Mn6auB9dJ4g==";
74 }
75 
EnterpriseSpaceDlpPermissionKit()76 EnterpriseSpaceDlpPermissionKit::EnterpriseSpaceDlpPermissionKit() {}
77 
GetInstance()78 EnterpriseSpaceDlpPermissionKit* EnterpriseSpaceDlpPermissionKit::GetInstance()
79 {
80     static EnterpriseSpaceDlpPermissionKit instance;
81     return &instance;
82 }
83 
~EnterpriseSpaceDlpPermissionKit()84 EnterpriseSpaceDlpPermissionKit::~EnterpriseSpaceDlpPermissionKit() {}
85 
GenerateRandomWorkDir(std::string & workDir)86 static int32_t GenerateRandomWorkDir(std::string &workDir)
87 {
88     DlpBlob dir;
89     int32_t res = DlpOpensslGenerateRandom(sizeof(uint64_t) * BIT_NUM_OF_UINT8, &dir);
90     if (res != DLP_OK) {
91         DLP_LOG_ERROR(LABEL, "Generate dir fail, errno=%{public}d", res);
92         return res;
93     }
94 
95     workDir = std::to_string(*reinterpret_cast<uint64_t *>(dir.data));
96     delete[] dir.data;
97     return DLP_OK;
98 }
99 
PrepareWorkDir(const std::string & path)100 static int32_t PrepareWorkDir(const std::string& path)
101 {
102     if (mkdir(path.c_str(), S_IRWXU) < 0) {
103         DLP_LOG_ERROR(LABEL, "mkdir work dir failed errno %{public}d", errno);
104         return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
105     }
106     return DLP_OK;
107 }
108 
SerializePermInfo(DLPFileAccess perm,json & rightInfoJson)109 static void SerializePermInfo(DLPFileAccess perm, json& rightInfoJson)
110 {
111     bool read = false;
112     bool edit = false;
113     bool fullCtrl = false;
114 
115     switch (perm) {
116         case DLPFileAccess::READ_ONLY: {
117             read = true;
118             break;
119         }
120         case DLPFileAccess::CONTENT_EDIT: {
121             edit = true;
122             break;
123         }
124         case DLPFileAccess::FULL_CONTROL: {
125             read = true;
126             edit = true;
127             fullCtrl = true;
128             break;
129         }
130         default:
131             break;
132     }
133     rightInfoJson[READ_INDEX] = read;
134     rightInfoJson[EDIT_INDEX] = edit;
135     rightInfoJson[FC_INDEX] = fullCtrl;
136 }
137 
SerializeAuthUserList(const std::vector<AuthUserInfo> & authUsers,json & authUsersJson)138 static void SerializeAuthUserList(const std::vector<AuthUserInfo>& authUsers, json& authUsersJson)
139 {
140     for (const AuthUserInfo& info : authUsers) {
141         json rightInfoJson;
142         SerializePermInfo(info.authPerm, rightInfoJson);
143         authUsersJson[info.authAccount.c_str()][RIGHT_INDEX] = rightInfoJson;
144     }
145 }
146 
SerializeEveryoneInfo(const PermissionPolicy & policy,json & permInfoJson)147 static void SerializeEveryoneInfo(const PermissionPolicy& policy, json& permInfoJson)
148 {
149     if (policy.supportEveryone_) {
150         json rightInfoJson;
151         SerializePermInfo(policy.everyonePerm_, rightInfoJson);
152         permInfoJson[EVERYONE_INDEX][RIGHT_INDEX] = rightInfoJson;
153         return;
154     }
155 }
156 
SerializePermissionPolicy(const PermissionPolicy & policy,std::string & policyString)157 static int32_t SerializePermissionPolicy(const PermissionPolicy& policy, std::string& policyString)
158 {
159     json policyJson;
160     json authUsersJson;
161     SerializeAuthUserList(policy.authUsers_, authUsersJson);
162     policyJson[OWNER_ACCOUNT_NAME] = policy.ownerAccount_;
163     policyJson[OWNER_ACCOUNT_ID] = policy.ownerAccountId_;
164     policyJson[ACCOUNT_INDEX] = authUsersJson;
165     policyJson[PERM_EXPIRY_TIME] = policy.expireTime_;
166     policyJson[NEED_ONLINE] = policy.needOnline_;
167     policyJson[CUSTOM_PROPERTY] = policy.customProperty_;
168     SerializeEveryoneInfo(policy, policyJson);
169     policyString = policyJson.dump();
170     return DLP_OK;
171 }
172 
SetCustomProperty(DlpProperty & property,const CustomProperty & customProperty)173 static void SetCustomProperty(DlpProperty& property, const CustomProperty& customProperty)
174 {
175     property.customProperty.enterprise = customProperty.enterprise;
176 }
177 
EnterpriseSpaceParseDlpFileProperty(std::shared_ptr<DlpFile> & filePtr,PermissionPolicy & policy,bool needCheckCustomProperty)178 int32_t EnterpriseSpaceDlpPermissionKit::EnterpriseSpaceParseDlpFileProperty(std::shared_ptr<DlpFile>& filePtr,
179     PermissionPolicy& policy, bool needCheckCustomProperty)
180 {
181     int32_t result = filePtr->ProcessDlpFile();
182     if (result != DLP_OK) {
183         return result;
184     }
185     struct DlpBlob cert;
186     filePtr->GetEncryptCert(cert);
187     sptr<CertParcel> certParcel = new (std::nothrow) CertParcel();
188     if (certParcel == nullptr) {
189         DLP_LOG_ERROR(LABEL, "Alloc certParcel parcel fail");
190         return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
191     }
192     certParcel->cert = std::vector<uint8_t>(cert.data, cert.data + cert.size);
193     struct DlpBlob offlineCert = { 0 };
194     uint32_t flag = filePtr->GetOfflineAccess();
195     if (flag != 0) {
196         filePtr->GetOfflineCert(offlineCert);
197         certParcel->offlineCert = std::vector<uint8_t>(offlineCert.data, offlineCert.data + offlineCert.size);
198     }
199     filePtr->GetContactAccount(certParcel->contactAccount);
200     certParcel->isNeedAdapter = filePtr->NeedAdapter();
201     certParcel->needCheckCustomProperty = needCheckCustomProperty;
202     result = DlpPermissionKit::ParseDlpCertificate(certParcel, policy, APPID, filePtr->GetOfflineAccess());
203     if (result != DLP_OK) {
204         DLP_LOG_ERROR(LABEL, "Parse cert fail, errno=%{public}d", result);
205         return result;
206     }
207     result = filePtr->SetPolicy(policy);
208     if (result != DLP_OK) {
209         DLP_LOG_ERROR(LABEL, "Set policy fail, errno=%{public}d", result);
210         return result;
211     }
212     return DLP_OK;
213 }
214 
EnterpriseSpacePrepareWorkDir(int32_t dlpFileFd,std::shared_ptr<DlpFile> & filePtr,std::string & workDir)215 int32_t EnterpriseSpaceDlpPermissionKit::EnterpriseSpacePrepareWorkDir(int32_t dlpFileFd,
216     std::shared_ptr<DlpFile>& filePtr, std::string& workDir)
217 {
218     int32_t result = DlpUtils::GetFilePathWithFd(dlpFileFd, workDir);
219     if (result != DLP_OK) {
220         DLP_LOG_ERROR(LABEL, "Get file path with fd fail, errno = %{public}d.", result);
221         return result;
222     }
223 
224     workDir += PATH_CACHE;
225 
226     std::string randomWorkDir;
227     result = GenerateRandomWorkDir(randomWorkDir);
228     if (result != DLP_OK) {
229         DLP_LOG_ERROR(LABEL, "Generate dir fail, errno=%{public}d", result);
230         return result;
231     }
232 
233     std::string realWorkDir = workDir + '_' + randomWorkDir;
234     result = PrepareWorkDir(realWorkDir);
235     if (result != DLP_OK) {
236         DLP_LOG_ERROR(LABEL, "Prepare dir fail, errno=%{public}d", result);
237         return result;
238     }
239 
240     int64_t timeStamp =
241         std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
242             .count();
243     bool isFromUriName = false;
244     std::string realSuffix = DlpUtils::GetRealTypeForEnterpriseWithFd(dlpFileFd, isFromUriName);
245     if (realSuffix == "") {
246         DLP_LOG_ERROR(LABEL, "Get real suffix error.");
247         return DLP_PARSE_ERROR_VALUE_INVALID;
248     }
249     std::string lower = DlpUtils::ToLowerString(realSuffix);
250     std::string realType = "";
251     for (size_t len = MAX_REALY_TYPE_LENGTH; len >= MIN_REALY_TYPE_LENGTH; len--) {
252         if (len > lower.size()) {
253             continue;
254         }
255         std::string newStr = lower.substr(0, len);
256         auto iter = FILE_TYPE_MAP.find(newStr);
257         if (iter != FILE_TYPE_MAP.end()) {
258             realType = newStr;
259             break;
260         }
261     }
262     filePtr = std::make_shared<DlpZipFile>(dlpFileFd, realWorkDir, timeStamp, realType);
263     return DLP_OK;
264 }
265 
EnterpriseSpaceParseDlpFileFormat(std::shared_ptr<DlpFile> & filePtr,bool needCheckCustomProperty)266 int32_t EnterpriseSpaceDlpPermissionKit::EnterpriseSpaceParseDlpFileFormat(std::shared_ptr<DlpFile>& filePtr,
267     bool needCheckCustomProperty)
268 {
269     PermissionPolicy policy;
270     int result = EnterpriseSpaceParseDlpFileProperty(filePtr, policy, needCheckCustomProperty);
271     if (result != DLP_OK) {
272         DLP_LOG_ERROR(LABEL, "Enterprise space parse dlp property fail, errno=%{public}d", result);
273         return result;
274     }
275     struct DlpBlob key = {.size = policy.GetAeskeyLen(), .data = policy.GetAeskey()};
276     struct DlpCipherParam param = {.iv = {.size = policy.GetIvLen(), .data = policy.GetIv()}};
277     struct DlpUsageSpec usage = {.mode = DLP_MODE_CTR, .algParam = &param};
278     struct DlpBlob hmacKey = {.size = policy.GetHmacKeyLen(), .data = policy.GetHmacKey()};
279     result = filePtr->SetCipher(key, usage, hmacKey);
280     if (result != DLP_OK) {
281         return result;
282     }
283     result = filePtr->HmacCheck();
284     if (result != DLP_OK) {
285         return result;
286     }
287     return result;
288 }
289 
EncryptDlpFile(DlpProperty property,CustomProperty customProperty,int32_t plainFileFd,int32_t dlpFileFd)290 int32_t EnterpriseSpaceDlpPermissionKit::EncryptDlpFile(DlpProperty property,
291     CustomProperty customProperty, int32_t plainFileFd, int32_t dlpFileFd)
292 {
293     DLP_LOG_INFO(LABEL, "Start generate dlp file from enterprise space service.");
294     if (plainFileFd < 0 || dlpFileFd < 0) {
295         DLP_LOG_ERROR(LABEL, "Encrypt dlp file fail, plain file fd or dlp file fd invalid");
296         return DLP_PARSE_ERROR_FD_ERROR;
297     }
298     SetCustomProperty(property, customProperty);
299     std::shared_ptr<DlpFile> filePtr = nullptr;
300     std::string workDir;
301     int32_t result = EnterpriseSpacePrepareWorkDir(dlpFileFd, filePtr, workDir);
302     if (result != DLP_OK) {
303         DLP_LOG_ERROR(LABEL, "Enterprise space prepare workDir fail, errno=%{public}d", result);
304         return result;
305     }
306 
307     result = DlpFileManager::GetInstance().SetDlpFileParams(filePtr, property);
308     if (result != DLP_OK) {
309         DLP_LOG_ERROR(LABEL, "Generate dlp file fail, set dlp obj params error, errno=%{public}d", result);
310         return result;
311     }
312 
313     result = filePtr->GenFile(plainFileFd);
314     if (result != DLP_OK) {
315         DLP_LOG_ERROR(LABEL, "Generate dlp file fail, errno=%{public}d", result);
316         return result;
317     }
318 
319     return DLP_OK;
320 }
321 
DecryptDlpFile(int32_t plainFileFd,int32_t dlpFileFd)322 int32_t EnterpriseSpaceDlpPermissionKit::DecryptDlpFile(int32_t plainFileFd, int32_t dlpFileFd)
323 {
324     DLP_LOG_INFO(LABEL, "Start decrypt dlp file from enterprise space service.");
325     if (plainFileFd < 0 || dlpFileFd < 0) {
326         DLP_LOG_ERROR(LABEL, "Decrypt dlp file fail, plain file fd or dlp file fd invalid");
327         return DLP_PARSE_ERROR_FD_ERROR;
328     }
329 
330     std::shared_ptr<DlpFile> filePtr = nullptr;
331     std::string workDir;
332     int32_t result = EnterpriseSpacePrepareWorkDir(dlpFileFd, filePtr, workDir);
333     if (result != DLP_OK) {
334         DLP_LOG_ERROR(LABEL, "Enterprise space prepare workDir fail, errno=%{public}d", result);
335         return result;
336     }
337 
338     result = EnterpriseSpaceParseDlpFileFormat(filePtr, true);
339     if (result != DLP_OK) {
340         DLP_LOG_ERROR(LABEL, "Open dlp file fail, parse dlp file error, errno=%{public}d", result);
341         return result;
342     }
343 
344     result = DlpFileManager::GetInstance().RecoverDlpFile(filePtr, plainFileFd);
345     if (result != DLP_OK) {
346         DLP_LOG_ERROR(LABEL, "recover dlp file fail with enterprise space.");
347     }
348     return DLP_OK;
349 }
350 
QueryDlpFileProperty(int32_t dlpFileFd,std::string & policyJsonString)351 int32_t EnterpriseSpaceDlpPermissionKit::QueryDlpFileProperty(int32_t dlpFileFd, std::string &policyJsonString)
352 {
353     DLP_LOG_INFO(LABEL, "Start query dlp file property from enterprise space service.");
354     if (dlpFileFd < 0) {
355         DLP_LOG_ERROR(LABEL, "Query dlp property fail, dlp file fd invalid");
356         return DLP_PARSE_ERROR_FD_ERROR;
357     }
358 
359     std::shared_ptr<DlpFile> filePtr = nullptr;
360     std::string workDir;
361     int32_t result = EnterpriseSpacePrepareWorkDir(dlpFileFd, filePtr, workDir);
362     if (result != DLP_OK) {
363         DLP_LOG_ERROR(LABEL, "Enterprise space prepare workDir fail, errno=%{public}d", result);
364         return result;
365     }
366     PermissionPolicy policy;
367     result = EnterpriseSpaceParseDlpFileProperty(filePtr, policy, false);
368     if (result != DLP_OK) {
369         DLP_LOG_ERROR(LABEL, "Enterprise space parse dlp property fail, errno=%{public}d", result);
370         return result;
371     }
372     SerializePermissionPolicy(policy, policyJsonString);
373     return DLP_OK;
374 }
375 
376 }
377 }
378 }
379