• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_zip.h"
17 
18 #include <cstdlib>
19 #include <cstdio>
20 #include <fcntl.h>
21 #include <memory>
22 #include <set>
23 #include <string>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include "dlp_permission_log.h"
28 
29 #include "securec.h"
30 
31 namespace OHOS {
32 namespace Security {
33 namespace DlpPermission {
34 using Defer = std::shared_ptr<void>;
35 namespace {
36 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpFileZip"};
37 const uint32_t ZIP_BUFF_SIZE = 1024;
38 const int32_t DLP_ZIP_FAIL = -1;
39 const int32_t DLP_ZIP_OK = 0;
40 const int32_t FILE_COUNT = 3;
41 const int32_t MAX_PATH = 30;
42 const int32_t MAX_CERT_SIZE = 30 * 1024;
43 const std::string DLP_CERT = "dlp_cert";
44 const std::string DLP_GENERAL_INFO = "dlp_general_info";
45 const std::set<std::string> FILE_NAME_SET = {"dlp_cert", "dlp_general_info", "encrypted_data"};
46 }
47 
AddZeroBuffToZip(zipFile & zf,const char * nameInZip,uint32_t size)48 int32_t AddZeroBuffToZip(zipFile& zf, const char *nameInZip, uint32_t size)
49 {
50     if (!memcmp(DLP_CERT.c_str(), nameInZip, DLP_CERT.size()) && size < MAX_CERT_SIZE) {
51         uint8_t* buffer = new (std::nothrow) uint8_t[MAX_CERT_SIZE - size];
52         if (buffer == nullptr) {
53             DLP_LOG_ERROR(LABEL, "buffer is nullptr");
54             return DLP_ZIP_FAIL;
55         }
56         (void)memset_s(buffer, MAX_CERT_SIZE - size, 0, MAX_CERT_SIZE - size);
57         int32_t err = zipWriteInFileInZip(zf, buffer, (unsigned)(MAX_CERT_SIZE - size));
58         delete[] buffer;
59         if (err != ZIP_OK) {
60             DLP_LOG_ERROR(LABEL, "zipWriteInFileInZip fail err %{public}d, %{public}s", err, nameInZip);
61             return DLP_ZIP_FAIL;
62         }
63     }
64     return ZIP_OK;
65 }
66 
AddBuffToZip(const void * buf,uint32_t size,const char * nameInZip,const char * zipName)67 int32_t AddBuffToZip(const void *buf, uint32_t size, const char *nameInZip, const char *zipName)
68 {
69     if (buf == nullptr || zipName == nullptr) {
70         DLP_LOG_ERROR(LABEL, "Buff or zipName is nullptr.");
71         return DLP_ZIP_FAIL;
72     }
73     zipFile zf = zipOpen64(zipName, APPEND_STATUS_ADDINZIP);
74     if (zf == nullptr) {
75         DLP_LOG_ERROR(LABEL, "AddBuffToZip fail err %{public}d, zipName %{public}s",
76             errno, zipName);
77         return DLP_ZIP_FAIL;
78     }
79     int compressLevel = 0;
80     zip_fileinfo zi = {};
81 
82     int32_t err = zipOpenNewFileInZip3_64(zf, nameInZip, &zi,
83         NULL, 0, NULL, 0, NULL /* comment */,
84         (compressLevel != 0) ? Z_DEFLATED : 0,
85         compressLevel, 0,
86         /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
87         -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
88         NULL, 0, 0);
89     if (err != ZIP_OK) {
90         DLP_LOG_ERROR(LABEL, "AddBuffToZip fail err %{public}d, nameInZip %{public}s", err, nameInZip);
91         (void)zipClose(zf, NULL);
92         return DLP_ZIP_FAIL;
93     }
94     int32_t res = DLP_ZIP_OK;
95     err = zipWriteInFileInZip (zf, buf, (unsigned)size);
96     if (err != ZIP_OK) {
97         DLP_LOG_ERROR(LABEL, "zipWriteInFileInZip fail err %{public}d, %{public}s", err, nameInZip);
98         res = DLP_ZIP_FAIL;
99     }
100 
101     if (AddZeroBuffToZip(zf, nameInZip, size) != ZIP_OK) {
102         DLP_LOG_ERROR(LABEL, "zipWriteInFileInZip fail err %{public}d, %{public}s", err, nameInZip);
103         res = DLP_ZIP_FAIL;
104     }
105 
106     if (zipCloseFileInZip(zf) != ZIP_OK) {
107         DLP_LOG_ERROR(LABEL, "zipCloseFileInZip fail nameInZip %{public}s", nameInZip);
108         res = DLP_ZIP_FAIL;
109     }
110 
111     if (zipClose(zf, NULL) != ZIP_OK) {
112         DLP_LOG_ERROR(LABEL, "zipClose fail nameInZip %{public}s", nameInZip);
113         return DLP_ZIP_FAIL;
114     }
115 
116     return res;
117 }
118 
AddFileContextToZip(int32_t fd,const char * nameInZip,const char * zipName)119 int32_t AddFileContextToZip(int32_t fd, const char *nameInZip, const char *zipName)
120 {
121     zipFile zf = zipOpen64(zipName, APPEND_STATUS_ADDINZIP);
122     if (zf == nullptr) {
123         DLP_LOG_ERROR(LABEL, "AddFileContextToZip fail err %{public}d, zipName %{public}s",
124             errno, zipName);
125         return DLP_ZIP_FAIL;
126     }
127     int32_t compressLevel = 0;
128     zip_fileinfo zi = {};
129 
130     int32_t err = zipOpenNewFileInZip3_64(zf, nameInZip, &zi,
131         NULL, 0, NULL, 0, NULL /* comment */,
132         (compressLevel != 0) ? Z_DEFLATED : 0,
133         compressLevel, 0,
134         /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
135         -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
136         NULL, 0, 0);
137     if (err != ZIP_OK) {
138         DLP_LOG_ERROR(LABEL, "create zip file fail err %{public}d, nameInZip %{public}s", err, nameInZip);
139         zipClose(zf, NULL);
140         return DLP_ZIP_FAIL;
141     }
142     int32_t readLen;
143     int32_t res = DLP_ZIP_OK;
144     auto buf = std::make_unique<char[]>(ZIP_BUFF_SIZE);
145     while ((readLen = read(fd, buf.get(), ZIP_BUFF_SIZE)) > 0) {
146         err = zipWriteInFileInZip (zf, buf.get(), (unsigned)readLen);
147         if (err != ZIP_OK) {
148             DLP_LOG_ERROR(LABEL, "zipWriteInFileInZip fail err %{public}d, %{public}s", err, nameInZip);
149             res = DLP_ZIP_FAIL;
150             break;
151         }
152     }
153 
154     if (readLen == -1) {
155         DLP_LOG_ERROR(LABEL, "read errno %{public}s", strerror(errno));
156         res = DLP_ZIP_FAIL;
157     }
158 
159     if (zipCloseFileInZip(zf) != ZIP_OK) {
160         DLP_LOG_ERROR(LABEL, "zipCloseFileInZip fail nameInZip %{public}s", nameInZip);
161         res = DLP_ZIP_FAIL;
162     }
163 
164     if (zipClose(zf, NULL) != ZIP_OK) {
165         DLP_LOG_ERROR(LABEL, "zipClose fail nameInZip %{public}s", nameInZip);
166         return DLP_ZIP_FAIL;
167     }
168 
169     return res;
170 }
171 
FdOpenFileFunc(void * opaque,const char * filename,int mode)172 static void *FdOpenFileFunc(void *opaque, const char *filename, int mode)
173 {
174     if ((opaque == nullptr) || (filename == nullptr)) {
175         return nullptr;
176     }
177     FILE *file = nullptr;
178     const char *modeFopen = nullptr;
179     uint32_t modeInner = static_cast<uint32_t>(mode);
180     if ((modeInner & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) {
181         modeFopen = "rb";
182     } else if (modeInner & ZLIB_FILEFUNC_MODE_EXISTING) {
183         modeFopen = "r+b";
184     } else if (modeInner & ZLIB_FILEFUNC_MODE_CREATE) {
185         modeFopen = "wb";
186     }
187     if (modeFopen != nullptr) {
188         int fd = dup(*static_cast<int *>(opaque));
189         if (fd != -1) {
190             file = fdopen(fd, modeFopen);
191         }
192     }
193 
194     return file;
195 }
196 
FdCloseFileFunc(void * opaque,void * stream)197 static int FdCloseFileFunc(void *opaque, void *stream)
198 {
199     if (fclose(static_cast<FILE *>(stream)) != 0) {
200         DLP_LOG_ERROR(LABEL, "fclose fail errno %{public}d", errno);
201     }
202     free(opaque);  // malloc'ed in FillFdOpenFileFunc()
203     return 0;
204 }
205 
FillFdOpenFileFunc(zlib_filefunc_def * pzlibFilefuncDef,int fd)206 static void FillFdOpenFileFunc(zlib_filefunc_def *pzlibFilefuncDef, int fd)
207 {
208     if (pzlibFilefuncDef == nullptr) {
209         return;
210     }
211     fill_fopen_filefunc(pzlibFilefuncDef);
212     pzlibFilefuncDef->zopen_file = FdOpenFileFunc;
213     pzlibFilefuncDef->zclose_file = FdCloseFileFunc;
214     int *ptrFd = static_cast<int *>(malloc(sizeof(fd)));
215     if (ptrFd == nullptr) {
216         return;
217     }
218     *ptrFd = fd;
219     pzlibFilefuncDef->opaque = ptrFd;
220 }
221 
OpenFdForUnzipping(int zipFD)222 static unzFile OpenFdForUnzipping(int zipFD)
223 {
224     zlib_filefunc_def zipFuncs;
225     FillFdOpenFileFunc(&zipFuncs, zipFD);
226     return unzOpen2("fd", &zipFuncs);
227 }
228 
OpenZipFile(int fd)229 static zipFile OpenZipFile(int fd)
230 {
231     zipFile uf = OpenFdForUnzipping(fd);
232     if (uf == nullptr) {
233         DLP_LOG_ERROR(LABEL, "unzOpenFile fail errno %{public}d", errno);
234         return nullptr;
235     }
236     return uf;
237 }
238 
CheckUnzipFileInfo(int32_t fd)239 bool CheckUnzipFileInfo(int32_t fd)
240 {
241     zipFile uf = OpenZipFile(fd);
242     if (uf == nullptr) {
243         DLP_LOG_ERROR(LABEL, "OpenZipFile fail errno %{public}d", errno);
244         return false;
245     }
246     unz_global_info64 globalnfo;
247     int res = unzGetGlobalInfo64(uf, &globalnfo);
248     if (res != UNZ_OK) {
249         DLP_LOG_ERROR(LABEL, "Call unzGetGloabalInfo64 fail res=%{public}d errno=%{public}d", res, errno);
250         (void)unzClose(uf);
251         return false;
252     }
253     //The number of files is equal to 3
254     if (globalnfo.number_entry != FILE_COUNT) {
255         DLP_LOG_ERROR(LABEL, "File count=%{public}llu", globalnfo.number_entry);
256         (void)unzClose(uf);
257         return false;
258     }
259     unz_file_info64 fileInfo;
260     char fileName[MAX_PATH + 1] = {0};
261     for (int32_t i = 0; i < FILE_COUNT; i++) {
262         res = unzGetCurrentFileInfo64(uf, &fileInfo, fileName, MAX_PATH, nullptr, 0, nullptr, 0);
263         if (res != UNZ_OK) {
264             DLP_LOG_ERROR(LABEL, "Call unzGetCurrentFileInfo64 fail res=%{public}d errno=%{public}d", res, errno);
265             (void)unzClose(uf);
266             return false;
267         }
268         fileName[MAX_PATH] = '\0';
269         //The file name has not been changed
270         auto it = FILE_NAME_SET.find(fileName);
271         if (it == FILE_NAME_SET.end()) {
272             DLP_LOG_ERROR(LABEL, "FileName=%{public}s do not found", fileName);
273             (void)unzClose(uf);
274             return false;
275         }
276         //The file has not been compressed
277         if (fileInfo.compressed_size < fileInfo.uncompressed_size) {
278             DLP_LOG_ERROR(LABEL, "Compressed_size=%{public}llu is less uncompress_size=%{public}llu",
279                 fileInfo.compressed_size, fileInfo.uncompressed_size);
280             (void)unzClose(uf);
281             return false;
282         }
283         unzGoToNextFile(uf);
284     }
285     (void)unzClose(uf);
286     return true;
287 }
288 
UnzipSpecificFile(int32_t fd,const char * nameInZip,const char * unZipName)289 int32_t UnzipSpecificFile(int32_t fd, const char*nameInZip, const char *unZipName)
290 {
291     zipFile uf;
292     int32_t outFd = open(unZipName, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
293     if (outFd == -1) {
294         DLP_LOG_ERROR(LABEL, "open fail %{public}s errno %{public}d", unZipName, errno);
295         return DLP_ZIP_FAIL;
296     }
297     Defer p(nullptr, [&](...) {
298         close(outFd);
299     });
300 
301     uf = OpenZipFile(fd);
302     if (uf == nullptr) {
303         return DLP_ZIP_FAIL;
304     }
305 
306     if (unzLocateFile(uf, nameInZip, 0) != UNZ_OK) {
307         DLP_LOG_ERROR(LABEL, "unzLocateFile fail %{public}s errno %{public}d", nameInZip, errno);
308         (void)unzClose(uf);
309         return DLP_ZIP_FAIL;
310     }
311 
312     int32_t err = unzOpenCurrentFile(uf);
313     if (err != UNZ_OK) {
314         DLP_LOG_ERROR(LABEL, "unzOpenCurrentFile fail %{public}s errno %{public}d", nameInZip, err);
315         (void)unzClose(uf);
316         return DLP_ZIP_FAIL;
317     }
318 
319     int32_t readSize = 0;
320     auto buf = std::make_unique<char[]>(ZIP_BUFF_SIZE);
321     do {
322         readSize = unzReadCurrentFile(uf, buf.get(), ZIP_BUFF_SIZE);
323         int32_t writeSize = write(outFd, buf.get(), readSize);
324         if (writeSize != readSize) {
325             err = DLP_ZIP_FAIL;
326             DLP_LOG_ERROR(LABEL, "write zip fail %{public}s errno %{public}d write %{public}d read %{public}d",
327                 nameInZip, errno, writeSize, readSize);
328             break;
329         }
330     } while (readSize > 0);
331 
332     if (readSize < 0) {
333         DLP_LOG_ERROR(LABEL, "unzReadCurrentFile fail %{public}s errno %{public}d", nameInZip, errno);
334     }
335 
336     if (unzCloseCurrentFile(uf) != ZIP_OK) {
337         DLP_LOG_ERROR(LABEL, "unzCloseCurrentFile fail nameInZip %{public}s", nameInZip);
338     }
339 
340     if (unzClose(uf) != ZIP_OK) {
341         DLP_LOG_ERROR(LABEL, "zipClose fail nameInZip %{public}s", nameInZip);
342         return DLP_ZIP_FAIL;
343     }
344 
345     return err;
346 }
347 
IsZipFile(int32_t fd)348 bool IsZipFile(int32_t fd)
349 {
350     unzFile uz = OpenFdForUnzipping(fd);
351     if (uz == nullptr) {
352         DLP_LOG_ERROR(LABEL, "unzOpenFile fail, %{public}d", errno);
353         return false;
354     }
355 
356     if (unzLocateFile(uz, DLP_GENERAL_INFO.c_str(), 0) != UNZ_OK) {
357         DLP_LOG_ERROR(LABEL, "unzLocateFile fail %{public}s errno %{public}d", DLP_GENERAL_INFO.c_str(), errno);
358         (void)unzClose(uz);
359         return false;
360     }
361 
362     (void)unzClose(uz);
363     return true;
364 }
365 }  // namespace DlpPermission
366 }  // namespace Security
367 }  // namespace OHOS
368