improve handling of RAR archives

git-svn: trunk@2648
remotes/push_mirror/metadata
Tomasz Kojm 19 years ago
parent 2484614eba
commit 2dbcf7004a
  1. 4
      clamav-devel/ChangeLog
  2. 28
      clamav-devel/libclamav/scanners.c
  3. 79
      clamav-devel/libclamav/unrar/unrar.c
  4. 2
      clamav-devel/libclamav/unrar/unrar.h

@ -1,3 +1,7 @@
Sun Jan 28 21:20:05 CET 2007 (tk)
---------------------------------
* libclamav: improve handling of RAR archives, thanks to Edwin
Sat Jan 27 13:54:35 CET 2007 (acab)
-----------------------------------
* 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
continue;
}
*/
return ret;
}
static int cli_unrar_checklimits(const cli_ctx *ctx, const rar_metadata_t *metadata, unsigned int files)
{
if(ctx->limits) {
if(ctx->limits->maxratio && metadata->unpack_size && metadata->pack_size) {
if((unsigned int) metadata->unpack_size / (unsigned int) metadata->pack_size >= ctx->limits->maxratio) {
cli_dbgmsg("RAR: Max ratio reached (normal: %u, compressed: %u, max: %ld)\n", metadata->unpack_size, metadata->pack_size, ctx->limits->maxratio);
*ctx->virname = "Oversized.RAR";
return CL_VIRUS;
if(BLOCKMAX) {
*ctx->virname = "Oversized.RAR";
return CL_VIRUS;
}
return CL_EMAXSIZE;
}
}
@ -207,7 +215,7 @@ static int cli_unrar_scanmetadata(int desc, rar_metadata_t *metadata, cli_ctx *c
*ctx->virname = "RAR.ExceededFileSize";
return CL_VIRUS;
}
return CL_SUCCESS;
return CL_EMAXSIZE;
}
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
*ctx->virname = "RAR.ExceededFilesLimit";
return CL_VIRUS;
}
return CL_BREAK;
return CL_EMAXFILES;
}
}
return ret;
return CL_SUCCESS;
}
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
do {
int rc;
rar_state.unpack_data->ofd = -1;
ret = cli_unrar_extract_next_prepare(&rar_state,dir);
if(ret != CL_SUCCESS)
break;
ret = cli_unrar_checklimits(ctx, rar_state.metadata_tail, rar_state.file_count);
if(ret && ret != CL_VIRUS) {
ret = CL_CLEAN;
continue;
} else if(ret == CL_VIRUS) {
break;
}
ret = cli_unrar_extract_next(&rar_state,dir);
if(rar_state.unpack_data->ofd > 0) {
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)
return CL_SUCCESS;
}
int cli_unrar_extract_next(rar_state_t* state,const char* dirname)
int cli_unrar_extract_next_prepare(rar_state_t* state,const char* dirname)
{
int retval;
unsigned char filename[1024];
int ofd;
rar_metadata_t *new_metadata;
file_header_t *file_header = read_block(state->fd, FILE_HEAD);
if (!file_header) {
state->file_header = read_block(state->fd, FILE_HEAD);
if (!state->file_header) {
return CL_BREAK;/* end of archive */
}
new_metadata = cli_malloc(sizeof(rar_metadata_t));
if (!new_metadata) {
return CL_EMEM;
}
new_metadata->pack_size = file_header->pack_size;
new_metadata->unpack_size = file_header->unpack_size;
new_metadata->crc = file_header->file_crc;
new_metadata->method = file_header->method;
new_metadata->filename = strdup(file_header->filename);
new_metadata->pack_size = state->file_header->pack_size;
new_metadata->unpack_size = state->file_header->unpack_size;
new_metadata->crc = state->file_header->file_crc;
new_metadata->method = state->file_header->method;
new_metadata->filename = strdup(state->file_header->filename);
new_metadata->next = NULL;
new_metadata->encrypted = FALSE;
if (state->metadata_tail == NULL) {
@ -1555,7 +1554,7 @@ int cli_unrar_extract_next(rar_state_t* state,const char* dirname)
state->metadata_tail->next = new_metadata;
state->metadata_tail = new_metadata;
}
if (file_header->flags & LHD_COMMENT) {
if (state->file_header->flags & LHD_COMMENT) {
comment_header_t *comment_header;
cli_dbgmsg("File comment present\n");
@ -1585,54 +1584,62 @@ int cli_unrar_extract_next(rar_state_t* state,const char* dirname)
free(comment_header);
}
}
if (lseek(state->fd, file_header->start_offset+file_header->head_size, SEEK_SET) !=
file_header->start_offset+file_header->head_size) {
cli_dbgmsg("Seek failed: %ld\n", state->offset+file_header->head_size);
free(file_header->filename);
free(file_header);
return CL_SUCCESS;
}
int cli_unrar_extract_next(rar_state_t* state,const char* dirname)
{
int ofd;
int retval;
if (lseek(state->fd, state->file_header->start_offset+state->file_header->head_size, SEEK_SET) !=
state->file_header->start_offset+state->file_header->head_size) {
cli_dbgmsg("Seek failed: %ld\n", state->offset+state->file_header->head_size);
free(state->file_header->filename);
free(state->file_header);
return CL_ERAR;
}
if (file_header->flags & LHD_PASSWORD) {
cli_dbgmsg("PASSWORDed file: %s\n", file_header->filename);
if (state->file_header->flags & LHD_PASSWORD) {
cli_dbgmsg("PASSWORDed file: %s\n", state->file_header->filename);
state->metadata_tail->encrypted = TRUE;
} else /*if (file_header->unpack_size)*/ {
snprintf(state->filename, 1024, "%s/%lu.ura", dirname, state->file_count);
ofd = open(state->filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600);
if (ofd < 0) {
free(file_header->filename);
free(file_header);
free(state->file_header->filename);
free(state->file_header);
cli_dbgmsg("ERROR: Failed to open output file\n");
return CL_EOPEN;
}
state->unpack_data->ofd = ofd;
if (file_header->method == 0x30) {
if (state->file_header->method == 0x30) {
cli_dbgmsg("Copying stored file (not packed)\n");
copy_file_data(state->fd, ofd, file_header->pack_size);
copy_file_data(state->fd, ofd, state->file_header->pack_size);
} else {
state->unpack_data->dest_unp_size = file_header->unpack_size;
state->unpack_data->pack_size = file_header->pack_size;
if (file_header->unpack_ver <= 15) {
state->unpack_data->dest_unp_size = state->file_header->unpack_size;
state->unpack_data->pack_size = state->file_header->pack_size;
if (state->file_header->unpack_ver <= 15) {
retval = rar_unpack(state->fd, 15, (state->file_count>1) &&
((state->main_hdr->flags&MHD_SOLID)!=0), state->unpack_data);
} else {
if ((state->file_count == 1) && (file_header->flags & LHD_SOLID)) {
if ((state->file_count == 1) && (state->file_header->flags & LHD_SOLID)) {
cli_warnmsg("RAR: First file can't be SOLID.\n");
return CL_ERAR;
} else {
retval = rar_unpack(state->fd, file_header->unpack_ver,
file_header->flags & LHD_SOLID, state->unpack_data);
retval = rar_unpack(state->fd, state->file_header->unpack_ver,
state->file_header->flags & LHD_SOLID, state->unpack_data);
}
}
cli_dbgmsg("Expected File CRC: 0x%x\n", file_header->file_crc);
cli_dbgmsg("Expected File CRC: 0x%x\n", state->file_header->file_crc);
cli_dbgmsg("Computed File CRC: 0x%x\n", state->unpack_data->unp_crc^0xffffffff);
if (state->unpack_data->unp_crc != 0xffffffff) {
if (file_header->file_crc != (state->unpack_data->unp_crc^0xffffffff)) {
if (state->file_header->file_crc != (state->unpack_data->unp_crc^0xffffffff)) {
cli_warnmsg("RAR CRC error. Please report the bug at http://bugs.clamav.net/\n");
}
}
if (!retval) {
cli_dbgmsg("Corrupt file detected\n");
if (file_header->flags & LHD_SOLID) {
if (state->file_header->flags & LHD_SOLID) {
cli_dbgmsg("SOLID archive, can't continue\n");
return CL_ERAR;
}
@ -1640,14 +1647,14 @@ int cli_unrar_extract_next(rar_state_t* state,const char* dirname)
}
}
if (lseek(state->fd, file_header->next_offset, SEEK_SET) != file_header->next_offset) {
cli_dbgmsg("ERROR: seek failed: %ld\n", file_header->next_offset);
free(file_header->filename);
free(file_header);
if (lseek(state->fd, state->file_header->next_offset, SEEK_SET) != state->file_header->next_offset) {
cli_dbgmsg("ERROR: seek failed: %ld\n", state->file_header->next_offset);
free(state->file_header->filename);
free(state->file_header);
return CL_ERAR;
}
free(file_header->filename);
free(file_header);
free(state->file_header->filename);
free(state->file_header);
unpack_free_data(state->unpack_data);
state->file_count++;
return CL_SUCCESS;

@ -293,6 +293,7 @@ typedef struct unpack_data_tag
} unpack_data_t;
typedef struct rar_state_tag {
file_header_t* file_header;
rar_metadata_t *metadata;
rar_metadata_t *metadata_tail;
unpack_data_t *unpack_data;
@ -327,6 +328,7 @@ enum BLOCK_TYPES
int cli_unrar_extract_next(rar_state_t* state,const char* dirname);
int cli_unrar_extract_next_prepare(rar_state_t* state,const char* dirname);
int cli_unrar_open(int fd, const char *dirname, rar_state_t* state);
void cli_unrar_close(rar_state_t* state);
unsigned int rar_get_char(int fd, unpack_data_t *unpack_data);

Loading…
Cancel
Save