~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/cvd.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-03-12 11:30:04 UTC
  • mfrom: (0.41.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100312113004-b0fop4bkycszdd0z
Tags: 0.96~rc1+dfsg-0ubuntu1
* New upstream RC - FFE (LP: #537636):
  - Add OfficialDatabaseOnly option to clamav-base.postinst.in
  - Add LocalSocketGroup option to clamav-base.postinst.in
  - Add LocalSocketMode option to clamav-base.postinst.in
  - Add CrossFilesystems option to clamav-base.postinst.in
  - Add ClamukoScannerCount option to clamav-base.postinst.in
  - Add BytecodeSecurity opiton to clamav-base.postinst.in
  - Add DetectionStatsHostID option to clamav-freshclam.postinst.in
  - Add Bytecode option to clamav-freshclam.postinst.in
  - Add MilterSocketGroup option to clamav-milter.postinst.in
  - Add MilterSocketMode option to clamav-milter.postinst.in
  - Add ReportHostname option to clamav-milter.postinst.in
  - Bump libclamav SO version to 6.1.0 in libclamav6.install
  - Drop clamdmon from clamav.examples (no longer shipped by upstream)
  - Drop libclamav.a from libclamav-dev.install (not built by upstream)
  - Update SO version for lintian override for libclamav6
  - Add new Bytecode Testing Tool, usr/bin/clambc, to clamav.install
  - Add build-depends on python and python-setuptools for new test suite
  - Update debian/copyright for the embedded copy of llvm (using the system
    llvm is not currently feasible)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2007-2008 Sourcefire, Inc.
 
2
 *  Copyright (C) 2007-2010 Sourcefire, Inc.
3
3
 *
4
4
 *  Authors: Tomasz Kojm
5
5
 *
41
41
#include "str.h"
42
42
#include "cvd.h"
43
43
#include "readdb.h"
 
44
#include "default.h"
 
45
#include "sha256.h"
44
46
 
45
47
#define TAR_BLOCKSIZE 512
46
48
 
47
 
#ifndef O_BINARY
48
 
#define O_BINARY        0
49
 
#endif
50
 
 
51
49
static int cli_untgz(int fd, const char *destdir)
52
50
{
53
51
        char *path, osize[13], name[101], type;
108
106
                return -1;
109
107
            }
110
108
 
111
 
            snprintf(path, pathlen, "%s/%s", destdir, name);
 
109
            snprintf(path, pathlen, "%s"PATHSEP"%s", destdir, name);
112
110
            cli_dbgmsg("cli_untgz: Unpacking %s\n", path);
113
111
            type = block[156];
114
112
 
182
180
    return 0;
183
181
}
184
182
 
185
 
static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, unsigned int options)
 
183
static int cli_tgzload(int fd, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, struct cli_dbinfo *dbinfo)
186
184
{
187
185
        char osize[13], name[101];
188
186
        char block[TAR_BLOCKSIZE];
189
187
        int nread, fdd, ret;
190
188
        unsigned int type, size, pad, compr = 1;
191
189
        off_t off;
192
 
        struct cli_dbio dbio;
 
190
        struct cli_dbinfo *db;
 
191
        unsigned char hash[32];
193
192
 
194
193
#define CLOSE_DBIO          \
195
194
    if(compr)               \
196
 
        gzclose(dbio.gzs);  \
 
195
        gzclose(dbio->gzs);  \
197
196
    else                    \
198
 
        fclose(dbio.fs)
 
197
        fclose(dbio->fs)
199
198
 
200
199
    cli_dbgmsg("in cli_tgzload()\n");
201
200
 
214
213
    }
215
214
 
