8139fd99 |
/* |
e1cbc270 |
* Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2007-2013 Sourcefire, Inc. |
8139fd99 |
* |
2023340a |
* Authors: Tomasz Kojm |
544fa973 |
* |
6289eda8 |
* Summary: Code to parse Clamav CVD database format. |
544fa973 |
* |
6289eda8 |
* Acknowledgements: ClamAV untar code is based on a public domain minitar utility
* by Charles G. Waldman. |
8139fd99 |
*
* This program is free software; you can redistribute it and/or modify |
bb34cb31 |
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. |
8139fd99 |
*
* 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 |
48b7b4a7 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA. |
8139fd99 |
*/
|
6d6e8271 |
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
|
8139fd99 |
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> |
288057e9 |
#ifdef HAVE_UNISTD_H |
5ff81952 |
#include <unistd.h> |
b58fdfc2 |
#endif
#include "zlib.h" |
c48c9d2b |
#include <time.h> |
b58fdfc2 |
#include <errno.h> |
8139fd99 |
#include "clamav.h" |
6a2532ca |
#include "others.h"
#include "dsig.h" |
e4ae7726 |
#include "str.h" |
079229d6 |
#include "cvd.h" |
056d95dc |
#include "readdb.h" |
a6a98456 |
#include "default.h" |
8139fd99 |
#define TAR_BLOCKSIZE 512
|
bebd86a6 |
static void cli_untgz_cleanup(char *path, gzFile infile, FILE *outfile, int fdd)
{ |
cd94be7a |
UNUSEDPARAM(fdd); |
bebd86a6 |
cli_dbgmsg("in cli_untgz_cleanup()\n");
if (path != NULL) |
288057e9 |
free(path);
if (infile != NULL)
gzclose(infile); |
bebd86a6 |
if (outfile != NULL)
fclose(outfile);
}
|
afff80ef |
static int cli_untgz(int fd, const char *destdir) |
8139fd99 |
{ |
288057e9 |
char *path, osize[13], name[101], type;
char block[TAR_BLOCKSIZE];
int nbytes, nread, nwritten, in_block = 0, fdd = -1;
unsigned int size, pathlen = strlen(destdir) + 100 + 5;
FILE *outfile = NULL;
STATBUF foo;
gzFile infile = NULL; |
a7ac5978 |
|
8139fd99 |
cli_dbgmsg("in cli_untgz()\n");
|
288057e9 |
if ((fdd = dup(fd)) == -1) {
cli_errmsg("cli_untgz: Can't duplicate descriptor %d\n", fd);
return -1;
}
if ((infile = gzdopen(fdd, "rb")) == NULL) {
cli_errmsg("cli_untgz: Can't gzdopen() descriptor %d, errno = %d\n", fdd, errno);
if (FSTAT(fdd, &foo) == 0)
close(fdd);
return -1;
}
path = (char *)cli_calloc(sizeof(char), pathlen);
if (!path) {
cli_errmsg("cli_untgz: Can't allocate memory for path\n");
cli_untgz_cleanup(NULL, infile, NULL, fdd);
return -1;
}
while (1) {
nread = gzread(infile, block, TAR_BLOCKSIZE);
if (!in_block && !nread)
break;
if (nread != TAR_BLOCKSIZE) {
cli_errmsg("cli_untgz: Incomplete block read\n");
cli_untgz_cleanup(path, infile, outfile, fdd);
return -1;
}
if (!in_block) {
if (block[0] == '\0') /* We're done */
break;
strncpy(name, block, 100);
name[100] = '\0';
if (strchr(name, '/')) {
cli_errmsg("cli_untgz: Slash separators are not allowed in CVD\n");
cli_untgz_cleanup(path, infile, outfile, fdd);
return -1;
}
snprintf(path, pathlen, "%s" PATHSEP "%s", destdir, name);
cli_dbgmsg("cli_untgz: Unpacking %s\n", path);
type = block[156];
switch (type) {
case '0':
case '\0':
break;
case '5':
cli_errmsg("cli_untgz: Directories are not supported in CVD\n");
cli_untgz_cleanup(path, infile, outfile, fdd);
return -1;
default:
cli_errmsg("cli_untgz: Unknown type flag '%c'\n", type);
cli_untgz_cleanup(path, infile, outfile, fdd);
return -1;
}
if (outfile) {
if (fclose(outfile)) {
cli_errmsg("cli_untgz: Cannot close file %s\n", path);
outfile = NULL;
cli_untgz_cleanup(path, infile, outfile, fdd);
return -1;
}
outfile = NULL;
}
if (!(outfile = fopen(path, "wb"))) {
cli_errmsg("cli_untgz: Cannot create file %s\n", path);
cli_untgz_cleanup(path, infile, outfile, fdd);
return -1;
}
strncpy(osize, block + 124, 12);
osize[12] = '\0';
if ((sscanf(osize, "%o", &size)) == 0) {
cli_errmsg("cli_untgz: Invalid size in header\n");
cli_untgz_cleanup(path, infile, outfile, fdd);
return -1;
}
if (size > 0)
in_block = 1;
} else { /* write or continue writing file contents */
nbytes = size > TAR_BLOCKSIZE ? TAR_BLOCKSIZE : size;
nwritten = fwrite(block, 1, nbytes, outfile);
if (nwritten != nbytes) {
cli_errmsg("cli_untgz: Wrote %d instead of %d (%s)\n", nwritten, nbytes, path);
cli_untgz_cleanup(path, infile, outfile, fdd);
return -1;
}
size -= nbytes;
if (size == 0)
in_block = 0;
} |
8139fd99 |
}
|
bebd86a6 |
cli_untgz_cleanup(path, infile, outfile, fdd); |
8139fd99 |
return 0;
}
|
bebd86a6 |
static void cli_tgzload_cleanup(int comp, struct cli_dbio *dbio, int fdd)
{ |
cd94be7a |
UNUSEDPARAM(fdd); |
bebd86a6 |
cli_dbgmsg("in cli_tgzload_cleanup()\n"); |
288057e9 |
if (comp) { |
bebd86a6 |
gzclose(dbio->gzs);
dbio->gzs = NULL; |
288057e9 |
} else { |
bebd86a6 |
fclose(dbio->fs);
dbio->fs = NULL;
} |
288057e9 |
if (dbio->buf != NULL) { |
bebd86a6 |
free(dbio->buf);
dbio->buf = NULL;
} |
a1cbd793 |
if (dbio->hashctx) { |
da6e06dd |
cl_hash_destroy(dbio->hashctx); |
a1cbd793 |
dbio->hashctx = NULL;
} |
bebd86a6 |
}
|
ace26bfe |
static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, struct cli_dbinfo *dbinfo) |
056d95dc |
{ |
288057e9 |
char osize[13], name[101];
char block[TAR_BLOCKSIZE];
int nread, fdd, ret;
unsigned int type, size, pad, compr = 1;
off_t off;
struct cli_dbinfo *db;
char hash[32]; |
056d95dc |
|
9d193ff2 |
cli_dbgmsg("in cli_tgzload()\n"); |
056d95dc |
|
288057e9 |
if (lseek(fd, 512, SEEK_SET) < 0) { |
0944b8ee |
return CL_ESEEK;
}
|
288057e9 |
if (cli_readn(fd, block, 7) != 7)
return CL_EFORMAT; /* truncated file? */ |
4d7a1184 |
|
288057e9 |
if (!strncmp(block, "COPYING", 7))
compr = 0; |
4d7a1184 |
|
288057e9 |
if (lseek(fd, 512, SEEK_SET) < 0) { |
0944b8ee |
return CL_ESEEK;
} |
e8ae4fae |
|
288057e9 |
if ((fdd = dup(fd)) == -1) {
cli_errmsg("cli_tgzload: Can't duplicate descriptor %d\n", fd);
return CL_EDUP; |
056d95dc |
}
|
288057e9 |
if (compr) {
if ((dbio->gzs = gzdopen(fdd, "rb")) == NULL) {
cli_errmsg("cli_tgzload: Can't gzdopen() descriptor %d, errno = %d\n", fdd, errno);
if (fdd > -1)
close(fdd);
return CL_EOPEN;
}
dbio->fs = NULL; |
e8ae4fae |
} else { |
288057e9 |
if ((dbio->fs = fdopen(fdd, "rb")) == NULL) {
cli_errmsg("cli_tgzload: Can't fdopen() descriptor %d, errno = %d\n", fdd, errno);
if (fdd > -1)
close(fdd);
return CL_EOPEN;
}
dbio->gzs = NULL; |
056d95dc |
}
|
ace26bfe |
dbio->bufsize = CLI_DEFAULT_DBIO_BUFSIZE; |
288057e9 |
dbio->buf = cli_malloc(dbio->bufsize);
if (!dbio->buf) {
cli_errmsg("cli_tgzload: Can't allocate memory for dbio->buf\n");
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB; |
a6a98456 |
} |
288057e9 |
dbio->bufpt = NULL; |
ace26bfe |
dbio->usebuf = 1;
dbio->readpt = dbio->buf; |
a6a98456 |
|
288057e9 |
while (1) {
if (compr)
nread = gzread(dbio->gzs, block, TAR_BLOCKSIZE);
else
nread = fread(block, 1, TAR_BLOCKSIZE, dbio->fs);
if (!nread)
break;
if (nread != TAR_BLOCKSIZE) {
cli_errmsg("cli_tgzload: Incomplete block read\n"); |
a1cbd793 |
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
} |
288057e9 |
if (block[0] == '\0') /* We're done */
break;
strncpy(name, block, 100);
name[100] = '\0';
if (strchr(name, '/')) {
cli_errmsg("cli_tgzload: Slash separators are not allowed in CVD\n");
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
}
type = block[156];
switch (type) {
case '0':
case '\0':
break;
case '5':
cli_errmsg("cli_tgzload: Directories are not supported in CVD\n");
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
default:
cli_errmsg("cli_tgzload: Unknown type flag '%c'\n", type);
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
}
strncpy(osize, block + 124, 12);
osize[12] = '\0';
if ((sscanf(osize, "%o", &size)) == 0) {
cli_errmsg("cli_tgzload: Invalid size in header\n");
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
}
dbio->size = size;
dbio->readsize = dbio->size < dbio->bufsize ? dbio->size : dbio->bufsize - 1;
dbio->bufpt = NULL;
dbio->readpt = dbio->buf;
if (!(dbio->hashctx)) { |
da6e06dd |
dbio->hashctx = cl_hash_init("sha256");
if (!(dbio->hashctx)) {
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
} |
288057e9 |
}
dbio->bread = 0;
/* cli_dbgmsg("cli_tgzload: Loading %s, size: %u\n", name, size); */
if (compr)
off = (off_t)gzseek(dbio->gzs, 0, SEEK_CUR);
else
off = ftell(dbio->fs);
|
afe940da |
if ((!dbinfo && cli_strbcasestr(name, ".info")) || (dbinfo && CLI_DBEXT(name))) { |
288057e9 |
ret = cli_load(name, engine, signo, options, dbio);
if (ret) {
cli_errmsg("cli_tgzload: Can't load %s\n", name);
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
}
if (!dbinfo) {
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_SUCCESS;
} else {
db = dbinfo;
while (db && strcmp(db->name, name))
db = db->next;
if (!db) {
cli_errmsg("cli_tgzload: File %s not found in .info\n", name);
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
}
if (dbio->bread) {
if (db->size != dbio->bread) {
cli_errmsg("cli_tgzload: File %s not correctly loaded\n", name);
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
}
cl_finish_hash(dbio->hashctx, hash);
dbio->hashctx = cl_hash_init("sha256");
if (!(dbio->hashctx)) {
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
}
if (memcmp(db->hash, hash, 32)) {
cli_errmsg("cli_tgzload: Invalid checksum for file %s\n", name);
cli_tgzload_cleanup(compr, dbio, fdd);
return CL_EMALFDB;
}
}
}
}
pad = size % TAR_BLOCKSIZE ? (TAR_BLOCKSIZE - (size % TAR_BLOCKSIZE)) : 0;
if (compr) {
if (off == gzseek(dbio->gzs, 0, SEEK_CUR))
gzseek(dbio->gzs, size + pad, SEEK_CUR);
else if (pad)
gzseek(dbio->gzs, pad, SEEK_CUR);
} else {
if (off == ftell(dbio->fs))
fseek(dbio->fs, size + pad, SEEK_CUR);
else if (pad)
fseek(dbio->fs, pad, SEEK_CUR);
} |
056d95dc |
}
|
bebd86a6 |
cli_tgzload_cleanup(compr, dbio, fdd); |
e8ae4fae |
return CL_SUCCESS; |
056d95dc |
}
|
e4ae7726 |
struct cl_cvd *cl_cvdparse(const char *head) |
8139fd99 |
{ |
288057e9 |
struct cl_cvd *cvd;
char *pt; |
6a2532ca |
|
288057e9 |
if (strncmp(head, "ClamAV-VDB:", 11)) {
cli_errmsg("cli_cvdparse: Not a CVD file\n");
return NULL; |
6a2532ca |
} |
8139fd99 |
|
288057e9 |
if (!(cvd = (struct cl_cvd *)cli_malloc(sizeof(struct cl_cvd)))) {
cli_errmsg("cl_cvdparse: Can't allocate memory for cvd\n");
return NULL; |
e12c29d2 |
} |
8139fd99 |
|
288057e9 |
if (!(cvd->time = cli_strtok(head, 1, ":"))) {
cli_errmsg("cli_cvdparse: Can't parse the creation time\n");
free(cvd);
return NULL; |
976bcd2a |
}
|
288057e9 |
if (!(pt = cli_strtok(head, 2, ":"))) {
cli_errmsg("cli_cvdparse: Can't parse the version number\n");
free(cvd->time);
free(cvd);
return NULL; |
976bcd2a |
} |
8139fd99 |
cvd->version = atoi(pt);
free(pt);
|
288057e9 |
if (!(pt = cli_strtok(head, 3, ":"))) {
cli_errmsg("cli_cvdparse: Can't parse the number of signatures\n");
free(cvd->time);
free(cvd);
return NULL; |
976bcd2a |
} |
8139fd99 |
cvd->sigs = atoi(pt);
free(pt);
|
288057e9 |
if (!(pt = cli_strtok(head, 4, ":"))) {
cli_errmsg("cli_cvdparse: Can't parse the functionality level\n");
free(cvd->time);
free(cvd);
return NULL; |
976bcd2a |
} |
b5134815 |
cvd->fl = atoi(pt); |
8139fd99 |
free(pt);
|
288057e9 |
if (!(cvd->md5 = cli_strtok(head, 5, ":"))) {
cli_errmsg("cli_cvdparse: Can't parse the MD5 checksum\n");
free(cvd->time);
free(cvd);
return NULL; |
976bcd2a |
}
|
288057e9 |
if (!(cvd->dsig = cli_strtok(head, 6, ":"))) {
cli_errmsg("cli_cvdparse: Can't parse the digital signature\n");
free(cvd->time);
free(cvd->md5);
free(cvd);
return NULL; |
976bcd2a |
}
|
288057e9 |
if (!(cvd->builder = cli_strtok(head, 7, ":"))) {
cli_errmsg("cli_cvdparse: Can't parse the builder name\n");
free(cvd->time);
free(cvd->md5);
free(cvd->dsig);
free(cvd);
return NULL; |
976bcd2a |
} |
8139fd99 |
|
288057e9 |
if ((pt = cli_strtok(head, 8, ":"))) {
cvd->stime = atoi(pt);
free(pt); |
a7ac5978 |
} else { |
288057e9 |
cli_dbgmsg("cli_cvdparse: No creation time in seconds (old file format)\n");
cvd->stime = 0; |
a7ac5978 |
} |
c48c9d2b |
|
8139fd99 |
return cvd;
}
struct cl_cvd *cl_cvdhead(const char *file)
{ |
288057e9 |
FILE *fs;
char head[513], *pt;
int i;
unsigned int bread; |
8139fd99 |
|
288057e9 |
if ((fs = fopen(file, "rb")) == NULL) {
cli_errmsg("cl_cvdhead: Can't open file %s\n", file);
return NULL; |
8139fd99 |
}
|
288057e9 |
if (!(bread = fread(head, 1, 512, fs))) {
cli_errmsg("cl_cvdhead: Can't read CVD header in %s\n", file);
fclose(fs);
return NULL; |
e4ae7726 |
}
|
1ccd6e94 |
fclose(fs); |
e4ae7726 |
|
b4bd1749 |
head[bread] = 0; |
288057e9 |
if ((pt = strpbrk(head, "\n\r")))
*pt = 0;
for (i = bread - 1; i > 0 && (head[i] == ' ' || head[i] == '\n' || head[i] == '\r'); head[i] = 0, i--)
; |
e4ae7726 |
return cl_cvdparse(head); |
8139fd99 |
}
void cl_cvdfree(struct cl_cvd *cvd)
{
free(cvd->time);
free(cvd->md5);
free(cvd->dsig);
free(cvd->builder);
free(cvd);
}
|
cdddd014 |
static int cli_cvdverify(FILE *fs, struct cl_cvd *cvdpt, unsigned int skipsig) |
6a2532ca |
{ |
288057e9 |
struct cl_cvd *cvd;
char *md5, head[513];
int i; |
a7ac5978 |
|
1ccd6e94 |
fseek(fs, 0, SEEK_SET); |
288057e9 |
if (fread(head, 1, 512, fs) != 512) {
cli_errmsg("cli_cvdverify: Can't read CVD header\n");
return CL_ECVD; |
e4ae7726 |
}
head[512] = 0; |
288057e9 |
for (i = 511; i > 0 && (head[i] == ' ' || head[i] == 10); head[i] = 0, i--)
; |
6a2532ca |
|
288057e9 |
if ((cvd = cl_cvdparse(head)) == NULL)
return CL_ECVD; |
6a2532ca |
|
288057e9 |
if (cvdpt)
memcpy(cvdpt, cvd, sizeof(struct cl_cvd)); |
6a2532ca |
|
288057e9 |
if (skipsig) {
cl_cvdfree(cvd);
return CL_SUCCESS; |
9d193ff2 |
}
|
d5fde2eb |
md5 = cli_hashstream(fs, NULL, 1); |
a6c9b781 |
if (md5 == NULL) { |
288057e9 |
cli_dbgmsg("cli_cvdverify: Cannot generate hash, out of memory\n");
cl_cvdfree(cvd);
return CL_EMEM; |
a6c9b781 |
} |
6a2532ca |
cli_dbgmsg("MD5(.tar.gz) = %s\n", md5);
|
288057e9 |
if (strncmp(md5, cvd->md5, 32)) {
cli_dbgmsg("cli_cvdverify: MD5 verification error\n");
free(md5);
cl_cvdfree(cvd);
return CL_EVERIFY; |
6a2532ca |
}
|
288057e9 |
if (cli_versig(md5, cvd->dsig)) {
cli_dbgmsg("cli_cvdverify: Digital signature verification error\n");
free(md5);
cl_cvdfree(cvd);
return CL_EVERIFY; |
6a2532ca |
}
|
e4ae7726 |
free(md5); |
9e431a95 |
cl_cvdfree(cvd); |
9d193ff2 |
return CL_SUCCESS; |
6a2532ca |
}
|
e4ae7726 |
int cl_cvdverify(const char *file) |
6a2532ca |
{ |
288057e9 |
struct cl_engine *engine;
FILE *fs;
int ret, dbtype = 0; |
a7ac5978 |
|
288057e9 |
if ((fs = fopen(file, "rb")) == NULL) {
cli_errmsg("cl_cvdverify: Can't open file %s\n", file);
return CL_EOPEN; |
6a2532ca |
}
|
288057e9 |
if (!(engine = cl_engine_new())) {
cli_errmsg("cld_cvdverify: Can't create new engine\n");
fclose(fs);
return CL_EMEM; |
f8202681 |
} |
7c92a662 |
engine->cb_stats_submit = NULL; /* Don't submit stats if we're just verifying a CVD */ |
f8202681 |
|
52da9175 |
if (!!cli_strbcasestr(file, ".cld")) |
288057e9 |
dbtype = 1; |
52da9175 |
else if (!!cli_strbcasestr(file, ".cud")) |
288057e9 |
dbtype = 2; |
52da9175 |
ret = cli_cvdload(fs, engine, NULL, CL_DB_STDOPT | CL_DB_PUA, dbtype, file, 1); |
e4ae7726 |
|
f8202681 |
cl_engine_free(engine);
fclose(fs); |
e4ae7726 |
return ret; |
6a2532ca |
}
|
cdddd014 |
int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int dbtype, const char *filename, unsigned int chkonly) |
8139fd99 |
{ |
288057e9 |
struct cl_cvd cvd, dupcvd;
FILE *dupfs;
int ret;
time_t s_time;
int cfd;
struct cli_dbio dbio;
struct cli_dbinfo *dbinfo = NULL;
char *dupname; |
8139fd99 |
|
a1cbd793 |
dbio.hashctx = NULL;
|
8139fd99 |
cli_dbgmsg("in cli_cvdload()\n");
|
6a2532ca |
/* verify */ |
288057e9 |
if ((ret = cli_cvdverify(fs, &cvd, dbtype)))
return ret;
if (dbtype <= 1) {
/* check for duplicate db */
dupname = cli_strdup(filename);
if (!dupname)
return CL_EMEM;
dupname[strlen(dupname) - 2] = (dbtype == 1 ? 'v' : 'l');
if (!access(dupname, R_OK) && (dupfs = fopen(dupname, "rb"))) {
if ((ret = cli_cvdverify(dupfs, &dupcvd, !dbtype))) {
fclose(dupfs);
free(dupname);
return ret;
}
fclose(dupfs);
if (dupcvd.version > cvd.version) {
cli_warnmsg("Detected duplicate databases %s and %s. The %s database is older and will not be loaded, you should manually remove it from the database directory.\n", filename, dupname, filename);
free(dupname);
return CL_SUCCESS;
} else if (dupcvd.version == cvd.version && !dbtype) {
cli_warnmsg("Detected duplicate databases %s and %s, please manually remove one of them\n", filename, dupname);
free(dupname);
return CL_SUCCESS;
}
}
free(dupname);
}
if (strstr(filename, "daily.")) {
time(&s_time);
if (cvd.stime > s_time) {
if (cvd.stime - (unsigned int)s_time > 3600) {
cli_warnmsg("******************************************************\n");
cli_warnmsg("*** Virus database timestamp in the future! ***\n");
cli_warnmsg("*** Please check the timezone and clock settings ***\n");
cli_warnmsg("******************************************************\n");
}
} else if ((unsigned int)s_time - cvd.stime > 604800) {
cli_warnmsg("**************************************************\n");
cli_warnmsg("*** The virus database is older than 7 days! ***\n");
cli_warnmsg("*** Please update it as soon as possible. ***\n");
cli_warnmsg("**************************************************\n");
}
engine->dbversion[0] = cvd.version;
engine->dbversion[1] = cvd.stime;
}
if (cvd.fl > cl_retflevel()) {
cli_warnmsg("*******************************************************************\n");
cli_warnmsg("*** This version of the ClamAV engine is outdated. ***\n");
cli_warnmsg("*** Read https://www.clamav.net/documents/installing-clamav ***\n");
cli_warnmsg("*******************************************************************\n");
}
cfd = fileno(fs); |
f8202681 |
dbio.chkonly = 0; |
288057e9 |
if (dbtype == 2)
ret = cli_tgzload(cfd, engine, signo, options | CL_DB_UNSIGNED, &dbio, NULL); |
cdddd014 |
else |
288057e9 |
ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, NULL);
if (ret != CL_SUCCESS)
return ret; |
ace26bfe |
|
a2b0a11e |
dbinfo = engine->dbinfo; |
288057e9 |
if (!dbinfo || !dbinfo->cvd || (dbinfo->cvd->version != cvd.version) || (dbinfo->cvd->sigs != cvd.sigs) || (dbinfo->cvd->fl != cvd.fl) || (dbinfo->cvd->stime != cvd.stime)) {
cli_errmsg("cli_cvdload: Corrupted CVD header\n");
return CL_EMALFDB; |
de351ee1 |
} |
a2b0a11e |
dbinfo = engine->dbinfo ? engine->dbinfo->next : NULL; |
288057e9 |
if (!dbinfo) {
cli_errmsg("cli_cvdload: dbinfo error\n");
return CL_EMALFDB; |
e828f534 |
} |
a2b0a11e |
|
f8202681 |
dbio.chkonly = chkonly; |
288057e9 |
if (dbtype == 2)
options |= CL_DB_UNSIGNED; |
cdddd014 |
else |
288057e9 |
options |= CL_DB_SIGNED | CL_DB_OFFICIAL; |
cdddd014 |
ret = cli_tgzload(cfd, engine, signo, options, &dbio, dbinfo); |
ace26bfe |
|
288057e9 |
while (engine->dbinfo) {
dbinfo = engine->dbinfo;
engine->dbinfo = dbinfo->next; |
544fa973 |
MPOOL_FREE(engine->mempool, dbinfo->name);
MPOOL_FREE(engine->mempool, dbinfo->hash); |
288057e9 |
if (dbinfo->cvd)
cl_cvdfree(dbinfo->cvd); |
544fa973 |
MPOOL_FREE(engine->mempool, dbinfo); |
ac1b219c |
}
|
ace26bfe |
return ret; |
8139fd99 |
} |
afff80ef |
int cli_cvdunpack(const char *file, const char *dir)
{ |
288057e9 |
int fd, ret; |
afff80ef |
|
288057e9 |
fd = open(file, O_RDONLY | O_BINARY);
if (fd == -1)
return -1; |
afff80ef |
|
288057e9 |
if (lseek(fd, 512, SEEK_SET) < 0) {
close(fd);
return -1; |
afff80ef |
}
ret = cli_untgz(fd, dir);
close(fd);
return ret;
} |