e6417b01 |
/* |
c442ca9c |
* Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc. |
e6417b01 |
*
* Authors: Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h> |
f1e02ed2 |
#ifdef HAVE_UNISTD_H |
e6417b01 |
#include <unistd.h> |
f1e02ed2 |
#endif |
e6417b01 |
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
|
60d8d2c3 |
#include "clamav.h" |
e6417b01 |
#include "others.h"
#include "cpio.h"
#include "scanners.h" |
570b1d00 |
#include "matcher.h" |
e6417b01 |
struct cpio_hdr_old {
uint16_t magic;
uint16_t dev;
uint16_t ino;
uint16_t mode;
uint16_t uid;
uint16_t gid;
uint16_t nlink;
uint16_t rdev;
uint16_t mtime[2];
uint16_t namesize;
uint16_t filesize[2];
};
struct cpio_hdr_odc {
char magic[6];
char dev[6];
char ino[6];
char mode[6];
char uid[6];
char gid[6];
char nlink[6];
char rdev[6];
char mtime[11];
char namesize[6];
char filesize[11];
};
struct cpio_hdr_newc {
char magic[6];
char ino[8];
char mode[8];
char uid[8];
char gid[8];
char nlink[8];
char mtime[8];
char filesize[8];
char devmajor[8];
char devminor[8];
char rdevmajor[8];
char rdevminor[8];
char namesize[8];
char check[8];
};
|
3222a096 |
#define EC16(v, conv) (conv ? cbswap16(v) : v) |
e6417b01 |
static void sanitname(char *name)
{
while(*name) {
if(!isascii(*name) || strchr("%\\\t\n\r", *name))
*name = '_';
name++;
}
}
|
87af1d57 |
int cli_scancpio_old(cli_ctx *ctx) |
e6417b01 |
{
struct cpio_hdr_old hdr_old;
char name[513];
unsigned int file = 0, trailer = 0;
uint32_t filesize, namesize, hdr_namesize; |
7a307529 |
int ret = CL_CLEAN, conv; |
87af1d57 |
off_t pos = 0; |
7a307529 |
int virus_found = 0; |
e6417b01 |
|
87af1d57 |
while(fmap_readn(*ctx->fmap, &hdr_old, pos, sizeof(hdr_old)) == sizeof(hdr_old)) {
pos += sizeof(hdr_old); |
7a307529 |
if(!hdr_old.magic && trailer) {
ret = CL_SUCCESS;
goto leave;
} |
e6417b01 |
if(hdr_old.magic == 070707) {
conv = 0;
} else if(hdr_old.magic == 0143561) {
conv = 1;
} else {
cli_dbgmsg("cli_scancpio_old: Invalid magic number\n"); |
7a307529 |
ret = CL_EFORMAT;
goto leave; |
e6417b01 |
}
cli_dbgmsg("CPIO: -- File %u --\n", ++file);
if(hdr_old.namesize) {
hdr_namesize = EC16(hdr_old.namesize, conv);
namesize = MIN(sizeof(name), hdr_namesize); |
cd94be7a |
if ((uint32_t)fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) { |
e6417b01 |
cli_dbgmsg("cli_scancpio_old: Can't read file name\n");
return CL_EFORMAT;
} |
87af1d57 |
pos += namesize; |
e6417b01 |
name[namesize - 1] = 0;
sanitname(name);
cli_dbgmsg("CPIO: Name: %s\n", name);
if(!strcmp(name, "TRAILER!!!"))
trailer = 1;
if(namesize < hdr_namesize) {
if(hdr_namesize % 2)
hdr_namesize++; |
87af1d57 |
pos += hdr_namesize - namesize; |
e6417b01 |
} else if(hdr_namesize % 2) |
87af1d57 |
pos++; |
e6417b01 |
} |
f1d82e2f |
filesize = (uint32_t)((uint32_t)EC16(hdr_old.filesize[0], conv) << 16 | EC16(hdr_old.filesize[1], conv)); |
e6417b01 |
cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
if(!filesize)
continue;
|
7a307529 |
if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) { |
d7979d4f |
if (!SCAN_ALLMATCHES) |
7a307529 |
return CL_VIRUS;
virus_found = 1;
} |
570b1d00 |
|
e6417b01 |
if((EC16(hdr_old.mode, conv) & 0170000) != 0100000) {
cli_dbgmsg("CPIO: Not a regular file, skipping\n");
} else {
ret = cli_checklimits("cli_scancpio_old", ctx, filesize, 0, 0);
if(ret == CL_EMAXFILES) { |
7a307529 |
goto leave; |
e6417b01 |
} else if(ret == CL_SUCCESS) { |
328a3325 |
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY); |
7a307529 |
if(ret == CL_VIRUS) { |
d7979d4f |
if (!SCAN_ALLMATCHES) |
7a307529 |
return ret;
virus_found = 1;
} |
e6417b01 |
}
}
if(filesize % 2)
filesize++;
|
87af1d57 |
pos += filesize; |
e6417b01 |
}
|
7a307529 |
leave:
if (virus_found != 0)
return CL_VIRUS;
return ret; |
e6417b01 |
}
|
87af1d57 |
int cli_scancpio_odc(cli_ctx *ctx) |
e6417b01 |
{
struct cpio_hdr_odc hdr_odc;
char name[513], buff[12];
unsigned int file = 0, trailer = 0;
uint32_t filesize, namesize, hdr_namesize; |
7a307529 |
int ret = CL_CLEAN; |
87af1d57 |
off_t pos = 0; |
7a307529 |
int virus_found = 0; |
e6417b01 |
|
87af1d57 |
while(fmap_readn(*ctx->fmap, &hdr_odc, pos, sizeof(hdr_odc)) == sizeof(hdr_odc)) {
pos += sizeof(hdr_odc); |
e6417b01 |
if(!hdr_odc.magic[0] && trailer) |
7a307529 |
goto leave; |
e6417b01 |
if(strncmp(hdr_odc.magic, "070707", 6)) {
cli_dbgmsg("cli_scancpio_odc: Invalid magic string\n"); |
7a307529 |
ret = CL_EFORMAT;
goto leave; |
e6417b01 |
}
cli_dbgmsg("CPIO: -- File %u --\n", ++file);
strncpy(buff, hdr_odc.namesize, 6);
buff[6] = 0;
if(sscanf(buff, "%o", &hdr_namesize) != 1) {
cli_dbgmsg("cli_scancpio_odc: Can't convert name size\n"); |
7a307529 |
ret = CL_EFORMAT;
goto leave; |
e6417b01 |
}
if(hdr_namesize) {
namesize = MIN(sizeof(name), hdr_namesize); |
cd94be7a |
if ((uint32_t)fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) { |
e6417b01 |
cli_dbgmsg("cli_scancpio_odc: Can't read file name\n"); |
7a307529 |
ret = CL_EFORMAT;
goto leave; |
e6417b01 |
} |
87af1d57 |
pos += namesize; |
e6417b01 |
name[namesize - 1] = 0;
sanitname(name);
cli_dbgmsg("CPIO: Name: %s\n", name);
if(!strcmp(name, "TRAILER!!!"))
trailer = 1;
if(namesize < hdr_namesize) |
87af1d57 |
pos += hdr_namesize - namesize; |
e6417b01 |
}
strncpy(buff, hdr_odc.filesize, 11);
buff[11] = 0;
if(sscanf(buff, "%o", &filesize) != 1) {
cli_dbgmsg("cli_scancpio_odc: Can't convert file size\n"); |
7a307529 |
ret = CL_EFORMAT;
goto leave; |
e6417b01 |
}
cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
if(!filesize)
continue;
|
7a307529 |
if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) { |
d7979d4f |
if (!SCAN_ALLMATCHES) |
7a307529 |
return CL_VIRUS;
virus_found = 1;
} |
570b1d00 |
|
e6417b01 |
ret = cli_checklimits("cli_scancpio_odc", ctx, filesize, 0, 0);
if(ret == CL_EMAXFILES) { |
7a307529 |
goto leave; |
e6417b01 |
} else if(ret == CL_SUCCESS) { |
328a3325 |
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY); |
7a307529 |
if(ret == CL_VIRUS) { |
d7979d4f |
if (!SCAN_ALLMATCHES) |
7a307529 |
return ret;
virus_found = 1;
} |
e6417b01 |
}
|
87af1d57 |
pos += filesize; |
e6417b01 |
}
|
7a307529 |
leave:
if (virus_found != 0)
return CL_VIRUS;
return ret; |
e6417b01 |
}
|
87af1d57 |
int cli_scancpio_newc(cli_ctx *ctx, int crc) |
e6417b01 |
{
struct cpio_hdr_newc hdr_newc;
char name[513], buff[9];
unsigned int file = 0, trailer = 0;
uint32_t filesize, namesize, hdr_namesize, pad; |
7a307529 |
int ret = CL_CLEAN; |
87af1d57 |
off_t pos = 0; |
7a307529 |
int virus_found = 0; |
e6417b01 |
|
c76e6305 |
memset(name, 0, 513); |
e6417b01 |
|
87af1d57 |
while(fmap_readn(*ctx->fmap, &hdr_newc, pos, sizeof(hdr_newc)) == sizeof(hdr_newc)) {
pos += sizeof(hdr_newc); |
e6417b01 |
if(!hdr_newc.magic[0] && trailer) |
7a307529 |
goto leave; |
e6417b01 |
if((!crc && strncmp(hdr_newc.magic, "070701", 6)) || (crc && strncmp(hdr_newc.magic, "070702", 6))) {
cli_dbgmsg("cli_scancpio_newc: Invalid magic string\n"); |
7a307529 |
ret = CL_EFORMAT;
goto leave; |
e6417b01 |
}
cli_dbgmsg("CPIO: -- File %u --\n", ++file);
strncpy(buff, hdr_newc.namesize, 8);
buff[8] = 0;
if(sscanf(buff, "%x", &hdr_namesize) != 1) {
cli_dbgmsg("cli_scancpio_newc: Can't convert name size\n"); |
7a307529 |
ret = CL_EFORMAT;
goto leave; |
e6417b01 |
}
if(hdr_namesize) {
namesize = MIN(sizeof(name), hdr_namesize); |
cd94be7a |
if ((uint32_t)fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) { |
e6417b01 |
cli_dbgmsg("cli_scancpio_newc: Can't read file name\n"); |
7a307529 |
ret = CL_EFORMAT;
goto leave; |
e6417b01 |
} |
87af1d57 |
pos += namesize; |
e6417b01 |
name[namesize - 1] = 0;
sanitname(name);
cli_dbgmsg("CPIO: Name: %s\n", name);
if(!strcmp(name, "TRAILER!!!"))
trailer = 1;
pad = (4 - (sizeof(hdr_newc) + hdr_namesize) % 4) % 4;
if(namesize < hdr_namesize) {
if(pad)
hdr_namesize += pad; |
87af1d57 |
pos += hdr_namesize - namesize; |
e6417b01 |
} else if(pad) |
87af1d57 |
pos += pad; |
e6417b01 |
}
strncpy(buff, hdr_newc.filesize, 8);
buff[8] = 0;
if(sscanf(buff, "%x", &filesize) != 1) {
cli_dbgmsg("cli_scancpio_newc: Can't convert file size\n"); |
7a307529 |
ret = CL_EFORMAT;
goto leave; |
e6417b01 |
}
cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
if(!filesize)
continue;
|
7a307529 |
if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS) { |
d7979d4f |
if (!SCAN_ALLMATCHES) |
7a307529 |
return CL_VIRUS;
virus_found = 1;
} |
e6417b01 |
ret = cli_checklimits("cli_scancpio_newc", ctx, filesize, 0, 0);
if(ret == CL_EMAXFILES) { |
7a307529 |
goto leave; |
e6417b01 |
} else if(ret == CL_SUCCESS) { |
328a3325 |
ret = cli_map_scan(*ctx->fmap, pos, filesize, ctx, CL_TYPE_ANY); |
7a307529 |
if(ret == CL_VIRUS) { |
d7979d4f |
if (!SCAN_ALLMATCHES) |
7a307529 |
return ret;
virus_found = 1;
} |
e6417b01 |
}
if((pad = filesize % 4))
filesize += (4 - pad);
|
87af1d57 |
pos += filesize; |
e6417b01 |
}
|
7a307529 |
leave:
if (virus_found != 0)
return CL_VIRUS;
return ret; |
e6417b01 |
} |