~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/scanners.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:
22
22
#include "clamav-config.h"
23
23
#endif
24
24
 
 
25
#ifndef _WIN32
 
26
#include <sys/time.h>
 
27
#endif
25
28
#include <stdio.h>
26
29
#include <string.h>
27
30
#include <stdlib.h>
35
38
#include <sys/param.h>
36
39
#endif
37
40
#include <fcntl.h>
38
 
#ifndef C_WINDOWS
39
41
#include <dirent.h>
40
 
#include <netinet/in.h>
41
 
#endif
42
 
 
43
 
#if HAVE_MMAP
44
 
#if HAVE_SYS_MMAN_H
45
 
#include <sys/mman.h>
46
 
#else /* HAVE_SYS_MMAN_H */
47
 
#undef HAVE_MMAP
48
 
#endif
49
 
#endif
50
 
 
51
 
#ifndef O_BINARY
52
 
#define O_BINARY        0
53
 
#endif
54
42
 
55
43
#define DCONF_ARCH  ctx->dconf->archive
56
44
#define DCONF_DOC   ctx->dconf->doc
85
73
#include "cab.h"
86
74
#include "rtf.h"
87
75
#include "unarj.h"
88
 
#include "nulsft.h"
 
76
#include "nsis/nulsft.h"
89
77
#include "autoit.h"
90
78
#include "textnorm.h"
91
79
#include <zlib.h>
92
80
#include "unzip.h"
93
81
#include "dlp.h"
94
82
#include "default.h"
 
83
#include "cpio.h"
 
84
#include "macho.h"
 
85
#include "ishield.h"
 
86
#include "7z.h"
 
87
#include "fmap.h"
 
88
#include "cache.h"
95
89
 
96
90
#ifdef HAVE_BZLIB_H
97
91
#include <bzlib.h>
104
98
 
105
99
static int cli_scanfile(const char *filename, cli_ctx *ctx);
106
100
 
107
 
static int cli_scandir(const char *dirname, cli_ctx *ctx, cli_file_t container)
 
101
static int cli_scandir(const char *dirname, cli_ctx *ctx)
108
102
{
109
103
        DIR *dd;
110
104
        struct dirent *dent;
116
110
#endif
117
111
        struct stat statbuf;
118
112
        char *fname;
119
 
        int fd, ret = CL_CLEAN;
120
 
        cli_file_t ftype;
121
113
 
122
114
 
123
115
    if((dd = opendir(dirname)) != NULL) {
128
120
#else
129
121
        while((dent = readdir(dd))) {
130
122
#endif
131
 
#if     (!defined(C_INTERIX)) && (!defined(C_WINDOWS))
132
123
            if(dent->d_ino)
133
 
#endif
134
124
            {
135
125
                if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
136
126
                    /* build the full name */
140
130
                        return CL_EMEM;
141
131
                    }
142
132
 
143
 
                    sprintf(fname, "%s/%s", dirname, dent->d_name);
 
133
                    sprintf(fname, "%s"PATHSEP"%s", dirname, dent->d_name);
144
134
 
145
135
                    /* stat the file */
146
136
                    if(lstat(fname, &statbuf) != -1) {
147
137
                        if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) {
148
 
                            if(cli_scandir(fname, ctx, container) == CL_VIRUS) {
 
138
                            if(cli_scandir(fname, ctx) == CL_VIRUS) {
149
139
                                free(fname);
150
140
                                closedir(dd);
151
141
                                return CL_VIRUS;
157
147
                                    closedir(dd);
158
148
                                    return CL_VIRUS;
159
149
                                }
160
 
 
161
 
                                if(container == CL_TYPE_MAIL) {
162
 
                                    fd = open(fname, O_RDONLY|O_BINARY);
163
 
                                    if(fd == -1) {
164
 
                                            char err[128];
165
 
                                            cli_warnmsg("Cannot open file %s: %s, mode: %x\n", fname, cli_strerror(errno, err, sizeof(err)), statbuf.st_mode);
166
 
                                            free(fname);
167
 
                                            continue;
168
 
                                    }
169
 
                                    ftype = cli_filetype2(fd, ctx->engine);
170
 
                                    if(ftype >= CL_TYPE_TEXT_ASCII && ftype <= CL_TYPE_TEXT_UTF16BE) {
171
 
                                        lseek(fd, 0, SEEK_SET);
172
 
                                        ret = cli_scandesc(fd, ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR);
173
 
                                    }
174
 
                                    close(fd);
175
 
                                    if(ret == CL_VIRUS) {
176
 
                                        free(fname);
177
 
                                        closedir(dd);
178
 
                                        return CL_VIRUS;
179
 
                                    }
180
 
                                }
181
150
                            }
182
151
                        }
183
152
                    }
197
166
static int cli_unrar_scanmetadata(int desc, unrar_metadata_t *metadata, cli_ctx *ctx, unsigned int files, uint32_t* sfx_check)
198
167
{
199
168
        int ret = CL_SUCCESS;
200
 
        struct cli_meta_node* mdata;
201
 
 
202
169
 
203
170
    if(files == 1 && sfx_check) {
204
171
        if(*sfx_check == metadata->crc)
212
179
        (unsigned int) metadata->unpack_size, metadata->method,
213
180
        metadata->pack_size ? (unsigned int) (metadata->unpack_size / metadata->pack_size) : 0);
214
181
 
215
 
    /* Scan metadata */
216
 
    mdata = ctx->engine->rar_mlist;
217
 
    if(mdata) do {
218
 
        if(mdata->encrypted != metadata->encrypted)
219
 
            continue;
220
 
 
221
 
        if(mdata->crc32 && (unsigned int) mdata->crc32 != metadata->crc)
222
 
            continue;
223
 
 
224
 
        if(mdata->csize > 0 && (unsigned int) mdata->csize != metadata->pack_size)
225
 
            continue;
226
 
 
227
 
        if(mdata->size >= 0 && (unsigned int) mdata->size != metadata->unpack_size)
228
 
            continue;
229
 
 
230
 
        if(mdata->method >= 0 && mdata->method != metadata->method)
231
 
            continue;
232
 
 
233
 
        if(mdata->fileno && mdata->fileno != files)
234
 
            continue;
235
 
 
236
 
        if(mdata->maxdepth && ctx->recursion > mdata->maxdepth)
237
 
            continue;
238
 
 
239
 
        if(mdata->filename && !cli_matchregex(metadata->filename, mdata->filename))
240
 
            continue;
241
 
 
242
 
        break; /* matched */
243
 
 
244
 
    } while((mdata = mdata->next));
245
 
 
246
 
    if(mdata) {
247
 
        *ctx->virname = mdata->virname;
248
 
        return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
249
 
    }
 
182
    if(cli_matchmeta(ctx, metadata->filename, metadata->pack_size, metadata->unpack_size, metadata->encrypted, files, metadata->crc, NULL) == CL_VIRUS)
 
183
        return CL_VIRUS;
250
184
 
251
185
    if(DETECT_ENCRYPTED && metadata->encrypted) {
252
186
        cli_dbgmsg("RAR: Encrypted files found in archive.\n");
253
187
        lseek(desc, 0, SEEK_SET);
254
188
        ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR);
255
189
        if(ret != CL_VIRUS) {
256
 
            *ctx->virname = "Encrypted.RAR";
 
190
            *ctx->virname = "Heuristics.Encrypted.RAR";
257
191
            return CL_VIRUS;
258
192
        }
259
193
    }
295
229
                lseek(desc, 0, SEEK_SET);
296
230
                ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR);
297
231
                if(ret != CL_VIRUS)
298
 
                    *ctx->virname = "Encrypted.RAR";
 
232
                    *ctx->virname = "Heuristics.Encrypted.RAR";
299
233
                return CL_VIRUS;
300
234
            }
301
235
            return CL_CLEAN;
361
295
 
362
296
    metadata = metadata_tmp = rar_state.metadata; 
363
297
 
364
 
    if(cli_scandir(rar_state.comment_dir, ctx, 0) == CL_VIRUS)
 
298
    if(cli_scandir(rar_state.comment_dir, ctx) == CL_VIRUS)
365
299
        ret = CL_VIRUS;
366
300
 
367
301
    cli_unrar_close(&rar_state);
385
319
 
