• 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 <string>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include "dlp_permission_log.h"
27 
28 #include "securec.h"
29 
30 namespace OHOS {
31 namespace Security {
32 namespace DlpPermission {
33 using Defer = std::shared_ptr<void>;
34 namespace {
35 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpFileZip"};
36 const uint32_t ZIP_BUFF_SIZE = 1024;
37 const int32_t DLP_ZIP_FAIL = -1;
38 const int32_t DLP_ZIP_OK = 0;
39 const std::string DLP_GENERAL_INFO = "dlp_general_info";
40 }
41 
AddBuffToZip(const void * buf,uint32_t size,const char * nameInZip,const char * zipName)42 int32_t AddBuffToZip(const void *buf, uint32_t size, const char *nameInZip, const char *zipName)
43 {
44     zipFile zf = zipOpen64(zipName, APPEND_STATUS_ADDINZIP);
45     if (zf == nullptr) {
46         DLP_LOG_ERROR(LABEL, "AddBuffToZip fail err %{public}d, zipName %{public}s",
47             errno, zipName);
48         return DLP_ZIP_FAIL;
49     }
50     int opt_compress_level = 0;
51     zip_fileinfo zi = {};
52 
53     int32_t err = zipOpenNewFileInZip3_64(zf, nameInZip, &zi,
54         NULL, 0, NULL, 0, NULL /* comment */,
55         (opt_compress_level != 0) ? Z_DEFLATED : 0,
56         opt_compress_level, 0,
57         /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
58         -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
59         NULL, 0, 0);
60     if (err != ZIP_OK) {
61         DLP_LOG_ERROR(LABEL, "AddBuffToZip fail err %{public}d, nameInZip %{public}s", err, nameInZip);
62         (void)zipClose(zf, NULL);
63         return DLP_ZIP_FAIL;
64     }
65 
66     err = zipWriteInFileInZip (zf, buf, (unsigned)size);
67     if (err != ZIP_OK) {
68         DLP_LOG_ERROR(LABEL, "zipWriteInFileInZip fail err %{public}d, %{public}s", err, nameInZip);
69     }
70 
71     if (zipCloseFileInZip(zf) != ZIP_OK) {
72         DLP_LOG_ERROR(LABEL, "zipCloseFileInZip fail nameInZip %{public}s", nameInZip);
73     }
74 
75     if (zipClose(zf, NULL) != ZIP_OK) {
76         DLP_LOG_ERROR(LABEL, "zipClose fail nameInZip %{public}s", nameInZip);
77         return DLP_ZIP_FAIL;
78     }
79 
80     return DLP_ZIP_OK;
81 }
82 
AddFileContextToZip(int32_t fd,const char * nameInZip,const char * zipName)83 int32_t AddFileContextToZip(int32_t fd, const char *nameInZip, const char *zipName)
84 {
85     zipFile zf = zipOpen64(zipName, APPEND_STATUS_ADDINZIP);
86     if (zf == nullptr) {
87         DLP_LOG_ERROR(LABEL, "AddFileContextToZip fail err %{public}d, zipName %{public}s",
88             errno, zipName);
89         return DLP_ZIP_FAIL;
90     }
91     int32_t opt_compress_level = 0;
92     zip_fileinfo zi = {};
93 
94     int32_t err = zipOpenNewFileInZip3_64(zf, nameInZip, &zi,
95         NULL, 0, NULL, 0, NULL /* comment */,
96         (opt_compress_level != 0) ? Z_DEFLATED : 0,
97         opt_compress_level, 0,
98         /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
99         -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
100         NULL, 0, 0);
101     if (err != ZIP_OK) {
102         DLP_LOG_ERROR(LABEL, "create zip file fail err %{public}d, nameInZip %{public}s", err, nameInZip);
103         zipClose(zf, NULL);
104         return DLP_ZIP_FAIL;
105     }
106 
107     int32_t size_read;
108     auto buf = std::make_unique<char[]>(ZIP_BUFF_SIZE);
109     while ((size_read = read(fd, buf.get(), ZIP_BUFF_SIZE)) > 0) {
110         err = zipWriteInFileInZip (zf, buf.get(), (unsigned)size_read);
111         if (err != ZIP_OK) {
112             DLP_LOG_ERROR(LABEL, "zipWriteInFileInZip fail err %{public}d, %{public}s", err, nameInZip);
113             break;
114         }
115     }
116 
117     if (size_read == -1) {
118         DLP_LOG_ERROR(LABEL, "read errno %{public}s", strerror(errno));
119     }
120 
121     if (zipCloseFileInZip(zf) != ZIP_OK) {
122         DLP_LOG_ERROR(LABEL, "zipCloseFileInZip fail nameInZip %{public}s", nameInZip);
123     }
124 
125     if (zipClose(zf, NULL) != ZIP_OK) {
126         DLP_LOG_ERROR(LABEL, "zipClose fail nameInZip %{public}s", nameInZip);
127         return DLP_ZIP_FAIL;
128     }
129 
130     return DLP_ZIP_OK;
131 }
132 
OpenZipFile(int fd)133 static zipFile OpenZipFile(int fd)
134 {
135     zipFile uf;
136     int32_t fd2 = dup(fd);
137     if (fd2 == -1) {
138         DLP_LOG_ERROR(LABEL, "dup fail errno %{public}d", errno);
139         return nullptr;
140     }
141 
142     FILE *ff = fdopen(fd2, "rb");
143     if (ff == nullptr) {
144         DLP_LOG_ERROR(LABEL, "fdopen fail errno %{public}d", errno);
145         (void)close(fd2);
146         return nullptr;
147     }
148 
149     uf = unzOpenFile(ff);
150     if (uf == nullptr) {
151         DLP_LOG_ERROR(LABEL, "unzOpenFile fail errno %{public}d", errno);
152         return nullptr;
153     }
154     return uf;
155 }
156 
UnzipSpecificFile(int32_t fd,const char * nameInZip,const char * unZipName)157 int32_t UnzipSpecificFile(int32_t fd, const char*nameInZip, const char *unZipName)
158 {
159     zipFile uf;
160     int32_t outFd = open(unZipName, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
161     if (outFd == -1) {
162         DLP_LOG_ERROR(LABEL, "open fail %{public}s errno %{public}d", unZipName, errno);
163         return DLP_ZIP_FAIL;
164     }
165     Defer p(nullptr, [&](...) {
166         close(outFd);
167     });
168 
169     uf = OpenZipFile(fd);
170     if (uf == nullptr) {
171         return DLP_ZIP_FAIL;
172     }
173 
174     if (unzLocateFile(uf, nameInZip, 0) != UNZ_OK) {
175         DLP_LOG_ERROR(LABEL, "unzLocateFile fail %{public}s errno %{public}d", nameInZip, errno);
176         (void)unzClose(uf);
177         return DLP_ZIP_FAIL;
178     }
179 
180     int32_t err = unzOpenCurrentFile(uf);
181     if (err != UNZ_OK) {
182         DLP_LOG_ERROR(LABEL, "unzOpenCurrentFile fail %{public}s errno %{public}d", nameInZip, err);
183         (void)unzClose(uf);
184         return DLP_ZIP_FAIL;
185     }
186 
187     int32_t readSize;
188     auto buf = std::make_unique<char[]>(ZIP_BUFF_SIZE);
189     do {
190         readSize = unzReadCurrentFile(uf, buf.get(), ZIP_BUFF_SIZE);
191         int32_t writeSize = write(outFd, buf.get(), readSize);
192         if (writeSize != readSize) {
193             err = DLP_ZIP_FAIL;
194             DLP_LOG_ERROR(LABEL, "write zip fail %{public}s errno %{public}d write %{public}d read %{public}d",
195                 nameInZip, errno, writeSize, readSize);
196             break;
197         }
198     } while (readSize > 0);
199 
200     if (readSize < 0) {
201         DLP_LOG_ERROR(LABEL, "unzReadCurrentFile fail %{public}s errno %{public}d", nameInZip, errno);
202     }
203 
204     if (unzCloseCurrentFile(uf) != ZIP_OK) {
205         DLP_LOG_ERROR(LABEL, "unzCloseCurrentFile fail nameInZip %{public}s", nameInZip);
206     }
207 
208     if (unzClose(uf) != ZIP_OK) {
209         DLP_LOG_ERROR(LABEL, "zipClose fail nameInZip %{public}s", nameInZip);
210         return DLP_ZIP_FAIL;
211     }
212 
213     return err;
214 }
215 
IsZipFile(int32_t fd)216 bool IsZipFile(int32_t fd)
217 {
218     int32_t fd2 = dup(fd);
219     if (fd2 == -1) {
220         DLP_LOG_ERROR(LABEL, "dup fail %{public}d, %{public}d", fd2, errno);
221         return false;
222     }
223     FILE *ff = fdopen(fd2, "rb");
224     if (ff == nullptr) {
225         DLP_LOG_ERROR(LABEL, "fdopen fail %{public}d", errno);
226         (void)close(fd2);
227         return false;
228     }
229     unzFile uz = unzOpenFile(ff);
230     if (uz == nullptr) {
231         DLP_LOG_ERROR(LABEL, "unzOpenFile fail, %{public}d", errno);
232         return false;
233     }
234 
235     if (unzLocateFile(uz, DLP_GENERAL_INFO.c_str(), 0) != UNZ_OK) {
236         DLP_LOG_ERROR(LABEL, "unzLocateFile fail %{public}s errno %{public}d", DLP_GENERAL_INFO.c_str(), errno);
237         (void)unzClose(uz);
238         return false;
239     }
240 
241     (void)unzClose(uz);
242     return true;
243 }
244 }  // namespace DlpPermission
245 }  // namespace Security
246 }  // namespace OHOS
247