... | ... |
@@ -56,129 +56,132 @@ |
56 | 56 |
|
57 | 57 |
#define ZIP_MAX_NUM_OVERLAPPING_FILES 5 |
58 | 58 |
|
59 |
-#define ZIP_CRC32(r,c,b,l) \ |
|
60 |
- do { \ |
|
61 |
- r = crc32(~c,b,l); \ |
|
62 |
- r = ~r; \ |
|
63 |
- } while(0) |
|
59 |
+#define ZIP_CRC32(r, c, b, l) \ |
|
60 |
+ do { \ |
|
61 |
+ r = crc32(~c, b, l); \ |
|
62 |
+ r = ~r; \ |
|
63 |
+ } while (0) |
|
64 | 64 |
|
65 |
- |
|
66 |
-static int wrap_inflateinit2(void *a, int b) { |
|
67 |
- return inflateInit2(a, b); |
|
65 |
+static int wrap_inflateinit2(void *a, int b) |
|
66 |
+{ |
|
67 |
+ return inflateInit2(a, b); |
|
68 | 68 |
} |
69 | 69 |
|
70 |
-static int unz(const uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, uint16_t flags, unsigned int *fu, cli_ctx *ctx, char *tmpd, zip_cb zcb) { |
|
71 |
- char name[1024], obuf[BUFSIZ]; |
|
72 |
- char *tempfile = name; |
|
73 |
- int of, ret=CL_CLEAN; |
|
74 |
- unsigned int res=1, written=0; |
|
75 |
- |
|
76 |
- if(tmpd) { |
|
77 |
- snprintf(name, sizeof(name), "%s"PATHSEP"zip.%03u", tmpd, *fu); |
|
78 |
- name[sizeof(name)-1]='\0'; |
|
79 |
- } else { |
|
80 |
- if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM; |
|
81 |
- } |
|
82 |
- if((of = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR))==-1) { |
|
83 |
- cli_warnmsg("cli_unzip: failed to create temporary file %s\n", tempfile); |
|
84 |
- if(!tmpd) free(tempfile); |
|
85 |
- return CL_ETMPFILE; |
|
86 |
- } |
|
87 |
- switch (method) { |
|
88 |
- case ALG_STORED: |
|
89 |
- if(csize<usize) { |
|
90 |
- unsigned int fake = *fu + 1; |
|
91 |
- cli_dbgmsg("cli_unzip: attempting to inflate stored file with inconsistent size\n"); |
|
92 |
- if ((ret=unz(src, csize, usize, ALG_DEFLATE, 0, &fake, ctx, tmpd, zcb))==CL_CLEAN) { |
|
93 |
- (*fu)++; |
|
94 |
- res=fake-(*fu); |
|
95 |
- } |
|
96 |
- else break; |
|
97 |
- } |
|
98 |
- if(res==1) { |
|
99 |
- if(ctx->engine->maxfilesize && csize > ctx->engine->maxfilesize) { |
|
100 |
- cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (long unsigned int) ctx->engine->maxfilesize); |
|
101 |
- csize = ctx->engine->maxfilesize; |
|
102 |
- } |
|
103 |
- if(cli_writen(of, src, csize)!=(int)csize) ret = CL_EWRITE; |
|
104 |
- else res=0; |
|
105 |
- } |
|
106 |
- break; |
|
107 |
- |
|
108 |
- case ALG_DEFLATE: |
|
109 |
- case ALG_DEFLATE64: { |
|
110 |
- union { |
|
111 |
- z_stream64 strm64; |
|
112 |
- z_stream strm; |
|
113 |
- } strm; |
|
114 |
- typedef int (*unz_init_) (void *, int); |
|
115 |
- typedef int (*unz_unz_) (void *, int); |
|
116 |
- typedef int (*unz_end_) (void *); |
|
117 |
- unz_init_ unz_init; |
|
118 |
- unz_unz_ unz_unz; |
|
119 |
- unz_end_ unz_end; |
|
120 |
- int wbits; |
|
121 |
- void **next_in; |
|
122 |
- void **next_out; |
|
123 |
- unsigned int *avail_in; |
|
124 |
- unsigned int *avail_out; |
|
125 |
- |
|
126 |
- if(method == ALG_DEFLATE64) { |
|
127 |
- unz_init = (unz_init_)inflate64Init2; |
|
128 |
- unz_unz = (unz_unz_)inflate64; |
|
129 |
- unz_end = (unz_end_)inflate64End; |
|
130 |
- next_in = (void *)&strm.strm64.next_in; |
|
131 |
- next_out = (void *)&strm.strm64.next_out; |
|
132 |
- avail_in = &strm.strm64.avail_in; |
|
133 |
- avail_out = &strm.strm64.avail_out; |
|
134 |
- wbits=MAX_WBITS64; |
|
70 |
+static int unz(const uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, uint16_t flags, unsigned int *fu, cli_ctx *ctx, char *tmpd, zip_cb zcb) |
|
71 |
+{ |
|
72 |
+ char name[1024], obuf[BUFSIZ]; |
|
73 |
+ char *tempfile = name; |
|
74 |
+ int of, ret = CL_CLEAN; |
|
75 |
+ unsigned int res = 1, written = 0; |
|
76 |
+ |
|
77 |
+ if (tmpd) { |
|
78 |
+ snprintf(name, sizeof(name), "%s" PATHSEP "zip.%03u", tmpd, *fu); |
|
79 |
+ name[sizeof(name) - 1] = '\0'; |
|
135 | 80 |
} else { |
136 |
- unz_init = (unz_init_)wrap_inflateinit2; |
|
137 |
- unz_unz = (unz_unz_)inflate; |
|
138 |
- unz_end = (unz_end_)inflateEnd; |
|
139 |
- next_in = (void *)&strm.strm.next_in; |
|
140 |
- next_out = (void *)&strm.strm.next_out; |
|
141 |
- avail_in = &strm.strm.avail_in; |
|
142 |
- avail_out = &strm.strm.avail_out; |
|
143 |
- wbits=MAX_WBITS; |
|
144 |
- } |
|
145 |
- |
|
146 |
- memset(&strm, 0, sizeof(strm)); |
|
147 |
- |
|
148 |
- *next_in = (void*) src; |
|
149 |
- *next_out = obuf; |
|
150 |
- *avail_in = csize; |
|
151 |
- *avail_out = sizeof(obuf); |
|
152 |
- if (unz_init(&strm, -wbits)!=Z_OK) { |
|
153 |
- cli_dbgmsg("cli_unzip: zinit failed\n"); |
|
154 |
- break; |
|
155 |
- } |
|
156 |
- while(1) { |
|
157 |
- while((res = unz_unz(&strm, Z_NO_FLUSH))==Z_OK) {}; |
|
158 |
- if(*avail_out!=sizeof(obuf)) { |
|
159 |
- written+=sizeof(obuf)-(*avail_out); |
|
160 |
- if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) { |
|
161 |
- cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (long unsigned int) ctx->engine->maxfilesize); |
|
162 |
- res = Z_STREAM_END; |
|
163 |
- break; |
|
164 |
- } |
|
165 |
- if(cli_writen(of, obuf, sizeof(obuf)-(*avail_out)) != (int)(sizeof(obuf)-(*avail_out))) { |
|
166 |
- cli_warnmsg("cli_unzip: falied to write %lu inflated bytes\n", (unsigned long int)sizeof(obuf)-(*avail_out)); |
|
167 |
- ret = CL_EWRITE; |
|
168 |
- res = 100; |
|
169 |
- break; |
|
170 |
- } |
|
171 |
- *next_out = obuf; |
|
172 |
- *avail_out = sizeof(obuf); |
|
173 |
- continue; |
|
174 |
- } |
|
175 |
- break; |
|
176 |
- } |
|
177 |
- unz_end(&strm); |
|
178 |
- if ((res == Z_STREAM_END) | (res == Z_BUF_ERROR)) res=0; |
|
179 |
- break; |
|
180 |
- } |
|
81 |
+ if (!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM; |
|
82 |
+ } |
|
83 |
+ if ((of = open(tempfile, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR)) == -1) { |
|
84 |
+ cli_warnmsg("cli_unzip: failed to create temporary file %s\n", tempfile); |
|
85 |
+ if (!tmpd) free(tempfile); |
|
86 |
+ return CL_ETMPFILE; |
|
87 |
+ } |
|
88 |
+ switch (method) { |
|
89 |
+ case ALG_STORED: |
|
90 |
+ if (csize < usize) { |
|
91 |
+ unsigned int fake = *fu + 1; |
|
92 |
+ cli_dbgmsg("cli_unzip: attempting to inflate stored file with inconsistent size\n"); |
|
93 |
+ if ((ret = unz(src, csize, usize, ALG_DEFLATE, 0, &fake, ctx, tmpd, zcb)) == CL_CLEAN) { |
|
94 |
+ (*fu)++; |
|
95 |
+ res = fake - (*fu); |
|
96 |
+ } else |
|
97 |
+ break; |
|
98 |
+ } |
|
99 |
+ if (res == 1) { |
|
100 |
+ if (ctx->engine->maxfilesize && csize > ctx->engine->maxfilesize) { |
|
101 |
+ cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (long unsigned int)ctx->engine->maxfilesize); |
|
102 |
+ csize = ctx->engine->maxfilesize; |
|
103 |
+ } |
|
104 |
+ if (cli_writen(of, src, csize) != (int)csize) |
|
105 |
+ ret = CL_EWRITE; |
|
106 |
+ else |
|
107 |
+ res = 0; |
|
108 |
+ } |
|
109 |
+ break; |
|
181 | 110 |
|
111 |
+ case ALG_DEFLATE: |
|
112 |
+ case ALG_DEFLATE64: { |
|
113 |
+ union { |
|
114 |
+ z_stream64 strm64; |
|
115 |
+ z_stream strm; |
|
116 |
+ } strm; |
|
117 |
+ typedef int (*unz_init_)(void *, int); |
|
118 |
+ typedef int (*unz_unz_)(void *, int); |
|
119 |
+ typedef int (*unz_end_)(void *); |
|
120 |
+ unz_init_ unz_init; |
|
121 |
+ unz_unz_ unz_unz; |
|
122 |
+ unz_end_ unz_end; |
|
123 |
+ int wbits; |
|
124 |
+ void **next_in; |
|
125 |
+ void **next_out; |
|
126 |
+ unsigned int *avail_in; |
|
127 |
+ unsigned int *avail_out; |
|
128 |
+ |
|
129 |
+ if (method == ALG_DEFLATE64) { |
|
130 |
+ unz_init = (unz_init_)inflate64Init2; |
|
131 |
+ unz_unz = (unz_unz_)inflate64; |
|
132 |
+ unz_end = (unz_end_)inflate64End; |
|
133 |
+ next_in = (void *)&strm.strm64.next_in; |
|
134 |
+ next_out = (void *)&strm.strm64.next_out; |
|
135 |
+ avail_in = &strm.strm64.avail_in; |
|
136 |
+ avail_out = &strm.strm64.avail_out; |
|
137 |
+ wbits = MAX_WBITS64; |
|
138 |
+ } else { |
|
139 |
+ unz_init = (unz_init_)wrap_inflateinit2; |
|
140 |
+ unz_unz = (unz_unz_)inflate; |
|
141 |
+ unz_end = (unz_end_)inflateEnd; |
|
142 |
+ next_in = (void *)&strm.strm.next_in; |
|
143 |
+ next_out = (void *)&strm.strm.next_out; |
|
144 |
+ avail_in = &strm.strm.avail_in; |
|
145 |
+ avail_out = &strm.strm.avail_out; |
|
146 |
+ wbits = MAX_WBITS; |
|
147 |
+ } |
|
148 |
+ |
|
149 |
+ memset(&strm, 0, sizeof(strm)); |
|
150 |
+ |
|
151 |
+ *next_in = (void *)src; |
|
152 |
+ *next_out = obuf; |
|
153 |
+ *avail_in = csize; |
|
154 |
+ *avail_out = sizeof(obuf); |
|
155 |
+ if (unz_init(&strm, -wbits) != Z_OK) { |
|
156 |
+ cli_dbgmsg("cli_unzip: zinit failed\n"); |
|
157 |
+ break; |
|
158 |
+ } |
|
159 |
+ while (1) { |
|
160 |
+ while ((res = unz_unz(&strm, Z_NO_FLUSH)) == Z_OK) { |
|
161 |
+ }; |
|
162 |
+ if (*avail_out != sizeof(obuf)) { |
|
163 |
+ written += sizeof(obuf) - (*avail_out); |
|
164 |
+ if (ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) { |
|
165 |
+ cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (long unsigned int)ctx->engine->maxfilesize); |
|
166 |
+ res = Z_STREAM_END; |
|
167 |
+ break; |
|
168 |
+ } |
|
169 |
+ if (cli_writen(of, obuf, sizeof(obuf) - (*avail_out)) != (int)(sizeof(obuf) - (*avail_out))) { |
|
170 |
+ cli_warnmsg("cli_unzip: falied to write %lu inflated bytes\n", (unsigned long int)sizeof(obuf) - (*avail_out)); |
|
171 |
+ ret = CL_EWRITE; |
|
172 |
+ res = 100; |
|
173 |
+ break; |
|
174 |
+ } |
|
175 |
+ *next_out = obuf; |
|
176 |
+ *avail_out = sizeof(obuf); |
|
177 |
+ continue; |
|
178 |
+ } |
|
179 |
+ break; |
|
180 |
+ } |
|
181 |
+ unz_end(&strm); |
|
182 |
+ if ((res == Z_STREAM_END) | (res == Z_BUF_ERROR)) res = 0; |
|
183 |
+ break; |
|
184 |
+ } |
|
182 | 185 |
|
183 | 186 |
#if HAVE_BZLIB_H |
184 | 187 |
#ifdef NOBZ2PREFIX |
... | ... |
@@ -187,131 +190,129 @@ static int unz(const uint8_t *src, uint32_t csize, uint32_t usize, uint16_t meth |
187 | 187 |
#define BZ2_bzDecompressInit bzDecompressInit |
188 | 188 |
#endif |
189 | 189 |
|
190 |
- case ALG_BZIP2: { |
|
191 |
- bz_stream strm; |
|
192 |
- memset(&strm, 0, sizeof(strm)); |
|
193 |
- strm.next_in = (char *)src; |
|
194 |
- strm.next_out = obuf; |
|
195 |
- strm.avail_in = csize; |
|
196 |
- strm.avail_out = sizeof(obuf); |
|
197 |
- if (BZ2_bzDecompressInit(&strm, 0, 0)!=BZ_OK) { |
|
198 |
- cli_dbgmsg("cli_unzip: bzinit failed\n"); |
|
199 |
- break; |
|
200 |
- } |
|
201 |
- while((res = BZ2_bzDecompress(&strm))==BZ_OK || res==BZ_STREAM_END) { |
|
202 |
- if(strm.avail_out!=sizeof(obuf)) { |
|
203 |
- written+=sizeof(obuf)-strm.avail_out; |
|
204 |
- if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) { |
|
205 |
- cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (unsigned long int) ctx->engine->maxfilesize); |
|
206 |
- res = BZ_STREAM_END; |
|
207 |
- break; |
|
208 |
- } |
|
209 |
- if(cli_writen(of, obuf, sizeof(obuf)-strm.avail_out) != (int)(sizeof(obuf)-strm.avail_out)) { |
|
210 |
- cli_warnmsg("cli_unzip: falied to write %lu bunzipped bytes\n", (long unsigned int)sizeof(obuf)-strm.avail_out); |
|
211 |
- ret = CL_EWRITE; |
|
212 |
- res = 100; |
|
213 |
- break; |
|
214 |
- } |
|
215 |
- strm.next_out = obuf; |
|
216 |
- strm.avail_out = sizeof(obuf); |
|
217 |
- if (res == BZ_OK) continue; /* after returning BZ_STREAM_END once, decompress returns an error */ |
|
218 |
- } |
|
219 |
- break; |
|
220 |
- } |
|
221 |
- BZ2_bzDecompressEnd(&strm); |
|
222 |
- if (res == BZ_STREAM_END) res=0; |
|
223 |
- break; |
|
224 |
- } |
|
190 |
+ case ALG_BZIP2: { |
|
191 |
+ bz_stream strm; |
|
192 |
+ memset(&strm, 0, sizeof(strm)); |
|
193 |
+ strm.next_in = (char *)src; |
|
194 |
+ strm.next_out = obuf; |
|
195 |
+ strm.avail_in = csize; |
|
196 |
+ strm.avail_out = sizeof(obuf); |
|
197 |
+ if (BZ2_bzDecompressInit(&strm, 0, 0) != BZ_OK) { |
|
198 |
+ cli_dbgmsg("cli_unzip: bzinit failed\n"); |
|
199 |
+ break; |
|
200 |
+ } |
|
201 |
+ while ((res = BZ2_bzDecompress(&strm)) == BZ_OK || res == BZ_STREAM_END) { |
|
202 |
+ if (strm.avail_out != sizeof(obuf)) { |
|
203 |
+ written += sizeof(obuf) - strm.avail_out; |
|
204 |
+ if (ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) { |
|
205 |
+ cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (unsigned long int)ctx->engine->maxfilesize); |
|
206 |
+ res = BZ_STREAM_END; |
|
207 |
+ break; |
|
208 |
+ } |
|
209 |
+ if (cli_writen(of, obuf, sizeof(obuf) - strm.avail_out) != (int)(sizeof(obuf) - strm.avail_out)) { |
|
210 |
+ cli_warnmsg("cli_unzip: falied to write %lu bunzipped bytes\n", (long unsigned int)sizeof(obuf) - strm.avail_out); |
|
211 |
+ ret = CL_EWRITE; |
|
212 |
+ res = 100; |
|
213 |
+ break; |
|
214 |
+ } |
|
215 |
+ strm.next_out = obuf; |
|
216 |
+ strm.avail_out = sizeof(obuf); |
|
217 |
+ if (res == BZ_OK) continue; /* after returning BZ_STREAM_END once, decompress returns an error */ |
|
218 |
+ } |
|
219 |
+ break; |
|
220 |
+ } |
|
221 |
+ BZ2_bzDecompressEnd(&strm); |
|
222 |
+ if (res == BZ_STREAM_END) res = 0; |
|
223 |
+ break; |
|
224 |
+ } |
|
225 | 225 |
#endif /* HAVE_BZLIB_H */ |
226 | 226 |
|
227 |
+ case ALG_IMPLODE: { |
|
228 |
+ struct xplstate strm; |
|
229 |
+ strm.next_in = (void *)src; |
|
230 |
+ strm.next_out = (uint8_t *)obuf; |
|
231 |
+ strm.avail_in = csize; |
|
232 |
+ strm.avail_out = sizeof(obuf); |
|
233 |
+ if (explode_init(&strm, flags) != EXPLODE_OK) { |
|
234 |
+ cli_dbgmsg("cli_unzip: explode_init() failed\n"); |
|
235 |
+ break; |
|
236 |
+ } |
|
237 |
+ while ((res = explode(&strm)) == EXPLODE_OK) { |
|
238 |
+ if (strm.avail_out != sizeof(obuf)) { |
|
239 |
+ written += sizeof(obuf) - strm.avail_out; |
|
240 |
+ if (ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) { |
|
241 |
+ cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (unsigned long int)ctx->engine->maxfilesize); |
|
242 |
+ res = 0; |
|
243 |
+ break; |
|
244 |
+ } |
|
245 |
+ if (cli_writen(of, obuf, sizeof(obuf) - strm.avail_out) != (int)(sizeof(obuf) - strm.avail_out)) { |
|
246 |
+ cli_warnmsg("cli_unzip: falied to write %lu exploded bytes\n", (unsigned long int)sizeof(obuf) - strm.avail_out); |
|
247 |
+ ret = CL_EWRITE; |
|
248 |
+ res = 100; |
|
249 |
+ break; |
|
250 |
+ } |
|
251 |
+ strm.next_out = (uint8_t *)obuf; |
|
252 |
+ strm.avail_out = sizeof(obuf); |
|
253 |
+ continue; |
|
254 |
+ } |
|
255 |
+ break; |
|
256 |
+ } |
|
257 |
+ break; |
|
258 |
+ } |
|
227 | 259 |
|
228 |
- case ALG_IMPLODE: { |
|
229 |
- struct xplstate strm; |
|
230 |
- strm.next_in = (void*)src; |
|
231 |
- strm.next_out = (uint8_t *)obuf; |
|
232 |
- strm.avail_in = csize; |
|
233 |
- strm.avail_out = sizeof(obuf); |
|
234 |
- if (explode_init(&strm, flags)!=EXPLODE_OK) { |
|
235 |
- cli_dbgmsg("cli_unzip: explode_init() failed\n"); |
|
236 |
- break; |
|
237 |
- } |
|
238 |
- while((res = explode(&strm))==EXPLODE_OK) { |
|
239 |
- if(strm.avail_out!=sizeof(obuf)) { |
|
240 |
- written+=sizeof(obuf)-strm.avail_out; |
|
241 |
- if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) { |
|
242 |
- cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (unsigned long int) ctx->engine->maxfilesize); |
|
243 |
- res = 0; |
|
244 |
- break; |
|
245 |
- } |
|
246 |
- if(cli_writen(of, obuf, sizeof(obuf)-strm.avail_out) != (int)(sizeof(obuf)-strm.avail_out)) { |
|
247 |
- cli_warnmsg("cli_unzip: falied to write %lu exploded bytes\n", (unsigned long int) sizeof(obuf)-strm.avail_out); |
|
248 |
- ret = CL_EWRITE; |
|
249 |
- res = 100; |
|
250 |
- break; |
|
251 |
- } |
|
252 |
- strm.next_out = (uint8_t *)obuf; |
|
253 |
- strm.avail_out = sizeof(obuf); |
|
254 |
- continue; |
|
255 |
- } |
|
256 |
- break; |
|
257 |
- } |
|
258 |
- break; |
|
259 |
- } |
|
260 |
- |
|
261 |
- |
|
262 |
- case ALG_LZMA: |
|
263 |
- /* easy but there's not a single sample in the zoo */ |
|
260 |
+ case ALG_LZMA: |
|
261 |
+ /* easy but there's not a single sample in the zoo */ |
|
264 | 262 |
|
265 | 263 |
#if !HAVE_BZLIB_H |
266 |
- case ALG_BZIP2: |
|
264 |
+ case ALG_BZIP2: |
|
267 | 265 |
#endif |
268 |
- case ALG_SHRUNK: |
|
269 |
- case ALG_REDUCE1: |
|
270 |
- case ALG_REDUCE2: |
|
271 |
- case ALG_REDUCE3: |
|
272 |
- case ALG_REDUCE4: |
|
273 |
- case ALG_TOKENZD: |
|
274 |
- case ALG_OLDTERSE: |
|
275 |
- case ALG_RSVD1: |
|
276 |
- case ALG_RSVD2: |
|
277 |
- case ALG_RSVD3: |
|
278 |
- case ALG_RSVD4: |
|
279 |
- case ALG_RSVD5: |
|
280 |
- case ALG_NEWTERSE: |
|
281 |
- case ALG_LZ77: |
|
282 |
- case ALG_WAVPACK: |
|
283 |
- case ALG_PPMD: |
|
284 |
- cli_dbgmsg("cli_unzip: unsupported method (%d)\n", method); |
|
285 |
- break; |
|
286 |
- default: |
|
287 |
- cli_dbgmsg("cli_unzip: unknown method (%d)\n", method); |
|
288 |
- break; |
|
289 |
- } |
|
290 |
- |
|
291 |
- if(!res) { |
|
292 |
- (*fu)++; |
|
293 |
- cli_dbgmsg("cli_unzip: extracted to %s\n", tempfile); |
|
294 |
- if (lseek(of, 0, SEEK_SET) == -1) { |
|
295 |
- cli_dbgmsg("cli_unzip: call to lseek() failed\n"); |
|
296 |
- if (!(tmpd)) |
|
297 |
- free(tempfile); |
|
266 |
+ case ALG_SHRUNK: |
|
267 |
+ case ALG_REDUCE1: |
|
268 |
+ case ALG_REDUCE2: |
|
269 |
+ case ALG_REDUCE3: |
|
270 |
+ case ALG_REDUCE4: |
|
271 |
+ case ALG_TOKENZD: |
|
272 |
+ case ALG_OLDTERSE: |
|
273 |
+ case ALG_RSVD1: |
|
274 |
+ case ALG_RSVD2: |
|
275 |
+ case ALG_RSVD3: |
|
276 |
+ case ALG_RSVD4: |
|
277 |
+ case ALG_RSVD5: |
|
278 |
+ case ALG_NEWTERSE: |
|
279 |
+ case ALG_LZ77: |
|
280 |
+ case ALG_WAVPACK: |
|
281 |
+ case ALG_PPMD: |
|
282 |
+ cli_dbgmsg("cli_unzip: unsupported method (%d)\n", method); |
|
283 |
+ break; |
|
284 |
+ default: |
|
285 |
+ cli_dbgmsg("cli_unzip: unknown method (%d)\n", method); |
|
286 |
+ break; |
|
287 |
+ } |
|
288 |
+ |
|
289 |
+ if (!res) { |
|
290 |
+ (*fu)++; |
|
291 |
+ cli_dbgmsg("cli_unzip: extracted to %s\n", tempfile); |
|
292 |
+ if (lseek(of, 0, SEEK_SET) == -1) { |
|
293 |
+ cli_dbgmsg("cli_unzip: call to lseek() failed\n"); |
|
294 |
+ if (!(tmpd)) |
|
295 |
+ free(tempfile); |
|
296 |
+ close(of); |
|
297 |
+ return CL_ESEEK; |
|
298 |
+ } |
|
299 |
+ ret = zcb(of, tempfile, ctx); |
|
298 | 300 |
close(of); |
299 |
- return CL_ESEEK; |
|
301 |
+ if (!ctx->engine->keeptmp) |
|
302 |
+ if (cli_unlink(tempfile)) ret = CL_EUNLINK; |
|
303 |
+ if (!tmpd) free(tempfile); |
|
304 |
+ return ret; |
|
300 | 305 |
} |
301 |
- ret = zcb(of, tempfile, ctx); |
|
306 |
+ |
|
302 | 307 |
close(of); |
303 |
- if(!ctx->engine->keeptmp) |
|
304 |
- if(cli_unlink(tempfile)) ret = CL_EUNLINK; |
|
305 |
- if(!tmpd) free(tempfile); |
|
308 |
+ if (!ctx->engine->keeptmp) |
|
309 |
+ if (cli_unlink(tempfile)) ret = CL_EUNLINK; |
|
310 |
+ if (!tmpd) free(tempfile); |
|
311 |
+ cli_dbgmsg("cli_unzip: extraction failed\n"); |
|
306 | 312 |
return ret; |
307 |
- } |
|
308 |
- |
|
309 |
- close(of); |
|
310 |
- if(!ctx->engine->keeptmp) |
|
311 |
- if(cli_unlink(tempfile)) ret = CL_EUNLINK; |
|
312 |
- if(!tmpd) free(tempfile); |
|
313 |
- cli_dbgmsg("cli_unzip: extraction failed\n"); |
|
314 |
- return ret; |
|
315 | 313 |
} |
316 | 314 |
|
317 | 315 |
/* zip update keys, taken from zip specification */ |
... | ... |
@@ -342,7 +343,7 @@ static inline void zinitkey(uint32_t key[3], struct cli_pwdb *password) |
342 | 342 |
|
343 | 343 |
/* update keys with password */ |
344 | 344 |
for (i = 0; i < password->length; i++) |
345 |
- zupdatekey(key, password->passwd[i]); |
|
345 |
+ zupdatekey(key, password->passwd[i]); |
|
346 | 346 |
} |
347 | 347 |
|
348 | 348 |
/* zip decrypt byte */ |
... | ... |
@@ -363,522 +364,533 @@ static inline int zdecrypt(const uint8_t *src, uint32_t csize, uint32_t usize, c |
363 | 363 |
struct cli_pwdb *password, *pass_any, *pass_zip; |
364 | 364 |
|
365 | 365 |
if (!ctx || !ctx->engine) |
366 |
- return CL_ENULLARG; |
|
366 |
+ return CL_ENULLARG; |
|
367 | 367 |
|
368 | 368 |
/* dconf */ |
369 | 369 |
if (ctx->dconf && !(ctx->dconf->archive & ARCH_CONF_PASSWD)) { |
370 |
- cli_dbgmsg("cli_unzip: decrypt - skipping encrypted file\n"); |
|
371 |
- return CL_SUCCESS; |
|
370 |
+ cli_dbgmsg("cli_unzip: decrypt - skipping encrypted file\n"); |
|
371 |
+ return CL_SUCCESS; |
|
372 | 372 |
} |
373 | 373 |
|
374 | 374 |
pass_any = ctx->engine->pwdbs[CLI_PWDB_ANY]; |
375 | 375 |
pass_zip = ctx->engine->pwdbs[CLI_PWDB_ZIP]; |
376 | 376 |
|
377 | 377 |
while (pass_any || pass_zip) { |
378 |
- password = pass_zip ? pass_zip : pass_any; |
|
379 |
- |
|
380 |
- zinitkey(key, password); |
|
381 |
- |
|
382 |
- /* decrypting the encryption header */ |
|
383 |
- memcpy(eh, src, SIZEOF_EH); |
|
384 |
- |
|
385 |
- for (i = 0; i < SIZEOF_EH; i++) { |
|
386 |
- eh[i] ^= zdecryptbyte(key); |
|
387 |
- zupdatekey(key, eh[i]); |
|
388 |
- } |
|
389 |
- |
|
390 |
- /* verify that the password is correct */ |
|
391 |
- if (LH_version > 20) { /* higher than 2.0 */ |
|
392 |
- uint16_t a = eh[SIZEOF_EH-1]; |
|
393 |
- |
|
394 |
- if (LH_flags & F_USEDD) { |
|
395 |
- cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x%02x 0x%x (moddate)\n", LH_version, a, LH_mtime); |
|
396 |
- if (a == ((LH_mtime >> 8) & 0xff)) |
|
397 |
- v = 1; |
|
398 |
- } else { |
|
399 |
- cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x%02x 0x%x (crc32)\n", LH_version, a, LH_crc32); |
|
400 |
- if (a == ((LH_crc32 >> 24) & 0xff)) |
|
401 |
- v = 1; |
|
402 |
- } |
|
403 |
- } else { |
|
404 |
- uint16_t a = eh[SIZEOF_EH-1], b = eh[SIZEOF_EH-2]; |
|
405 |
- |
|
406 |
- if (LH_flags & F_USEDD) { |
|
407 |
- cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x0000%02x%02x 0x%x (moddate)\n", LH_version, a, b, LH_mtime); |
|
408 |
- if ((b | (a << 8)) == (LH_mtime & 0xffff)) |
|
409 |
- v = 1; |
|
410 |
- } else { |
|
411 |
- cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x0000%02x%02x 0x%x (crc32)\n", LH_version, eh[SIZEOF_EH-1], eh[SIZEOF_EH-2], LH_crc32); |
|
412 |
- if ((b | (a << 8)) == ((LH_crc32 >> 16) & 0xffff)) |
|
413 |
- v = 1; |
|
414 |
- } |
|
415 |
- } |
|
416 |
- |
|
417 |
- if (v) { |
|
418 |
- char name[1024], obuf[BUFSIZ]; |
|
419 |
- char *tempfile = name; |
|
420 |
- unsigned int written = 0, total = 0; |
|
421 |
- fmap_t *dcypt_map; |
|
422 |
- const uint8_t *dcypt_zip; |
|
423 |
- int of; |
|
424 |
- |
|
425 |
- cli_dbgmsg("cli_unzip: decrypt - password [%s] matches\n", password->name); |
|
426 |
- |
|
427 |
- /* output decrypted data to tempfile */ |
|
428 |
- if(tmpd) { |
|
429 |
- snprintf(name, sizeof(name), "%s"PATHSEP"zip.decrypt.%03u", tmpd, *fu); |
|
430 |
- name[sizeof(name)-1]='\0'; |
|
431 |
- } else { |
|
432 |
- if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM; |
|
433 |
- } |
|
434 |
- if((of = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR))==-1) { |
|
435 |
- cli_warnmsg("cli_unzip: decrypt - failed to create temporary file %s\n", tempfile); |
|
436 |
- if(!tmpd) free(tempfile); |
|
437 |
- return CL_ETMPFILE; |
|
438 |
- } |
|
439 |
- |
|
440 |
- for (i = 12; i < csize; i++) { |
|
441 |
- obuf[written] = src[i] ^ zdecryptbyte(key); |
|
442 |
- zupdatekey(key, obuf[written]); |
|
443 |
- |
|
444 |
- written++; |
|
445 |
- if (written >= BUFSIZ) { |
|
446 |
- if (cli_writen(of, obuf, written)!=(int)written) { |
|
447 |
- ret = CL_EWRITE; |
|
448 |
- goto zd_clean; |
|
449 |
- } |
|
450 |
- total += written; |
|
451 |
- written = 0; |
|
452 |
- } |
|
453 |
- } |
|
454 |
- if (written) { |
|
455 |
- if (cli_writen(of, obuf, written)!=(int)written) { |
|
456 |
- ret = CL_EWRITE; |
|
457 |
- goto zd_clean; |
|
458 |
- } |
|
459 |
- total += written; |
|
460 |
- written = 0; |
|
461 |
- } |
|
462 |
- |
|
463 |
- cli_dbgmsg("cli_unzip: decrypt - decrypted %u bytes to %s\n", total, tempfile); |
|
464 |
- |
|
465 |
- /* decrypt data to new fmap -> buffer */ |
|
466 |
- if (!(dcypt_map = fmap(of, 0, total))) { |
|
467 |
- cli_warnmsg("cli_unzip: decrypt - failed to create fmap on decrypted file %s\n", tempfile); |
|
468 |
- ret = CL_EMAP; |
|
469 |
- goto zd_clean; |
|
470 |
- } |
|
471 |
- |
|
472 |
- if (!(dcypt_zip = fmap_need_off_once(dcypt_map, 0, total))) { |
|
473 |
- cli_warnmsg("cli_unzip: decrypt - failed to acquire buffer on decrypted file %s\n", tempfile); |
|
474 |
- funmap(dcypt_map); |
|
475 |
- ret = CL_EREAD; |
|
476 |
- goto zd_clean; |
|
477 |
- } |
|
478 |
- |
|
479 |
- /* call unz on decrypted output */ |
|
480 |
- ret = unz(dcypt_zip, csize - SIZEOF_EH, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb); |
|
481 |
- |
|
482 |
- /* clean-up and return */ |
|
483 |
- funmap(dcypt_map); |
|
484 |
- zd_clean: |
|
485 |
- close(of); |
|
486 |
- if (!ctx->engine->keeptmp) |
|
378 |
+ password = pass_zip ? pass_zip : pass_any; |
|
379 |
+ |
|
380 |
+ zinitkey(key, password); |
|
381 |
+ |
|
382 |
+ /* decrypting the encryption header */ |
|
383 |
+ memcpy(eh, src, SIZEOF_EH); |
|
384 |
+ |
|
385 |
+ for (i = 0; i < SIZEOF_EH; i++) { |
|
386 |
+ eh[i] ^= zdecryptbyte(key); |
|
387 |
+ zupdatekey(key, eh[i]); |
|
388 |
+ } |
|
389 |
+ |
|
390 |
+ /* verify that the password is correct */ |
|
391 |
+ if (LH_version > 20) { /* higher than 2.0 */ |
|
392 |
+ uint16_t a = eh[SIZEOF_EH - 1]; |
|
393 |
+ |
|
394 |
+ if (LH_flags & F_USEDD) { |
|
395 |
+ cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x%02x 0x%x (moddate)\n", LH_version, a, LH_mtime); |
|
396 |
+ if (a == ((LH_mtime >> 8) & 0xff)) |
|
397 |
+ v = 1; |
|
398 |
+ } else { |
|
399 |
+ cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x%02x 0x%x (crc32)\n", LH_version, a, LH_crc32); |
|
400 |
+ if (a == ((LH_crc32 >> 24) & 0xff)) |
|
401 |
+ v = 1; |
|
402 |
+ } |
|
403 |
+ } else { |
|
404 |
+ uint16_t a = eh[SIZEOF_EH - 1], b = eh[SIZEOF_EH - 2]; |
|
405 |
+ |
|
406 |
+ if (LH_flags & F_USEDD) { |
|
407 |
+ cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x0000%02x%02x 0x%x (moddate)\n", LH_version, a, b, LH_mtime); |
|
408 |
+ if ((b | (a << 8)) == (LH_mtime & 0xffff)) |
|
409 |
+ v = 1; |
|
410 |
+ } else { |
|
411 |
+ cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x0000%02x%02x 0x%x (crc32)\n", LH_version, eh[SIZEOF_EH - 1], eh[SIZEOF_EH - 2], LH_crc32); |
|
412 |
+ if ((b | (a << 8)) == ((LH_crc32 >> 16) & 0xffff)) |
|
413 |
+ v = 1; |
|
414 |
+ } |
|
415 |
+ } |
|
416 |
+ |
|
417 |
+ if (v) { |
|
418 |
+ char name[1024], obuf[BUFSIZ]; |
|
419 |
+ char *tempfile = name; |
|
420 |
+ unsigned int written = 0, total = 0; |
|
421 |
+ fmap_t *dcypt_map; |
|
422 |
+ const uint8_t *dcypt_zip; |
|
423 |
+ int of; |
|
424 |
+ |
|
425 |
+ cli_dbgmsg("cli_unzip: decrypt - password [%s] matches\n", password->name); |
|
426 |
+ |
|
427 |
+ /* output decrypted data to tempfile */ |
|
428 |
+ if (tmpd) { |
|
429 |
+ snprintf(name, sizeof(name), "%s" PATHSEP "zip.decrypt.%03u", tmpd, *fu); |
|
430 |
+ name[sizeof(name) - 1] = '\0'; |
|
431 |
+ } else { |
|
432 |
+ if (!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM; |
|
433 |
+ } |
|
434 |
+ if ((of = open(tempfile, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR)) == -1) { |
|
435 |
+ cli_warnmsg("cli_unzip: decrypt - failed to create temporary file %s\n", tempfile); |
|
436 |
+ if (!tmpd) free(tempfile); |
|
437 |
+ return CL_ETMPFILE; |
|
438 |
+ } |
|
439 |
+ |
|
440 |
+ for (i = 12; i < csize; i++) { |
|
441 |
+ obuf[written] = src[i] ^ zdecryptbyte(key); |
|
442 |
+ zupdatekey(key, obuf[written]); |
|
443 |
+ |
|
444 |
+ written++; |
|
445 |
+ if (written >= BUFSIZ) { |
|
446 |
+ if (cli_writen(of, obuf, written) != (int)written) { |
|
447 |
+ ret = CL_EWRITE; |
|
448 |
+ goto zd_clean; |
|
449 |
+ } |
|
450 |
+ total += written; |
|
451 |
+ written = 0; |
|
452 |
+ } |
|
453 |
+ } |
|
454 |
+ if (written) { |
|
455 |
+ if (cli_writen(of, obuf, written) != (int)written) { |
|
456 |
+ ret = CL_EWRITE; |
|
457 |
+ goto zd_clean; |
|
458 |
+ } |
|
459 |
+ total += written; |
|
460 |
+ written = 0; |
|
461 |
+ } |
|
462 |
+ |
|
463 |
+ cli_dbgmsg("cli_unzip: decrypt - decrypted %u bytes to %s\n", total, tempfile); |
|
464 |
+ |
|
465 |
+ /* decrypt data to new fmap -> buffer */ |
|
466 |
+ if (!(dcypt_map = fmap(of, 0, total))) { |
|
467 |
+ cli_warnmsg("cli_unzip: decrypt - failed to create fmap on decrypted file %s\n", tempfile); |
|
468 |
+ ret = CL_EMAP; |
|
469 |
+ goto zd_clean; |
|
470 |
+ } |
|
471 |
+ |
|
472 |
+ if (!(dcypt_zip = fmap_need_off_once(dcypt_map, 0, total))) { |
|
473 |
+ cli_warnmsg("cli_unzip: decrypt - failed to acquire buffer on decrypted file %s\n", tempfile); |
|
474 |
+ funmap(dcypt_map); |
|
475 |
+ ret = CL_EREAD; |
|
476 |
+ goto zd_clean; |
|
477 |
+ } |
|
478 |
+ |
|
479 |
+ /* call unz on decrypted output */ |
|
480 |
+ ret = unz(dcypt_zip, csize - SIZEOF_EH, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb); |
|
481 |
+ |
|
482 |
+ /* clean-up and return */ |
|
483 |
+ funmap(dcypt_map); |
|
484 |
+ zd_clean: |
|
485 |
+ close(of); |
|
486 |
+ if (!ctx->engine->keeptmp) |
|
487 | 487 |
if (cli_unlink(tempfile)) { |
488 |
- if (!tmpd) free(tempfile); |
|
489 |
- return CL_EUNLINK; |
|
490 |
- } |
|
488 |
+ if (!tmpd) free(tempfile); |
|
489 |
+ return CL_EUNLINK; |
|
490 |
+ } |
|
491 | 491 |
if (!tmpd) free(tempfile); |
492 |
- return ret; |
|
493 |
- } |
|
492 |
+ return ret; |
|
493 |
+ } |
|
494 | 494 |
|
495 |
- if (pass_zip) |
|
496 |
- pass_zip = pass_zip->next; |
|
497 |
- else |
|
498 |
- pass_any = pass_any->next; |
|
495 |
+ if (pass_zip) |
|
496 |
+ pass_zip = pass_zip->next; |
|
497 |
+ else |
|
498 |
+ pass_any = pass_any->next; |
|
499 | 499 |
} |
500 | 500 |
|
501 | 501 |
cli_dbgmsg("cli_unzip: decrypt - skipping encrypted file, no valid passwords\n"); |
502 | 502 |
return CL_SUCCESS; |
503 | 503 |
} |
504 | 504 |
|
505 |
-static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int *fu, unsigned int fc, const uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd, int detect_encrypted, zip_cb zcb, uint32_t *file_local_header_size, uint32_t* file_local_data_size) { |
|
506 |
- const uint8_t *lh, *zip; |
|
507 |
- char name[256]; |
|
508 |
- uint32_t csize, usize; |
|
509 |
- int virus_found = 0; |
|
510 |
- |
|
511 |
- if(!(lh = fmap_need_off(map, loff, SIZEOF_LH))) { |
|
512 |
- cli_dbgmsg("cli_unzip: lh - out of file\n"); |
|
513 |
- return 0; |
|
514 |
- } |
|
515 |
- if(LH_magic != 0x04034b50) { |
|
516 |
- if (!ch) cli_dbgmsg("cli_unzip: lh - wrkcomplete\n"); |
|
517 |
- else cli_dbgmsg("cli_unzip: lh - bad magic\n"); |
|
518 |
- fmap_unneed_off(map, loff, SIZEOF_LH); |
|
519 |
- return 0; |
|
520 |
- } |
|
521 |
- |
|
522 |
- zip = lh + SIZEOF_LH; |
|
523 |
- zsize-=SIZEOF_LH; |
|
524 |
- |
|
525 |
- if(zsize<=LH_flen) { |
|
526 |
- cli_dbgmsg("cli_unzip: lh - fname out of file\n"); |
|
527 |
- fmap_unneed_off(map, loff, SIZEOF_LH); |
|
528 |
- return 0; |
|
529 |
- } |
|
530 |
- if(ctx->engine->cdb || cli_debug_flag) { |
|
531 |
- uint32_t nsize = (LH_flen>=sizeof(name))?sizeof(name)-1:LH_flen; |
|
532 |
- const char *src; |
|
533 |
- if(nsize && (src = fmap_need_ptr_once(map, zip, nsize))) { |
|
534 |
- memcpy(name, zip, nsize); |
|
535 |
- name[nsize]='\0'; |
|
536 |
- } else |
|
537 |
- name[0] = '\0'; |
|
538 |
- } |
|
539 |
- zip+=LH_flen; |
|
540 |
- zsize-=LH_flen; |
|
541 |
- |
|
542 |
- cli_dbgmsg("cli_unzip: lh - ZMDNAME:%d:%s:%u:%u:%x:%u:%u:%u\n", ((LH_flags & F_ENCR)!=0), name, LH_usize, LH_csize, LH_crc32, LH_method, fc, ctx->recursion); |
|
543 |
- /* ZMDfmt virname:encrypted(0-1):filename(exact|*):usize(exact|*):csize(exact|*):crc32(exact|*):method(exact|*):fileno(exact|*):maxdepth(exact|*) */ |
|
544 |
- |
|
545 |
- if(cli_matchmeta(ctx, name, LH_csize, LH_usize, (LH_flags & F_ENCR)!=0, fc, LH_crc32, NULL) == CL_VIRUS) { |
|
546 |
- *ret = CL_VIRUS; |
|
547 |
- if (!SCAN_ALLMATCHES) |
|
548 |
- return 0; |
|
549 |
- virus_found = 1; |
|
550 |
- } |
|
551 |
- |
|
552 |
- if(LH_flags & F_MSKED) { |
|
553 |
- cli_dbgmsg("cli_unzip: lh - header has got unusable masked data\n"); |
|
554 |
- /* FIXME: need to find/craft a sample */ |
|
555 |
- fmap_unneed_off(map, loff, SIZEOF_LH); |
|
556 |
- return 0; |
|
557 |
- } |
|
558 |
- |
|
559 |
- if(detect_encrypted && (LH_flags & F_ENCR) && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) { |
|
560 |
- cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n"); |
|
561 |
- *ret = cli_append_virus(ctx, "Heuristics.Encrypted.Zip"); |
|
562 |
- if ((*ret == CL_VIRUS && !SCAN_ALLMATCHES) || *ret != CL_CLEAN) { |
|
505 |
+static unsigned int lhdr(fmap_t *map, uint32_t loff, uint32_t zsize, unsigned int *fu, unsigned int fc, const uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd, int detect_encrypted, zip_cb zcb, uint32_t *file_local_header_size, uint32_t *file_local_data_size) |
|
506 |
+{ |
|
507 |
+ const uint8_t *lh, *zip; |
|
508 |
+ char name[256]; |
|
509 |
+ uint32_t csize, usize; |
|
510 |
+ int virus_found = 0; |
|
511 |
+ |
|
512 |
+ if (!(lh = fmap_need_off(map, loff, SIZEOF_LH))) { |
|
513 |
+ cli_dbgmsg("cli_unzip: lh - out of file\n"); |
|
514 |
+ return 0; |
|
515 |
+ } |
|
516 |
+ if (LH_magic != 0x04034b50) { |
|
517 |
+ if (!ch) |
|
518 |
+ cli_dbgmsg("cli_unzip: lh - wrkcomplete\n"); |
|
519 |
+ else |
|
520 |
+ cli_dbgmsg("cli_unzip: lh - bad magic\n"); |
|
521 |
+ fmap_unneed_off(map, loff, SIZEOF_LH); |
|
522 |
+ return 0; |
|
523 |
+ } |
|
524 |
+ |
|
525 |
+ zip = lh + SIZEOF_LH; |
|
526 |
+ zsize -= SIZEOF_LH; |
|
527 |
+ |
|
528 |
+ if (zsize <= LH_flen) { |
|
529 |
+ cli_dbgmsg("cli_unzip: lh - fname out of file\n"); |
|
530 |
+ fmap_unneed_off(map, loff, SIZEOF_LH); |
|
531 |
+ return 0; |
|
532 |
+ } |
|
533 |
+ if (ctx->engine->cdb || cli_debug_flag) { |
|
534 |
+ uint32_t nsize = (LH_flen >= sizeof(name)) ? sizeof(name) - 1 : LH_flen; |
|
535 |
+ const char *src; |
|
536 |
+ if (nsize && (src = fmap_need_ptr_once(map, zip, nsize))) { |
|
537 |
+ memcpy(name, zip, nsize); |
|
538 |
+ name[nsize] = '\0'; |
|
539 |
+ } else |
|
540 |
+ name[0] = '\0'; |
|
541 |
+ } |
|
542 |
+ zip += LH_flen; |
|
543 |
+ zsize -= LH_flen; |
|
544 |
+ |
|
545 |
+ cli_dbgmsg("cli_unzip: lh - ZMDNAME:%d:%s:%u:%u:%x:%u:%u:%u\n", ((LH_flags & F_ENCR) != 0), name, LH_usize, LH_csize, LH_crc32, LH_method, fc, ctx->recursion); |
|
546 |
+ /* ZMDfmt virname:encrypted(0-1):filename(exact|*):usize(exact|*):csize(exact|*):crc32(exact|*):method(exact|*):fileno(exact|*):maxdepth(exact|*) */ |
|
547 |
+ |
|
548 |
+ if (cli_matchmeta(ctx, name, LH_csize, LH_usize, (LH_flags & F_ENCR) != 0, fc, LH_crc32, NULL) == CL_VIRUS) { |
|
549 |
+ *ret = CL_VIRUS; |
|
550 |
+ if (!SCAN_ALLMATCHES) |
|
551 |
+ return 0; |
|
552 |
+ virus_found = 1; |
|
553 |
+ } |
|
554 |
+ |
|
555 |
+ if (LH_flags & F_MSKED) { |
|
556 |
+ cli_dbgmsg("cli_unzip: lh - header has got unusable masked data\n"); |
|
557 |
+ /* FIXME: need to find/craft a sample */ |
|
558 |
+ fmap_unneed_off(map, loff, SIZEOF_LH); |
|
559 |
+ return 0; |
|
560 |
+ } |
|
561 |
+ |
|
562 |
+ if (detect_encrypted && (LH_flags & F_ENCR) && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) { |
|
563 |
+ cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n"); |
|
564 |
+ *ret = cli_append_virus(ctx, "Heuristics.Encrypted.Zip"); |
|
565 |
+ if ((*ret == CL_VIRUS && !SCAN_ALLMATCHES) || *ret != CL_CLEAN) { |
|
566 |
+ fmap_unneed_off(map, loff, SIZEOF_LH); |
|
567 |
+ return 0; |
|
568 |
+ } |
|
569 |
+ virus_found = 1; |
|
570 |
+ } |
|
571 |
+ |
|
572 |
+ if (LH_flags & F_USEDD) { |
|
573 |
+ cli_dbgmsg("cli_unzip: lh - has data desc\n"); |
|
574 |
+ if (!ch) { |
|
575 |
+ fmap_unneed_off(map, loff, SIZEOF_LH); |
|
576 |
+ return 0; |
|
577 |
+ } else { |
|
578 |
+ usize = CH_usize; |
|
579 |
+ csize = CH_csize; |
|
580 |
+ } |
|
581 |
+ } else { |
|
582 |
+ usize = LH_usize; |
|
583 |
+ csize = LH_csize; |
|
584 |
+ } |
|
585 |
+ |
|
586 |
+ if (zsize <= LH_elen) { |
|
587 |
+ cli_dbgmsg("cli_unzip: lh - extra out of file\n"); |
|
563 | 588 |
fmap_unneed_off(map, loff, SIZEOF_LH); |
564 | 589 |
return 0; |
565 | 590 |
} |
566 |
- virus_found = 1; |
|
567 |
- } |
|
568 |
- |
|
569 |
- if(LH_flags & F_USEDD) { |
|
570 |
- cli_dbgmsg("cli_unzip: lh - has data desc\n"); |
|
571 |
- if(!ch) { |
|
572 |
- fmap_unneed_off(map, loff, SIZEOF_LH); |
|
573 |
- return 0; |
|
574 |
- } |
|
575 |
- else { usize = CH_usize; csize = CH_csize; } |
|
576 |
- } else { usize = LH_usize; csize = LH_csize; } |
|
577 |
- |
|
578 |
- if(zsize<=LH_elen) { |
|
579 |
- cli_dbgmsg("cli_unzip: lh - extra out of file\n"); |
|
580 |
- fmap_unneed_off(map, loff, SIZEOF_LH); |
|
581 |
- return 0; |
|
582 |
- } |
|
583 |
- zip+=LH_elen; |
|
584 |
- zsize-=LH_elen; |
|
585 |
- |
|
586 |
- if (NULL != file_local_header_size) |
|
587 |
- *file_local_header_size = zip - lh; |
|
588 |
- if (NULL != file_local_data_size) |
|
589 |
- *file_local_data_size = csize; |
|
590 |
- |
|
591 |
- if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */ |
|
592 |
- cli_dbgmsg("cli_unzip: lh - skipping empty file\n"); |
|
593 |
- } else { |
|
594 |
- if(zsize<csize) { |
|
595 |
- cli_dbgmsg("cli_unzip: lh - stream out of file\n"); |
|
596 |
- fmap_unneed_off(map, loff, SIZEOF_LH); |
|
597 |
- return 0; |
|
598 |
- } |
|
599 |
- |
|
600 |
- if(LH_flags & F_ENCR) { |
|
601 |
- if(fmap_need_ptr_once(map, zip, csize)) |
|
602 |
- *ret = zdecrypt(zip, csize, usize, lh, fu, ctx, tmpd, zcb); |
|
603 |
- } else { |
|
604 |
- if(fmap_need_ptr_once(map, zip, csize)) |
|
605 |
- *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb); |
|
606 |
- } |
|
607 |
- zip+=csize; |
|
608 |
- zsize-=csize; |
|
609 |
- } |
|
610 |
- |
|
611 |
- if (virus_found != 0) |
|
612 |
- *ret = CL_VIRUS; |
|
613 |
- |
|
614 |
- fmap_unneed_off(map, loff, SIZEOF_LH); /* unneed now. block is guaranteed to exists till the next need */ |
|
615 |
- if(LH_flags & F_USEDD) { |
|
616 |
- if(zsize<12) { |
|
617 |
- cli_dbgmsg("cli_unzip: lh - data desc out of file\n"); |
|
618 |
- return 0; |
|
619 |
- } |
|
620 |
- zsize-=12; |
|
621 |
- if(fmap_need_ptr_once(map, zip, 4)) { |
|
622 |
- if(cli_readint32(zip)==0x08074b50) { |
|
623 |
- if(zsize<4) { |
|
624 |
- cli_dbgmsg("cli_unzip: lh - data desc out of file\n"); |
|
625 |
- return 0; |
|
626 |
- } |
|
627 |
- zip+=4; |
|
628 |
- } |
|
629 |
- } |
|
630 |
- zip+=12; |
|
631 |
- } |
|
632 |
- return zip-lh; |
|
591 |
+ zip += LH_elen; |
|
592 |
+ zsize -= LH_elen; |
|
593 |
+ |
|
594 |
+ if (NULL != file_local_header_size) |
|
595 |
+ *file_local_header_size = zip - lh; |
|
596 |
+ if (NULL != file_local_data_size) |
|
597 |
+ *file_local_data_size = csize; |
|
598 |
+ |
|
599 |
+ if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */ |
|
600 |
+ cli_dbgmsg("cli_unzip: lh - skipping empty file\n"); |
|
601 |
+ } else { |
|
602 |
+ if (zsize < csize) { |
|
603 |
+ cli_dbgmsg("cli_unzip: lh - stream out of file\n"); |
|
604 |
+ fmap_unneed_off(map, loff, SIZEOF_LH); |
|
605 |
+ return 0; |
|
606 |
+ } |
|
607 |
+ |
|
608 |
+ if (LH_flags & F_ENCR) { |
|
609 |
+ if (fmap_need_ptr_once(map, zip, csize)) |
|
610 |
+ *ret = zdecrypt(zip, csize, usize, lh, fu, ctx, tmpd, zcb); |
|
611 |
+ } else { |
|
612 |
+ if (fmap_need_ptr_once(map, zip, csize)) |
|
613 |
+ *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb); |
|
614 |
+ } |
|
615 |
+ zip += csize; |
|
616 |
+ zsize -= csize; |
|
617 |
+ } |
|
618 |
+ |
|
619 |
+ if (virus_found != 0) |
|
620 |
+ *ret = CL_VIRUS; |
|
621 |
+ |
|
622 |
+ fmap_unneed_off(map, loff, SIZEOF_LH); /* unneed now. block is guaranteed to exists till the next need */ |
|
623 |
+ if (LH_flags & F_USEDD) { |
|
624 |
+ if (zsize < 12) { |
|
625 |
+ cli_dbgmsg("cli_unzip: lh - data desc out of file\n"); |
|
626 |
+ return 0; |
|
627 |
+ } |
|
628 |
+ zsize -= 12; |
|
629 |
+ if (fmap_need_ptr_once(map, zip, 4)) { |
|
630 |
+ if (cli_readint32(zip) == 0x08074b50) { |
|
631 |
+ if (zsize < 4) { |
|
632 |
+ cli_dbgmsg("cli_unzip: lh - data desc out of file\n"); |
|
633 |
+ return 0; |
|
634 |
+ } |
|
635 |
+ zip += 4; |
|
636 |
+ } |
|
637 |
+ } |
|
638 |
+ zip += 12; |
|
639 |
+ } |
|
640 |
+ return zip - lh; |
|
633 | 641 |
} |
634 | 642 |
|
635 |
-static unsigned int chdr(fmap_t *map, uint32_t coff, uint32_t zsize, unsigned int *fu, unsigned int fc, int *ret, cli_ctx *ctx, char *tmpd, struct zip_requests *requests, uint32_t *file_local_offset, uint32_t *file_local_header_size, uint32_t *file_local_data_size) { |
|
636 |
- char name[256]; |
|
637 |
- int last = 0; |
|
638 |
- const uint8_t *ch; |
|
639 |
- int virus_found = 0; |
|
640 |
- |
|
641 |
- if (NULL != file_local_offset) |
|
642 |
- *file_local_offset = 0; |
|
643 |
- if (NULL != file_local_header_size) |
|
644 |
- *file_local_header_size = 0; |
|
645 |
- if (NULL != file_local_data_size) |
|
646 |
- *file_local_data_size = 0; |
|
647 |
- |
|
648 |
- if(!(ch = fmap_need_off(map, coff, SIZEOF_CH)) || CH_magic != 0x02014b50) { |
|
649 |
- if(ch) fmap_unneed_ptr(map, ch, SIZEOF_CH); |
|
650 |
- cli_dbgmsg("cli_unzip: ch - wrkcomplete\n"); |
|
651 |
- return 0; |
|
652 |
- } |
|
653 |
- coff+=SIZEOF_CH; |
|
654 |
- |
|
655 |
- cli_dbgmsg("cli_unzip: ch - flags %x - method %x - csize %x - usize %x - flen %x - elen %x - clen %x - disk %x - off %x\n", CH_flags, CH_method, CH_csize, CH_usize, CH_flen, CH_elen, CH_clen, CH_dsk, CH_off); |
|
656 |
- |
|
657 |
- if(zsize-coff<=CH_flen) { |
|
658 |
- cli_dbgmsg("cli_unzip: ch - fname out of file\n"); |
|
659 |
- last=1; |
|
660 |
- } |
|
661 |
- |
|
662 |
- name[0]='\0'; |
|
663 |
- if(!last) { |
|
664 |
- unsigned int size = (CH_flen>=sizeof(name))?sizeof(name)-1:CH_flen; |
|
665 |
- const char *src = fmap_need_off_once(map, coff, size); |
|
666 |
- if(src) { |
|
667 |
- memcpy(name, src, size); |
|
668 |
- name[size]='\0'; |
|
669 |
- cli_dbgmsg("cli_unzip: ch - fname: %s\n", name); |
|
670 |
- } |
|
671 |
- } |
|
672 |
- coff+=CH_flen; |
|
673 |
- |
|
674 |
- /* requests do not supply a ctx; also prevent multiple scans */ |
|
675 |
- if(ctx && cli_matchmeta(ctx, name, CH_csize, CH_usize, (CH_flags & F_ENCR)!=0, fc, CH_crc32, NULL) == CL_VIRUS) |
|
676 |
- virus_found = 1; |
|
677 |
- |
|
678 |
- if(zsize-coff<=CH_elen && !last) { |
|
679 |
- cli_dbgmsg("cli_unzip: ch - extra out of file\n"); |
|
680 |
- last=1; |
|
681 |
- } |
|
682 |
- coff+=CH_elen; |
|
683 |
- |
|
684 |
- if(zsize-coff<CH_clen && !last) { |
|
685 |
- cli_dbgmsg("cli_unzip: ch - comment out of file\n"); |
|
686 |
- last = 1; |
|
687 |
- } |
|
688 |
- coff+=CH_clen; |
|
689 |
- |
|
690 |
- if (!requests) { |
|
691 |
- if(CH_off<zsize-SIZEOF_LH) { |
|
692 |
- if (NULL != file_local_offset) |
|
693 |
- *file_local_offset = CH_off; |
|
694 |
- lhdr(map, CH_off, zsize-CH_off, fu, fc, ch, ret, ctx, tmpd, 1, zip_scan_cb, file_local_header_size, file_local_data_size); |
|
695 |
- } else cli_dbgmsg("cli_unzip: ch - local hdr out of file\n"); |
|
696 |
- } |
|
697 |
- else { |
|
698 |
- int i; |
|
699 |
- size_t len; |
|
700 |
- |
|
701 |
- if (!last) { |
|
702 |
- for (i = 0; i < requests->namecnt; ++i) { |
|
703 |
- cli_dbgmsg("checking for %i: %s\n", i, requests->names[i]); |
|
704 |
- |
|
705 |
- len = MIN(sizeof(name)-1, requests->namelens[i]); |
|
706 |
- if (!strncmp(requests->names[i], name, len)) { |
|
707 |
- requests->match = 1; |
|
708 |
- requests->found = i; |
|
709 |
- requests->loff = CH_off; |
|
710 |
- } |
|
711 |
- } |
|
712 |
- } |
|
713 |
- } |
|
714 |
- |
|
715 |
- if (virus_found == 1) |
|
716 |
- *ret = CL_VIRUS; |
|
717 |
- fmap_unneed_ptr(map, ch, SIZEOF_CH); |
|
718 |
- return (last?0:coff); |
|
643 |
+static unsigned int chdr(fmap_t *map, uint32_t coff, uint32_t zsize, unsigned int *fu, unsigned int fc, int *ret, cli_ctx *ctx, char *tmpd, struct zip_requests *requests, uint32_t *file_local_offset, uint32_t *file_local_header_size, uint32_t *file_local_data_size) |
|
644 |
+{ |
|
645 |
+ char name[256]; |
|
646 |
+ int last = 0; |
|
647 |
+ const uint8_t *ch; |
|
648 |
+ int virus_found = 0; |
|
649 |
+ |
|
650 |
+ if (NULL != file_local_offset) |
|
651 |
+ *file_local_offset = 0; |
|
652 |
+ if (NULL != file_local_header_size) |
|
653 |
+ *file_local_header_size = 0; |
|
654 |
+ if (NULL != file_local_data_size) |
|
655 |
+ *file_local_data_size = 0; |
|
656 |
+ |
|
657 |
+ if (!(ch = fmap_need_off(map, coff, SIZEOF_CH)) || CH_magic != 0x02014b50) { |
|
658 |
+ if (ch) fmap_unneed_ptr(map, ch, SIZEOF_CH); |
|
659 |
+ cli_dbgmsg("cli_unzip: ch - wrkcomplete\n"); |
|
660 |
+ return 0; |
|
661 |
+ } |
|
662 |
+ coff += SIZEOF_CH; |
|
663 |
+ |
|
664 |
+ cli_dbgmsg("cli_unzip: ch - flags %x - method %x - csize %x - usize %x - flen %x - elen %x - clen %x - disk %x - off %x\n", CH_flags, CH_method, CH_csize, CH_usize, CH_flen, CH_elen, CH_clen, CH_dsk, CH_off); |
|
665 |
+ |
|
666 |
+ if (zsize - coff <= CH_flen) { |
|
667 |
+ cli_dbgmsg("cli_unzip: ch - fname out of file\n"); |
|
668 |
+ last = 1; |
|
669 |
+ } |
|
670 |
+ |
|
671 |
+ name[0] = '\0'; |
|
672 |
+ if (!last) { |
|
673 |
+ unsigned int size = (CH_flen >= sizeof(name)) ? sizeof(name) - 1 : CH_flen; |
|
674 |
+ const char *src = fmap_need_off_once(map, coff, size); |
|
675 |
+ if (src) { |
|
676 |
+ memcpy(name, src, size); |
|
677 |
+ name[size] = '\0'; |
|
678 |
+ cli_dbgmsg("cli_unzip: ch - fname: %s\n", name); |
|
679 |
+ } |
|
680 |
+ } |
|
681 |
+ coff += CH_flen; |
|
682 |
+ |
|
683 |
+ /* requests do not supply a ctx; also prevent multiple scans */ |
|
684 |
+ if (ctx && cli_matchmeta(ctx, name, CH_csize, CH_usize, (CH_flags & F_ENCR) != 0, fc, CH_crc32, NULL) == CL_VIRUS) |
|
685 |
+ virus_found = 1; |
|
686 |
+ |
|
687 |
+ if (zsize - coff <= CH_elen && !last) { |
|
688 |
+ cli_dbgmsg("cli_unzip: ch - extra out of file\n"); |
|
689 |
+ last = 1; |
|
690 |
+ } |
|
691 |
+ coff += CH_elen; |
|
692 |
+ |
|
693 |
+ if (zsize - coff < CH_clen && !last) { |
|
694 |
+ cli_dbgmsg("cli_unzip: ch - comment out of file\n"); |
|
695 |
+ last = 1; |
|
696 |
+ } |
|
697 |
+ coff += CH_clen; |
|
698 |
+ |
|
699 |
+ if (!requests) { |
|
700 |
+ if (CH_off < zsize - SIZEOF_LH) { |
|
701 |
+ if (NULL != file_local_offset) |
|
702 |
+ *file_local_offset = CH_off; |
|
703 |
+ lhdr(map, CH_off, zsize - CH_off, fu, fc, ch, ret, ctx, tmpd, 1, zip_scan_cb, file_local_header_size, file_local_data_size); |
|
704 |
+ } else |
|
705 |
+ cli_dbgmsg("cli_unzip: ch - local hdr out of file\n"); |
|
706 |
+ } else { |
|
707 |
+ int i; |
|
708 |
+ size_t len; |
|
709 |
+ |
|
710 |
+ if (!last) { |
|
711 |
+ for (i = 0; i < requests->namecnt; ++i) { |
|
712 |
+ cli_dbgmsg("checking for %i: %s\n", i, requests->names[i]); |
|
713 |
+ |
|
714 |
+ len = MIN(sizeof(name) - 1, requests->namelens[i]); |
|
715 |
+ if (!strncmp(requests->names[i], name, len)) { |
|
716 |
+ requests->match = 1; |
|
717 |
+ requests->found = i; |
|
718 |
+ requests->loff = CH_off; |
|
719 |
+ } |
|
720 |
+ } |
|
721 |
+ } |
|
722 |
+ } |
|
723 |
+ |
|
724 |
+ if (virus_found == 1) |
|
725 |
+ *ret = CL_VIRUS; |
|
726 |
+ fmap_unneed_ptr(map, ch, SIZEOF_CH); |
|
727 |
+ return (last ? 0 : coff); |
|
719 | 728 |
} |
720 | 729 |
|
721 |
-int cli_unzip(cli_ctx *ctx) { |
|
722 |
- unsigned int fc=0, fu=0; |
|
723 |
- int ret=CL_CLEAN; |
|
724 |
- uint32_t fsize, lhoff = 0, coff = 0; |
|
725 |
- fmap_t *map = *ctx->fmap; |
|
726 |
- char *tmpd; |
|
727 |
- const char *ptr; |
|
728 |
- int virus_found = 0; |
|
730 |
+int cli_unzip(cli_ctx *ctx) |
|
731 |
+{ |
|
732 |
+ unsigned int fc = 0, fu = 0; |
|
733 |
+ int ret = CL_CLEAN; |
|
734 |
+ uint32_t fsize, lhoff = 0, coff = 0; |
|
735 |
+ fmap_t *map = *ctx->fmap; |
|
736 |
+ char *tmpd; |
|
737 |
+ const char *ptr; |
|
738 |
+ int virus_found = 0; |
|
729 | 739 |
#if HAVE_JSON |
730 |
- int toval = 0; |
|
740 |
+ int toval = 0; |
|
731 | 741 |
#endif |
732 |
- int bZipBombDetected = 0; |
|
733 |
- uint32_t cur_file_local_offset = 0; |
|
734 |
- uint32_t cur_file_local_header_size = 0; |
|
735 |
- uint32_t cur_file_local_data_size = 0; |
|
736 |
- uint32_t prev_file_local_offset = 0; |
|
737 |
- uint32_t prev_file_local_header_size = 0; |
|
738 |
- uint32_t prev_file_local_data_size = 0; |
|
739 |
- |
|
740 |
- cli_dbgmsg("in cli_unzip\n"); |
|
741 |
- fsize = (uint32_t)map->len; |
|
742 |
- if(sizeof(off_t)!=sizeof(uint32_t) && (size_t)fsize!=map->len) { |
|
743 |
- cli_dbgmsg("cli_unzip: file too big\n"); |
|
744 |
- return CL_CLEAN; |
|
745 |
- } |
|
746 |
- if (fsize < SIZEOF_CH) { |
|
747 |
- cli_dbgmsg("cli_unzip: file too short\n"); |
|
748 |
- return CL_CLEAN; |
|
749 |
- } |
|
750 |
- if (!(tmpd = cli_gentemp(ctx->engine->tmpdir))) { |
|
751 |
- return CL_ETMPDIR; |
|
752 |
- } |
|
753 |
- if (mkdir(tmpd, 0700)) { |
|
754 |
- cli_dbgmsg("cli_unzip: Can't create temporary directory %s\n", tmpd); |
|
755 |
- free(tmpd); |
|
756 |
- return CL_ETMPDIR; |
|
757 |
- } |
|
758 |
- |
|
759 |
- for(coff=fsize-22 ; coff>0 ; coff--) { /* sizeof(EOC)==22 */ |
|
760 |
- if(!(ptr = fmap_need_off_once(map, coff, 20))) |
|
761 |
- continue; |
|
762 |
- if(cli_readint32(ptr)==0x06054b50) { |
|
763 |
- uint32_t chptr = cli_readint32(&ptr[16]); |
|
764 |
- if(!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue; |
|
765 |
- coff=chptr; |
|
766 |
- break; |
|
767 |
- } |
|
768 |
- } |
|
769 |
- |
|
770 |
- if(coff) { |
|
771 |
- uint32_t nOverlappingFiles = 0; |
|
772 |
- |
|
773 |
- cli_dbgmsg("cli_unzip: central @%x\n", coff); |
|
774 |
- while((coff=chdr(map, coff, fsize, &fu, fc+1, &ret, ctx, tmpd, NULL, &cur_file_local_offset, &cur_file_local_header_size, &cur_file_local_data_size))) { |
|
775 |
- fc++; |
|
776 |
- if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) { |
|
777 |
- cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles); |
|
778 |
- ret=CL_EMAXFILES; |
|
779 |
- } |
|
780 |
- |
|
781 |
- if (cli_checktimelimit(ctx) != CL_SUCCESS) { |
|
782 |
- cli_dbgmsg("cli_unzip: Time limit reached (max: %u)\n", ctx->engine->maxscantime); |
|
783 |
- ret = CL_ETIMEOUT; |
|
784 |
- } |
|
785 |
- /* |
|
786 |
- * Detect overlapping files and zip bombs. |
|
787 |
- */ |
|
788 |
- if ((((cur_file_local_offset > prev_file_local_offset) && (cur_file_local_offset < prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size)) || |
|
789 |
- ((prev_file_local_offset > cur_file_local_offset) && (prev_file_local_offset < cur_file_local_offset + cur_file_local_header_size + cur_file_local_data_size))) && |
|
790 |
- (cur_file_local_header_size + cur_file_local_data_size > 0)) { |
|
791 |
- /* Overlapping file detected */ |
|
792 |
- nOverlappingFiles++; |
|
793 |
- |
|
794 |
- cli_dbgmsg("cli_unzip: Overlapping files detected.\n"); |
|
795 |
- cli_dbgmsg(" previous file end: %u\n", prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size); |
|
796 |
- cli_dbgmsg(" current file start: %u\n", cur_file_local_offset); |
|
797 |
- if (ZIP_MAX_NUM_OVERLAPPING_FILES < nOverlappingFiles) { |
|
798 |
- if (SCAN_HEURISTICS) { |
|
799 |
- ret = cli_append_virus(ctx, "Heuristics.Zip.OverlappingFiles"); |
|
800 |
- virus_found = 1; |
|
801 |
- } else { |
|
802 |
- ret = CL_EFORMAT; |
|
803 |
- } |
|
804 |
- bZipBombDetected = 1; |
|
742 |
+ int bZipBombDetected = 0; |
|
743 |
+ uint32_t cur_file_local_offset = 0; |
|
744 |
+ uint32_t cur_file_local_header_size = 0; |
|
745 |
+ uint32_t cur_file_local_data_size = 0; |
|
746 |
+ uint32_t prev_file_local_offset = 0; |
|
747 |
+ uint32_t prev_file_local_header_size = 0; |
|
748 |
+ uint32_t prev_file_local_data_size = 0; |
|
749 |
+ |
|
750 |
+ cli_dbgmsg("in cli_unzip\n"); |
|
751 |
+ fsize = (uint32_t)map->len; |
|
752 |
+ if (sizeof(off_t) != sizeof(uint32_t) && (size_t)fsize != map->len) { |
|
753 |
+ cli_dbgmsg("cli_unzip: file too big\n"); |
|
754 |
+ return CL_CLEAN; |
|
755 |
+ } |
|
756 |
+ if (fsize < SIZEOF_CH) { |
|
757 |
+ cli_dbgmsg("cli_unzip: file too short\n"); |
|
758 |
+ return CL_CLEAN; |
|
759 |
+ } |
|
760 |
+ if (!(tmpd = cli_gentemp(ctx->engine->tmpdir))) { |
|
761 |
+ return CL_ETMPDIR; |
|
762 |
+ } |
|
763 |
+ if (mkdir(tmpd, 0700)) { |
|
764 |
+ cli_dbgmsg("cli_unzip: Can't create temporary directory %s\n", tmpd); |
|
765 |
+ free(tmpd); |
|
766 |
+ return CL_ETMPDIR; |
|
767 |
+ } |
|
768 |
+ |
|
769 |
+ for (coff = fsize - 22; coff > 0; coff--) { /* sizeof(EOC)==22 */ |
|
770 |
+ if (!(ptr = fmap_need_off_once(map, coff, 20))) |
|
771 |
+ continue; |
|
772 |
+ if (cli_readint32(ptr) == 0x06054b50) { |
|
773 |
+ uint32_t chptr = cli_readint32(&ptr[16]); |
|
774 |
+ if (!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue; |
|
775 |
+ coff = chptr; |
|
776 |
+ break; |
|
805 | 777 |
} |
806 | 778 |
} |
807 |
- prev_file_local_offset = cur_file_local_offset; |
|
808 |
- prev_file_local_header_size = cur_file_local_header_size; |
|
809 |
- prev_file_local_data_size = cur_file_local_data_size; |
|
779 |
+ |
|
780 |
+ if (coff) { |
|
781 |
+ uint32_t nOverlappingFiles = 0; |
|
782 |
+ |
|
783 |
+ cli_dbgmsg("cli_unzip: central @%x\n", coff); |
|
784 |
+ while ((coff = chdr(map, coff, fsize, &fu, fc + 1, &ret, ctx, tmpd, NULL, &cur_file_local_offset, &cur_file_local_header_size, &cur_file_local_data_size))) { |
|
785 |
+ fc++; |
|
786 |
+ if (ctx->engine->maxfiles && fu >= ctx->engine->maxfiles) { |
|
787 |
+ cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles); |
|
788 |
+ ret = CL_EMAXFILES; |
|
789 |
+ } |
|
790 |
+ |
|
791 |
+ if (cli_checktimelimit(ctx) != CL_SUCCESS) { |
|
792 |
+ cli_dbgmsg("cli_unzip: Time limit reached (max: %u)\n", ctx->engine->maxscantime); |
|
793 |
+ ret = CL_ETIMEOUT; |
|
794 |
+ } |
|
795 |
+ /* |
|
796 |
+ * Detect overlapping files and zip bombs. |
|
797 |
+ */ |
|
798 |
+ if ((((cur_file_local_offset > prev_file_local_offset) && (cur_file_local_offset < prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size)) || |
|
799 |
+ ((prev_file_local_offset > cur_file_local_offset) && (prev_file_local_offset < cur_file_local_offset + cur_file_local_header_size + cur_file_local_data_size))) && |
|
800 |
+ (cur_file_local_header_size + cur_file_local_data_size > 0)) { |
|
801 |
+ /* Overlapping file detected */ |
|
802 |
+ nOverlappingFiles++; |
|
803 |
+ |
|
804 |
+ cli_dbgmsg("cli_unzip: Overlapping files detected.\n"); |
|
805 |
+ cli_dbgmsg(" previous file end: %u\n", prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size); |
|
806 |
+ cli_dbgmsg(" current file start: %u\n", cur_file_local_offset); |
|
807 |
+ if (ZIP_MAX_NUM_OVERLAPPING_FILES < nOverlappingFiles) { |
|
808 |
+ if (SCAN_HEURISTICS) { |
|
809 |
+ ret = cli_append_virus(ctx, "Heuristics.Zip.OverlappingFiles"); |
|
810 |
+ virus_found = 1; |
|
811 |
+ } else { |
|
812 |
+ ret = CL_EFORMAT; |
|
813 |
+ } |
|
814 |
+ bZipBombDetected = 1; |
|
815 |
+ } |
|
816 |
+ } |
|
817 |
+ prev_file_local_offset = cur_file_local_offset; |
|
818 |
+ prev_file_local_header_size = cur_file_local_header_size; |
|
819 |
+ prev_file_local_data_size = cur_file_local_data_size; |
|
810 | 820 |
|
811 | 821 |
#if HAVE_JSON |
812 |
- if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) { |
|
813 |
- ret=CL_ETIMEOUT; |
|
814 |
- } |
|
822 |
+ if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) { |
|
823 |
+ ret = CL_ETIMEOUT; |
|
824 |
+ } |
|
815 | 825 |
#endif |
816 |
- if (ret != CL_CLEAN) { |
|
817 |
- if (ret == CL_VIRUS && SCAN_ALLMATCHES && !bZipBombDetected) { |
|
818 |
- ret = CL_CLEAN; |
|
819 |
- virus_found = 1; |
|
820 |
- } else |
|
821 |
- break; |
|
822 |
- } |
|
823 |
- } |
|
824 |
- } else cli_dbgmsg("cli_unzip: central not found, using localhdrs\n"); |
|
825 |
- if (virus_found == 1) |
|
826 |
- ret = CL_VIRUS; |
|
827 |
- if(fu<=(fc/4)) { /* FIXME: make up a sane ratio or remove the whole logic */ |
|
828 |
- fc = 0; |
|
829 |
- while (ret==CL_CLEAN && lhoff<fsize && (coff=lhdr(map, lhoff, fsize-lhoff, &fu, fc+1, NULL, &ret, ctx, tmpd, 1, zip_scan_cb, NULL, NULL))) { |
|
830 |
- fc++; |
|
831 |
- lhoff+=coff; |
|
832 |
- if (SCAN_ALLMATCHES && ret == CL_VIRUS) { |
|
833 |
- ret = CL_CLEAN; |
|
834 |
- virus_found = 1; |
|
835 |
- } |
|
836 |
- if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) { |
|
837 |
- cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles); |
|
838 |
- ret=CL_EMAXFILES; |
|
839 |
- } |
|
826 |
+ if (ret != CL_CLEAN) { |
|
827 |
+ if (ret == CL_VIRUS && SCAN_ALLMATCHES && !bZipBombDetected) { |
|
828 |
+ ret = CL_CLEAN; |
|
829 |
+ virus_found = 1; |
|
830 |
+ } else |
|
831 |
+ break; |
|
832 |
+ } |
|
833 |
+ } |
|
834 |
+ } else |
|
835 |
+ cli_dbgmsg("cli_unzip: central not found, using localhdrs\n"); |
|
836 |
+ if (virus_found == 1) |
|
837 |
+ ret = CL_VIRUS; |
|
838 |
+ if (fu <= (fc / 4)) { /* FIXME: make up a sane ratio or remove the whole logic */ |
|
839 |
+ fc = 0; |
|
840 |
+ while (ret == CL_CLEAN && lhoff < fsize && (coff = lhdr(map, lhoff, fsize - lhoff, &fu, fc + 1, NULL, &ret, ctx, tmpd, 1, zip_scan_cb, NULL, NULL))) { |
|
841 |
+ fc++; |
|
842 |
+ lhoff += coff; |
|
843 |
+ if (SCAN_ALLMATCHES && ret == CL_VIRUS) { |
|
844 |
+ ret = CL_CLEAN; |
|
845 |
+ virus_found = 1; |
|
846 |
+ } |
|
847 |
+ if (ctx->engine->maxfiles && fu >= ctx->engine->maxfiles) { |
|
848 |
+ cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles); |
|
849 |
+ ret = CL_EMAXFILES; |
|
850 |
+ } |
|
840 | 851 |
#if HAVE_JSON |
841 |
- if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) { |
|
842 |
- ret=CL_ETIMEOUT; |
|
843 |
- } |
|
852 |
+ if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) { |
|
853 |
+ ret = CL_ETIMEOUT; |
|
854 |
+ } |
|
844 | 855 |
#endif |
845 |
- |
|
856 |
+ } |
|
846 | 857 |
} |
847 |
- } |
|
848 | 858 |
|
849 |
- if (!ctx->engine->keeptmp) cli_rmdirs(tmpd); |
|
850 |
- free(tmpd); |
|
859 |
+ if (!ctx->engine->keeptmp) cli_rmdirs(tmpd); |
|
860 |
+ free(tmpd); |
|
851 | 861 |
|
852 |
- if (ret == CL_CLEAN && virus_found) |
|
853 |
- ret = CL_VIRUS; |
|
862 |
+ if (ret == CL_CLEAN && virus_found) |
|
863 |
+ ret = CL_VIRUS; |
|
854 | 864 |
|
855 |
- return ret; |
|
865 |
+ return ret; |
|
856 | 866 |
} |
857 | 867 |
|
858 | 868 |
int unzip_single_internal(cli_ctx *ctx, off_t lhoffl, zip_cb zcb) |
859 | 869 |
{ |
860 |
- int ret=CL_CLEAN; |
|
861 |
- unsigned int fu=0; |
|
862 |
- uint32_t fsize; |
|
863 |
- fmap_t *map = *ctx->fmap; |
|
864 |
- |
|
865 |
- cli_dbgmsg("in cli_unzip_single\n"); |
|
866 |
- fsize = (uint32_t)(map->len - lhoffl); |
|
867 |
- if (lhoffl<0 || (size_t)lhoffl>map->len || (sizeof(off_t)!=sizeof(uint32_t) && (size_t)fsize!=map->len - lhoffl)) { |
|
868 |
- cli_dbgmsg("cli_unzip: bad offset\n"); |
|
869 |
- return CL_CLEAN; |
|
870 |
- } |
|
871 |
- if (fsize < SIZEOF_LH) { |
|
872 |
- cli_dbgmsg("cli_unzip: file too short\n"); |
|
873 |
- return CL_CLEAN; |
|
874 |
- } |
|
875 |
- |
|
876 |
- lhdr(map, lhoffl, fsize, &fu, 0, NULL, &ret, ctx, NULL, 0, zcb, NULL, NULL); |
|
877 |
- |
|
878 |
- return ret; |
|
870 |
+ int ret = CL_CLEAN; |
|
871 |
+ unsigned int fu = 0; |
|
872 |
+ uint32_t fsize; |
|
873 |
+ fmap_t *map = *ctx->fmap; |
|
874 |
+ |
|
875 |
+ cli_dbgmsg("in cli_unzip_single\n"); |
|
876 |
+ fsize = (uint32_t)(map->len - lhoffl); |
|
877 |
+ if (lhoffl < 0 || (size_t)lhoffl > map->len || (sizeof(off_t) != sizeof(uint32_t) && (size_t)fsize != map->len - lhoffl)) { |
|
878 |
+ cli_dbgmsg("cli_unzip: bad offset\n"); |
|
879 |
+ return CL_CLEAN; |
|
880 |
+ } |
|
881 |
+ if (fsize < SIZEOF_LH) { |
|
882 |
+ cli_dbgmsg("cli_unzip: file too short\n"); |
|
883 |
+ return CL_CLEAN; |
|
884 |
+ } |
|
885 |
+ |
|
886 |
+ lhdr(map, lhoffl, fsize, &fu, 0, NULL, &ret, ctx, NULL, 0, zcb, NULL, NULL); |
|
887 |
+ |
|
888 |
+ return ret; |
|
879 | 889 |
} |
880 | 890 |
|
881 |
-int cli_unzip_single(cli_ctx *ctx, off_t lhoffl) { |
|
891 |
+int cli_unzip_single(cli_ctx *ctx, off_t lhoffl) |
|
892 |
+{ |
|
882 | 893 |
return unzip_single_internal(ctx, lhoffl, zip_scan_cb); |
883 | 894 |
} |
884 | 895 |
|
... | ... |
@@ -893,7 +905,7 @@ int unzip_search_add(struct zip_requests *requests, const char *name, size_t nle |
893 | 893 |
|
894 | 894 |
cli_dbgmsg("unzip_search_add: adding %s (len %llu)\n", name, (long long unsigned)nlen); |
895 | 895 |
|
896 |
- requests->names[requests->namecnt] = name; |
|
896 |
+ requests->names[requests->namecnt] = name; |
|
897 | 897 |
requests->namelens[requests->namecnt] = nlen; |
898 | 898 |
requests->namecnt++; |
899 | 899 |
|
... | ... |
@@ -903,7 +915,7 @@ int unzip_search_add(struct zip_requests *requests, const char *name, size_t nle |
903 | 903 |
int unzip_search(cli_ctx *ctx, fmap_t *map, struct zip_requests *requests) |
904 | 904 |
{ |
905 | 905 |
unsigned int fc = 0; |
906 |
- fmap_t *zmap = map; |
|
906 |
+ fmap_t *zmap = map; |
|
907 | 907 |
size_t fsize; |
908 | 908 |
uint32_t coff = 0; |
909 | 909 |
const char *ptr; |
... | ... |
@@ -921,7 +933,7 @@ int unzip_search(cli_ctx *ctx, fmap_t *map, struct zip_requests *requests) |
921 | 921 |
if (ctx && !map) |
922 | 922 |
zmap = *ctx->fmap; |
923 | 923 |
fsize = zmap->len; |
924 |
- if(sizeof(off_t)!=sizeof(uint32_t) && fsize!=zmap->len) { |
|
924 |
+ if (sizeof(off_t) != sizeof(uint32_t) && fsize != zmap->len) { |
|
925 | 925 |
cli_dbgmsg("unzip_search: file too big\n"); |
926 | 926 |
return CL_CLEAN; |
927 | 927 |
} |
... | ... |
@@ -930,32 +942,32 @@ int unzip_search(cli_ctx *ctx, fmap_t *map, struct zip_requests *requests) |
930 | 930 |
return CL_CLEAN; |
931 | 931 |
} |
932 | 932 |
|
933 |
- for(coff=fsize-22 ; coff>0 ; coff--) { /* sizeof(EOC)==22 */ |
|
934 |
- if(!(ptr = fmap_need_off_once(zmap, coff, 20))) |
|
933 |
+ for (coff = fsize - 22; coff > 0; coff--) { /* sizeof(EOC)==22 */ |
|
934 |
+ if (!(ptr = fmap_need_off_once(zmap, coff, 20))) |
|
935 | 935 |
continue; |
936 |
- if(cli_readint32(ptr)==0x06054b50) { |
|
936 |
+ if (cli_readint32(ptr) == 0x06054b50) { |
|
937 | 937 |
uint32_t chptr = cli_readint32(&ptr[16]); |
938 |
- if(!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue; |
|
939 |
- coff=chptr; |
|
938 |
+ if (!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue; |
|
939 |
+ coff = chptr; |
|
940 | 940 |
break; |
941 | 941 |
} |
942 | 942 |
} |
943 | 943 |
|
944 |
- if(coff) { |
|
944 |
+ if (coff) { |
|
945 | 945 |
cli_dbgmsg("unzip_search: central @%x\n", coff); |
946 |
- while(ret==CL_CLEAN && (coff=chdr(zmap, coff, fsize, NULL, fc+1, &ret, ctx, NULL, requests, NULL, NULL, NULL))) { |
|
946 |
+ while (ret == CL_CLEAN && (coff = chdr(zmap, coff, fsize, NULL, fc + 1, &ret, ctx, NULL, requests, NULL, NULL, NULL))) { |
|
947 | 947 |
if (requests->match) { |
948 |
- ret=CL_VIRUS; |
|
948 |
+ ret = CL_VIRUS; |
|
949 | 949 |
} |
950 | 950 |
|
951 | 951 |
fc++; |
952 | 952 |
if (ctx && ctx->engine->maxfiles && fc >= ctx->engine->maxfiles) { |
953 | 953 |
cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles); |
954 |
- ret=CL_EMAXFILES; |
|
954 |
+ ret = CL_EMAXFILES; |
|
955 | 955 |
} |
956 | 956 |
#if HAVE_JSON |
957 | 957 |
if (ctx && cli_json_timeout_cycle_check(ctx, (int *)(&toval)) != CL_SUCCESS) { |
958 |
- ret=CL_ETIMEOUT; |
|
958 |
+ ret = CL_ETIMEOUT; |
|
959 | 959 |
} |
960 | 960 |
#endif |
961 | 961 |
} |
... | ... |
@@ -988,4 +1000,3 @@ int unzip_search_single(cli_ctx *ctx, const char *name, size_t nlen, uint32_t *l |
988 | 988 |
|
989 | 989 |
return ret; |
990 | 990 |
} |
991 |
- |