386
320
static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
387
321
{
388
 
        int ret = CL_CLEAN, rc;
 
322
        int ret = CL_CLEAN, rc, file = 0;
389
323
        arj_metadata_t metadata;
390
324
        char *dir;
391
325
 
419
353
        if (ret != CL_SUCCESS) {
420
354
           break;
421
355
        }
 
356
        file++;
 
357
        if(cli_matchmeta(ctx, metadata.filename, metadata.comp_size, metadata.orig_size, metadata.encrypted, file, 0, NULL) == CL_VIRUS)
 
358
            return CL_VIRUS;
 
359
 
422
360
        if ((ret = cli_checklimits("ARJ", ctx, metadata.orig_size, metadata.comp_size, 0))!=CL_CLEAN) {
423
361
            ret = CL_SUCCESS;
424
362
            if (metadata.filename)
462
400
    return ret;
463
401
}
464
402
 
465
 
static int cli_scangzip(int desc, cli_ctx *ctx)
 
403
 
 
404
static int cli_scangzip_with_zib_from_the_80s(cli_ctx *ctx, unsigned char *buff) {
 
405
    int fd, ret, outsize = 0, bytes;
 
406
    fmap_t *map = *ctx->fmap;
 
407
    char *tmpname;
 
408
    gzFile gz;
 
409
 
 
410
    fd = dup(map->fd);
 
411
    if(fd < 0)
 
412
        return CL_EDUP;
 
413
 
 
414
    lseek(fd, 0, SEEK_SET);
 
415
    if(!(gz = gzdopen(fd, "rb"))) {
 
416
        close(fd);
 
417
        return CL_EOPEN;
 
418
    }
 
419
 
 
420
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
 
421
        cli_dbgmsg("GZip: Can't generate temporary file.\n");
 
422
        gzclose(gz);
 
423
        return ret;
 
424
    }
 
425
    
 
426
    while((bytes = gzread(gz, buff, FILEBUFF)) > 0) {
 
427
        outsize += bytes;
 
428
        if(cli_checklimits("GZip", ctx, outsize, 0, 0)!=CL_CLEAN)
 
429
            break;
 
430
        if(cli_writen(fd, buff, bytes) != bytes) {
 
431
            close(fd);
 
432
            gzclose(gz);
 
433
            if(cli_unlink(tmpname)) {
 
434
                free(tmpname);
 
435
                return CL_EUNLINK;
 
436
            }
 
437
            free(tmpname);
 
438
            return CL_EWRITE;
 
439
        }
 
440
    }
 
441
 
 
442
    gzclose(gz);
 
443
 
 
444
    if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
 
445
        cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
 
446
        close(fd);
 
447
        if(!ctx->engine->keeptmp) {
 
448
            if (cli_unlink(tmpname)) {
 
449
                free(tmpname);
 
450
                return CL_EUNLINK;
 
451
            }
 
452
        }
 
453
        free(tmpname);
 
454
        return CL_VIRUS;
 
455
    }
 
456
    close(fd);
 
457
    if(!ctx->engine->keeptmp)
 
458
        if (cli_unlink(tmpname)) ret = CL_EUNLINK;
 
459
    free(tmpname);
 
460
    return ret;
 
461
}
 
462
 
 
463
static int cli_scangzip(cli_ctx *ctx)
466
464
{
467
 
        int fd, bytes, ret = CL_CLEAN;
468
 
        unsigned long int size = 0;
469
 
        char *buff;
 
465
        int fd, ret = CL_CLEAN;
 
466
        unsigned char buff[FILEBUFF];
470
467
        char *tmpname;
471
 
        gzFile gd;
472
 
 
473
 
 
 
468
        z_stream z;
 
469
        size_t at = 0, outsize = 0;
 
470
        fmap_t *map = *ctx->fmap;
 
471
        
474
472
    cli_dbgmsg("in cli_scangzip()\n");
475
473
 
476
 
    if((gd = gzdopen(dup(desc), "rb")) == NULL) {
477
 
        cli_dbgmsg("GZip: Can't open descriptor %d\n", desc);
478
 
        return CL_EOPEN;
 
474
    memset(&z, 0, sizeof(z));
 
475
    if((ret = inflateInit2(&z, MAX_WBITS + 16)) != Z_OK) {
 
476
        cli_dbgmsg("GZip: InflateInit failed: %d\n", ret);
 
477
        return cli_scangzip_with_zib_from_the_80s(ctx, buff);
479
478
    }
480
479
 
481
 
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
 
480
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
482
481
        cli_dbgmsg("GZip: Can't generate temporary file.\n");
483
 
        gzclose(gd);
 
482
        inflateEnd(&z);
484
483
        return ret;
485
484
    }
486
485
 
487
 
    if(!(buff = (char *) cli_malloc(FILEBUFF))) {
488
 
        cli_dbgmsg("GZip: Unable to malloc %u bytes.\n", FILEBUFF);
489
 
        gzclose(gd);
490
 
        close(fd);
491
 
        if(!ctx->engine->keeptmp) {
492
 
            if(cli_unlink(tmpname)) {
493
 
                free(tmpname);
494
 
                return CL_EUNLINK;
495
 
            }
496
 
        }
497
 
        return CL_EMEM;
498
 
    }
499
 
 
500
 
    while((bytes = gzread(gd, buff, FILEBUFF)) > 0) {
501
 
        size += bytes;
502
 
 
503
 
        if(cli_checklimits("GZip", ctx, size + FILEBUFF, 0, 0)!=CL_CLEAN)
504
 
            break;
505
 
 
506
 
        if(cli_writen(fd, buff, bytes) != bytes) {
507
 
            cli_dbgmsg("GZip: Can't write to file.\n");
 
486
    while (at < map->len) {
 
487
        unsigned int bytes = MIN(map->len - at, map->pgsz);
 
488
        if(!(z.next_in = fmap_need_off_once(map, at, bytes))) {
 
489
            cli_dbgmsg("GZip: Can't read %u bytes @ %lu.\n", bytes, (long unsigned)at);
 
490
            inflateEnd(&z);
508
491
            close(fd);
509
 
            if(!ctx->engine->keeptmp) {
510
 
                if (cli_unlink(tmpname)) {
 
492
            if (cli_unlink(tmpname)) {
 
493
                free(tmpname);
 
494
                return CL_EUNLINK;
 
495
            }
 
496
            free(tmpname);
 
497
            return CL_EREAD;
 
498
        }
 
499
        at += bytes;
 
500
        z.avail_in = bytes;
 
501
        do {
 
502
            int inf;
 
503
            z.avail_out = sizeof(buff);
 
504
            z.next_out = buff;
 
505
            inf = inflate(&z, Z_NO_FLUSH);
 
506
            if(inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
 
507
                cli_dbgmsg("GZip: Bad stream.\n");
 
508
                at = map->len;
 
509
                break;
 
510
            }
 
511
            if(cli_writen(fd, buff, sizeof(buff) - z.avail_out) < 0) {
 
512
                inflateEnd(&z);     
 
513
                close(fd);
 
514
                if (cli_unlink(tmpname)) {
511
515
                    free(tmpname);
512
 
                    gzclose(gd);
513
 
                    free(buff);
514
516
                    return CL_EUNLINK;
515
517
                }
516
 
            }
517
 
            free(tmpname);      
518
 
            gzclose(gd);
519
 
            free(buff);
520
 
            return CL_EWRITE;
521
 
        }
522
 
    }
523
 
 
524
 
    free(buff);
525
 
    gzclose(gd);
526
 
 
527
 
    if(ret == CL_VIRUS) {
528
 
        close(fd);
529
 
        if(!ctx->engine->keeptmp)
530
 
            if (cli_unlink(tmpname)) ret = CL_EUNLINK;
531
 
        free(tmpname);  
532
 
        return ret;
533
 
    }
534
 
 
535
 
    lseek(fd, 0, SEEK_SET);
536
 
    if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
 
518
                free(tmpname);
 
519
                return CL_EWRITE;
 
520
            }
 
521
            outsize += sizeof(buff) - z.avail_out;
 
522
            if(cli_checklimits("GZip", ctx, outsize, 0, 0)!=CL_CLEAN) {
 
523
                at = map->len;
 
524
                break;
 
525
            }
 
526
            if(inf == Z_STREAM_END) {
 
527
                at -= z.avail_in;
 
528
                inflateReset(&z);
 
529
                break;
 
530
            }
 
531
        } while (z.avail_out == 0);
 
532
    }
 
533
 
 
534
    inflateEnd(&z);         
 
535
 
 
536
    if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
537
537
        cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
538
538
        close(fd);
539
539
        if(!ctx->engine->keeptmp) {
542
542
                return CL_EUNLINK;
543
543
            }
544
544
        }
545
 
        free(tmpname);  
 
545
        free(tmpname);
546
546
        return CL_VIRUS;
547
547
    }
548
548
    close(fd);
549
549
    if(!ctx->engine->keeptmp)
550
550
        if (cli_unlink(tmpname)) ret = CL_EUNLINK;
551
 
    free(tmpname);      
552
 
 
 
551
    free(tmpname);
553
552
    return ret;
554
553
}
555
554
 
716
715
    for(file = cab.files; file; file = file->next) {
717
716
        files++;
718
717
 
 
718
        if(cli_matchmeta(ctx, file->name, 0, file->length, 0, files, 0, NULL) == CL_VIRUS) {
 
719
            ret = CL_VIRUS;
 
720
            break;
 
721
        }
 
722
 
 
723
        if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
 
724
            ret = CL_CLEAN;
 
725
            break;
 
726
        }
 
727
 
719
728
        if(!(tempname = cli_gentemp(ctx->engine->tmpdir))) {
720
729
            ret = CL_EMEM;
721
730
            break;
722
731
        }
723
732
 
724
 
        if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
725
 
            ret = CL_CLEAN;
