• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = &param};
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 = &param};
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