1 /*
2 * Copyright (c) 2023-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 #include "dlp_file_manager.h"
16
17 #include <dirent.h>
18 #include <cstdio>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include <string>
23
24 #include "dlp_crypt.h"
25 #include "dlp_file.h"
26 #include "dlp_raw_file.h"
27 #include "dlp_zip_file.h"
28 #include "dlp_zip.h"
29 #include "dlp_permission.h"
30 #include "dlp_permission_kit.h"
31 #include "dlp_permission_log.h"
32 #include "hitrace_meter.h"
33 #include "securec.h"
34 #include "dlp_utils.h"
35
36 namespace OHOS {
37 namespace Security {
38 namespace DlpPermission {
39 namespace {
40 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpFileManager"};
41 static constexpr uint32_t MAX_DLP_FILE_SIZE = 1000; // max open dlp file
42 const std::string PATH_CACHE = "/cache";
43 const std::string SUPPORT_PHOTO_DLP = "support_photo_dlp";
44 const std::string SUPPORT_VIDEO_DLP = "support_video_dlp";
45
46 static const std::string DEFAULT_STRING = "";
47 }
48
AddDlpFileNode(const std::shared_ptr<DlpFile> & filePtr)49 int32_t DlpFileManager::AddDlpFileNode(const std::shared_ptr<DlpFile>& filePtr)
50 {
51 if (filePtr == nullptr) {
52 DLP_LOG_ERROR(LABEL, "Add dlp file node failed, filePtr is null");
53 return DLP_PARSE_ERROR_VALUE_INVALID;
54 }
55 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->g_DlpMapLock_);
56 if (g_DlpFileMap_.size() >= MAX_DLP_FILE_SIZE) {
57 DLP_LOG_ERROR(LABEL, "Add dlp file node failed, too many files");
58 return DLP_PARSE_ERROR_TOO_MANY_OPEN_DLP_FILE;
59 }
60 auto iter = g_DlpFileMap_.find(filePtr->dlpFd_);
61 if (iter != g_DlpFileMap_.end()) {
62 DLP_LOG_ERROR(LABEL, "Add dlp file node fail, fd %{public}d already exist", filePtr->dlpFd_);
63 return DLP_PARSE_ERROR_FILE_ALREADY_OPENED;
64 }
65 g_DlpFileMap_[filePtr->dlpFd_] = filePtr;
66 return DLP_OK;
67 }
68
RemoveDlpFileNode(const std::shared_ptr<DlpFile> & filePtr)69 int32_t DlpFileManager::RemoveDlpFileNode(const std::shared_ptr<DlpFile>& filePtr)
70 {
71 if (filePtr == nullptr) {
72 DLP_LOG_ERROR(LABEL, "Remove dlp file node fail, filePtr is null");
73 return DLP_PARSE_ERROR_VALUE_INVALID;
74 }
75 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->g_DlpMapLock_);
76 for (auto iter = g_DlpFileMap_.begin(); iter != g_DlpFileMap_.end(); iter++) {
77 if (filePtr->dlpFd_ == iter->first) {
78 g_DlpFileMap_.erase(iter);
79 return DLP_OK;
80 }
81 }
82
83 DLP_LOG_ERROR(LABEL, "Remove dlp file node fail, fd %{public}d not exist", filePtr->dlpFd_);
84 return DLP_PARSE_ERROR_FILE_NOT_OPENED;
85 }
86
GetDlpFile(int32_t dlpFd)87 std::shared_ptr<DlpFile> DlpFileManager::GetDlpFile(int32_t dlpFd)
88 {
89 Utils::UniqueReadGuard<Utils::RWLock> infoGuard(this->g_DlpMapLock_);
90 for (auto iter = g_DlpFileMap_.begin(); iter != g_DlpFileMap_.end(); iter++) {
91 if (dlpFd == iter->first) {
92 return iter->second;
93 }
94 }
95
96 return nullptr;
97 }
98
GenerateCertData(const PermissionPolicy & policy,struct DlpBlob & certData) const99 int32_t DlpFileManager::GenerateCertData(const PermissionPolicy& policy, struct DlpBlob& certData) const
100 {
101 std::vector<uint8_t> cert;
102 StartTrace(HITRACE_TAG_ACCESS_CONTROL, "DlpGenerateCertificate");
103 int32_t result = DlpPermissionKit::GenerateDlpCertificate(policy, cert);
104 FinishTrace(HITRACE_TAG_ACCESS_CONTROL);
105 if (result != DLP_OK) {
106 DLP_LOG_ERROR(LABEL, "Generate dlp cert fail, errno=%{public}d", result);
107 return result;
108 }
109 return GenerateCertBlob(cert, certData);
110 }
111
GenerateCertBlob(const std::vector<uint8_t> & cert,struct DlpBlob & certData) const112 int32_t DlpFileManager::GenerateCertBlob(const std::vector<uint8_t>& cert, struct DlpBlob& certData) const
113 {
114 size_t certSize = cert.size();
115 if (certSize > DLP_MAX_CERT_SIZE) {
116 DLP_LOG_ERROR(LABEL, "Check dlp cert fail, cert is too large, size=%{public}zu", certSize);
117 return DLP_PARSE_ERROR_VALUE_INVALID;
118 }
119 if (certSize == 0) {
120 DLP_LOG_ERROR(LABEL, "Check dlp cert fail, cert is zero, size=%{public}zu", certSize);
121 return DLP_PARSE_ERROR_VALUE_INVALID;
122 }
123
124 uint8_t* certBuffer = new (std::nothrow) uint8_t[certSize];
125 if (certBuffer == nullptr) {
126 DLP_LOG_ERROR(LABEL, "Copy dlp cert fail, alloc buff fail");
127 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
128 }
129
130 if (memcpy_s(certBuffer, certSize, &cert[0], certSize) != EOK) {
131 DLP_LOG_ERROR(LABEL, "Copy dlp cert fail, memcpy_s fail");
132 (void)memset_s(certBuffer, certSize, 0, certSize);
133 delete[] certBuffer;
134 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
135 }
136 if (certData.data != nullptr) {
137 (void)memset_s(certData.data, certData.size, 0, certData.size);
138 delete[] certData.data;
139 }
140 certData.data = certBuffer;
141 certData.size = static_cast<uint32_t>(certSize);
142 return DLP_OK;
143 }
144
CleanBlobParam(struct DlpBlob & blob)145 static int32_t CleanBlobParam(struct DlpBlob& blob)
146 {
147 if (blob.data == nullptr || blob.size == 0) {
148 DLP_LOG_ERROR(LABEL, "blobData null");
149 return DLP_PARSE_ERROR_VALUE_INVALID;
150 }
151
152 (void)memset_s(blob.data, blob.size, 0, blob.size);
153 delete[] blob.data;
154 blob.data = nullptr;
155 blob.size = 0;
156 return DLP_OK;
157 }
158
CleanTempBlob(struct DlpBlob & key,struct DlpCipherParam ** tagIv,struct DlpBlob & hmacKey) const159 void DlpFileManager::CleanTempBlob(struct DlpBlob& key, struct DlpCipherParam** tagIv, struct DlpBlob& hmacKey) const
160 {
161 if (key.data != nullptr) {
162 CleanBlobParam(key);
163 }
164 if (hmacKey.data != nullptr) {
165 CleanBlobParam(hmacKey);
166 }
167 if (tagIv == nullptr || (*tagIv) == nullptr) {
168 return;
169 }
170 if ((*tagIv)->iv.data != nullptr) {
171 CleanBlobParam((*tagIv)->iv);
172 }
173 delete (*tagIv);
174 (*tagIv) = nullptr;
175 }
176
PrepareDlpEncryptParms(PermissionPolicy & policy,struct DlpBlob & key,struct DlpUsageSpec & usage,struct DlpBlob & certData,struct DlpBlob & hmacKey) const177 int32_t DlpFileManager::PrepareDlpEncryptParms(PermissionPolicy& policy, struct DlpBlob& key,
178 struct DlpUsageSpec& usage, struct DlpBlob& certData, struct DlpBlob& hmacKey) const
179 {
180 DLP_LOG_INFO(LABEL, "Generate key");
181 int32_t res = DlpOpensslGenerateRandomKey(DLP_AES_KEY_SIZE_256, &key);
182 if (res != DLP_OK) {
183 DLP_LOG_ERROR(LABEL, "Generate key fail, errno=%{public}d", res);
184 return res;
185 }
186
187 struct DlpCipherParam* tagIv = new (std::nothrow) struct DlpCipherParam;
188 if (tagIv == nullptr) {
189 DLP_LOG_ERROR(LABEL, "Alloc iv buff fail");
190 CleanTempBlob(key, &tagIv, hmacKey);
191 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
192 }
193 DLP_LOG_INFO(LABEL, "Generate iv");
194 res = DlpOpensslGenerateRandomKey(IV_SIZE * BIT_NUM_OF_UINT8, &tagIv->iv);
195 if (res != DLP_OK) {
196 DLP_LOG_ERROR(LABEL, "Generate iv fail, errno=%{public}d", res);
197 CleanTempBlob(key, &tagIv, hmacKey);
198 return res;
199 }
200
201 DLP_LOG_INFO(LABEL, "Generate hmac key");
202 res = DlpOpensslGenerateRandomKey(DLP_AES_KEY_SIZE_256, &hmacKey);
203 if (res != DLP_OK) {
204 DLP_LOG_ERROR(LABEL, "Generate hmacKey fail, errno=%{public}d", res);
205 CleanTempBlob(key, &tagIv, hmacKey);
206 return res;
207 }
208
209 usage.mode = DLP_MODE_CTR;
210 usage.algParam = tagIv;
211 policy.SetAeskey(key.data, key.size);
212 policy.SetIv(tagIv->iv.data, tagIv->iv.size);
213 policy.SetHmacKey(hmacKey.data, hmacKey.size);
214
215 DLP_LOG_INFO(LABEL, "Generate cert");
216 res = GenerateCertData(policy, certData);
217 if (res != DLP_OK) {
218 DLP_LOG_ERROR(LABEL, "Generate cert fail, errno=%{public}d", res);
219 CleanTempBlob(key, &tagIv, hmacKey);
220 return res;
221 }
222
223 return DLP_OK;
224 }
225
UpdateDlpFile(const std::vector<uint8_t> & cert,std::shared_ptr<DlpFile> & filePtr)226 int32_t DlpFileManager::UpdateDlpFile(const std::vector<uint8_t>& cert, std::shared_ptr<DlpFile>& filePtr)
227 {
228 std::lock_guard<std::mutex> lock(g_offlineLock_);
229 int32_t result = filePtr->CheckDlpFile();
230 if (result != DLP_OK) {
231 return result;
232 }
233 struct DlpBlob certBlob;
234 #ifdef SUPPORT_DLP_CREDENTIAL
235 result = GenerateCertBlob(cert, certBlob);
236 if (result != DLP_OK) {
237 return result;
238 }
239 #else
240 return DLP_OK;
241 #endif
242 int32_t res = filePtr->UpdateCertAndText(cert, certBlob);
243 (void)memset_s(certBlob.data, certBlob.size, 0, certBlob.size);
244 delete[] certBlob.data;
245 return res;
246 }
247
FreeChiperBlob(struct DlpBlob & key,struct DlpBlob & certData,struct DlpUsageSpec & usage,struct DlpBlob & hmacKey) const248 void DlpFileManager::FreeChiperBlob(struct DlpBlob& key, struct DlpBlob& certData,
249 struct DlpUsageSpec& usage, struct DlpBlob& hmacKey) const
250 {
251 if (key.data != nullptr) {
252 CleanBlobParam(key);
253 }
254
255 if (certData.data != nullptr) {
256 CleanBlobParam(certData);
257 }
258 if (usage.algParam != nullptr) {
259 if (usage.algParam->iv.data != nullptr) {
260 CleanBlobParam(usage.algParam->iv);
261 }
262 delete usage.algParam;
263 usage.algParam = nullptr;
264 }
265
266 if (hmacKey.data != nullptr) {
267 CleanBlobParam(hmacKey);
268 }
269 }
270
SetDlpFileParams(std::shared_ptr<DlpFile> & filePtr,const DlpProperty & property) const271 int32_t DlpFileManager::SetDlpFileParams(std::shared_ptr<DlpFile>& filePtr, const DlpProperty& property) const
272 {
273 PermissionPolicy policy(property);
274 struct DlpBlob key;
275 struct DlpBlob certData;
276 struct DlpUsageSpec usage;
277 struct DlpBlob hmacKey;
278
279 int result = policy.CheckActionUponExpiry();
280 if (result != DLP_OK) {
281 DLP_LOG_ERROR(LABEL, "Check action upon expiry fail, errno=%{public}d", result);
282 return result;
283 }
284
285 result = PrepareDlpEncryptParms(policy, key, usage, certData, hmacKey);
286 if (result != DLP_OK) {
287 DLP_LOG_ERROR(LABEL, "Set dlp obj params fail, prepare encrypt params error, errno=%{public}d", result);
288 return result;
289 }
290 result = filePtr->SetCipher(key, usage, hmacKey);
291 if (result != DLP_OK) {
292 FreeChiperBlob(key, certData, usage, hmacKey);
293 DLP_LOG_ERROR(LABEL, "Set dlp obj params fail, set cipher error, errno=%{public}d", result);
294 return result;
295 }
296
297 result = filePtr->SetPolicy(policy);
298 if (result != DLP_OK) {
299 FreeChiperBlob(key, certData, usage, hmacKey);
300 DLP_LOG_ERROR(LABEL, "Set dlp obj params fail, set policy error, errno=%{public}d", result);
301 return result;
302 }
303
304 result = filePtr->SetEncryptCert(certData);
305 if (result != DLP_OK) {
306 FreeChiperBlob(key, certData, usage, hmacKey);
307 DLP_LOG_ERROR(LABEL, "Set dlp obj params fail, set cert error, errno=%{public}d", result);
308 return result;
309 }
310
311 result = filePtr->SetContactAccount(property.contactAccount);
312 if (result != DLP_OK) {
313 DLP_LOG_WARN(LABEL, "Set dlp obj params fail, set contact account error, errno=%{public}d", result);
314 }
315
316 filePtr->SetOfflineAccess(property.offlineAccess);
317
318 FreeChiperBlob(key, certData, usage, hmacKey);
319 return result;
320 }
321
RemoveDirRecursive(const char * path)322 static bool RemoveDirRecursive(const char *path)
323 {
324 if (path == nullptr) {
325 return false;
326 }
327 DIR *dir = opendir(path);
328 if (dir == nullptr) {
329 return false;
330 }
331
332 dirent *entry;
333 while ((entry = readdir(dir)) != nullptr) {
334 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
335 continue;
336 }
337 std::string subPath = std::string(path) + "/" + entry->d_name;
338 if ((entry->d_type == DT_DIR) && (!RemoveDirRecursive(subPath.c_str()))) {
339 closedir(dir);
340 return false;
341 }
342 if ((entry->d_type != DT_DIR) && (remove(subPath.c_str()) != 0)) {
343 closedir(dir);
344 return false;
345 }
346 }
347
348 closedir(dir);
349
350 if (rmdir(path) != 0) {
351 DLP_LOG_ERROR(LABEL, "rmdir fail, errno %{public}s", strerror(errno));
352 return false;
353 }
354 return true;
355 }
356
357 std::mutex g_dirCleanLock;
PrepareDirs(const std::string & path)358 static void PrepareDirs(const std::string& path)
359 {
360 std::lock_guard<std::mutex> lock(g_dirCleanLock);
361 static bool cleanOnce = true;
362 if (cleanOnce) {
363 cleanOnce = false;
364 RemoveDirRecursive(path.c_str());
365 mkdir(path.c_str(), S_IRWXU);
366 }
367 }
368
GenerateRandomWorkDir(std::string & workDir)369 static int32_t GenerateRandomWorkDir(std::string &workDir)
370 {
371 DlpBlob dir;
372 int32_t res = DlpOpensslGenerateRandom(sizeof(uint64_t) * BIT_NUM_OF_UINT8, &dir);
373 if (res != DLP_OK) {
374 DLP_LOG_ERROR(LABEL, "Generate dir fail, errno=%{public}d", res);
375 return res;
376 }
377
378 workDir = std::to_string(*reinterpret_cast<uint64_t *>(dir.data));
379 delete[] dir.data;
380 return DLP_OK;
381 }
382
PrepareWorkDir(const std::string & path)383 static void PrepareWorkDir(const std::string& path)
384 {
385 mkdir(path.c_str(), S_IRWXU);
386 }
387
GetFileSuffix(const std::string & fileName)388 static std::string GetFileSuffix(const std::string& fileName)
389 {
390 char escape = '.';
391 std::size_t escapeLocate = fileName.find_last_of(escape);
392 if (escapeLocate >= fileName.size()) {
393 DLP_LOG_ERROR(LABEL, "Get file suffix fail, no '.' in file name");
394 return DEFAULT_STRING;
395 }
396
397 return DlpUtils::ToLowerString(fileName.substr(escapeLocate + 1));
398 }
399
GenRawDlpFile(DlpFileMes & dlpFileMes,const DlpProperty & property,std::shared_ptr<DlpFile> & filePtr)400 int32_t DlpFileManager::GenRawDlpFile(DlpFileMes& dlpFileMes, const DlpProperty& property,
401 std::shared_ptr<DlpFile>& filePtr)
402 {
403 filePtr = std::make_shared<DlpRawFile>(dlpFileMes.dlpFileFd, dlpFileMes.realFileType);
404 int32_t result = SetDlpFileParams(filePtr, property);
405 if (result != DLP_OK) {
406 DLP_LOG_ERROR(LABEL, "Generate dlp file fail, set dlp obj params error, errno=%{public}d", result);
407 return result;
408 }
409
410 result = filePtr->GenFile(dlpFileMes.plainFileFd);
411 if (result != DLP_OK) {
412 DLP_LOG_ERROR(LABEL, "Generate dlp file fail, errno=%{public}d", result);
413 return result;
414 }
415 return AddDlpFileNode(filePtr);
416 }
417
GenZipDlpFile(DlpFileMes & dlpFileMes,const DlpProperty & property,std::shared_ptr<DlpFile> & filePtr,const std::string & workDir)418 int32_t DlpFileManager::GenZipDlpFile(DlpFileMes& dlpFileMes, const DlpProperty& property,
419 std::shared_ptr<DlpFile>& filePtr, const std::string& workDir)
420 {
421 std::string cache = workDir + PATH_CACHE;
422 PrepareDirs(cache);
423
424 std::string randomWorkDir;
425 int32_t result = GenerateRandomWorkDir(randomWorkDir);
426 if (result != DLP_OK) {
427 DLP_LOG_ERROR(LABEL, "GenerateRandomWorkDir fail, errno=%{public}d", result);
428 return result;
429 }
430 std::string realWorkDir = cache + '/' + randomWorkDir;
431 PrepareWorkDir(realWorkDir);
432 int64_t timeStamp = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()
433 .time_since_epoch()).count();
434
435 filePtr = std::make_shared<DlpZipFile>(dlpFileMes.dlpFileFd, realWorkDir, timeStamp, dlpFileMes.realFileType);
436 result = SetDlpFileParams(filePtr, property);
437 if (result != DLP_OK) {
438 DLP_LOG_ERROR(LABEL, "SetDlpFileParams fail, errno=%{public}d", result);
439 return result;
440 }
441 result = filePtr->GenFile(dlpFileMes.plainFileFd);
442 if (result != DLP_OK) {
443 DLP_LOG_ERROR(LABEL, "GenFile fail, errno=%{public}d", result);
444 return result;
445 }
446 return AddDlpFileNode(filePtr);
447 }
448
GenerateDlpFile(int32_t plainFileFd,int32_t dlpFileFd,const DlpProperty & property,std::shared_ptr<DlpFile> & filePtr,const std::string & workDir)449 int32_t DlpFileManager::GenerateDlpFile(
450 int32_t plainFileFd, int32_t dlpFileFd, const DlpProperty& property, std::shared_ptr<DlpFile>& filePtr,
451 const std::string& workDir)
452 {
453 if (plainFileFd < 0 || dlpFileFd < 0) {
454 DLP_LOG_ERROR(LABEL, "fd invalid, plainFileFd: %{public}d, dlpFileFd: %{public}d", plainFileFd, dlpFileFd);
455 return DLP_PARSE_ERROR_FD_ERROR;
456 }
457
458 off_t fileLen = lseek(plainFileFd, 0, SEEK_END);
459 if (fileLen == static_cast<off_t>(-1) || fileLen > static_cast<off_t>(DLP_MAX_CONTENT_SIZE)) {
460 DLP_LOG_ERROR(LABEL, "fileLen invalid");
461 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
462 }
463 if (lseek(plainFileFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
464 DLP_LOG_ERROR(LABEL, "lseek invalid, %{public}s", strerror(errno));
465 return DLP_PARSE_ERROR_FILE_OPERATE_FAIL;
466 }
467
468 if (GetDlpFile(dlpFileFd) != nullptr) {
469 DLP_LOG_ERROR(LABEL, "Generate dlp file fail, dlp file has generated, if you want to rebuild, close it first");
470 return DLP_PARSE_ERROR_FILE_ALREADY_OPENED;
471 }
472
473 std::string fileName;
474 int32_t result = DlpUtils::GetFileNameWithDlpFd(dlpFileFd, fileName);
475 if (result != DLP_OK) {
476 DLP_LOG_ERROR(LABEL, "GetFileNameWithFd fail, errno=%{public}d", result);
477 return result;
478 }
479 DLP_LOG_DEBUG(LABEL, "the filename is %{public}s", fileName.c_str());
480
481 std::string realFileType = GetFileSuffix(fileName);
482 if (realFileType == DEFAULT_STRING) {
483 DLP_LOG_ERROR(LABEL, "GetFileSuffix fail");
484 return DLP_PARSE_ERROR_VALUE_INVALID;
485 }
486 std::string fileType = DlpUtils::GetFileTypeBySuffix(realFileType, true);
487 if (fileType == DEFAULT_STRING) {
488 DLP_LOG_ERROR(LABEL, "GetFileTypeBySuffix fail");
489 return DLP_PARSE_ERROR_VALUE_INVALID;
490 }
491 DlpFileMes dlpFileMes = {plainFileFd, dlpFileFd, realFileType};
492 if ((fileType == SUPPORT_PHOTO_DLP || fileType == SUPPORT_VIDEO_DLP) &&
493 property.ownerAccountType == CLOUD_ACCOUNT) {
494 return GenRawDlpFile(dlpFileMes, property, filePtr);
495 }
496 return GenZipDlpFile(dlpFileMes, property, filePtr, workDir);
497 }
498
GetAppIdWithBundleName(const std::string & bundleName,const int32_t & userId)499 static std::string GetAppIdWithBundleName(const std::string &bundleName, const int32_t &userId)
500 {
501 AppExecFwk::BundleInfo bundleInfo;
502 bool result = DlpUtils::GetBundleInfoWithBundleName(bundleName,
503 static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_SIGNATURE_INFO), bundleInfo, userId);
504 if (!result) {
505 DLP_LOG_ERROR(LABEL, "get appId error");
506 return DEFAULT_STRING;
507 }
508 return bundleInfo.appId;
509 }
510
SupportDlpWithAppId(const std::string & appId,const int32_t & dlpFileFd,const std::string & realSuffix,const bool isFromUriName)511 static int32_t SupportDlpWithAppId(const std::string &appId, const int32_t &dlpFileFd, const std::string &realSuffix,
512 const bool isFromUriName)
513 {
514 std::string fileType = DlpUtils::GetFileTypeBySuffix(realSuffix, isFromUriName);
515 if (fileType == DEFAULT_STRING) {
516 DLP_LOG_ERROR(LABEL, "get fileType error.");
517 return DLP_PARSE_ERROR_NOT_SUPPORT_FILE_TYPE;
518 }
519
520 int32_t userId = 0;
521 if (!DlpUtils::GetUserIdByForegroundAccount(userId)) {
522 DLP_LOG_ERROR(LABEL, "Get os account localId error");
523 return DLP_PARSE_ERROR_GET_ACCOUNT_FAIL;
524 }
525
526 std::vector<std::string> authPolicy;
527 if (!DlpUtils::GetAuthPolicyWithType(DLP_AUTH_POLICY, fileType, authPolicy)) {
528 DLP_LOG_DEBUG(LABEL, "not have auth policy.");
529 return DLP_OK;
530 }
531 for (size_t i = 0; i < authPolicy.size(); i++) {
532 if (appId == GetAppIdWithBundleName(authPolicy[i], userId)) {
533 return DLP_OK;
534 }
535 }
536 DLP_LOG_ERROR(LABEL, "Check DLP auth policy error.");
537 return DLP_CREDENTIAL_ERROR_APPID_NOT_AUTHORIZED;
538 }
539
DlpRawHmacCheckAndUpdata(std::shared_ptr<DlpFile> & filePtr,const std::vector<uint8_t> & offlineCert)540 int32_t DlpFileManager::DlpRawHmacCheckAndUpdata(std::shared_ptr<DlpFile>& filePtr,
541 const std::vector<uint8_t>& offlineCert)
542 {
543 int32_t result = filePtr->HmacCheck();
544 if (result != DLP_OK) {
545 return result;
546 }
547 result = UpdateDlpFile(offlineCert, filePtr);
548 if (result != DLP_OK) {
549 return result;
550 }
551 return AddDlpFileNode(filePtr);
552 }
553
OpenRawDlpFile(int32_t dlpFileFd,std::shared_ptr<DlpFile> & filePtr,const std::string & appId,const std::string & realType)554 int32_t DlpFileManager::OpenRawDlpFile(int32_t dlpFileFd, std::shared_ptr<DlpFile>& filePtr, const std::string& appId,
555 const std::string& realType)
556 {
557 filePtr = std::make_shared<DlpRawFile>(dlpFileFd, realType);
558 int32_t result = filePtr->ProcessDlpFile();
559 if (result != DLP_OK) {
560 return result;
561 }
562 struct DlpBlob cert;
563 filePtr->GetEncryptCert(cert);
564 sptr<CertParcel> certParcel = new (std::nothrow) CertParcel();
565 if (certParcel == nullptr) {
566 DLP_LOG_ERROR(LABEL, "Alloc certParcel parcel fail");
567 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
568 }
569 certParcel->cert = std::vector<uint8_t>(cert.data, cert.data + cert.size);
570 struct DlpBlob offlineCert = { 0 };
571 if (filePtr->GetOfflineCertSize() != 0) {
572 filePtr->GetOfflineCert(offlineCert);
573 certParcel->cert = std::vector<uint8_t>(offlineCert.data, offlineCert.data + offlineCert.size);
574 }
575 PermissionPolicy policy;
576 filePtr->GetContactAccount(certParcel->contactAccount);
577 certParcel->isNeedAdapter = filePtr->NeedAdapter();
578 certParcel->needCheckCustomProperty = true;
579 StartTrace(HITRACE_TAG_ACCESS_CONTROL, "DlpParseCertificate");
580 result = DlpPermissionKit::ParseDlpCertificate(certParcel, policy, appId, filePtr->GetOfflineAccess());
581 FinishTrace(HITRACE_TAG_ACCESS_CONTROL);
582 if (result != DLP_OK) {
583 DLP_LOG_ERROR(LABEL, "Parse cert fail, errno=%{public}d", result);
584 return result;
585 }
586 result = filePtr->SetPolicy(policy);
587 if (result != DLP_OK) {
588 return result;
589 }
590 struct DlpBlob key = {.size = policy.GetAeskeyLen(), .data = policy.GetAeskey()};
591 struct DlpCipherParam param = {.iv = {.size = policy.GetIvLen(), .data = policy.GetIv()}};
592 struct DlpUsageSpec usage = {.mode = DLP_MODE_CTR, .algParam = ¶m};
593 struct DlpBlob hmacKey = {.size = policy.GetHmacKeyLen(), .data = policy.GetHmacKey()};
594 result = filePtr->SetCipher(key, usage, hmacKey);
595 if (result != DLP_OK) {
596 return result;
597 }
598 return DlpRawHmacCheckAndUpdata(filePtr, certParcel->offlineCert);
599 }
600
ParseZipDlpFileAndAddNode(std::shared_ptr<DlpFile> & filePtr,const std::string & appId)601 int32_t DlpFileManager::ParseZipDlpFileAndAddNode(std::shared_ptr<DlpFile>& filePtr, const std::string& appId)
602 {
603 int32_t result = filePtr->ProcessDlpFile();
604 if (result != DLP_OK) {
605 return result;
606 }
607 struct DlpBlob cert;
608 filePtr->GetEncryptCert(cert);
609 sptr<CertParcel> certParcel = new (std::nothrow) CertParcel();
610 if (certParcel == nullptr) {
611 DLP_LOG_ERROR(LABEL, "Alloc certParcel parcel fail");
612 return DLP_PARSE_ERROR_MEMORY_OPERATE_FAIL;
613 }
614 certParcel->cert = std::vector<uint8_t>(cert.data, cert.data + cert.size);
615 PermissionPolicy policy;
616 filePtr->GetContactAccount(certParcel->contactAccount);
617 certParcel->isNeedAdapter = filePtr->NeedAdapter();
618 certParcel->needCheckCustomProperty = true;
619 StartTrace(HITRACE_TAG_ACCESS_CONTROL, "DlpParseCertificate");
620 result = DlpPermissionKit::ParseDlpCertificate(certParcel, policy, appId, filePtr->GetOfflineAccess());
621 FinishTrace(HITRACE_TAG_ACCESS_CONTROL);
622 if (result != DLP_OK) {
623 DLP_LOG_ERROR(LABEL, "Parse cert fail, errno=%{public}d", result);
624 return result;
625 }
626 result = filePtr->SetPolicy(policy);
627 if (result != DLP_OK) {
628 return result;
629 }
630 struct DlpBlob key = {.size = policy.GetAeskeyLen(), .data = policy.GetAeskey()};
631 struct DlpCipherParam param = {.iv = {.size = policy.GetIvLen(), .data = policy.GetIv()}};
632 struct DlpUsageSpec usage = {.mode = DLP_MODE_CTR, .algParam = ¶m};
633 struct DlpBlob hmacKey = {.size = policy.GetHmacKeyLen(), .data = policy.GetHmacKey()};
634 result = filePtr->SetCipher(key, usage, hmacKey);
635 if (result != DLP_OK) {
636 return result;
637 }
638 result = filePtr->HmacCheck();
639 if (result != DLP_OK) {
640 return result;
641 }
642 result = UpdateDlpFile(certParcel->offlineCert, filePtr);
643 if (result != DLP_OK) {
644 DLP_LOG_ERROR(LABEL, "UpdateDlpFile fail");
645 return result;
646 }
647 return AddDlpFileNode(filePtr);
648 }
649
OpenZipDlpFile(int32_t dlpFileFd,std::shared_ptr<DlpFile> & filePtr,const std::string & workDir,const std::string & appId,const std::string & realType)650 int32_t DlpFileManager::OpenZipDlpFile(int32_t dlpFileFd, std::shared_ptr<DlpFile>& filePtr,
651 const std::string& workDir, const std::string& appId,
652 const std::string& realType)
653 {
654 std::string cache = workDir + PATH_CACHE;
655 PrepareDirs(cache);
656 std::string randomWorkDir;
657 int32_t result = GenerateRandomWorkDir(randomWorkDir);
658 if (result != DLP_OK) {
659 DLP_LOG_ERROR(LABEL, "Generate dir fail, errno=%{public}d", result);
660 return result;
661 }
662 std::string realWorkDir = cache + '/' + randomWorkDir;
663 PrepareWorkDir(realWorkDir);
664 int64_t timeStamp = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()
665 .time_since_epoch()).count();
666
667 filePtr = std::make_shared<DlpZipFile>(dlpFileFd, realWorkDir, timeStamp, realType);
668 return ParseZipDlpFileAndAddNode(filePtr, appId);
669 }
670
OpenDlpFile(int32_t dlpFileFd,std::shared_ptr<DlpFile> & filePtr,const std::string & workDir,const std::string & appId)671 int32_t DlpFileManager::OpenDlpFile(int32_t dlpFileFd, std::shared_ptr<DlpFile>& filePtr, const std::string& workDir,
672 const std::string& appId)
673 {
674 if (dlpFileFd < 0) {
675 DLP_LOG_ERROR(LABEL, "Open dlp file fail, fd %{public}d is invalid", dlpFileFd);
676 return DLP_PARSE_ERROR_FD_ERROR;
677 }
678 bool isFromUriName = false;
679 std::string realSuffix = DlpUtils::GetRealTypeWithFd(dlpFileFd, isFromUriName);
680 if (realSuffix == DEFAULT_STRING) {
681 DLP_LOG_ERROR(LABEL, "GetRealTypeWithFd fail");
682 return DLP_PARSE_ERROR_NOT_SUPPORT_FILE_TYPE;
683 }
684 DLP_LOG_DEBUG(LABEL, "realSuffix is %{public}s", realSuffix.c_str());
685 int32_t ret = SupportDlpWithAppId(appId, dlpFileFd, realSuffix, isFromUriName);
686 if (ret != DLP_OK) {
687 DLP_LOG_ERROR(LABEL, "SupportDlpWithAppId fail");
688 return ret;
689 }
690 filePtr = GetDlpFile(dlpFileFd);
691 if (filePtr != nullptr) {
692 DLP_LOG_ERROR(LABEL, "Open dlp file fail, fd %{public}d has opened", dlpFileFd);
693 return DLP_OK;
694 }
695 std::string lower = DlpUtils::ToLowerString(realSuffix);
696 std::string realType = lower;
697 if (isFromUriName) {
698 for (size_t len = MAX_REALY_TYPE_LENGTH; len >= MIN_REALY_TYPE_LENGTH; len--) {
699 if (len > lower.size()) {
700 continue;
701 }
702 std::string newStr = lower.substr(0, len);
703 auto iter = FILE_TYPE_MAP.find(newStr);
704 if (iter != FILE_TYPE_MAP.end()) {
705 realType = newStr;
706 DLP_LOG_INFO(LABEL, "Assign realType newStr %{public}s", newStr.c_str());
707 break;
708 }
709 }
710 }
711 if (IsZipFile(dlpFileFd)) {
712 return OpenZipDlpFile(dlpFileFd, filePtr, workDir, appId, realType);
713 } else {
714 return OpenRawDlpFile(dlpFileFd, filePtr, appId, realType);
715 }
716 }
717
CloseDlpFile(const std::shared_ptr<DlpFile> & dlpFile)718 int32_t DlpFileManager::CloseDlpFile(const std::shared_ptr<DlpFile>& dlpFile)
719 {
720 if (dlpFile == nullptr) {
721 DLP_LOG_ERROR(LABEL, "Close dlp file fail, dlp obj is null");
722 return DLP_PARSE_ERROR_PTR_NULL;
723 }
724
725 return RemoveDlpFileNode(dlpFile);
726 }
727
RecoverDlpFile(std::shared_ptr<DlpFile> & filePtr,int32_t plainFd) const728 int32_t DlpFileManager::RecoverDlpFile(std::shared_ptr<DlpFile>& filePtr, int32_t plainFd) const
729 {
730 if (filePtr == nullptr) {
731 DLP_LOG_ERROR(LABEL, "Recover dlp file fail, dlp obj is null");
732 return DLP_PARSE_ERROR_PTR_NULL;
733 }
734 if (plainFd < 0) {
735 DLP_LOG_ERROR(LABEL, "Recover dlp file fail, fd %{public}d is invalid", plainFd);
736 return DLP_PARSE_ERROR_FD_ERROR;
737 }
738
739 return filePtr->RemoveDlpPermission(plainFd);
740 }
741
GetInstance()742 DlpFileManager& DlpFileManager::GetInstance()
743 {
744 static DlpFileManager instance;
745 return instance;
746 }
747 } // namespace DlpPermission
748 } // namespace Security
749 } // namespace OHOS
750