726
 
            break;
727
 
        }
728
733
        if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
729
734
            file->max_size = ctx->engine->maxscansize - ctx->scansize;
730
735
        else
782
787
 
783
788
        for(i = 0; i < vba_project->count; i++) {
784
789
            for(j = 0; (unsigned int)j < vba_project->colls[i]; j++) {
785
 
                snprintf(vbaname, 1024, "%s/%s_%u", vba_project->dir, vba_project->name[i], j);
 
790
                snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", vba_project->dir, vba_project->name[i], j);
786
791
                vbaname[sizeof(vbaname)-1] = '\0';
787
792
                fd = open(vbaname, O_RDONLY|O_BINARY);
788
793
                if(fd == -1) continue;
816
821
 
817
822
    if(ret == CL_CLEAN && (hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) {
818
823
        while(hashcnt--) {
819
 
            snprintf(vbaname, 1024, "%s/%s_%u", dirname, hash, hashcnt);
 
824
            snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
820
825
            vbaname[sizeof(vbaname)-1] = '\0';
821
826
            fd = open(vbaname, O_RDONLY|O_BINARY);
822
827
            if (fd == -1) continue;
823
828
            if ((fullname = cli_ppt_vba_read(fd, ctx))) {
824
 
                if(cli_scandir(fullname, ctx, 0) == CL_VIRUS) {
 
829
                if(cli_scandir(fullname, ctx) == CL_VIRUS) {
825
830
                    ret = CL_VIRUS;
826
831
                }
827
832
                if(!ctx->engine->keeptmp)
834
839
 
835
840
    if (ret == CL_CLEAN && (hashcnt = uniq_get(U, "worddocument", 12, &hash))) {
836
841
        while(hashcnt--) {
837
 
            snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
 
842
            snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
838
843
            vbaname[sizeof(vbaname)-1] = '\0';
839
844
            fd = open(vbaname, O_RDONLY|O_BINARY);
840
845
            if (fd == -1) continue;
881
886
    /* Check directory for embedded OLE objects */
882
887
    hashcnt = uniq_get(U, "_1_ole10native", 14, &hash);
883
888
    while(hashcnt--) {
884
 
        snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
 
889
        snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
885
890
        vbaname[sizeof(vbaname)-1] = '\0';
886
891
 
887
892
        fd = open(vbaname, O_RDONLY|O_BINARY);
906
911
#else
907
912
        while((dent = readdir(dd))) {
908
913
#endif
909
 
#if     (!defined(C_INTERIX)) && (!defined(C_WINDOWS))
910
914
            if(dent->d_ino)
911
 
#endif
912
915
            {
913
916
                if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
914
917
                    /* build the full name */
917
920
                        ret = CL_EMEM;
918
921
                        break;
919
922
                    }
920
 
                    sprintf(fullname, "%s/%s", dirname, dent->d_name);
 
923
                    sprintf(fullname, "%s"PATHSEP"%s", dirname, dent->d_name);
921
924
 
922
925
                    /* stat the file */
923
926
                    if(lstat(fullname, &statbuf) != -1) {
941
944
    return ret;
942
945
}
943
946
 
944
 
static int cli_scanhtml(int desc, cli_ctx *ctx)
 
947
static int cli_scanhtml(cli_ctx *ctx)
945
948
{
946
949
        char *tempname, fullname[1024];
947
950
        int ret=CL_CLEAN, fd;
948
 
        struct stat sb;
 
951
        fmap_t *map = *ctx->fmap;
949
952
 
950
953
    cli_dbgmsg("in cli_scanhtml()\n");
951
954
 
952
 
    if(fstat(desc, &sb) == -1) {
953
 
        cli_errmsg("cli_scanhtml: fstat() failed for descriptor %d\n", desc);
954
 
        return CL_ESTAT;
955
 
    }
956
 
 
957
955
    /* Because HTML detection is FP-prone and html_normalise_fd() needs to
958
956
     * mmap the file don't normalise files larger than 10 MB.
959
957
     */
960
958
 
961
 
    if(sb.st_size > 10485760) {
 
959
    if(map->len > 10485760) {
962
960
        cli_dbgmsg("cli_scanhtml: exiting (file larger than 10 MB)\n");
963
961
        return CL_CLEAN;
964
962
    }
974
972
 
975
973
    cli_dbgmsg("cli_scanhtml: using tempdir %s\n", tempname);
976
974
 
977
 
    html_normalise_fd(desc, tempname, NULL, ctx->dconf);
978
 
    snprintf(fullname, 1024, "%s/nocomment.html", tempname);
 
975
    html_normalise_map(map, tempname, NULL, ctx->dconf);
 
976
    snprintf(fullname, 1024, "%s"PATHSEP"nocomment.html", tempname);
979
977
    fd = open(fullname, O_RDONLY|O_BINARY);
980
978
    if (fd >= 0) {
981
979
            ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
982
980
            close(fd);
983
981
    }
984
982
 
985
 
    if(ret == CL_CLEAN && sb.st_size < 2097152) {
 
983
    if(ret == CL_CLEAN && map->len < 2097152) {
986
984
            /* limit to 2 MB, we're not interesting in scanning large files in notags form */
987
985
            /* TODO: don't even create notags if file is over 2 MB */
988
 
            snprintf(fullname, 1024, "%s/notags.html", tempname);
 
986
            snprintf(fullname, 1024, "%s"PATHSEP"notags.html", tempname);
989
987
            fd = open(fullname, O_RDONLY|O_BINARY);
990
988
            if(fd >= 0) {
991
989
                    ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
994
992
    }
995
993
 
996
994
    if(ret == CL_CLEAN) {
997
 
            snprintf(fullname, 1024, "%s/javascript", tempname);
 
995
            snprintf(fullname, 1024, "%s"PATHSEP"javascript", tempname);
998
996
            fd = open(fullname, O_RDONLY|O_BINARY);
999
997
            if(fd >= 0) {
1000
998
                    ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
1007
1005
    }
1008
1006
 
1009
1007
    if (ret == CL_CLEAN) {
1010
 
        snprintf(fullname, 1024, "%s/rfc2397", tempname);
1011
 
        ret = cli_scandir(fullname, ctx, 0);
 
1008
        snprintf(fullname, 1024, "%s"PATHSEP"rfc2397", tempname);
 
1009
        ret = cli_scandir(fullname, ctx);
1012
1010
    }
1013
1011
 
1014
1012
    if(!ctx->engine->keeptmp)
1018
1016
    return ret;
1019
1017
}
1020
1018
 
1021
 
static int cli_scanscript(int desc, cli_ctx *ctx)
 
1019
static int cli_scanscript(cli_ctx *ctx)
1022
1020
{
1023
 
        unsigned char buff[FILEBUFF];
 
1021
        unsigned char *buff;
1024
1022
        unsigned char* normalized;
1025
1023
        struct text_norm_state state;
1026
 
        struct stat sb;
1027
1024
        char *tmpname = NULL;
1028
1025
        int ofd = -1, ret;
1029
 
        ssize_t nread;
1030
1026
        const struct cli_matcher *troot = ctx->engine->root[7];
1031
1027
        uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0;
1032
1028
        struct cli_matcher *groot = ctx->engine->root[0];
1033
1029
        struct cli_ac_data gmdata, tmdata;
1034
1030
        struct cli_ac_data *mdata[2];
 
1031
        fmap_t *map = *ctx->fmap;
 
1032
        size_t at = 0;
1035
1033
 
1036
1034
        cli_dbgmsg("in cli_scanscript()\n");
1037
1035
 
1038
 
        if(fstat(desc, &sb) == -1) {
1039
 
                cli_errmsg("cli_scanscript: fstat() failed for descriptor %d\n", desc);
1040
 
                return CL_ESTAT;
1041
 
        }
1042
 
 
1043
 
        /* don't normalize files that are too large */
1044
 
        if(sb.st_size > 5242880) {
 
1036
        if(map->len > 5242880) {
1045
1037
                cli_dbgmsg("cli_scanscript: exiting (file larger than 5 MB)\n");
1046
1038
                return CL_CLEAN;
1047
1039
        }
1063
1055
        text_normalize_init(&state, normalized, SCANBUFF + maxpatlen);
1064
1056
        ret = CL_CLEAN;
1065
1057
 
1066
 
        if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
 
1058
        if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
1067
1059
            return ret;
1068
1060
 
1069
 
        if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) {
 
1061
        if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) {
1070
1062
            cli_ac_freedata(&tmdata);
1071
1063
            return ret;
1072
1064
        }
1073
1065
        mdata[0] = &tmdata;
1074
1066
        mdata[1] = &gmdata;
1075
1067
 
1076
 
        do {
1077
 
                nread = cli_readn(desc, buff, sizeof(buff));
1078
 
                if(nread <= 0 || state.out_pos + nread > state.out_len) {
1079
 
                        /* flush if error/EOF, or too little buffer space left */
1080
 
                        if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
1081
 
                                cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
1082
 
                                close(ofd);
1083
 
                                ofd = -1;
1084
 
                                /* we can continue to scan in memory */
1085
 
                        }
1086
 
                        /* when we flush the buffer also scan */
1087
 
                        if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
1088
 
                                ret = CL_VIRUS;
1089
 
                                if(ofd != -1)
1090
 
                                    ret = cli_checkfp(ofd, ctx) ? CL_CLEAN : CL_VIRUS;
1091
 
                                break;
1092
 
                        }
1093
 
                        if(ctx->scanned)
1094
 
                            *ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
1095
 
                        offset += state.out_pos;
1096
 
                        /* carry over maxpatlen from previous buffer */
1097
 
                        if (state.out_pos > maxpatlen)
1098
 
                                memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen); 
1099
 
                        text_normalize_reset(&state);
1100
 
                        state.out_pos = maxpatlen;
1101
 
                }
1102
 
                if(nread > 0 && (text_normalize_buffer(&state, buff, nread) != nread)) {
1103
 
                        cli_dbgmsg("cli_scanscript: short read during normalizing\n");
1104
 
                }
1105
 
                /* used a do {}while() here, since we need to flush our buffers at the end,
1106
 
                 * and using while(){} loop would mean code duplication */
1107
 
        } while (nread > 0);
1108
 
 
 
1068
        while(1) {
 
1069
            size_t len = MIN(map->pgsz, map->len - at);
 
1070
            buff = fmap_need_off_once(map, at, len);
 
1071
            at += len;
 
1072
            if(!buff || !len || state.out_pos + len > state.out_len) {
 
1073
                /* flush if error/EOF, or too little buffer space left */
 
1074
                if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
 
1075
                    cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
 
1076
                    close(ofd);
 
1077
                    ofd = -1;
 
1078
                    /* we can continue to scan in memory */
 
1079
                }
 
1080
                /* when we flush the buffer also scan */
 
1081
                if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
 
1082
                    ret = CL_VIRUS;
 
1083
                    break;
 
1084
                }
 
1085
                if(ctx->scanned)
 
1086
                    *ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
 
1087
                offset += state.out_pos;
 
1088
                /* carry over maxpatlen from previous buffer */
 
1089
                if (state.out_pos > maxpatlen)
 
1090
                    memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen); 
 
1091
                text_normalize_reset(&state);
 
1092
                state.out_pos = maxpatlen;
 
1093
            }
 
1094
            if(!len) break;
 
1095
            if(text_normalize_buffer(&state, buff, len) != len) {
 
1096
                cli_dbgmsg("cli_scanscript: short read during normalizing\n");
 
1097
            }
 
1098
        }
1109
1099
        cli_ac_freedata(&tmdata);
1110
1100
        cli_ac_freedata(&gmdata);
1111
1101
        if(ctx->engine->keeptmp) {
1117
1107
        return ret;
1118
1108
}
1119
1109
 
1120
 
static int cli_scanhtml_utf16(int desc, cli_ctx *ctx)
 
1110
static int cli_scanhtml_utf16(cli_ctx *ctx)
1121
1111
{
1122
 
        char *tempname, buff[512], *decoded;
 
1112
        char *tempname, *decoded, *buff;
1123
1113
        int ret = CL_CLEAN, fd, bytes;
1124
 
 
 
1114
        size_t at = 0;
 
1115
        fmap_t *map = *ctx->fmap;
1125
1116
 
1126
1117
    cli_dbgmsg("in cli_scanhtml_utf16()\n");
1127
1118
 
1136
1127
 
1137
1128
    cli_dbgmsg("cli_scanhtml_utf16: using tempfile %s\n", tempname);
1138
1129
 
1139
 
    while((bytes = read(desc, buff, sizeof(buff))) > 0) {
 
1130
    while(at < map->len) {
 
1131
        bytes = MIN(map->len - at, map->pgsz * 16);
 
1132
        if(!(buff = fmap_need_off_once(map, at, bytes))) {
 
1133
            close(fd);
 
1134
            cli_unlink(tempname);
 
1135
            free(tempname);
 
1136
            return CL_EREAD;
 
1137
        }
 
1138
        at += bytes;
1140
1139
        decoded = cli_utf16toascii(buff, bytes);
1141
1140
        if(decoded) {
1142
 
            if(write(fd, decoded, strlen(decoded)) == -1) {
 
1141
            if(write(fd, decoded, bytes / 2) == -1) {
1143
1142
                cli_errmsg("cli_scanhtml_utf16: Can't write to file %s\n", tempname);
1144
1143
                free(decoded);
1145
1144
                close(fd);
1151
1150
        }
1152
1151
    }
1153
1152
 
1154
 
    lseek(fd, 0, SEEK_SET);
1155
 
    ret = cli_scanhtml(fd, ctx);
 
1153
    *ctx->fmap = fmap(fd, 0, 0);
 
1154
    if(*ctx->fmap) {
 
1155
        ret = cli_scanhtml(ctx);
 
1156
        funmap(*ctx->fmap);
 
1157
    } else
 
1158
        cli_errmsg("cli_scanhtml_utf16: fmap of %s failed\n", tempname);
 
1159
 
 
1160
    *ctx->fmap = map;
1156
1161
    close(fd);
1157
1162
 
1158
1163
    if(!ctx->engine->keeptmp) {
1164
1169
    return ret;
1165
1170
}
1166
1171
 
1167
 
static int cli_scanole2(int desc, cli_ctx *ctx)
 
1172
static int cli_scanole2(cli_ctx *ctx)
1168
1173
{
1169
1174
        char *dir;
1170
1175
        int ret = CL_CLEAN;
1185
1190
        return CL_ETMPDIR;
1186
1191
    }
1187
1192
 
1188
 
    ret = cli_ole2_extract(desc, dir, ctx, &vba);
 
1193
    ret = cli_ole2_extract(dir, ctx, &vba);
1189
1194
    if(ret!=CL_CLEAN && ret!=CL_VIRUS) {
1190
1195
        cli_dbgmsg("OLE2: %s\n", cl_strerror(ret));
1191
1196
        if(!ctx->engine->keeptmp)
1200
1205
        ret = cli_vba_scandir(dir, ctx, vba);
1201
1206
        uniq_free(vba);
1202
1207
        if(ret != CL_VIRUS)
1203
 
            if(cli_scandir(dir, ctx, 0) == CL_VIRUS)
 
1208
            if(cli_scandir(dir, ctx) == CL_VIRUS)
1204
1209
                ret = CL_VIRUS;
1205
1210
        ctx->recursion--;
1206
1211
    }
1238
1243
    return ret;
1239
1244
}
1240
1245
 
1241
 
static int cli_scanbinhex(int desc, cli_ctx *ctx)
1242
 
{
1243
 
        char *dir;
1244
 
        int ret = CL_CLEAN;
1245
 
 
1246
 
 
1247
 
    cli_dbgmsg("in cli_scanbinhex()\n");
1248
 
 
1249
 
    /* generate temporary directory */
1250
 
    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
1251
 
        return CL_EMEM;
1252
 
 
1253
 
    if(mkdir(dir, 0700)) {
1254
 
        cli_errmsg("Binhex: Can't create temporary directory %s\n", dir);
1255
 
        free(dir);
1256
 
        return CL_ETMPDIR;
1257
 
    }
1258
 
 
1259
 
    if((ret = cli_binhex(dir, desc)))
1260
 
        cli_dbgmsg("Binhex: %s\n", cl_strerror(ret));
1261
 
    else
1262
 
        ret = cli_scandir(dir, ctx, 0);
1263
 
 
1264
 
    if(!ctx->engine->keeptmp)
1265
 
        cli_rmdirs(dir);
1266
 
 
1267
 
    free(dir);
1268
 
    return ret;
1269
 
}
1270
 
 
1271
1246
static int cli_scanmschm(int desc, cli_ctx *ctx)
1272
1247
{
1273
1248
        int ret = CL_CLEAN, rc;
1296
1271
    }
1297
1272
 
1298
1273
   do {
1299
 
        ret = cli_chm_prepare_file(desc, dir, &metadata);
 
1274
        ret = cli_chm_prepare_file(&metadata);
1300
1275
        if (ret != CL_SUCCESS) {
1301
1276
           break;
1302
1277
        }
1303
 
        ret = cli_chm_extract_file(desc, dir, &metadata, ctx);
 
1278
        ret = cli_chm_extract_file(dir, &metadata, ctx);
1304
1279
        if (ret == CL_SUCCESS) {
1305
1280
            lseek(metadata.ofd, 0, SEEK_SET);
1306
1281
            rc = cli_magic_scandesc(metadata.ofd, ctx);
1345
1320
    }
1346
1321
 
1347
1322
    if (html_screnc_decode(desc, tempname))
1348
 
        ret = cli_scandir(tempname, ctx, 0);
 
1323
        ret = cli_scandir(tempname, ctx);
1349
1324
 
1350
1325
    if(!ctx->engine->keeptmp)
1351
1326
        cli_rmdirs(tempname);
1359
1334
        int ret = CL_CLEAN;
1360
1335
 
1361
1336
    if(cli_check_riff_exploit(desc) == 2) {
1362
 
        if(!cli_checkfp(desc, ctx)) {
1363
 
            ret = CL_VIRUS;
1364
 
            *ctx->virname = "Exploit.W32.MS05-002";
1365
 
        }
 
1337
        ret = CL_VIRUS;
 
1338
        *ctx->virname = "Heuristics.Exploit.W32.MS05-002";
1366
1339
    }
1367
1340
 
1368
1341
    return ret;
1373
1346
        int ret = CL_CLEAN;
1374
1347
 
1375
1348
    if(cli_check_jpeg_exploit(desc, ctx) == 1) {
1376
 
        if(!cli_checkfp(desc, ctx)) {
1377
 
            ret = CL_VIRUS;
1378
 
            *ctx->virname = "Exploit.W32.MS04-028";
1379
 
        }
 
1349
        ret = CL_VIRUS;
 
1350
        *ctx->virname = "Heuristics.Exploit.W32.MS04-028";
1380
1351
    }
1381
1352
 
1382
1353
    return ret;
1467
1438
    return ret;
1468
1439
}
1469
1440
 
1470
 
static int cli_scanpdf(int desc, cli_ctx *ctx, off_t offset)
 
1441
static int cli_scanpdf(cli_ctx *ctx, off_t offset)
1471
1442
{
1472
1443
        int ret;
1473
1444
        char *dir = cli_gentemp(ctx->engine->tmpdir);
1481
1452
        return CL_ETMPDIR;
1482
1453
    }
1483
1454
 
1484
 
    ret = cli_pdf(dir, desc, ctx, offset);
 
1455
    ret = cli_pdf(dir, ctx, offset);
1485
1456
 
1486
1457
    if(!ctx->engine->keeptmp)
1487
1458
        cli_rmdirs(dir);
1507
1478
    ret = cli_tnef(dir, desc, ctx);
1508
1479
 
1509
1480
    if(ret == CL_CLEAN)
1510
 
        ret = cli_scandir(dir, ctx, 0);
 
1481
        ret = cli_scandir(dir, ctx);
1511
1482
 
1512
1483
    if(!ctx->engine->keeptmp)
1513
1484
        cli_rmdirs(dir);
1516
1487
    return ret;
1517
1488
}
1518
1489
 
1519
 
static int cli_scanuuencoded(int desc, cli_ctx *ctx)
 
1490
static int cli_scanuuencoded(cli_ctx *ctx)
1520
1491
{
1521
1492
        int ret;
1522
1493
        char *dir = cli_gentemp(ctx->engine->tmpdir);
1530
1501
        return CL_ETMPDIR;
1531
1502
    }
1532
1503
 
1533
 
    ret = cli_uuencode(dir, desc);
 
1504
    ret = cli_uuencode(dir, *ctx->fmap);
1534
1505
 
1535
1506
    if(ret == CL_CLEAN)
1536
 
        ret = cli_scandir(dir, ctx, 0);
 
1507
        ret = cli_scandir(dir, ctx);
1537
1508
 
1538
1509
    if(!ctx->engine->keeptmp)
1539
1510
        cli_rmdirs(dir);
1570
1541
        return ret;
1571
1542
    }
1572
1543
 
1573
 
    ret = cli_scandir(dir, ctx, CL_TYPE_MAIL);
 
1544
    ret = cli_scandir(dir, ctx);
1574
1545
 
1575
1546
    if(!ctx->engine->keeptmp)
1576
1547
        cli_rmdirs(dir);
1635
1606
 
1636
1607
    if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) {
1637
1608
        cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count);
1638
 
        *ctx->virname = "Structured.CreditCardNumber";
1639
 
        return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 
1609
        *ctx->virname = "Heuristics.Structured.CreditCardNumber";
 
1610
        return CL_VIRUS;
1640
1611
    }
1641
1612
 
1642
1613
    if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) {
1643
1614
        cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count);
1644
 
        *ctx->virname = "Structured.SSN";
1645
 
        return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 
1615
        *ctx->virname = "Heuristics.Structured.SSN";
 
1616
        return CL_VIRUS;
1646
1617
    }
1647
1618
 
1648
1619
    return CL_CLEAN;
1714
1685
    return CL_CLEAN;
1715
1686
}
1716
1687
 
1717
 
static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype)
 
1688
static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype, unsigned char *refhash)
1718
1689
{
1719
1690
        int ret = CL_CLEAN, nret = CL_CLEAN;
1720
1691
        struct cli_matched_type *ftoffset = NULL, *fpt;
1721
1692
        uint32_t lastzip, lastrar;
1722
1693
        struct cli_exe_info peinfo;
1723
1694
        unsigned int acmode = AC_SCAN_VIR, break_loop = 0;
1724
 
        struct stat sb;
 
1695
        fmap_t *map = *ctx->fmap;
 
1696
        cli_file_t current_container_type = ctx->container_type;
 
1697
        size_t current_container_size = ctx->container_size;
1725
1698
 
1726
1699
 
1727
1700
    if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
1730
1703
    if(typercg)
1731
1704
        acmode |= AC_SCAN_FT;
1732
1705
 
1733
 
    if(lseek(desc, 0, SEEK_SET) < 0) {
1734
 
        cli_errmsg("cli_scanraw: lseek() failed\n");
1735
 
        return CL_ESEEK;
1736
 
    }
1737
 
 
1738
 
    ret = cli_scandesc(desc, ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode);
 
1706
    ret = cli_fmap_scandesc(ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode, refhash);
1739
1707
 
1740
1708
    if(ret >= CL_TYPENO) {
1741
1709
        ctx->recursion++;
1756
1724
            while(fpt) {
1757
1725
                if(fpt->offset) switch(fpt->type) {
1758
1726
                    case CL_TYPE_RARSFX:
1759
 
                            cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1760
1727
                        if(type != CL_TYPE_RAR && have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR)) {
 
1728
                            ctx->container_type = CL_TYPE_RAR;
 
1729
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1761
1730
                            cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1762
 
                            nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar);
 
1731
                            nret = cli_scanrar(map->fd, ctx, fpt->offset, &lastrar);
1763
1732
                        }
1764
1733
                        break;
1765
1734
 
1766
1735
                    case CL_TYPE_ZIPSFX:
1767
1736
                        if(type != CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
 
1737
                            ctx->container_type = CL_TYPE_ZIP;
 
1738
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1768
1739
                            cli_dbgmsg("ZIP/ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
1769
 
                            nret = cli_unzip_single(desc, ctx, fpt->offset);
 
1740
                            nret = cli_unzip_single(ctx, fpt->offset);
1770
1741
                        }
1771
1742
                        break;
1772
1743
 
1773
1744
                    case CL_TYPE_CABSFX:
1774
1745
                        if(type != CL_TYPE_MSCAB && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB)) {
 
1746
                            ctx->container_type = CL_TYPE_MSCAB;
 
1747
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1775
1748
                            cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
1776
 
                            nret = cli_scanmscab(desc, ctx, fpt->offset);
 
1749
                            nret = cli_scanmscab(map->fd, ctx, fpt->offset);
1777
1750
                        }
1778
1751
                        break;
1779
1752
                    case CL_TYPE_ARJSFX:
1780
1753
                        if(type != CL_TYPE_ARJ && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ)) {
 
1754
                            ctx->container_type = CL_TYPE_ARJ;
 
1755
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1781
1756
                            cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
1782
 
                            nret = cli_scanarj(desc, ctx, fpt->offset, &lastrar);
 
1757
                            nret = cli_scanarj(map->fd, ctx, fpt->offset, &lastrar);
1783
1758
                        }
1784
1759
                        break;
1785
1760
 
1786
1761
                    case CL_TYPE_NULSFT:
1787
1762
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_NSIS) && fpt->offset > 4) {
 
1763
                            ctx->container_type = CL_TYPE_NULSFT;
 
1764
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1788
1765
                            cli_dbgmsg("NSIS signature found at %u\n", (unsigned int) fpt->offset-4);
1789
 
                            nret = cli_scannulsft(desc, ctx, fpt->offset - 4);
 
1766
                            nret = cli_scannulsft(map->fd, ctx, fpt->offset - 4);
1790
1767
                        }
1791
1768
                        break;
1792
1769
 
1793
1770
                    case CL_TYPE_AUTOIT:
1794
1771
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_AUTOIT)) {
 
1772
                            ctx->container_type = CL_TYPE_AUTOIT;
 
1773
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1795
1774
                            cli_dbgmsg("AUTOIT signature found at %u\n", (unsigned int) fpt->offset);
1796
 
                            nret = cli_scanautoit(desc, ctx, fpt->offset + 23);
 
1775
                            nret = cli_scanautoit(map->fd, ctx, fpt->offset + 23);
 
1776
                        }
 
1777
                        break;
 
1778
 
 
1779
                    case CL_TYPE_ISHIELD_MSI:
 
1780
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ISHIELD)) {
 
1781
                            ctx->container_type = CL_TYPE_AUTOIT;
 
1782
                            ctx->container_size = map->len - fpt->offset; /* not precise */
 
1783
                            cli_dbgmsg("ISHIELD-MSI signature found at %u\n", (unsigned int) fpt->offset);
 
1784
                            nret = cli_scanishield_msi(ctx, fpt->offset + 14);
1797
1785
                        }