216
215
    if(compr) {
217
 
        if((dbio.gzs = gzdopen(fdd, "rb")) == NULL) {
 
216
        if((dbio->gzs = gzdopen(fdd, "rb")) == NULL) {
218
217
            cli_errmsg("cli_tgzload: Can't gzdopen() descriptor %d, errno = %d\n", fdd, errno);
219
218
            return CL_EOPEN;
220
219
        }
221
 
        dbio.fs = NULL;
 
220
        dbio->fs = NULL;
222
221
    } else {
223
 
        if((dbio.fs = fdopen(fdd, "rb")) == NULL) {
 
222
        if((dbio->fs = fdopen(fdd, "rb")) == NULL) {
224
223
            cli_errmsg("cli_tgzload: Can't fdopen() descriptor %d, errno = %d\n", fdd, errno);
225
224
            return CL_EOPEN;
226
225
        }
227
 
        dbio.gzs = NULL;
228
 
    }
 
226
        dbio->gzs = NULL;
 
227
    }
 
228
 
 
229
    dbio->bufsize = CLI_DEFAULT_DBIO_BUFSIZE;
 
230
    dbio->buf = cli_malloc(dbio->bufsize);
 
231
    if(!dbio->buf) {
 
232
        cli_errmsg("cli_tgzload: Can't allocate memory for dbio->buf\n");
 
233
        CLOSE_DBIO;
 
234
        return CL_EMALFDB;
 
235
    }
 
236
    dbio->bufpt = NULL;
 
237
    dbio->usebuf = 1;
 
238
    dbio->readpt = dbio->buf;
229
239
 
230
240
    while(1) {
231
241
 
232
242
        if(compr)
233
 
            nread = gzread(dbio.gzs, block, TAR_BLOCKSIZE);
 
243
            nread = gzread(dbio->gzs, block, TAR_BLOCKSIZE);
234
244
        else
235
 
            nread = fread(block, 1, TAR_BLOCKSIZE, dbio.fs);
 
245
            nread = fread(block, 1, TAR_BLOCKSIZE, dbio->fs);
236
246
 
237
247
        if(!nread)
238
248
            break;
239
249
 
240
250
        if(nread != TAR_BLOCKSIZE) {
241
251
            cli_errmsg("cli_tgzload: Incomplete block read\n");
 
252
            free(dbio->buf);
242
253
            CLOSE_DBIO;
243
254
            return CL_EMALFDB;
244
255
        }
251
262
 
252
263
        if(strchr(name, '/')) {
253
264
            cli_errmsg("cli_tgzload: Slash separators are not allowed in CVD\n");
 
265
            free(dbio->buf);
254
266
            CLOSE_DBIO;
255
267
            return CL_EMALFDB;
256
268
        }
263
275
                break;
264
276
            case '5':
265
277
                cli_errmsg("cli_tgzload: Directories are not supported in CVD\n");
 
278
                free(dbio->buf);
266
279
                CLOSE_DBIO;
267
280
                return CL_EMALFDB;
268
281
            default:
269
282
                cli_errmsg("cli_tgzload: Unknown type flag '%c'\n", type);
 
283
                free(dbio->buf);
270
284
                CLOSE_DBIO;
271
285
                return CL_EMALFDB;
272
286
        }
276
290
 
277
291
        if((sscanf(osize, "%o", &size)) == 0) {
278
292
            cli_errmsg("cli_tgzload: Invalid size in header\n");
 
293
            free(dbio->buf);
279
294
            CLOSE_DBIO;
280
295
            return CL_EMALFDB;
281
296
        }
282
 
        dbio.size = size;
 
297
        dbio->size = size;
 
298
        dbio->readsize = dbio->size < dbio->bufsize ? dbio->size : dbio->bufsize - 1;
 
299
        dbio->bufpt = NULL;
 
300
        dbio->readpt = dbio->buf;
 
301
        sha256_init(&dbio->sha256ctx);
 
302
        dbio->bread = 0;
283
303
 
284
304
        /* cli_dbgmsg("cli_tgzload: Loading %s, size: %u\n", name, size); */
285
305
        if(compr)
286
 
            off = (off_t) gzseek(dbio.gzs, 0, SEEK_CUR);
 
306
            off = (off_t) gzseek(dbio->gzs, 0, SEEK_CUR);
287
307
        else
288
 
            off = ftell(dbio.fs);
 
308
            off = ftell(dbio->fs);
289
309
 
290
 
        if(CLI_DBEXT(name)) {
291
 
            ret = cli_load(name, engine, signo, options, &dbio);
 
310
        if((!dbinfo && cli_strbcasestr(name, ".info")) || (dbinfo && CLI_DBEXT(name))) {
 
311
            ret = cli_load(name, engine, signo, options, dbio);
292
312
            if(ret) {
293
313
                cli_errmsg("cli_tgzload: Can't load %s\n", name);
 
314
                free(dbio->buf);
294
315
                CLOSE_DBIO;
295
316
                return CL_EMALFDB;
296
317
            }
 
318
            if(!dbinfo) {
 
319
                free(dbio->buf);
 
320
                CLOSE_DBIO;
 
321
                return CL_SUCCESS;
 
322
            } else {
 
323
                db = dbinfo;
 
324
                while(db && strcmp(db->name, name))
 
325
                    db = db->next;
 
326
                if(!db) {
 
327
                    cli_errmsg("cli_tgzload: File %s not found in .info\n", name);
 
328
                    free(dbio->buf);
 
329
                    CLOSE_DBIO;
 
330
                    return CL_EMALFDB;
 
331
                }
 
332
                if(dbio->bread) {
 
333
                    if(db->size != dbio->bread) {
 
334
                        cli_errmsg("cli_tgzload: File %s not correctly loaded\n", name);
 
335
                        free(dbio->buf);
 
336
                        CLOSE_DBIO;
 
337
                        return CL_EMALFDB;
 
338
                    }
 
339
                    sha256_final(&dbio->sha256ctx, hash);
 
340
                    if(memcmp(db->hash, hash, 32)) {
 
341
                        cli_errmsg("cli_tgzload: Invalid checksum for file %s\n", name);
 
342
                        free(dbio->buf);
 
343
                        CLOSE_DBIO;
 
344
                        return CL_EMALFDB;
 
345
                    }
 
346
                }
 
347
            }
297
348
        }
298
349
        pad = size % TAR_BLOCKSIZE ? (TAR_BLOCKSIZE - (size % TAR_BLOCKSIZE)) : 0;
299
350
        if(compr) {
300
 
            if(off == gzseek(dbio.gzs, 0, SEEK_CUR))
301
 
                gzseek(dbio.gzs, size + pad, SEEK_CUR);
 
351
            if(off == gzseek(dbio->gzs, 0, SEEK_CUR))
 
352
                gzseek(dbio->gzs, size + pad, SEEK_CUR);
302
353
            else if(pad)
303
 
                gzseek(dbio.gzs, pad, SEEK_CUR);
 
354
                gzseek(dbio->gzs, pad, SEEK_CUR);
304
355
        } else {
305
 
            if(off == ftell(dbio.fs))
306
 
                fseek(dbio.fs, size + pad, SEEK_CUR);
 
356
            if(off == ftell(dbio->fs))
 
357
                fseek(dbio->fs, size + pad, SEEK_CUR);
307
358
            else if(pad)
308
 
                fseek(dbio.fs, pad, SEEK_CUR);
 
359
                fseek(dbio->fs, pad, SEEK_CUR);
309
360
        }
310
361
    }
311
362
 
 
363
    free(dbio->buf);
312
364
    CLOSE_DBIO;
313
365
    return CL_SUCCESS;
314
366
}
502
554
    return ret;
