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