1798
1786
                        break;
1799
1787
 
1800
1788
                    case CL_TYPE_PDF:
1801
1789
                        if(type != CL_TYPE_PDF && SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
 
1790
                            ctx->container_type = CL_TYPE_PDF;
 
1791
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1802
1792
                            cli_dbgmsg("PDF signature found at %u\n", (unsigned int) fpt->offset);
1803
 
                            nret = cli_scanpdf(desc, ctx, fpt->offset);
 
1793
                            nret = cli_scanpdf(ctx, fpt->offset);
1804
1794
                        }
1805
1795
                        break;
1806
1796
 
1807
1797
                    case CL_TYPE_MSEXE:
1808
1798
                        if(SCAN_PE && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2) && ctx->dconf->pe) {
1809
 
                            fstat(desc, &sb);
1810
 
                            if(sb.st_size > 10485760)
 
1799
                            if(map->len > 10485760)
1811
1800
                                break;
 
1801
                            ctx->container_type = CL_TYPE_MSEXE; /* PE is a container for another executable here */
 
1802
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1812
1803
                            memset(&peinfo, 0, sizeof(struct cli_exe_info));
1813
1804
                            peinfo.offset = fpt->offset;
1814
 
                            lseek(desc, fpt->offset, SEEK_SET);
1815
 
                            if(cli_peheader(desc, &peinfo) == 0) {
 
1805
                            lseek(map->fd, fpt->offset, SEEK_SET);
 
1806
                            if(cli_peheader(map, &peinfo) == 0) {
1816
1807
                                cli_dbgmsg("*** Detected embedded PE file at %u ***\n", (unsigned int) fpt->offset);
1817
1808
                                if(peinfo.section)
1818
1809
                                    free(peinfo.section);
1819
1810
 
1820
 
                                lseek(desc, fpt->offset, SEEK_SET);
1821
 
                                nret = cli_scanembpe(desc, ctx);
 
1811
                                lseek(map->fd, fpt->offset, SEEK_SET);
 
1812
                                nret = cli_scanembpe(map->fd, ctx);
1822
1813
                                break_loop = 1; /* we can stop here and other
1823
1814
                                                 * embedded executables will
1824
1815
                                                 * be found recursively
1837
1828
 
1838
1829
                fpt = fpt->next;
1839
1830
            }
 
1831
            ctx->container_type = current_container_type;
 
1832
            ctx->container_size = current_container_size;
1840
1833
        }
1841
1834
 
1842
1835
        if(nret != CL_VIRUS) switch(ret) {
1843
1836
            case CL_TYPE_HTML:
1844
1837
                if(SCAN_HTML && type == CL_TYPE_TEXT_ASCII && (DCONF_DOC & DOC_CONF_HTML)) {
1845
1838
                    *dettype = CL_TYPE_HTML;
1846
 
                    nret = cli_scanhtml(desc, ctx);
 
1839
                    nret = cli_scanhtml(ctx);
1847
1840
                }
1848
1841
                break;
1849
1842
 
1850
1843
            case CL_TYPE_MAIL:
 
1844
                ctx->container_type = CL_TYPE_MAIL;
 
1845
                ctx->container_size = map->len;
1851
1846
                if(SCAN_MAIL && type == CL_TYPE_TEXT_ASCII && (DCONF_MAIL & MAIL_CONF_MBOX))
1852
 
                    nret = cli_scanmail(desc, ctx);
 
1847
                    nret = cli_scanmail(map->fd, ctx);
 
1848
                ctx->container_type = current_container_type;
 
1849
                ctx->container_size = current_container_size;
1853
1850
                break;
1854
1851
 
1855
1852
            default:
1866
1863
    }
1867
1864
 
1868
1865
    if(ret == CL_VIRUS)
1869
 
        cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
 
1866
        cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, map->fd);
1870
1867
 
1871
1868
    return ret;
1872
1869
}
1873
1870
 
 
1871
 
 
1872
static void emax_reached(cli_ctx *ctx) {
 
1873
    fmap_t **ctx_fmap = ctx->fmap;
 
1874
    if (!ctx_fmap)
 
1875
        return;
 
1876
    while(*ctx_fmap) {
 
1877
        fmap_t *map = *ctx_fmap;
 
1878
        map->dont_cache_flag = 1;
 
1879
        ctx_fmap--;
 
1880
    }
 
1881
    cli_dbgmsg("emax_reached: marked parents as non cacheable\n");
 
1882
}
 
1883
 
 
1884
#define LINESTR(x) #x
 
1885
#define LINESTR2(x) LINESTR(x)
 
1886
#define __AT__  " at line "LINESTR2(__LINE__)
 
1887
#define ret_from_magicscan(retcode) do {                                        \
 
1888
    cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__);       \
 
1889
    return retcode;                                                     \
 
1890
    } while(0)
 
1891
 
1874
1892
int cli_magic_scandesc(int desc, cli_ctx *ctx)
1875
1893
{
1876
1894
        int ret = CL_CLEAN;
1877
1895
        cli_file_t type, dettype = 0;
1878
1896
        struct stat sb;
1879
1897
        uint8_t typercg = 1;
 
1898
        cli_file_t current_container_type = ctx->container_type;
 
1899
        size_t current_container_size = ctx->container_size, hashed_size;
 
1900
        unsigned char hash[16];
 
1901
        bitset_t *old_hook_lsig_matches;
1880
1902
 
 
1903
    cli_dbgmsg("in cli_magic_scandesc (reclevel: %u/%u)\n", ctx->recursion, ctx->engine->maxreclevel);
1881
1904
    if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
1882
1905
        cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
1883
 
        return CL_CLEAN;
 
1906
        emax_reached(ctx);
 
1907
        ret_from_magicscan(CL_CLEAN);
1884
1908
    }
1885
1909
 
1886
1910
    if(fstat(desc, &sb) == -1) {
1887
1911
        cli_errmsg("magic_scandesc: Can't fstat descriptor %d\n", desc);
1888
 
        return CL_ESTAT;
 
1912
        ret_from_magicscan(CL_ESTAT);
1889
1913
    }
1890
1914
 
1891
1915
    if(sb.st_size <= 5) {
1892
1916
        cli_dbgmsg("Small data (%u bytes)\n", (unsigned int) sb.st_size);
1893
 
        return CL_CLEAN;
 
1917
        ret_from_magicscan(CL_CLEAN);
1894
1918
    }
1895
1919
 
1896
1920
    if(!ctx->engine) {
1897
1921
        cli_errmsg("CRITICAL: engine == NULL\n");
1898
 
        return CL_ENULLARG;
 
1922
        ret_from_magicscan(CL_ENULLARG);
1899
1923
    }
1900
1924
 
1901
1925
    if(!(ctx->engine->dboptions & CL_DB_COMPILED)) {
1902
1926
        cli_errmsg("CRITICAL: engine not compiled\n");
1903
 
        return CL_EMALFDB;
1904
 
    }
1905
 
 
1906
 
    if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
1907
 
        return CL_CLEAN;
 
1927
        ret_from_magicscan(CL_EMALFDB);
 
1928
    }
 
1929
 
 
1930
    if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN) {
 
1931
        emax_reached(ctx);
 
1932
        ret_from_magicscan(CL_CLEAN);
 
1933
    }
 
1934
 
 
1935
    ctx->fmap++;
 
1936
    if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
 
1937
        cli_errmsg("CRITICAL: fmap() failed\n");
 
1938
        ctx->fmap--;
 
1939
        ret_from_magicscan(CL_EMEM);
 
1940
    }
 
1941
 
 
1942
    if(cache_check(hash, ctx) == CL_CLEAN) {
 
1943
        funmap(*ctx->fmap);
 
1944
        ctx->fmap--;
 
1945
        ret_from_magicscan(CL_CLEAN);
 
1946
    }
 
1947
    hashed_size = (*ctx->fmap)->len;
 
1948
    old_hook_lsig_matches = ctx->hook_lsig_matches;
 
1949
    ctx->hook_lsig_matches = NULL;
1908
1950
 
1909
1951
    if(!ctx->options || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
1910
1952
        if(ctx->recursion == ctx->engine->maxreclevel)
1911
1953
            cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n");
1912
1954
        else
1913
1955
            cli_dbgmsg("Raw mode: No support for special files\n");
1914
 
        if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS)
 
1956
 
 
1957
        if((ret = cli_fmap_scandesc(ctx, 0, 0, NULL, AC_SCAN_VIR, hash)) == CL_VIRUS)
1915
1958
            cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
1916
 
        return ret;
 
1959
        else if(ret == CL_CLEAN) {
 
1960
            if(ctx->recursion != ctx->engine->maxreclevel)
 
1961
                cache_add(hash, hashed_size, ctx); /* Only cache if limits are not reached */
 
1962
            else 
 
1963
                emax_reached(ctx);
 
1964
        }
 
1965
 
 
1966
        ctx->hook_lsig_matches = old_hook_lsig_matches;
 
1967
        funmap(*ctx->fmap);
 
1968
        ctx->fmap--;
 
1969
        ret_from_magicscan(ret);
1917
1970
    }
1918
1971
 
1919
 
    lseek(desc, 0, SEEK_SET);
1920
 
    type = cli_filetype2(desc, ctx->engine);
 
1972
    type = cli_filetype2(*ctx->fmap, ctx->engine); /* FIXMEFMAP: port to fmap */
1921
1973
    if(type == CL_TYPE_ERROR) {
1922
1974
        cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
1923
 
        return CL_EREAD;
1924
 
    }
1925
 
    lseek(desc, 0, SEEK_SET);
 
1975
        funmap(*ctx->fmap);
 
1976
        ctx->fmap--;
 
1977
        ctx->hook_lsig_matches = old_hook_lsig_matches;
 
1978
        ret_from_magicscan(CL_EREAD);
 
1979
    }
 