503
555
}
504
556
 
505
 
int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int daily, unsigned int options, unsigned int cld)
 
557
int cli_cvdload(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, unsigned int cld, const char *dbname)
506
558
{
507
 
        char *dir;
508
559
        struct cl_cvd cvd;
509
560
        int ret;
510
561
        time_t s_time;
511
562
        int cfd;
 
563
        struct cli_dbio dbio;
 
564
        struct cli_dbinfo *dbinfo = NULL;
512
565
 
513
566
    cli_dbgmsg("in cli_cvdload()\n");
514
567
 
515
568
    /* verify */
516
 
 
517
569
    if((ret = cli_cvdverify(fs, &cvd, cld)))
518
570
        return ret;
519
571
 
520
 
    if(cvd.stime && daily) {
 
572
    if(strstr(dbname, "daily.")) {
521
573
        time(&s_time);
522
574
        if(cvd.stime > s_time) {
523
575
            if(cvd.stime - (unsigned int ) s_time > 3600) {
532
584
            cli_warnmsg("***   Please update it as soon as possible.    ***\n");
533
585
            cli_warnmsg("**************************************************\n");
534
586
        }
 
587
        engine->dbversion[0] = cvd.version;
 
588
        engine->dbversion[1] = cvd.stime;
535
589
    }
536
590
 
537
591
    if(cvd.fl > cl_retflevel()) {
542
596
    }
543
597
 
544
598
    cfd = fileno(fs);
545
 
    /* use only operations on file descriptors, and not on the FILE* from here on 
546
 
     * if we seek the FILE*, the underlying descriptor may not seek as expected
547
 
     * (for example on OpenBSD, cygwin, etc.).
548
 
     * So seek the descriptor directly.
549
 
     */ 
550
 
    if(lseek(cfd, 512, SEEK_SET) == -1) {
551
 
        cli_errmsg("cli_cvdload(): lseek(fs, 512, SEEK_SET) failed\n");
552
 
        return CL_ESEEK;
553
 
    }
554
 
 
555
 
    if(daily) {
556
 
        engine->dbversion[0] = cvd.version;
557
 
        engine->dbversion[1] = cvd.stime;
558
 
    }
559
 
 
560
 
    if(options & CL_DB_CVDNOTMP) {
561
 
 
562
 
        return cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL);
563
 
 
564
 
    } else {
565
 
 
566
 
        if(!(dir = cli_gentemp(engine->tmpdir)))
567
 
            return CL_EMEM;
568
 
 
569
 
        if(mkdir(dir, 0700)) {
570
 
            cli_errmsg("cli_cvdload(): Can't create temporary directory %s\n", dir);
571
 
            free(dir);
572
 
            return CL_ETMPDIR;
573
 
        }
574
 
 
575
 
        if(cli_untgz(cfd, dir)) {
576
 
            cli_errmsg("cli_cvdload(): Can't unpack CVD file.\n");
577
 
            free(dir);
578
 
            return CL_ECVD;
579
 
        }
580
 
 
581
 
        /* load extracted directory */
582
 
        ret = cl_load(dir, engine, signo, options | CL_DB_OFFICIAL);
583
 
 
584
 
        cli_rmdirs(dir);
585
 
        free(dir);
586
 
 
 
599
    ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, NULL);
 
600
    if(ret != CL_SUCCESS)
587
601
        return ret;
588
 
    }
 
602
 
 
603
    dbinfo = engine->dbinfo;
 
604
    if(!dbinfo || !dbinfo->cvd || (dbinfo->cvd->version != cvd.version) || (dbinfo->cvd->sigs != cvd.sigs) || (dbinfo->cvd->fl != cvd.fl) || (dbinfo->cvd->stime != cvd.stime)) {
 
605
        cli_errmsg("cli_cvdload: Corrupted CVD header\n");
 
606
        return CL_EMALFDB;
 
607
    }
 
608
    dbinfo = engine->dbinfo ? engine->dbinfo->next : NULL;
 
609
    if(!dbinfo)
 
610
        return CL_EMALFDB;
 
611
 
 
612
    options |= CL_DB_SIGNED;
 
613
    ret = cli_tgzload(cfd, engine, signo, options | CL_DB_OFFICIAL, &dbio, dbinfo);
 
614
 
 
615
    while(engine->dbinfo) {
 
616
        dbinfo = engine->dbinfo;
 
617
        engine->dbinfo = dbinfo->next;
 
618
        mpool_free(engine->mempool, dbinfo->name);
 
619
        mpool_free(engine->mempool, dbinfo->hash);
 
620
        if(dbinfo->cvd)
 
621
            cl_cvdfree(dbinfo->cvd);
 
622
        mpool_free(engine->mempool, dbinfo);
 
623
    }
 
624
 
 
625
    return ret;
589
626
}
590
627
 
591
628
int cli_cvdunpack(const char *file, const char *dir)