• 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 
16 #include "dlp_file_kits.h"
17 #include <cstdlib>
18 #include <fcntl.h>
19 #include <string>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include <unordered_map>
24 #include "dlp_file.h"
25 #include "dlp_permission_log.h"
26 #include "dlp_zip.h"
27 #include "file_uri.h"
28 #include "securec.h"
29 #include "dlp_utils.h"
30 #include "dlp_permission.h"
31 
32 namespace OHOS {
33 namespace Security {
34 namespace DlpPermission {
35 namespace {
36     static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpFileKits"};
37     static const std::string FILE_SCHEME_PREFIX = "file://";
38     static const std::string DEFAULT_STRINGS = "";
39     static const uint32_t BYTE_TO_HEX_OPER_LENGTH = 2;
40     static const uint32_t CURRENT_VERSION = 3;
41     static const uint32_t FILE_HEAD = 8;
42     static const uint32_t HMAC_SIZE = 32;
43 } // namespace
44 using Want = OHOS::AAFwk::Want;
45 using WantParams = OHOS::AAFwk::WantParams;
46 
47 static const std::unordered_map<std::string, std::string> SUFFIX_MIMETYPE_MAP = {
48     {"txt", "text/plain"},
49     {"doc", "application/msword"},
50     {"docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
51     {"pdf", "application/pdf"},
52     {"ppt", "application/vnd.ms-powerpoint"},
53     {"pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
54     {"xls", "application/vnd.ms-excel"},
55     {"xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
56     {"bmp", "image/bmp"},
57     {"bm", "image/bmp"},
58     {"dng", "image/x-adobe-dng"},
59     {"gif", "image/gif"},
60     {"heic", "image/heic"},
61     {"heics", "image/heic"},
62     {"heif", "image/heif"},
63     {"heifs", "image/heif"},
64     {"hif", "image/heif"},
65     {"jpg", "image/jpeg"},
66     {"jpeg", "image/jpeg"},
67     {"jpe", "image/jpeg"},
68     {"png", "image/png"},
69     {"webp", "image/webp"},
70     {"cur", "image/ico"},
71     {"raf", "image/x-fuji-raf"},
72     {"ico", "image/x-icon"},
73     {"nrw", "image/x-nikon-nrw"},
74     {"rw2", "image/x-panasonic-raw"},
75     {"pef", "image/x-pentax-pef"},
76     {"srw", "image/x-samsung-srw"},
77     {"svg", "image/svg+xml"},
78     {"arw", "image/x-sony-arw"},
79     {"3gpp2", "video/3gpp2"},
80     {"3gp2", "video/3gpp2"},
81     {"3g2", "video/3gpp2"},
82     {"3gpp", "video/3gpp"},
83     {"3gp", "video/3gpp"},
84     {"avi", "video/avi"},
85     {"m4v", "video/mp4"},
86     {"f4v", "video/mp4"},
87     {"mp4v", "video/mp4"},
88     {"mpeg4", "video/mp4"},
89     {"mp4", "video/mp4"},
90     {"m2ts", "video/mp2t"},
91     {"mts", "video/mp2t"},
92     {"ts", "video/mp2ts"},
93     {"vt", "video/vnd.youtube.yt"},
94     {"wrf", "video/x-webex"},
95     {"mpeg", "video/mpeg"},
96     {"mpeg2", "video/mpeg"},
97     {"mpv2", "video/mpeg"},
98     {"mp2v", "video/mpeg"},
99     {"m2v", "video/mpeg"},
100     {"m2t", "video/mpeg"},
101     {"mpeg1", "video/mpeg"},
102     {"mpv1", "video/mpeg"},
103     {"mp1v", "video/mpeg"},
104     {"m1v", "video/mpeg"},
105     {"mpg", "video/mpeg"},
106     {"mov", "video/quicktime"},
107     {"mkv", "video/x-matroska"},
108     {"webm", "video/webm"},
109     {"h264", "video/H264"},
110     {"wbmp", "image/vnd.wap.wbmp"},
111     {"nef", "image/x-nikon-nef"},
112     {"cr2", "image/x-canon-cr2"},
113 };
114 
IsDlpFileName(const std::string & dlpFileName)115 static bool IsDlpFileName(const std::string& dlpFileName)
116 {
117     uint32_t dlpSuffixLen = DLP_FILE_SUFFIX.size();
118     uint32_t fileNameLen = dlpFileName.size();
119     if (fileNameLen < dlpSuffixLen) {
120         return false;
121     }
122 
123     std::string fileSuffix = dlpFileName.substr(fileNameLen - dlpSuffixLen, dlpSuffixLen);
124     if (DlpUtils::ToLowerString(fileSuffix) != DLP_FILE_SUFFIX) {
125         return false;
126     }
127     return true;
128 }
129 
GetMimeTypeBySuffix(const std::string & suffix)130 static std::string GetMimeTypeBySuffix(const std::string& suffix)
131 {
132     std::string lower = DlpUtils::ToLowerString(suffix);
133     for (size_t len = MAX_REALY_TYPE_LENGTH; len >= MIN_REALY_TYPE_LENGTH; len--) {
134         if (len > lower.size()) {
135             continue;
136         }
137         std::string newStr = lower.substr(0, len);
138         auto iter = SUFFIX_MIMETYPE_MAP.find(newStr);
139         if (iter != SUFFIX_MIMETYPE_MAP.end()) {
140             return iter->second;
141         }
142     }
143     return DEFAULT_STRING;
144 }
145 
IsValidDlpHeader(const struct DlpHeader & head)146 static bool IsValidDlpHeader(const struct DlpHeader& head)
147 {
148     if (head.magic != DLP_FILE_MAGIC || head.certSize == 0 || head.certSize > DLP_MAX_CERT_SIZE ||
149         head.contactAccountSize == 0 || head.contactAccountSize > DLP_MAX_CERT_SIZE ||
150         head.contactAccountOffset != sizeof(struct DlpHeader) + FILE_HEAD ||
151         head.txtOffset != head.contactAccountOffset + head.contactAccountSize ||
152         head.txtSize > DLP_MAX_CONTENT_SIZE || head.hmacOffset != head.txtOffset + head.txtSize ||
153         head.hmacSize != HMAC_SIZE * BYTE_TO_HEX_OPER_LENGTH || head.offlineCertSize > DLP_MAX_CERT_SIZE ||
154         !(head.certOffset == head.txtOffset || head.certOffset == head.hmacOffset + head.hmacSize)) {
155         DLP_LOG_ERROR(LABEL, "Parse dlp file header error.");
156         return false;
157     }
158     return true;
159 }
160 
IsDlpFile(int32_t dlpFd)161 bool DlpFileKits::IsDlpFile(int32_t dlpFd)
162 {
163     if (dlpFd < 0) {
164         DLP_LOG_ERROR(LABEL, "dlp file fd is invalid");
165         return false;
166     }
167 
168     if (IsZipFile(dlpFd)) {
169         return CheckUnzipFileInfo(dlpFd);
170     }
171 
172     off_t curPos = lseek(dlpFd, 0, SEEK_CUR);
173     if (curPos < 0) {
174         DLP_LOG_ERROR(LABEL, "seek dlp file current failed, %{public}s", strerror(errno));
175         return false;
176     }
177 
178     if (lseek(dlpFd, 0, SEEK_SET) == static_cast<off_t>(-1)) {
179         DLP_LOG_ERROR(LABEL, "seek dlp file start failed, %{public}s", strerror(errno));
180         return false;
181     }
182 
183     uint32_t version = 0;
184     if (read(dlpFd, &version, sizeof(uint32_t)) != sizeof(uint32_t)) {
185         DLP_LOG_ERROR(LABEL, "can not read version, %{public}s", strerror(errno));
186         return false;
187     }
188 
189     uint32_t dlpHeaderSize = 0;
190     if (read(dlpFd, &dlpHeaderSize, sizeof(uint32_t)) != sizeof(uint32_t)) {
191         DLP_LOG_ERROR(LABEL, "can not read dlpHeaderSize, %{public}s", strerror(errno));
192         return false;
193     }
194     if (version != CURRENT_VERSION || dlpHeaderSize != sizeof(struct DlpHeader)) {
195         DLP_LOG_ERROR(LABEL, "version or dlpHeaderSize is error");
196         return false;
197     }
198 
199     struct DlpHeader head;
200     if (read(dlpFd, &head, sizeof(struct DlpHeader)) != sizeof(struct DlpHeader)) {
201         DLP_LOG_ERROR(LABEL, "can not read dlp file head, %{public}s", strerror(errno));
202         return false;
203     }
204 
205     if (lseek(dlpFd, curPos, SEEK_SET) < 0) {
206         DLP_LOG_ERROR(LABEL, "seek dlp file back failed, %{public}s", strerror(errno));
207         return false;
208     }
209 
210     return IsValidDlpHeader(head);
211 }
212 
GetSandboxFlag(Want & want)213 bool DlpFileKits::GetSandboxFlag(Want& want)
214 {
215     std::string action = want.GetAction();
216     if (!action.empty() && action != TAG_ACTION_VIEW && action != TAG_ACTION_EDIT) {
217         DLP_LOG_DEBUG(LABEL, "Action %{public}s is not dlp scene", action.c_str());
218         return false;
219     }
220 
221     std::string uri = want.GetUriString();
222     if (uri.find(FILE_SCHEME_PREFIX) != 0) {
223         DLP_LOG_DEBUG(LABEL, "uri is missing file://");
224         return false;
225     }
226     AppFileService::ModuleFileUri::FileUri fileUri(uri);
227     std::string fileName = fileUri.GetName();
228     if (fileName.empty() || !IsDlpFileName(fileName)) {
229         DLP_LOG_DEBUG(LABEL, "File name is not exist or not dlp, name=%{private}s", fileName.c_str());
230         return false;
231     }
232     std::string path = fileUri.GetRealPath();
233     int fd = open(path.c_str(), O_RDONLY);
234     if (fd == -1) {
235         DLP_LOG_ERROR(LABEL, "open file error, error=%{public}d", errno);
236         return false;
237     }
238     if (!IsDlpFile(fd)) {
239         DLP_LOG_WARN(LABEL, "Fd %{public}d is not dlp file", fd);
240     }
241     bool isFromUriName = false;
242     std::string realSuffix = DlpUtils::GetRealTypeWithFd(fd, isFromUriName);
243     if (realSuffix != DEFAULT_STRING) {
244         DLP_LOG_DEBUG(LABEL, "Real suffix is %{public}s", realSuffix.c_str());
245         std::string realType = GetMimeTypeBySuffix(realSuffix);
246         if (realType != DEFAULT_STRING) {
247             want.SetType(realType);
248         } else {
249             DLP_LOG_INFO(LABEL, "Real suffix %{public}s not match known type, using origin type %{public}s",
250                 realSuffix.c_str(), want.GetType().c_str());
251         }
252     }
253     close(fd);
254     fd = -1;
255     DLP_LOG_INFO(LABEL, "Sanbox flag is true");
256     return true;
257 }
258 
ConvertAbilityInfoWithBundleName(const std::string & abilityName,const std::string & bundleName,std::vector<AppExecFwk::AbilityInfo> & abilityInfos)259 static int32_t ConvertAbilityInfoWithBundleName(const std::string &abilityName, const std::string &bundleName,
260     std::vector<AppExecFwk::AbilityInfo> &abilityInfos)
261 {
262     Want want;
263     AppExecFwk::ElementName name;
264     name.SetAbilityName(abilityName);
265     name.SetBundleName(bundleName);
266     want.SetElement(name);
267 
268     int32_t flags = static_cast<int32_t>(AppExecFwk::GetAbilityInfoFlag::GET_ABILITY_INFO_DEFAULT);
269     int32_t userId = 0;
270     int32_t ret = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
271     if (ret != ERR_OK) {
272         DLP_LOG_ERROR(LABEL, "Get os account localId error, %{public}d", ret);
273         return DLP_PARSE_ERROR_GET_ACCOUNT_FAIL;
274     }
275 
276     auto bundleMgrProxy = DlpUtils::GetBundleMgrProxy();
277     if (bundleMgrProxy == nullptr) {
278         return DLP_SERVICE_ERROR_IPC_REQUEST_FAIL;
279     }
280     ret = bundleMgrProxy->QueryAbilityInfosV9(want, flags, userId, abilityInfos);
281     if (ret != ERR_OK) {
282         DLP_LOG_ERROR(LABEL, "Get ability info error, %{public}d", ret);
283         return DLP_PARSE_ERROR_BMS_ERROR;
284     }
285     return DLP_OK;
286 }
287 
IsSupportDlp(const std::vector<std::string> & authPolicy,const std::string & bundleName)288 static bool IsSupportDlp(const std::vector<std::string> &authPolicy, const std::string &bundleName)
289 {
290     auto it = std::find(authPolicy.begin(), authPolicy.end(), bundleName);
291     if (it != authPolicy.end()) {
292         return true;
293     }
294     return false;
295 }
296 
GetRealFileType(const AAFwk::Want & want)297 static std::string GetRealFileType(const AAFwk::Want &want)
298 {
299     std::string uri = want.GetUriString();
300     if (uri.find(FILE_SCHEME_PREFIX) != 0) {
301         DLP_LOG_DEBUG(LABEL, "uri is missing file://");
302         return DEFAULT_STRINGS;
303     }
304     AppFileService::ModuleFileUri::FileUri fileUri(uri);
305     std::string fileName = fileUri.GetName();
306     if (fileName.empty() || !IsDlpFileName(fileName)) {
307         DLP_LOG_ERROR(LABEL, "File name is not exist or not dlp, name=%{private}s", fileName.c_str());
308         return DEFAULT_STRINGS;
309     }
310 
311     std::string realMimeType = want.GetType();
312     if (realMimeType == DEFAULT_STRING) {
313         DLP_LOG_ERROR(LABEL, "get real mime mype error.");
314         return DEFAULT_STRINGS;
315     }
316 
317     std::string realSuffix = DEFAULT_STRING;
318     for (const auto& p : SUFFIX_MIMETYPE_MAP) {
319         if (p.second == realMimeType) {
320             realSuffix = p.first;
321             break;
322         }
323     }
324     std::string fileType = DlpUtils::GetFileTypeBySuffix(realSuffix, false);
325     if (fileType == DEFAULT_STRING) {
326         DLP_LOG_ERROR(LABEL, "%{public}s is not support dlp.", realSuffix.c_str());
327     }
328     return fileType;
329 }
330 
ConvertAbilityInfoWithSupportDlp(const AAFwk::Want & want,std::vector<AppExecFwk::AbilityInfo> & abilityInfos)331 void DlpFileKits::ConvertAbilityInfoWithSupportDlp(const AAFwk::Want &want,
332     std::vector<AppExecFwk::AbilityInfo> &abilityInfos)
333 {
334     std::string fileType = GetRealFileType(want);
335     if (fileType == DEFAULT_STRING) {
336         return;
337     }
338 
339     std::vector<std::string> authPolicy;
340     if (!DlpUtils::GetAuthPolicyWithType(DLP_AUTH_POLICY, fileType, authPolicy)) {
341         return;
342     }
343 
344     for (auto it = abilityInfos.begin(); it != abilityInfos.end();) {
345         if (!IsSupportDlp(authPolicy, it->bundleName)) {
346             abilityInfos.erase(it);
347         } else {
348             ++it;
349         }
350     }
351 
352     if (abilityInfos.size() != 0) {
353         return;
354     }
355     std::vector<std::string> defalutAuthPolicy;
356     if (!DlpUtils::GetAuthPolicyWithType(DLP_AUTH_POLICY, DLP_DEFAULT_AUTH_POLICY, defalutAuthPolicy) ||
357         defalutAuthPolicy.size() <= 1) {
358         return;
359     }
360     int32_t ret = ConvertAbilityInfoWithBundleName(defalutAuthPolicy[0], defalutAuthPolicy[1], abilityInfos);
361     if (ret != DLP_OK) {
362         DLP_LOG_ERROR(LABEL, "Query ability info with bundleName error.");
363     }
364 }
365 
IsDlpFileBySuffix(const std::string & fileSuffix)366 bool DlpFileKits::IsDlpFileBySuffix(const std::string &fileSuffix)
367 {
368     std::string lowerFileSuffix = DlpUtils::ToLowerString(fileSuffix);
369     if (lowerFileSuffix != DLP_FILE_SUFFIX) {
370         DLP_LOG_DEBUG(LABEL, "%{public}s is not dlp file suffix", lowerFileSuffix.c_str());
371         return false;
372     }
373     return true;
374 }
375 }  // namespace DlpPermission
376 }  // namespace Security
377 }  // namespace OHOS
378