1980
    lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
 
1981
 
 
1982
    ctx->hook_lsig_matches = cli_bitset_init();
 
1983
    if (!ctx->hook_lsig_matches) {
 
1984
        ctx->hook_lsig_matches = old_hook_lsig_matches;
 
1985
        ret_from_magicscan(CL_EMEM);
 
1986
    }
1926
1987
 
1927
1988
    if(type != CL_TYPE_IGNORED && ctx->engine->sdb) {
1928
 
        if((ret = cli_scanraw(desc, ctx, type, 0, &dettype)) == CL_VIRUS)
1929
 
            return CL_VIRUS;
1930
 
        lseek(desc, 0, SEEK_SET);
 
1989
        if((ret = cli_scanraw(ctx, type, 0, &dettype, hash)) == CL_VIRUS) {
 
1990
            ret = cli_checkfp(hash, hashed_size, ctx);
 
1991
            funmap(*ctx->fmap);
 
1992
            ctx->fmap--;
 
1993
            cli_bitset_free(ctx->hook_lsig_matches);
 
1994
            ctx->hook_lsig_matches = old_hook_lsig_matches;
 
1995
            ret_from_magicscan(ret);
 
1996
        }
 
1997
        lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
1931
1998
    }
1932
1999
 
1933
2000
    ctx->recursion++;
