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