git-svn: trunk@2648
Tomasz Kojm authored on 2007/01/29 05:22:16... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Sun Jan 28 21:20:05 CET 2007 (tk) |
|
2 |
+--------------------------------- |
|
3 |
+ * libclamav: improve handling of RAR archives, thanks to Edwin |
|
4 |
+ |
|
1 | 5 |
Sat Jan 27 13:54:35 CET 2007 (acab) |
2 | 6 |
----------------------------------- |
3 | 7 |
* libclamav/pe.c: fix debug message logic, fixed handling of non aligned raw |
... | ... |
@@ -192,12 +192,20 @@ static int cli_unrar_scanmetadata(int desc, rar_metadata_t *metadata, cli_ctx *c |
192 | 192 |
continue; |
193 | 193 |
} |
194 | 194 |
*/ |
195 |
+ return ret; |
|
196 |
+} |
|
197 |
+ |
|
198 |
+static int cli_unrar_checklimits(const cli_ctx *ctx, const rar_metadata_t *metadata, unsigned int files) |
|
199 |
+{ |
|
195 | 200 |
if(ctx->limits) { |
196 | 201 |
if(ctx->limits->maxratio && metadata->unpack_size && metadata->pack_size) { |
197 | 202 |
if((unsigned int) metadata->unpack_size / (unsigned int) metadata->pack_size >= ctx->limits->maxratio) { |
198 | 203 |
cli_dbgmsg("RAR: Max ratio reached (normal: %u, compressed: %u, max: %ld)\n", metadata->unpack_size, metadata->pack_size, ctx->limits->maxratio); |
199 |
- *ctx->virname = "Oversized.RAR"; |
|
200 |
- return CL_VIRUS; |
|
204 |
+ if(BLOCKMAX) { |
|
205 |
+ *ctx->virname = "Oversized.RAR"; |
|
206 |
+ return CL_VIRUS; |
|
207 |
+ } |
|
208 |
+ return CL_EMAXSIZE; |
|
201 | 209 |
} |
202 | 210 |
} |
203 | 211 |
|
... | ... |
@@ -207,7 +215,7 @@ static int cli_unrar_scanmetadata(int desc, rar_metadata_t *metadata, cli_ctx *c |
207 | 207 |
*ctx->virname = "RAR.ExceededFileSize"; |
208 | 208 |
return CL_VIRUS; |
209 | 209 |
} |
210 |
- return CL_SUCCESS; |
|
210 |
+ return CL_EMAXSIZE; |
|
211 | 211 |
} |
212 | 212 |
|
213 | 213 |
if(ctx->limits->maxfiles && (files > ctx->limits->maxfiles)) { |
... | ... |
@@ -216,11 +224,11 @@ static int cli_unrar_scanmetadata(int desc, rar_metadata_t *metadata, cli_ctx *c |
216 | 216 |
*ctx->virname = "RAR.ExceededFilesLimit"; |
217 | 217 |
return CL_VIRUS; |
218 | 218 |
} |
219 |
- return CL_BREAK; |
|
219 |
+ return CL_EMAXFILES; |
|
220 | 220 |
} |
221 | 221 |
} |
222 | 222 |
|
223 |
- return ret; |
|
223 |
+ return CL_SUCCESS; |
|
224 | 224 |
} |
225 | 225 |
|
226 | 226 |
static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check) |
... | ... |
@@ -255,6 +263,16 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c |
255 | 255 |
do { |
256 | 256 |
int rc; |
257 | 257 |
rar_state.unpack_data->ofd = -1; |
258 |
+ ret = cli_unrar_extract_next_prepare(&rar_state,dir); |
|
259 |
+ if(ret != CL_SUCCESS) |
|
260 |
+ break; |
|
261 |
+ ret = cli_unrar_checklimits(ctx, rar_state.metadata_tail, rar_state.file_count); |
|
262 |
+ if(ret && ret != CL_VIRUS) { |
|
263 |
+ ret = CL_CLEAN; |
|
264 |
+ continue; |
|
265 |
+ } else if(ret == CL_VIRUS) { |
|
266 |
+ break; |
|
267 |
+ } |
|
258 | 268 |
ret = cli_unrar_extract_next(&rar_state,dir); |
259 | 269 |
if(rar_state.unpack_data->ofd > 0) { |
260 | 270 |
lseek(rar_state.unpack_data->ofd,0,SEEK_SET); |
... | ... |
@@ -1527,26 +1527,25 @@ int cli_unrar_open(int fd, const char *dirname, rar_state_t* state) |
1527 | 1527 |
return CL_SUCCESS; |
1528 | 1528 |
} |
1529 | 1529 |
|
1530 |
-int cli_unrar_extract_next(rar_state_t* state,const char* dirname) |
|
1530 |
+int cli_unrar_extract_next_prepare(rar_state_t* state,const char* dirname) |
|
1531 | 1531 |
{ |
1532 |
- int retval; |
|
1533 | 1532 |
unsigned char filename[1024]; |
1534 | 1533 |
int ofd; |
1535 | 1534 |
|
1536 | 1535 |
rar_metadata_t *new_metadata; |
1537 |
- file_header_t *file_header = read_block(state->fd, FILE_HEAD); |
|
1538 |
- if (!file_header) { |
|
1536 |
+ state->file_header = read_block(state->fd, FILE_HEAD); |
|
1537 |
+ if (!state->file_header) { |
|
1539 | 1538 |
return CL_BREAK;/* end of archive */ |
1540 | 1539 |
} |
1541 | 1540 |
new_metadata = cli_malloc(sizeof(rar_metadata_t)); |
1542 | 1541 |
if (!new_metadata) { |
1543 | 1542 |
return CL_EMEM; |
1544 | 1543 |
} |
1545 |
- new_metadata->pack_size = file_header->pack_size; |
|
1546 |
- new_metadata->unpack_size = file_header->unpack_size; |
|
1547 |
- new_metadata->crc = file_header->file_crc; |
|
1548 |
- new_metadata->method = file_header->method; |
|
1549 |
- new_metadata->filename = strdup(file_header->filename); |
|
1544 |
+ new_metadata->pack_size = state->file_header->pack_size; |
|
1545 |
+ new_metadata->unpack_size = state->file_header->unpack_size; |
|
1546 |
+ new_metadata->crc = state->file_header->file_crc; |
|
1547 |
+ new_metadata->method = state->file_header->method; |
|
1548 |
+ new_metadata->filename = strdup(state->file_header->filename); |
|
1550 | 1549 |
new_metadata->next = NULL; |
1551 | 1550 |
new_metadata->encrypted = FALSE; |
1552 | 1551 |
if (state->metadata_tail == NULL) { |
... | ... |
@@ -1555,7 +1554,7 @@ int cli_unrar_extract_next(rar_state_t* state,const char* dirname) |
1555 | 1555 |
state->metadata_tail->next = new_metadata; |
1556 | 1556 |
state->metadata_tail = new_metadata; |
1557 | 1557 |
} |
1558 |
- if (file_header->flags & LHD_COMMENT) { |
|
1558 |
+ if (state->file_header->flags & LHD_COMMENT) { |
|
1559 | 1559 |
comment_header_t *comment_header; |
1560 | 1560 |
|
1561 | 1561 |
cli_dbgmsg("File comment present\n"); |
... | ... |
@@ -1585,54 +1584,62 @@ int cli_unrar_extract_next(rar_state_t* state,const char* dirname) |
1585 | 1585 |
free(comment_header); |
1586 | 1586 |
} |
1587 | 1587 |
} |
1588 |
- if (lseek(state->fd, file_header->start_offset+file_header->head_size, SEEK_SET) != |
|
1589 |
- file_header->start_offset+file_header->head_size) { |
|
1590 |
- cli_dbgmsg("Seek failed: %ld\n", state->offset+file_header->head_size); |
|
1591 |
- free(file_header->filename); |
|
1592 |
- free(file_header); |
|
1588 |
+ return CL_SUCCESS; |
|
1589 |
+} |
|
1590 |
+ |
|
1591 |
+int cli_unrar_extract_next(rar_state_t* state,const char* dirname) |
|
1592 |
+{ |
|
1593 |
+ int ofd; |
|
1594 |
+ int retval; |
|
1595 |
+ |
|
1596 |
+ if (lseek(state->fd, state->file_header->start_offset+state->file_header->head_size, SEEK_SET) != |
|
1597 |
+ state->file_header->start_offset+state->file_header->head_size) { |
|
1598 |
+ cli_dbgmsg("Seek failed: %ld\n", state->offset+state->file_header->head_size); |
|
1599 |
+ free(state->file_header->filename); |
|
1600 |
+ free(state->file_header); |
|
1593 | 1601 |
return CL_ERAR; |
1594 | 1602 |
} |
1595 |
- if (file_header->flags & LHD_PASSWORD) { |
|
1596 |
- cli_dbgmsg("PASSWORDed file: %s\n", file_header->filename); |
|
1603 |
+ if (state->file_header->flags & LHD_PASSWORD) { |
|
1604 |
+ cli_dbgmsg("PASSWORDed file: %s\n", state->file_header->filename); |
|
1597 | 1605 |
state->metadata_tail->encrypted = TRUE; |
1598 | 1606 |
} else /*if (file_header->unpack_size)*/ { |
1599 | 1607 |
snprintf(state->filename, 1024, "%s/%lu.ura", dirname, state->file_count); |
1600 | 1608 |
ofd = open(state->filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600); |
1601 | 1609 |
if (ofd < 0) { |
1602 |
- free(file_header->filename); |
|
1603 |
- free(file_header); |
|
1610 |
+ free(state->file_header->filename); |
|
1611 |
+ free(state->file_header); |
|
1604 | 1612 |
cli_dbgmsg("ERROR: Failed to open output file\n"); |
1605 | 1613 |
return CL_EOPEN; |
1606 | 1614 |
} |
1607 | 1615 |
state->unpack_data->ofd = ofd; |
1608 |
- if (file_header->method == 0x30) { |
|
1616 |
+ if (state->file_header->method == 0x30) { |
|
1609 | 1617 |
cli_dbgmsg("Copying stored file (not packed)\n"); |
1610 |
- copy_file_data(state->fd, ofd, file_header->pack_size); |
|
1618 |
+ copy_file_data(state->fd, ofd, state->file_header->pack_size); |
|
1611 | 1619 |
} else { |
1612 |
- state->unpack_data->dest_unp_size = file_header->unpack_size; |
|
1613 |
- state->unpack_data->pack_size = file_header->pack_size; |
|
1614 |
- if (file_header->unpack_ver <= 15) { |
|
1620 |
+ state->unpack_data->dest_unp_size = state->file_header->unpack_size; |
|
1621 |
+ state->unpack_data->pack_size = state->file_header->pack_size; |
|
1622 |
+ if (state->file_header->unpack_ver <= 15) { |
|
1615 | 1623 |
retval = rar_unpack(state->fd, 15, (state->file_count>1) && |
1616 | 1624 |
((state->main_hdr->flags&MHD_SOLID)!=0), state->unpack_data); |
1617 | 1625 |
} else { |
1618 |
- if ((state->file_count == 1) && (file_header->flags & LHD_SOLID)) { |
|
1626 |
+ if ((state->file_count == 1) && (state->file_header->flags & LHD_SOLID)) { |
|
1619 | 1627 |
cli_warnmsg("RAR: First file can't be SOLID.\n"); |
1620 | 1628 |
return CL_ERAR; |
1621 | 1629 |
} else { |
1622 |
- retval = rar_unpack(state->fd, file_header->unpack_ver, |
|
1623 |
- file_header->flags & LHD_SOLID, state->unpack_data); |
|
1630 |
+ retval = rar_unpack(state->fd, state->file_header->unpack_ver, |
|
1631 |
+ state->file_header->flags & LHD_SOLID, state->unpack_data); |
|
1624 | 1632 |
} |
1625 | 1633 |
} |
1626 |
- cli_dbgmsg("Expected File CRC: 0x%x\n", file_header->file_crc); |
|
1634 |
+ cli_dbgmsg("Expected File CRC: 0x%x\n", state->file_header->file_crc); |
|
1627 | 1635 |
cli_dbgmsg("Computed File CRC: 0x%x\n", state->unpack_data->unp_crc^0xffffffff); |
1628 | 1636 |
if (state->unpack_data->unp_crc != 0xffffffff) { |
1629 |
- if (file_header->file_crc != (state->unpack_data->unp_crc^0xffffffff)) { |
|
1637 |
+ if (state->file_header->file_crc != (state->unpack_data->unp_crc^0xffffffff)) { |
|
1630 | 1638 |
cli_warnmsg("RAR CRC error. Please report the bug at http://bugs.clamav.net/\n"); |
1631 | 1639 |
} |
1632 | 1640 |
} |
1633 | 1641 |
if (!retval) { |
1634 | 1642 |
cli_dbgmsg("Corrupt file detected\n"); |
1635 |
- if (file_header->flags & LHD_SOLID) { |
|
1643 |
+ if (state->file_header->flags & LHD_SOLID) { |
|
1636 | 1644 |
cli_dbgmsg("SOLID archive, can't continue\n"); |
1637 | 1645 |
return CL_ERAR; |
1638 | 1646 |
} |
... | ... |
@@ -1640,14 +1647,14 @@ int cli_unrar_extract_next(rar_state_t* state,const char* dirname) |
1640 | 1640 |
} |
1641 | 1641 |
|
1642 | 1642 |
} |
1643 |
- if (lseek(state->fd, file_header->next_offset, SEEK_SET) != file_header->next_offset) { |
|
1644 |
- cli_dbgmsg("ERROR: seek failed: %ld\n", file_header->next_offset); |
|
1645 |
- free(file_header->filename); |
|
1646 |
- free(file_header); |
|
1643 |
+ if (lseek(state->fd, state->file_header->next_offset, SEEK_SET) != state->file_header->next_offset) { |
|
1644 |
+ cli_dbgmsg("ERROR: seek failed: %ld\n", state->file_header->next_offset); |
|
1645 |
+ free(state->file_header->filename); |
|
1646 |
+ free(state->file_header); |
|
1647 | 1647 |
return CL_ERAR; |
1648 | 1648 |
} |
1649 |
- free(file_header->filename); |
|
1650 |
- free(file_header); |
|
1649 |
+ free(state->file_header->filename); |
|
1650 |
+ free(state->file_header); |
|
1651 | 1651 |
unpack_free_data(state->unpack_data); |
1652 | 1652 |
state->file_count++; |
1653 | 1653 |
return CL_SUCCESS; |
... | ... |
@@ -293,6 +293,7 @@ typedef struct unpack_data_tag |
293 | 293 |
} unpack_data_t; |
294 | 294 |
|
295 | 295 |
typedef struct rar_state_tag { |
296 |
+ file_header_t* file_header; |
|
296 | 297 |
rar_metadata_t *metadata; |
297 | 298 |
rar_metadata_t *metadata_tail; |
298 | 299 |
unpack_data_t *unpack_data; |
... | ... |
@@ -327,6 +328,7 @@ enum BLOCK_TYPES |
327 | 327 |
|
328 | 328 |
|
329 | 329 |
int cli_unrar_extract_next(rar_state_t* state,const char* dirname); |
330 |
+int cli_unrar_extract_next_prepare(rar_state_t* state,const char* dirname); |
|
330 | 331 |
int cli_unrar_open(int fd, const char *dirname, rar_state_t* state); |
331 | 332 |
void cli_unrar_close(rar_state_t* state); |
332 | 333 |
unsigned int rar_get_char(int fd, unpack_data_t *unpack_data); |