1934
 
 
1935
2001
    switch(type) {
1936
2002
        case CL_TYPE_IGNORED:
1937
2003
            break;
1938
2004
 
1939
2005
        case CL_TYPE_RAR:
 
2006
            ctx->container_type = CL_TYPE_RAR;
 
2007
            ctx->container_size = sb.st_size;
1940
2008
            if(have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
1941
2009
                ret = cli_scanrar(desc, ctx, 0, NULL);
1942
2010
            break;
1943
2011
 
1944
2012
        case CL_TYPE_ZIP:
 
2013
            ctx->container_type = CL_TYPE_ZIP;
 
2014
            ctx->container_size = sb.st_size;
1945
2015
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
1946
 
                ret = cli_unzip(desc, ctx);
 
2016
                ret = cli_unzip(ctx);
1947
2017
            break;
1948
2018
 
1949
2019
        case CL_TYPE_GZ:
1950
2020
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GZ))
1951
 
                ret = cli_scangzip(desc, ctx);
 
2021
                ret = cli_scangzip(ctx);
1952
2022
            break;
1953
2023
 
1954
2024
        case CL_TYPE_BZ:
1955
2025
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BZ))
1956
2026
                ret = cli_scanbzip(desc, ctx);
1957
2027
            break;
 
2028
 
1958
2029
        case CL_TYPE_ARJ:
 
2030
            ctx->container_type = CL_TYPE_ARJ;
 
2031
            ctx->container_size = sb.st_size;
1959
2032
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ))
1960
2033
                ret = cli_scanarj(desc, ctx, 0, NULL);
1961
2034
            break;
1962
2035
 
1963
2036
        case CL_TYPE_NULSFT:
1964
 
          if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_NSIS))
 
2037
            ctx->container_type = CL_TYPE_NULSFT;
 
2038
            ctx->container_size = sb.st_size;
 
2039
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_NSIS))
1965
2040
                ret = cli_scannulsft(desc, ctx, 0);
1966
2041
            break;
1967
2042
 
1968
2043
        case CL_TYPE_AUTOIT:
 
2044
            ctx->container_type = CL_TYPE_AUTOIT;
 
2045
            ctx->container_size = sb.st_size;
1969
2046
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_AUTOIT))
1970
2047
                ret = cli_scanautoit(desc, ctx, 23);
1971
2048
            break;
1976
2053
            break;
1977
2054
 
1978
2055
        case CL_TYPE_MSCAB:
 
2056
            ctx->container_type = CL_TYPE_MSCAB;
 
2057
            ctx->container_size = sb.st_size;
1979
2058
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB))
1980
2059
                ret = cli_scanmscab(desc, ctx, 0);
1981
2060
            break;
1982
2061
 
1983
2062
        case CL_TYPE_HTML:
1984
2063
            if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
1985
 
                ret = cli_scanhtml(desc, ctx);
 
2064
                ret = cli_scanhtml(ctx);
1986
2065
            break;
1987
2066
 
1988
2067
        case CL_TYPE_HTML_UTF16:
1989
2068
            if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
1990
 
                ret = cli_scanhtml_utf16(desc, ctx);
 
2069
                ret = cli_scanhtml_utf16(ctx);
1991
2070
            break;
1992
2071
 
1993
2072
        case CL_TYPE_SCRIPT:
1994
2073
            if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
1995
 
                ret = cli_scanscript(desc, ctx);
 
2074
                ret = cli_scanscript(ctx);
1996
2075
            break;
1997
2076
 
1998
2077
        case CL_TYPE_RTF:
 
2078
            ctx->container_type = CL_TYPE_RTF;
 
2079
            ctx->container_size = sb.st_size;
1999
2080
            if(SCAN_ARCHIVE && (DCONF_DOC & DOC_CONF_RTF))
2000
2081
                ret = cli_scanrtf(desc, ctx);
2001
2082
            break;
2002
2083
 
2003
2084
        case CL_TYPE_MAIL:
 
2085
            ctx->container_type = CL_TYPE_MAIL;
 
2086
            ctx->container_size = sb.st_size;
2004
2087
            if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX))
2005
2088
                ret = cli_scanmail(desc, ctx);
2006
2089
            break;
2012
2095
 
2013
2096
        case CL_TYPE_UUENCODED:
2014
2097
            if(DCONF_OTHER & OTHER_CONF_UUENC)
2015
 
                ret = cli_scanuuencoded(desc, ctx);
 
2098
                ret = cli_scanuuencoded(ctx);
2016
2099
            break;
2017
2100
 
2018
2101
        case CL_TYPE_MSCHM:
 
2102
            ctx->container_type = CL_TYPE_MSCHM;
 
2103
            ctx->container_size = sb.st_size;
2019
2104
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CHM))
2020
2105
                ret = cli_scanmschm(desc, ctx);
2021
2106
            break;
2022
2107
 
2023
2108
        case CL_TYPE_MSOLE2:
 
2109
            ctx->container_type = CL_TYPE_MSOLE2;
 
2110
            ctx->container_size = sb.st_size;
2024
2111
            if(SCAN_OLE2 && (DCONF_ARCH & ARCH_CONF_OLE2))
2025
 
                ret = cli_scanole2(desc, ctx);
 
2112
                ret = cli_scanole2(ctx);
 
2113
            break;
 
2114
 
 
2115
        case CL_TYPE_7Z:
 
2116
            ctx->container_type = CL_TYPE_7Z;
 
2117
            ctx->container_size = sb.st_size;
 
2118
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_7Z))
 
2119
                ret = cli_7unz(desc, ctx);
2026
2120
            break;
2027
2121
 
2028
2122
        case CL_TYPE_POSIX_TAR:
 
2123
            ctx->container_type = CL_TYPE_POSIX_TAR;
 
2124
            ctx->container_size = sb.st_size;
2029
2125
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
2030
2126
                ret = cli_scantar(desc, ctx, 1);
2031
2127
            break;
2032
2128
 
2033
2129
        case CL_TYPE_OLD_TAR:
 
2130
            ctx->container_type = CL_TYPE_OLD_TAR;
 
2131
            ctx->container_size = sb.st_size;
2034
2132
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
2035
2133
                ret = cli_scantar(desc, ctx, 0);
2036
2134
            break;
2037
2135
 
 
2136
        case CL_TYPE_CPIO_OLD:
 
2137
            ctx->container_type = CL_TYPE_CPIO_OLD;
 
2138
            ctx->container_size = sb.st_size;
 
2139
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
 
2140
                ret = cli_scancpio_old(desc, ctx);
 
2141
            break;
 
2142
 
 
2143
        case CL_TYPE_CPIO_ODC:
 
2144
            ctx->container_type = CL_TYPE_CPIO_ODC;
 
2145
            ctx->container_size = sb.st_size;
 
2146
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
 
2147
                ret = cli_scancpio_odc(desc, ctx);
 
2148
            break;
 
2149
 
 
2150
        case CL_TYPE_CPIO_NEWC:
 
2151
            ctx->container_type = CL_TYPE_CPIO_NEWC;
 
2152
            ctx->container_size = sb.st_size;
 
2153
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
 
2154
                ret = cli_scancpio_newc(desc, ctx, 0);
 
2155
            break;
 
2156
 
 
2157
        case CL_TYPE_CPIO_CRC:
 
2158
            ctx->container_type = CL_TYPE_CPIO_CRC;
 
2159
            ctx->container_size = sb.st_size;
 
2160
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
 
2161
                ret = cli_scancpio_newc(desc, ctx, 1);
 
2162
            break;
 
2163
 
2038
2164
        case CL_TYPE_BINHEX:
2039
2165
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BINHEX))
2040
 
                ret = cli_scanbinhex(desc, ctx);
 
2166
                ret = cli_binhex(ctx);
2041
2167
            break;
2042
2168
 
2043
2169
        case CL_TYPE_SCRENC:
2056
2182
            break;
2057
2183
 
2058
2184
        case CL_TYPE_PDF: /* FIXMELIMITS: pdf should be an archive! */
 
2185
            ctx->container_type = CL_TYPE_PDF;
 
2186
            ctx->container_size = sb.st_size;
2059
2187
            if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF))
2060
 
                ret = cli_scanpdf(desc, ctx, 0);
 
2188
                ret = cli_scanpdf(ctx, 0);
2061
2189
            break;
2062
2190
 
2063
2191
        case CL_TYPE_CRYPTFF:
2067
2195
 
2068
2196
        case CL_TYPE_ELF:
2069
2197
            if(SCAN_ELF && ctx->dconf->elf)
2070
 
                ret = cli_scanelf(desc, ctx);
 
2198
                ret = cli_scanelf(ctx);
 
2199
            break;
 
2200
 
 
2201
        case CL_TYPE_MACHO:
 
2202
            if(ctx->dconf->macho)
 
2203
                ret = cli_scanmacho(ctx, NULL);
 
2204
            break;
 
2205
 
 
2206
        case CL_TYPE_MACHO_UNIBIN:
 
2207
            if(ctx->dconf->macho)
 
2208
                ret = cli_scanmacho_unibin(ctx);
2071
2209
            break;
2072
2210
 
2073
2211
        case CL_TYPE_SIS:
 
2212
            ctx->container_type = CL_TYPE_SIS;
 
2213
            ctx->container_size = sb.st_size;
2074
2214
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_SIS))
2075
2215
                ret = cli_scansis(desc, ctx);
2076
2216
            break;
2092
2232
            break;
2093
2233
    }
2094
2234
    ctx->recursion--;
 
2235
    ctx->container_type = current_container_type;
 
2236
    ctx->container_size = current_container_size;
2095
2237
 
2096
 
    if(ret == CL_VIRUS)
2097
 
        return CL_VIRUS;
 
2238
    if(ret == CL_VIRUS) {
 
2239
        ret = cli_checkfp(hash, hashed_size, ctx);
 
2240
        funmap(*ctx->fmap);
 
2241
        ctx->fmap--;
 
2242
        cli_bitset_free(ctx->hook_lsig_matches);
 
2243
        ctx->hook_lsig_matches = old_hook_lsig_matches;
 
2244
        ret_from_magicscan(ret);
 
2245
    }
2098
2246
 
2099
2247
    if(type == CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
2100
2248
        if(sb.st_size > 1048576) {
2105
2253
 
2106
2254
    /* CL_TYPE_HTML: raw HTML files are not scanned, unless safety measure activated via DCONF */
2107
2255
    if(type != CL_TYPE_IGNORED && (type != CL_TYPE_HTML || !(DCONF_DOC & DOC_CONF_HTML_SKIPRAW)) && !ctx->engine->sdb) {
2108
 
        if(cli_scanraw(desc, ctx, type, typercg, &dettype) == CL_VIRUS)
2109
 
            return CL_VIRUS;
 
2256
        if(cli_scanraw(ctx, type, typercg, &dettype, hash) == CL_VIRUS) {
 
2257
            ret =  cli_checkfp(hash, hashed_size, ctx);
 
2258
            funmap(*ctx->fmap);
 
2259
            ctx->fmap--;
 
2260
            cli_bitset_free(ctx->hook_lsig_matches);
 
2261
            ctx->hook_lsig_matches = old_hook_lsig_matches;
 
2262
            ret_from_magicscan(ret);
 
2263
        }
2110
2264
    }
2111
2265
 
2112
2266
    ctx->recursion++;
2113
2267
    lseek(desc, 0, SEEK_SET);
2114
2268
    switch(type) {
 
2269
        /* bytecode hooks triggered by a lsig must be a hook
 
2270
         * called from one of the functions here */
2115
2271
        case CL_TYPE_TEXT_ASCII:
2116
2272
        case CL_TYPE_TEXT_UTF16BE:
2117
2273
        case CL_TYPE_TEXT_UTF16LE:
2118
2274
        case CL_TYPE_TEXT_UTF8:
2119
2275
            if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
2120
 
                ret = cli_scanscript(desc, ctx);
 
2276
                ret = cli_scanscript(ctx);
 
2277
            if(ret != CL_VIRUS && ctx->container_type == CL_TYPE_MAIL) {
 
2278
                lseek(desc, 0, SEEK_SET);
 
2279
                ret = cli_scandesc(desc, ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR);
 
2280
            }
2121
2281
            break;
2122
2282
        /* Due to performance reasons all executables were first scanned
2123
2283
         * in raw mode. Now we will try to unpack them
2124
2284
         */
2125
2285
        case CL_TYPE_MSEXE:
2126
2286
            if(SCAN_PE && ctx->dconf->pe)
2127
 
                ret = cli_scanpe(desc, ctx);
 
2287
                ret = cli_scanpe(ctx, NULL);
2128
2288
            break;
2129
 
 
2130
2289
        default:
2131
2290
            break;
2132
2291
    }
 
2292
 
 
2293
    if(ret == CL_VIRUS)
 
2294
        ret = cli_checkfp(hash, hashed_size, ctx);
2133
2295
    ctx->recursion--;
 
2296
    funmap(*ctx->fmap);
 
2297
    ctx->fmap--;
 
2298
    cli_bitset_free(ctx->hook_lsig_matches);
 
2299
    ctx->hook_lsig_matches = old_hook_lsig_matches;
2134
2300
 
2135
2301
    switch(ret) {
2136
2302
        case CL_EFORMAT:
2138
2304
        case CL_EMAXSIZE:
2139
2305
        case CL_EMAXFILES:
2140
2306
            cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(ret));
2141
 
            return CL_CLEAN;
 
2307
        case CL_CLEAN:
 
2308
            cache_add(hash, hashed_size, ctx);
 
2309
            ret_from_magicscan(CL_CLEAN);
2142
2310
        default:
2143
 
            return ret;
 
2311
            ret_from_magicscan(ret);
2144
2312
    }
2145
2313
}
2146
2314
 
2155
2323
    ctx.scanned = scanned;
2156
2324
    ctx.options = scanoptions;
2157
2325
    ctx.found_possibly_unwanted = 0;
 
2326
    ctx.container_type = CL_TYPE_ANY;
 
2327
    ctx.container_size = 0;
2158
2328
    ctx.dconf = (struct cli_dconf *) engine->dconf;
 
2329
    ctx.fmap = cli_calloc(sizeof(fmap_t *), ctx.engine->maxreclevel + 2);
 
2330
    if(!ctx.fmap)
 
2331
        return CL_EMEM;
 
2332
    ctx.hook_lsig_matches = cli_bitset_init();
2159
2333
 
2160
2334
    rc = cli_magic_scandesc(desc, &ctx);
 
2335
 
 
2336
    cli_bitset_free(ctx.hook_lsig_matches);
 
2337
    free(ctx.fmap);
2161
2338
    if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
2162
2339
        rc = CL_VIRUS;
2163
2340
    return rc;
2181
2358
        } else {
2182
2359
                cli_warnmsg("cli_found_possibly_unwanted called, but virname is not set\n");
2183
2360
        }
 
2361
        emax_reached(ctx);
2184
2362
        return CL_CLEAN;
2185
2363
}
2186
2364
 
2189
2367
        int fd, ret;
2190
2368
 
2191
2369
    /* internal version of cl_scanfile with arec/mrec preserved */
2192
 
    if((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
 
2370
    if((fd = safe_open(filename, O_RDONLY|O_BINARY)) == -1)
2193
2371
        return CL_EOPEN;
2194
2372
 
2195
2373
    ret = cli_magic_scandesc(fd, ctx);
2202
2380
{
2203
2381
        int fd, ret;
2204
2382
 
2205
 
 
2206
2383
    if((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
2207
2384
        return CL_EOPEN;
2208
2385