~ubuntu-branches/ubuntu/hardy/clamav/hardy-security

« back to all changes in this revision

Viewing changes to libclamav/scanners.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman, Marc Deslauriers, Scott Kitterman
  • Date: 2013-03-21 08:37:54 UTC
  • mfrom: (43.1.79 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20130321083754-r3dnl8aewkny2rxu
Tags: 0.97.7+dfsg-1ubuntu0.08.04.1
[ Marc Deslauriers ]
* SECURITY UPDATE: Updated to 0.97.7 to fix multiple security issues.
  (LP: #1157385)
  - CVE numbers pending

[ Scott Kitterman ]
* Changes to adapt to Hardy:
  - Build without llvm support on lpia to fix FTBFS (not a regression as
    llvm has never built on hardy lpia)
  - Drop -T -W from apparmor_parser calls in clamav-daemon and freshclam
    postinsts since it is not supported in Hardy's apparmor
  - Drop deny rule in freshclam apparmor profile since deny is not
    supported in Hardy's apparmor
  - Drop dh_lintian from debian/rules and adjust version of debhelper
    build-dep
  - Drop build-dep and libclamav-dev depends on non-existent libtommath-dev
  - Changed Section to 'utils' for clamav-dbg package
  - Ignore test suite errors on hppa
  - Build-depend on libltdl3-dev instead of libltdl-dev
  - Drop hardening flags changes
  - Drop unneeded versioning on lsb-base (clamav ships it's own status
    function)

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"
 
89
#include "events.h"
95
90
 
96
91
#ifdef HAVE_BZLIB_H
97
92
#include <bzlib.h>
104
99
 
105
100
static int cli_scanfile(const char *filename, cli_ctx *ctx);
106
101
 
107
 
static int cli_scandir(const char *dirname, cli_ctx *ctx, cli_file_t container)
 
102
static int cli_scandir(const char *dirname, cli_ctx *ctx)
108
103
{
109
104
        DIR *dd;
110
105
        struct dirent *dent;
116
111
#endif
117
112
        struct stat statbuf;
118
113
        char *fname;
119
 
        int fd, ret = CL_CLEAN;
120
 
        cli_file_t ftype;
121
 
 
 
114
        unsigned int viruses_found = 0;
122
115
 
123
116
    if((dd = opendir(dirname)) != NULL) {
124
117
#ifdef HAVE_READDIR_R_3
128
121
#else
129
122
        while((dent = readdir(dd))) {
130
123
#endif
131
 
#if     (!defined(C_INTERIX)) && (!defined(C_WINDOWS))
132
124
            if(dent->d_ino)
133
 
#endif
134
125
            {
135
126
                if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
136
127
                    /* build the full name */
140
131
                        return CL_EMEM;
141
132
                    }
142
133
 
143
 
                    sprintf(fname, "%s/%s", dirname, dent->d_name);
 
134
                    sprintf(fname, "%s"PATHSEP"%s", dirname, dent->d_name);
144
135
 
145
136
                    /* stat the file */
146
137
                    if(lstat(fname, &statbuf) != -1) {
147
138
                        if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) {
148
 
                            if(cli_scandir(fname, ctx, container) == CL_VIRUS) {
 
139
                            if(cli_scandir(fname, ctx) == CL_VIRUS) {
149
140
                                free(fname);
150
 
                                closedir(dd);
151
 
                                return CL_VIRUS;
152
 
                            }
 
141
 
 
142
                                if (SCAN_ALL) {
 
143
                                    viruses_found++;
 
144
                                    continue;
 
145
                                }
 
146
 
 
147
                                closedir(dd);
 
148
                                return CL_VIRUS;
 
149
                            }
153
150
                        } else {
154
151
                            if(S_ISREG(statbuf.st_mode)) {
155
152
                                if(cli_scanfile(fname, ctx) == CL_VIRUS) {
156
153
                                    free(fname);
157
 
                                    closedir(dd);
158
 
                                    return CL_VIRUS;
159
 
                                }
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
 
                                }
 
154
 
 
155
                                    if (SCAN_ALL) {
 
156
                                        viruses_found++;
 
157
                                        continue;
 
158
                                    }
 
159
 
 
160
                                    closedir(dd);
 
161
                                    return CL_VIRUS;
 
162
                                }
181
163
                            }
182
164
                        }
183
165
                    }
191
173
    }
192
174
 
193
175
    closedir(dd);
 
176
    if (SCAN_ALL && viruses_found)
 
177
        return CL_VIRUS;
194
178
    return CL_CLEAN;
195
179
}
196
180
 
197
181
static int cli_unrar_scanmetadata(int desc, unrar_metadata_t *metadata, cli_ctx *ctx, unsigned int files, uint32_t* sfx_check)
198
182
{
199
183
        int ret = CL_SUCCESS;
200
 
        struct cli_meta_node* mdata;
201
 
 
202
184
 
203
185
    if(files == 1 && sfx_check) {
204
186
        if(*sfx_check == metadata->crc)
212
194
        (unsigned int) metadata->unpack_size, metadata->method,
213
195
        metadata->pack_size ? (unsigned int) (metadata->unpack_size / metadata->pack_size) : 0);
214
196
 
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
 
    }
 
197
    if(cli_matchmeta(ctx, metadata->filename, metadata->pack_size, metadata->unpack_size, metadata->encrypted, files, metadata->crc, NULL) == CL_VIRUS)
 
198
        return CL_VIRUS;
250
199
 
251
200
    if(DETECT_ENCRYPTED && metadata->encrypted) {
252
201
        cli_dbgmsg("RAR: Encrypted files found in archive.\n");
253
202
        lseek(desc, 0, SEEK_SET);
254
 
        ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR);
 
203
        ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL);
255
204
        if(ret != CL_VIRUS) {
256
 
            *ctx->virname = "Encrypted.RAR";
 
205
            cli_append_virus(ctx, "Heuristics.Encrypted.RAR");
257
206
            return CL_VIRUS;
258
207
        }
259
208
    }
267
216
        unrar_metadata_t *metadata, *metadata_tmp;
268
217
        char *dir;
269
218
        unrar_state_t rar_state;
270
 
 
 
219
        unsigned int viruses_found = 0;
271
220
 
272
221
    cli_dbgmsg("in scanrar()\n");
273
222
 
293
242
            cli_dbgmsg("RAR: Encrypted main header\n");
294
243
            if(DETECT_ENCRYPTED) {
295
244
                lseek(desc, 0, SEEK_SET);
296
 
                ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR);
 
245
                ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL);
297
246
                if(ret != CL_VIRUS)
298
 
                    *ctx->virname = "Encrypted.RAR";
 
247
                    cli_append_virus(ctx, "Heuristics.Encrypted.RAR");
299
248
                return CL_VIRUS;
300
249
            }
301
250
            return CL_CLEAN;
345
294
            if(!ctx->engine->keeptmp) 
346
295
                if (cli_unlink(rar_state.filename)) ret = CL_EUNLINK;
347
296
            if(rc == CL_VIRUS ) {
348
 
                cli_dbgmsg("RAR: infected with %s\n",*ctx->virname);
 
297
                cli_dbgmsg("RAR: infected with %s\n", cli_get_last_virus(ctx));
349
298
                ret = CL_VIRUS;
 
299
                viruses_found++;
 
300
            }
 
301
        }
 
302
 
 
303
        if(ret == CL_VIRUS) {
 
304
            if(SCAN_ALL)
 
305
                ret = CL_SUCCESS;
 
306
            else
350
307
                break;
351
 
            }
352
308
        }
353
309
 
354
310
        if(ret == CL_SUCCESS)
361
317
 
362
318
    metadata = metadata_tmp = rar_state.metadata; 
363
319
 
364
 
    if(cli_scandir(rar_state.comment_dir, ctx, 0) == CL_VIRUS)
 
320
    if(cli_scandir(rar_state.comment_dir, ctx) == CL_VIRUS)
365
321
        ret = CL_VIRUS;
366
322
 
367
323
    cli_unrar_close(&rar_state);
380
336
    }
381
337
    cli_dbgmsg("RAR: Exit code: %d\n", ret);
382
338
 
 
339
    if (SCAN_ALL && viruses_found)
 
340
        return CL_VIRUS;
383
341
    return ret;
384
342
}
385
343
 
386
344
static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
387
345
{
388
 
        int ret = CL_CLEAN, rc;
 
346
        int ret = CL_CLEAN, rc, file = 0;
389
347
        arj_metadata_t metadata;
390
348
        char *dir;
391
349
 
419
377
        if (ret != CL_SUCCESS) {
420
378
           break;
421
379
        }
 
380
        file++;
 
381
        if(cli_matchmeta(ctx, metadata.filename, metadata.comp_size, metadata.orig_size, metadata.encrypted, file, 0, NULL) == CL_VIRUS)
 
382
            return CL_VIRUS;
 
383
 
422
384
        if ((ret = cli_checklimits("ARJ", ctx, metadata.orig_size, metadata.comp_size, 0))!=CL_CLEAN) {
423
385
            ret = CL_SUCCESS;
424
386
            if (metadata.filename)
431
393
            rc = cli_magic_scandesc(metadata.ofd, ctx);
432
394
            close(metadata.ofd);
433
395
            if (rc == CL_VIRUS) {
434
 
                cli_dbgmsg("ARJ: infected with %s\n",*ctx->virname);
 
396
                cli_dbgmsg("ARJ: infected with %s\n", cli_get_last_virus(ctx));
435
397
                ret = CL_VIRUS;
436
398
                if (metadata.filename) {
437
399
                    free(metadata.filename);
462
424
    return ret;
463
425
}
464
426
 
465
 
static int cli_scangzip(int desc, cli_ctx *ctx)
 
427
 
 
428
static int cli_scangzip_with_zib_from_the_80s(cli_ctx *ctx, unsigned char *buff) {
 
429
    int fd, ret, outsize = 0, bytes;
 
430
    fmap_t *map = *ctx->fmap;
 
431
    char *tmpname;
 
432
    gzFile gz;
 
433
 
 
434
    fd = dup(map->fd);
 
435
    if(fd < 0)
 
436
        return CL_EDUP;
 
437
 
 
438
    lseek(fd, 0, SEEK_SET);
 
439
    if(!(gz = gzdopen(fd, "rb"))) {
 
440
        close(fd);
 
441
        return CL_EOPEN;
 
442
    }
 
443
 
 
444
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
 
445
        cli_dbgmsg("GZip: Can't generate temporary file.\n");
 
446
        gzclose(gz);
 
447
        return ret;
 
448
    }
 
449
    
 
450
    while((bytes = gzread(gz, buff, FILEBUFF)) > 0) {
 
451
        outsize += bytes;
 
452
        if(cli_checklimits("GZip", ctx, outsize, 0, 0)!=CL_CLEAN)
 
453
            break;
 
454
        if(cli_writen(fd, buff, bytes) != bytes) {
 
455
            close(fd);
 
456
            gzclose(gz);
 
457
            if(cli_unlink(tmpname)) {
 
458
                free(tmpname);
 
459
                return CL_EUNLINK;
 
460
            }
 
461
            free(tmpname);
 
462
            return CL_EWRITE;
 
463
        }
 
464
    }
 
465
 
 
466
    gzclose(gz);
 
467
 
 
468
    if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
 
469
        cli_dbgmsg("GZip: Infected with %s\n", cli_get_last_virus(ctx));
 
470
        close(fd);
 
471
        if(!ctx->engine->keeptmp) {
 
472
            if (cli_unlink(tmpname)) {
 
473
                free(tmpname);
 
474
                return CL_EUNLINK;
 
475
            }
 
476
        }
 
477
        free(tmpname);
 
478
        return CL_VIRUS;
 
479
    }
 
480
    close(fd);
 
481
    if(!ctx->engine->keeptmp)
 
482
        if (cli_unlink(tmpname)) ret = CL_EUNLINK;
 
483
    free(tmpname);
 
484
    return ret;
 
485
}
 
486
 
 
487
static int cli_scangzip(cli_ctx *ctx)
466
488
{
467
 
        int fd, bytes, ret = CL_CLEAN;
468
 
        unsigned long int size = 0;
469
 
        char *buff;
 
489
        int fd, ret = CL_CLEAN;
 
490
        unsigned char buff[FILEBUFF];
470
491
        char *tmpname;
471
 
        gzFile gd;
472
 
 
473
 
 
 
492
        z_stream z;
 
493
        size_t at = 0, outsize = 0;
 
494
        fmap_t *map = *ctx->fmap;
 
495
        
474
496
    cli_dbgmsg("in cli_scangzip()\n");
475
497
 
476
 
    if((gd = gzdopen(dup(desc), "rb")) == NULL) {
477
 
        cli_dbgmsg("GZip: Can't open descriptor %d\n", desc);
478
 
        return CL_EOPEN;
 
498
    memset(&z, 0, sizeof(z));
 
499
    if((ret = inflateInit2(&z, MAX_WBITS + 16)) != Z_OK) {
 
500
        cli_dbgmsg("GZip: InflateInit failed: %d\n", ret);
 
501
        return cli_scangzip_with_zib_from_the_80s(ctx, buff);
479
502
    }
480
503
 
481
 
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
 
504
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
482
505
        cli_dbgmsg("GZip: Can't generate temporary file.\n");
483
 
        gzclose(gd);
 
506
        inflateEnd(&z);
484
507
        return ret;
485
508
    }
486
509
 
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");
 
510
    while (at < map->len) {
 
511
        unsigned int bytes = MIN(map->len - at, map->pgsz);
 
512
        if(!(z.next_in = fmap_need_off_once(map, at, bytes))) {
 
513
            cli_dbgmsg("GZip: Can't read %u bytes @ %lu.\n", bytes, (long unsigned)at);
 
514
            inflateEnd(&z);
508
515
            close(fd);
509
 
            if(!ctx->engine->keeptmp) {
510
 
                if (cli_unlink(tmpname)) {
 
516
            if (cli_unlink(tmpname)) {
 
517
                free(tmpname);
 
518
                return CL_EUNLINK;
 
519
            }
 
520
            free(tmpname);
 
521
            return CL_EREAD;
 
522
        }
 
523
        at += bytes;
 
524
        z.avail_in = bytes;
 
525
        do {
 
526
            int inf;
 
527
            z.avail_out = sizeof(buff);
 
528
            z.next_out = buff;
 
529
            inf = inflate(&z, Z_NO_FLUSH);
 
530
            if(inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
 
531
                cli_dbgmsg("GZip: Bad stream.\n");
 
532
                at = map->len;
 
533
                break;
 
534
            }
 
535
            if(cli_writen(fd, buff, sizeof(buff) - z.avail_out) < 0) {
 
536
                inflateEnd(&z);     
 
537
                close(fd);
 
538
                if (cli_unlink(tmpname)) {
511
539
                    free(tmpname);
512
 
                    gzclose(gd);
513
 
                    free(buff);
514
540
                    return CL_EUNLINK;
515
541
                }
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 ) {
537
 
        cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
 
542
                free(tmpname);
 
543
                return CL_EWRITE;
 
544
            }
 
545
            outsize += sizeof(buff) - z.avail_out;
 
546
            if(cli_checklimits("GZip", ctx, outsize, 0, 0)!=CL_CLEAN) {
 
547
                at = map->len;
 
548
                break;
 
549
            }
 
550
            if(inf == Z_STREAM_END) {
 
551
                at -= z.avail_in;
 
552
                inflateReset(&z);
 
553
                break;
 
554
            }
 
555
        } while (z.avail_out == 0);
 
556
    }
 
557
 
 
558
    inflateEnd(&z);         
 
559
 
 
560
    if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
 
561
        cli_dbgmsg("GZip: Infected with %s\n", cli_get_last_virus(ctx));
538
562
        close(fd);
539
563
        if(!ctx->engine->keeptmp) {
540
564
            if (cli_unlink(tmpname)) {
542
566
                return CL_EUNLINK;
543
567
            }
544
568
        }
545
 
        free(tmpname);  
 
569
        free(tmpname);
546
570
        return CL_VIRUS;
547
571
    }
548
572
    close(fd);
549
573
    if(!ctx->engine->keeptmp)
550
574
        if (cli_unlink(tmpname)) ret = CL_EUNLINK;
551
 
    free(tmpname);      
552
 
 
 
575
    free(tmpname);
553
576
    return ret;
554
577
}
555
578
 
652
675
 
653
676
    lseek(fd, 0, SEEK_SET);
654
677
    if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
655
 
        cli_dbgmsg("Bzip: Infected with %s\n", *ctx->virname);
 
678
        cli_dbgmsg("Bzip: Infected with %s\n", cli_get_last_virus(ctx));
656
679
    }
657
680
    close(fd);
658
681
    if(!ctx->engine->keeptmp)
706
729
        unsigned int files = 0;
707
730
        struct cab_archive cab;
708
731
        struct cab_file *file;
709
 
 
 
732
        unsigned int corrupted_input;
 
733
        unsigned int viruses_found = 0;
710
734
 
711
735
    cli_dbgmsg("in cli_scanmscab()\n");
712
736
 
716
740
    for(file = cab.files; file; file = file->next) {
717
741
        files++;
718
742
 
 
743
        if(cli_matchmeta(ctx, file->name, 0, file->length, 0, files, 0, NULL) == CL_VIRUS) {
 
744
            if (!SCAN_ALL) {
 
745
                ret = CL_VIRUS;
 
746
                break;
 
747
            }
 
748
            viruses_found++;
 
749
        }
 
750
 
 
751
        if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
 
752
            ret = CL_CLEAN;
 
753
            break;
 
754
        }
 
755
 
719
756
        if(!(tempname = cli_gentemp(ctx->engine->tmpdir))) {
720
757
            ret = CL_EMEM;
721
758
            break;
722
759
        }
723
760
 
724
 
        if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
725
 
            ret = CL_CLEAN;
726
 
            break;
727
 
        }
728
761
        if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
729
762
            file->max_size = ctx->engine->maxscansize - ctx->scansize;
730
763
        else
731
 
            file->max_size = ctx->engine->maxfilesize;
 
764
            file->max_size = ctx->engine->maxfilesize ? ctx->engine->maxfilesize : 0xffffffff;
732
765
 
733
766
        cli_dbgmsg("CAB: Extracting file %s to %s, size %u, max_size: %u\n", file->name, tempname, file->length, (unsigned int) file->max_size);
734
767
        file->written_size = 0;
735
768
        if((ret = cab_extract(file, tempname))) {
736
769
            cli_dbgmsg("CAB: Failed to extract file: %s\n", cl_strerror(ret));
737
770
        } else {
738
 
            if(file->length != file->written_size)
 
771
            corrupted_input = ctx->corrupted_input;
 
772
            if(file->length != file->written_size) {
739
773
                cli_dbgmsg("CAB: Length from header %u but wrote %u bytes\n", (unsigned int) file->length, (unsigned int) file->written_size);
740
 
 
 
774
                ctx->corrupted_input = 1;
 
775
            }
741
776
            ret = cli_scanfile(tempname, ctx);
 
777
            ctx->corrupted_input = corrupted_input;
742
778
        }
743
779
        if(!ctx->engine->keeptmp) {
744
 
            if (cli_unlink(tempname)) {
 
780
            if (!access(tempname, R_OK) && cli_unlink(tempname)) {
745
781
                free(tempname);
746
782
                ret = CL_EUNLINK;
747
783
                break;
748
784
            }
749
785
        }
750
786
        free(tempname);
751
 
        if(ret == CL_VIRUS)
752
 
            break;
 
787
        if(ret == CL_VIRUS) {
 
788
            if (SCAN_ALL)
 
789
                viruses_found++;
 
790
            else
 
791
                break;
 
792
        }
753
793
    }
754
794
 
755
795
    cab_free(&cab);
 
796
    if (viruses_found)
 
797
        return CL_VIRUS;
 
798
    return ret;
 
799
}
 
800
 
 
801
static int vba_scandata(const unsigned char *data, unsigned int len, cli_ctx *ctx)
 
802
{
 
803
        struct cli_matcher *groot = ctx->engine->root[0];
 
804
        struct cli_matcher *troot = ctx->engine->root[2];
 
805
        struct cli_ac_data gmdata, tmdata;
 
806
        struct cli_ac_data *mdata[2];
 
807
        int ret;
 
808
        unsigned int viruses_found = 0;
 
809
 
 
810
    if((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
 
811
        return ret;
 
812
 
 
813
    if((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) {
 
814
        cli_ac_freedata(&tmdata);
 
815
        return ret;
 
816
    }
 
817
    mdata[0] = &tmdata;
 
818
    mdata[1] = &gmdata;
 
819
 
 
820
    ret = cli_scanbuff(data, len, 0, ctx, CL_TYPE_MSOLE2, mdata);
 
821
 
 
822
    if(ret != CL_VIRUS || SCAN_ALL) {
 
823
        if (SCAN_ALL)
 
824
            viruses_found++;
 
825
        ret = cli_lsig_eval(ctx, troot, &tmdata, NULL, NULL);
 
826
        if(ret != CL_VIRUS || SCAN_ALL)
 
827
            if (SCAN_ALL)
 
828
                viruses_found++;
 
829
            ret = cli_lsig_eval(ctx, groot, &gmdata, NULL, NULL);
 
830
    }
 
831
    cli_ac_freedata(&tmdata);
 
832
    cli_ac_freedata(&gmdata);
 
833
 
 
834
    if (viruses_found)
 
835
        return CL_VIRUS;
756
836
    return ret;
757
837
}
758
838
 
759
839
static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U)
760
840
{
761
 
    int ret = CL_CLEAN, i, j, fd, data_len;
 
841
        int ret = CL_CLEAN, i, j, fd, data_len, hasmacros = 0;
762
842
        vba_project_t *vba_project;
763
843
        DIR *dd;
764
844
        struct dirent *dent;
773
853
        unsigned char *data;
774
854
        char *hash;
775
855
        uint32_t hashcnt;
 
856
        unsigned int viruses_found = 0;
776
857
 
777
858
 
778
859
    cli_dbgmsg("VBADir: %s\n", dirname);
782
863
 
783
864
        for(i = 0; i < vba_project->count; i++) {
784
865
            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);
 
866
                snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", vba_project->dir, vba_project->name[i], j);
786
867
                vbaname[sizeof(vbaname)-1] = '\0';
787
868
                fd = open(vbaname, O_RDONLY|O_BINARY);
788
869
                if(fd == -1) continue;
789
870
                cli_dbgmsg("VBADir: Decompress VBA project '%s_%u'\n", vba_project->name[i], j);
790
871
                data = (unsigned char *)cli_vba_inflate(fd, vba_project->offset[i], &data_len);
791
872
                close(fd);
792
 
 
 
873
                hasmacros++;
793
874
                if(!data) {
794
875
                    cli_dbgmsg("VBADir: WARNING: VBA project '%s_%u' decompressed to NULL\n", vba_project->name[i], j);
795
876
                } else {
796
877
                    /* cli_dbgmsg("Project content:\n%s", data); */
797
878
                    if(ctx->scanned)
798
879
                        *ctx->scanned += data_len / CL_COUNT_PRECISION;
799
 
                    if(cli_scanbuff(data, data_len, 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
800
 
                        free(data);
801
 
                        ret = CL_VIRUS;
802
 
                        break;
 
880
                    if(vba_scandata(data, data_len, ctx) == CL_VIRUS) {
 
881
                        if (SCAN_ALL) 
 
882
                            viruses_found++;
 
883
                        else {
 
884
                            free(data);
 
885
                            ret = CL_VIRUS;
 
886
                            break;
 
887
                        }
803
888
                    }
804
889
                    free(data);
805
890
                }
811
896
        free(vba_project->dir);
812
897
        free(vba_project->offset);
813
898
        free(vba_project);
814
 
        if (ret == CL_VIRUS) break;
 
899
        if (ret == CL_VIRUS && !SCAN_ALL)
 
900
            break;
815
901
    }
816
902
 
817
 
    if(ret == CL_CLEAN && (hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) {
 
903
    if((ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) && 
 
904
        (hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) {
818
905
        while(hashcnt--) {
819
 
            snprintf(vbaname, 1024, "%s/%s_%u", dirname, hash, hashcnt);
 
906
            snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
820
907
            vbaname[sizeof(vbaname)-1] = '\0';
821
908
            fd = open(vbaname, O_RDONLY|O_BINARY);
822
909
            if (fd == -1) continue;
823
910
            if ((fullname = cli_ppt_vba_read(fd, ctx))) {
824
 
                if(cli_scandir(fullname, ctx, 0) == CL_VIRUS) {
 
911
                if(cli_scandir(fullname, ctx) == CL_VIRUS) {
825
912
                    ret = CL_VIRUS;
 
913
                    viruses_found++;
826
914
                }
827
915
                if(!ctx->engine->keeptmp)
828
916
                    cli_rmdirs(fullname);
832
920
        }
833
921
    }
834
922
 
835
 
    if (ret == CL_CLEAN && (hashcnt = uniq_get(U, "worddocument", 12, &hash))) {
 
923
    if ((ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) && 
 
924
        (hashcnt = uniq_get(U, "worddocument", 12, &hash))) {
836
925
        while(hashcnt--) {
837
 
            snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
 
926
            snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
838
927
            vbaname[sizeof(vbaname)-1] = '\0';
839
928
            fd = open(vbaname, O_RDONLY|O_BINARY);
840
929
            if (fd == -1) continue;
847
936
            for (i = 0; i < vba_project->count; i++) {
848
937
                cli_dbgmsg("VBADir: Decompress WM project macro:%d key:%d length:%d\n", i, vba_project->key[i], vba_project->length[i]);
849
938
                data = (unsigned char *)cli_wm_decrypt_macro(fd, vba_project->offset[i], vba_project->length[i], vba_project->key[i]);
850
 
                
851
939
                if(!data) {
852
940
                        cli_dbgmsg("VBADir: WARNING: WM project '%s' macro %d decrypted to NULL\n", vba_project->name[i], i);
853
941
                } else {
854
942
                        cli_dbgmsg("Project content:\n%s", data);
855
943
                        if(ctx->scanned)
856
944
                            *ctx->scanned += vba_project->length[i] / CL_COUNT_PRECISION;
857
 
                        if(cli_scanbuff(data, vba_project->length[i], 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
 
945
                        if(vba_scandata(data, vba_project->length[i], ctx) == CL_VIRUS) {
 
946
                            if (SCAN_ALL)
 
947
                                viruses_found++;
 
948
                            else {
858
949
                                free(data);
859
950
                                ret = CL_VIRUS;
860
951
                                break;
 
952
                            }
861
953
                        }
862
954
                        free(data);
863
955
                }
871
963
            free(vba_project->key);
872
964
            free(vba_project->length);
873
965
            free(vba_project);
874
 
            if(ret == CL_VIRUS) break;
 
966
            if(ret == CL_VIRUS) {
 
967
                if (SCAN_ALL)
 
968
                    viruses_found++;
 
969
                else
 
970
                    break;
 
971
            }
875
972
        }
876
973
    }
877
974
 
878
 
    if(ret != CL_CLEAN)
 
975
    if(ret != CL_CLEAN && !(ret == CL_VIRUS && SCAN_ALL))
879
976
        return ret;
880
977
 
881
978
    /* Check directory for embedded OLE objects */
882
979
    hashcnt = uniq_get(U, "_1_ole10native", 14, &hash);
883
980
    while(hashcnt--) {
884
 
        snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
 
981
        snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
885
982
        vbaname[sizeof(vbaname)-1] = '\0';
886
983
 
887
984
        fd = open(vbaname, O_RDONLY|O_BINARY);
888
985
        if (fd >= 0) {
889
986
            ret = cli_scan_ole10(fd, ctx);
890
987
            close(fd);
891
 
            if(ret != CL_CLEAN)
 
988
            if(ret != CL_CLEAN && !(ret == CL_VIRUS && SCAN_ALL))
892
989
                return ret;
893
990
        }
894
991
    }
906
1003
#else
907
1004
        while((dent = readdir(dd))) {
908
1005
#endif
909
 
#if     (!defined(C_INTERIX)) && (!defined(C_WINDOWS))
910
1006
            if(dent->d_ino)
911
 
#endif
912
1007
            {
913
1008
                if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
914
1009
                    /* build the full name */
917
1012
                        ret = CL_EMEM;
918
1013
                        break;
919
1014
                    }
920
 
                    sprintf(fullname, "%s/%s", dirname, dent->d_name);
 
1015
                    sprintf(fullname, "%s"PATHSEP"%s", dirname, dent->d_name);
921
1016
 
922
1017
                    /* stat the file */
923
1018
                    if(lstat(fullname, &statbuf) != -1) {
924
1019
                        if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode))
925
1020
                          if (cli_vba_scandir(fullname, ctx, U) == CL_VIRUS) {
926
 
                                ret = CL_VIRUS;
927
 
                                free(fullname);
928
 
                                break;
929
 
                            }
 
1021
                              if (SCAN_ALL)
 
1022
                                  viruses_found++;
 
1023
                              else {
 
1024
                                  ret = CL_VIRUS;
 
1025
                                  free(fullname);
 
1026
                                  break;
 
1027
                              }
 
1028
                          }
930
1029
                    }
931
1030
                    free(fullname);
932
1031
                }
938
1037
    }
939
1038
 
940
1039
    closedir(dd);
 
1040
    if(BLOCK_MACROS && hasmacros) {
 
1041
        cli_append_virus(ctx, "Heuristics.OLE2.ContainsMacros");
 
1042
        ret = CL_VIRUS;
 
1043
        viruses_found++;
 
1044
    }
 
1045
    if (SCAN_ALL && viruses_found)
 
1046
        return CL_VIRUS;
941
1047
    return ret;
942
1048
}
943
1049
 
944
 
static int cli_scanhtml(int desc, cli_ctx *ctx)
 
1050
static int cli_scanhtml(cli_ctx *ctx)
945
1051
{
946
1052
        char *tempname, fullname[1024];
947
1053
        int ret=CL_CLEAN, fd;
948
 
        struct stat sb;
 
1054
        fmap_t *map = *ctx->fmap;
 
1055
        unsigned int viruses_found = 0;
949
1056
 
950
1057
    cli_dbgmsg("in cli_scanhtml()\n");
951
1058
 
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
1059
    /* Because HTML detection is FP-prone and html_normalise_fd() needs to
958
1060
     * mmap the file don't normalise files larger than 10 MB.
959
1061
     */
960
1062
 
961
 
    if(sb.st_size > 10485760) {
 
1063
    if(map->len > 10485760) {
962
1064
        cli_dbgmsg("cli_scanhtml: exiting (file larger than 10 MB)\n");
963
1065
        return CL_CLEAN;
964
1066
    }
974
1076
 
975
1077
    cli_dbgmsg("cli_scanhtml: using tempdir %s\n", tempname);
976
1078
 
977
 
    html_normalise_fd(desc, tempname, NULL, ctx->dconf);
978
 
    snprintf(fullname, 1024, "%s/nocomment.html", tempname);
 
1079
    html_normalise_map(map, tempname, NULL, ctx->dconf);
 
1080
    snprintf(fullname, 1024, "%s"PATHSEP"nocomment.html", tempname);
979
1081
    fd = open(fullname, O_RDONLY|O_BINARY);
980
1082
    if (fd >= 0) {
981
 
            ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
982
 
            close(fd);
 
1083
        if ((ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS)
 
1084
            viruses_found++;
 
1085
        close(fd);
983
1086
    }
984
1087
 
985
 
    if(ret == CL_CLEAN && sb.st_size < 2097152) {
 
1088
    if((ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) && map->len < 2097152) {
986
1089
            /* limit to 2 MB, we're not interesting in scanning large files in notags form */
987
1090
            /* TODO: don't even create notags if file is over 2 MB */
988
 
            snprintf(fullname, 1024, "%s/notags.html", tempname);
989
 
            fd = open(fullname, O_RDONLY|O_BINARY);
990
 
            if(fd >= 0) {
991
 
                    ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
992
 
                    close(fd);
993
 
            }
994
 
    }
995
 
 
996
 
    if(ret == CL_CLEAN) {
997
 
            snprintf(fullname, 1024, "%s/javascript", tempname);
998
 
            fd = open(fullname, O_RDONLY|O_BINARY);
999
 
            if(fd >= 0) {
1000
 
                    ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
1001
 
                    if (ret == CL_CLEAN) {
1002
 
                            lseek(fd, 0, SEEK_SET);
1003
 
                            ret = cli_scandesc(fd, ctx, CL_TYPE_TEXT_ASCII, 0, NULL, AC_SCAN_VIR);
1004
 
                    }
1005
 
                    close(fd);
1006
 
            }
1007
 
    }
1008
 
 
1009
 
    if (ret == CL_CLEAN) {
1010
 
        snprintf(fullname, 1024, "%s/rfc2397", tempname);
1011
 
        ret = cli_scandir(fullname, ctx, 0);
 
1091
            snprintf(fullname, 1024, "%s"PATHSEP"notags.html", tempname);
 
1092
            fd = open(fullname, O_RDONLY|O_BINARY);
 
1093
            if(fd >= 0) {
 
1094
                if ((ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS) 
 
1095
                    viruses_found++;
 
1096
                close(fd);
 
1097
            }
 
1098
    }
 
1099
 
 
1100
    if(ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) {
 
1101
            snprintf(fullname, 1024, "%s"PATHSEP"javascript", tempname);
 
1102
            fd = open(fullname, O_RDONLY|O_BINARY);
 
1103
            if(fd >= 0) {
 
1104
                if ((ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS)
 
1105
                    viruses_found++;
 
1106
                if (ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) {
 
1107
                    if ((ret = cli_scandesc(fd, ctx, CL_TYPE_TEXT_ASCII, 0, NULL, AC_SCAN_VIR, NULL)) == CL_VIRUS)
 
1108
                        viruses_found++;
 
1109
                }
 
1110
                close(fd);
 
1111
            }
 
1112
    }
 
1113
 
 
1114
    if (ret == CL_CLEAN || (ret == CL_VIRUS && SCAN_ALL)) {
 
1115
        snprintf(fullname, 1024, "%s"PATHSEP"rfc2397", tempname);
 
1116
        ret = cli_scandir(fullname, ctx);
1012
1117
    }
1013
1118
 
1014
1119
    if(!ctx->engine->keeptmp)
1015
1120
        cli_rmdirs(tempname);
1016
1121
 
1017
1122
    free(tempname);
 
1123
    if (SCAN_ALL && viruses_found)
 
1124
        return CL_VIRUS;
1018
1125
    return ret;
1019
1126
}
1020
1127
 
1021
 
static int cli_scanscript(int desc, cli_ctx *ctx)
 
1128
static int cli_scanscript(cli_ctx *ctx)
1022
1129
{
1023
 
        unsigned char buff[FILEBUFF];
 
1130
        unsigned char *buff;
1024
1131
        unsigned char* normalized;
1025
1132
        struct text_norm_state state;
1026
 
        struct stat sb;
1027
1133
        char *tmpname = NULL;
1028
1134
        int ofd = -1, ret;
1029
 
        ssize_t nread;
1030
 
        const struct cli_matcher *troot = ctx->engine->root[7];
 
1135
        struct cli_matcher *troot = ctx->engine->root[7];
1031
1136
        uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0;
1032
1137
        struct cli_matcher *groot = ctx->engine->root[0];
1033
1138
        struct cli_ac_data gmdata, tmdata;
1034
1139
        struct cli_ac_data *mdata[2];
 
1140
        fmap_t *map = *ctx->fmap;
 
1141
        size_t at = 0;
 
1142
        unsigned int viruses_found = 0;
1035
1143
 
1036
1144
        cli_dbgmsg("in cli_scanscript()\n");
1037
1145
 
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) {
 
1146
        if(map->len > 5242880) {
1045
1147
                cli_dbgmsg("cli_scanscript: exiting (file larger than 5 MB)\n");
1046
1148
                return CL_CLEAN;
1047
1149
        }
1053
1155
                        cli_dbgmsg("cli_scanscript: Can't generate temporary file/descriptor\n");
1054
1156
                        return ret;
1055
1157
                }
 
1158
                cli_dbgmsg("cli_scanscript: saving normalized file to %s\n", tmpname);
1056
1159
        }
1057
1160
 
1058
1161
        if(!(normalized = cli_malloc(SCANBUFF + maxpatlen))) {
1063
1166
        text_normalize_init(&state, normalized, SCANBUFF + maxpatlen);
1064
1167
        ret = CL_CLEAN;
1065
1168
 
1066
 
        if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
 
1169
        if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
1067
1170
            return ret;
1068
1171
 
1069
 
        if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) {
 
1172
        if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN))) {
1070
1173
            cli_ac_freedata(&tmdata);
1071
1174
            return ret;
1072
1175
        }
1073
1176
        mdata[0] = &tmdata;
1074
1177
        mdata[1] = &gmdata;
1075
1178
 
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
 
 
1109
 
        cli_ac_freedata(&tmdata);
1110
 
        cli_ac_freedata(&gmdata);
 
1179
        while(1) {
 
1180
            size_t len = MIN(map->pgsz, map->len - at);
 
1181
            buff = fmap_need_off_once(map, at, len);
 
1182
            at += len;
 
1183
            if(!buff || !len || state.out_pos + len > state.out_len) {
 
1184
                /* flush if error/EOF, or too little buffer space left */
 
1185
                if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
 
1186
                    cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
 
1187
                    close(ofd);
 
1188
                    ofd = -1;
 
1189
                    /* we can continue to scan in memory */
 
1190
                }
 
1191
                /* when we flush the buffer also scan */
 
1192
                if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
 
1193
                    if (SCAN_ALL)
 
1194
                        viruses_found++;
 
1195
                    else {
 
1196
                        ret = CL_VIRUS;
 
1197
                        break;
 
1198
                    }
 
1199
                }
 
1200
                if(ctx->scanned)
 
1201
                    *ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
 
1202
                offset += state.out_pos;
 
1203
                /* carry over maxpatlen from previous buffer */
 
1204
                if (state.out_pos > maxpatlen)
 
1205
                    memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen); 
 
1206
                text_normalize_reset(&state);
 
1207
                state.out_pos = maxpatlen;
 
1208
            }
 
1209
            if(!len) break;
 
1210
            if(text_normalize_buffer(&state, buff, len) != len) {
 
1211
                cli_dbgmsg("cli_scanscript: short read during normalizing\n");
 
1212
            }
 
1213
        }
1111
1214
        if(ctx->engine->keeptmp) {
1112
1215
                free(tmpname);
1113
1216
                close(ofd);
1114
1217
        }
1115
1218
        free(normalized);
 
1219
        if(ret != CL_VIRUS || SCAN_ALL)  {
 
1220
            if ((ret = cli_lsig_eval(ctx, troot, &tmdata, NULL, NULL)) == CL_VIRUS)
 
1221
                viruses_found++;
 
1222
            if(ret != CL_VIRUS || SCAN_ALL)
 
1223
                if ((ret = cli_lsig_eval(ctx, groot, &gmdata, NULL, NULL)) == CL_VIRUS)
 
1224
                    viruses_found++;
 
1225
        }
 
1226
        cli_ac_freedata(&tmdata);
 
1227
        cli_ac_freedata(&gmdata);
1116
1228
 
 
1229
        if (SCAN_ALL && viruses_found)
 
1230
            return CL_VIRUS;
1117
1231
        return ret;
1118
1232
}
1119
1233
 
1120
 
static int cli_scanhtml_utf16(int desc, cli_ctx *ctx)
 
1234
static int cli_scanhtml_utf16(cli_ctx *ctx)
1121
1235
{
1122
 
        char *tempname, buff[512], *decoded;
 
1236
        char *tempname, *decoded, *buff;
1123
1237
        int ret = CL_CLEAN, fd, bytes;
1124
 
 
 
1238
        size_t at = 0;
 
1239
        fmap_t *map = *ctx->fmap;
1125
1240
 
1126
1241
    cli_dbgmsg("in cli_scanhtml_utf16()\n");
1127
1242
 
1136
1251
 
1137
1252
    cli_dbgmsg("cli_scanhtml_utf16: using tempfile %s\n", tempname);
1138
1253
 
1139
 
    while((bytes = read(desc, buff, sizeof(buff))) > 0) {
 
1254
    while(at < map->len) {
 
1255
        bytes = MIN(map->len - at, map->pgsz * 16);
 
1256
        if(!(buff = fmap_need_off_once(map, at, bytes))) {
 
1257
            close(fd);
 
1258
            cli_unlink(tempname);
 
1259
            free(tempname);
 
1260
            return CL_EREAD;
 
1261
        }
 
1262
        at += bytes;
1140
1263
        decoded = cli_utf16toascii(buff, bytes);
1141
1264
        if(decoded) {
1142
 
            if(write(fd, decoded, strlen(decoded)) == -1) {
 
1265
            if(write(fd, decoded, bytes / 2) == -1) {
1143
1266
                cli_errmsg("cli_scanhtml_utf16: Can't write to file %s\n", tempname);
1144
1267
                free(decoded);
1145
1268
                close(fd);
1151
1274
        }
1152
1275
    }
1153
1276
 
1154
 
    lseek(fd, 0, SEEK_SET);
1155
 
    ret = cli_scanhtml(fd, ctx);
 
1277
    *ctx->fmap = fmap(fd, 0, 0);
 
1278
    if(*ctx->fmap) {
 
1279
        ret = cli_scanhtml(ctx);
 
1280
        funmap(*ctx->fmap);
 
1281
    } else
 
1282
        cli_errmsg("cli_scanhtml_utf16: fmap of %s failed\n", tempname);
 
1283
 
 
1284
    *ctx->fmap = map;
1156
1285
    close(fd);
1157
1286
 
1158
1287
    if(!ctx->engine->keeptmp) {
1164
1293
    return ret;
1165
1294
}
1166
1295
 
1167
 
static int cli_scanole2(int desc, cli_ctx *ctx)
 
1296
static int cli_scanole2(cli_ctx *ctx)
1168
1297
{
1169
1298
        char *dir;
1170
1299
        int ret = CL_CLEAN;
1185
1314
        return CL_ETMPDIR;
1186
1315
    }
1187
1316
 
1188
 
    ret = cli_ole2_extract(desc, dir, ctx, &vba);
 
1317
    ret = cli_ole2_extract(dir, ctx, &vba);
1189
1318
    if(ret!=CL_CLEAN && ret!=CL_VIRUS) {
1190
1319
        cli_dbgmsg("OLE2: %s\n", cl_strerror(ret));
1191
1320
        if(!ctx->engine->keeptmp)
1200
1329
        ret = cli_vba_scandir(dir, ctx, vba);
1201
1330
        uniq_free(vba);
1202
1331
        if(ret != CL_VIRUS)
1203
 
            if(cli_scandir(dir, ctx, 0) == CL_VIRUS)
 
1332
            if(cli_scandir(dir, ctx) == CL_VIRUS)
1204
1333
                ret = CL_VIRUS;
1205
1334
        ctx->recursion--;
1206
1335
    }
1238
1367
    return ret;
1239
1368
}
1240
1369
 
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
1370
static int cli_scanmschm(int desc, cli_ctx *ctx)
1272
1371
{
1273
1372
        int ret = CL_CLEAN, rc;
1274
1373
        chm_metadata_t metadata;
1275
1374
        char *dir;
 
1375
        unsigned int viruses_found = 0;
1276
1376
 
1277
1377
    cli_dbgmsg("in cli_scanmschm()\n");
1278
1378
 
1296
1396
    }
1297
1397
 
1298
1398
   do {
1299
 
        ret = cli_chm_prepare_file(desc, dir, &metadata);
 
1399
        ret = cli_chm_prepare_file(&metadata);
1300
1400
        if (ret != CL_SUCCESS) {
1301
1401
           break;
1302
1402
        }
1303
 
        ret = cli_chm_extract_file(desc, dir, &metadata, ctx);
 
1403
        ret = cli_chm_extract_file(dir, &metadata, ctx);
1304
1404
        if (ret == CL_SUCCESS) {
1305
1405
            lseek(metadata.ofd, 0, SEEK_SET);
1306
1406
            rc = cli_magic_scandesc(metadata.ofd, ctx);
1307
1407
            close(metadata.ofd);
1308
1408
            if (rc == CL_VIRUS) {
1309
 
                cli_dbgmsg("CHM: infected with %s\n",*ctx->virname);
1310
 
                ret = CL_VIRUS;
1311
 
                break;
 
1409
                cli_dbgmsg("CHM: infected with %s\n", cli_get_last_virus(ctx));
 
1410
                if (SCAN_ALL)
 
1411
                    viruses_found++;
 
1412
                else {
 
1413
                    ret = CL_VIRUS;
 
1414
                    break;
 
1415
                }
1312
1416
            }
1313
1417
        }
1314
1418
 
1325
1429
    if (ret == CL_BREAK)
1326
1430
        ret = CL_CLEAN;
1327
1431
 
 
1432
    if (SCAN_ALL && viruses_found)
 
1433
        return CL_VIRUS;
1328
1434
    return ret;
1329
1435
}
1330
1436
 
1345
1451
    }
1346
1452
 
1347
1453
    if (html_screnc_decode(desc, tempname))
1348
 
        ret = cli_scandir(tempname, ctx, 0);
 
1454
        ret = cli_scandir(tempname, ctx);
1349
1455
 
1350
1456
    if(!ctx->engine->keeptmp)
1351
1457
        cli_rmdirs(tempname);
1359
1465
        int ret = CL_CLEAN;
1360
1466
 
1361
1467
    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
 
        }
 
1468
        ret = CL_VIRUS;
 
1469
        cli_append_virus(ctx, "Heuristics.Exploit.W32.MS05-002");
1366
1470
    }
1367
1471
 
1368
1472
    return ret;
1373
1477
        int ret = CL_CLEAN;
1374
1478
 
1375
1479
    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
 
        }
 
1480
        ret = CL_VIRUS;
 
1481
        cli_append_virus(ctx, "Heuristics.Exploit.W32.MS04-028");
1380
1482
    }
1381
1483
 
1382
1484
    return ret;
1454
1556
    cli_dbgmsg("CryptFF: Scanning decrypted data\n");
1455
1557
 
1456
1558
    if((ret = cli_magic_scandesc(ndesc, ctx)) == CL_VIRUS)
1457
 
        cli_dbgmsg("CryptFF: Infected with %s\n", *ctx->virname);
 
1559
        cli_dbgmsg("CryptFF: Infected with %s\n", cli_get_last_virus_str(ctx));
1458
1560
 
1459
1561
    close(ndesc);
1460
1562
 
1467
1569
    return ret;
1468
1570
}
1469
1571
 
1470
 
static int cli_scanpdf(int desc, cli_ctx *ctx, off_t offset)
 
1572
static int cli_scanpdf(cli_ctx *ctx, off_t offset)
1471
1573
{
1472
1574
        int ret;
1473
1575
        char *dir = cli_gentemp(ctx->engine->tmpdir);
1481
1583
        return CL_ETMPDIR;
1482
1584
    }
1483
1585
 
1484
 
    ret = cli_pdf(dir, desc, ctx, offset);
 
1586
    ret = cli_pdf(dir, ctx, offset);
1485
1587
 
1486
1588
    if(!ctx->engine->keeptmp)
1487
1589
        cli_rmdirs(dir);
1507
1609
    ret = cli_tnef(dir, desc, ctx);
1508
1610
 
1509
1611
    if(ret == CL_CLEAN)
1510
 
        ret = cli_scandir(dir, ctx, 0);
 
1612
        ret = cli_scandir(dir, ctx);
1511
1613
 
1512
1614
    if(!ctx->engine->keeptmp)
1513
1615
        cli_rmdirs(dir);
1516
1618
    return ret;
1517
1619
}
1518
1620
 
1519
 
static int cli_scanuuencoded(int desc, cli_ctx *ctx)
 
1621
static int cli_scanuuencoded(cli_ctx *ctx)
1520
1622
{
1521
1623
        int ret;
1522
1624
        char *dir = cli_gentemp(ctx->engine->tmpdir);
1530
1632
        return CL_ETMPDIR;
1531
1633
    }
1532
1634
 
1533
 
    ret = cli_uuencode(dir, desc);
 
1635
    ret = cli_uuencode(dir, *ctx->fmap);
1534
1636
 
1535
1637
    if(ret == CL_CLEAN)
1536
 
        ret = cli_scandir(dir, ctx, 0);
 
1638
        ret = cli_scandir(dir, ctx);
1537
1639
 
1538
1640
    if(!ctx->engine->keeptmp)
1539
1641
        cli_rmdirs(dir);
1546
1648
{
1547
1649
        char *dir;
1548
1650
        int ret;
1549
 
 
 
1651
        unsigned int viruses_found = 0;
1550
1652
 
1551
1653
    cli_dbgmsg("Starting cli_scanmail(), recursion = %u\n", ctx->recursion);
1552
1654
 
1564
1666
     * Extract the attachments into the temporary directory
1565
1667
     */
1566
1668
    if((ret = cli_mbox(dir, desc, ctx))) {
1567
 
        if(!ctx->engine->keeptmp)
1568
 
            cli_rmdirs(dir);
1569
 
        free(dir);
1570
 
        return ret;
 
1669
        if (ret == CL_VIRUS && SCAN_ALL)
 
1670
            viruses_found++;
 
1671
        else {
 
1672
            if(!ctx->engine->keeptmp)
 
1673
                cli_rmdirs(dir);
 
1674
            free(dir);
 
1675
            return ret;
 
1676
        }
1571
1677
    }
1572
1678
 
1573
 
    ret = cli_scandir(dir, ctx, CL_TYPE_MAIL);
 
1679
    ret = cli_scandir(dir, ctx);
1574
1680
 
1575
1681
    if(!ctx->engine->keeptmp)
1576
1682
        cli_rmdirs(dir);
1577
1683
 
1578
1684
    free(dir);
 
1685
    if (SCAN_ALL && viruses_found)
 
1686
        return CL_VIRUS;
1579
1687
    return ret;
1580
1688
}
1581
1689
 
1588
1696
        int done = 0;
1589
1697
        int (*ccfunc)(const unsigned char *buffer, int length);
1590
1698
        int (*ssnfunc)(const unsigned char *buffer, int length);
1591
 
 
 
1699
        unsigned int viruses_found = 0;
1592
1700
 
1593
1701
    if(ctx == NULL)
1594
1702
        return CL_ENULLARG;
1635
1743
 
1636
1744
    if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) {
1637
1745
        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;
 
1746
        cli_append_virus(ctx,"Heuristics.Structured.CreditCardNumber");
 
1747
        if (SCAN_ALL)
 
1748
            viruses_found++;
 
1749
        else
 
1750
            return CL_VIRUS;
1640
1751
    }
1641
1752
 
1642
1753
    if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) {
1643
1754
        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;
 
1755
        cli_append_virus(ctx,"Heuristics.Structured.SSN");
 
1756
        if (SCAN_ALL)
 
1757
            viruses_found++;
 
1758
        else
 
1759
            return CL_VIRUS;
1646
1760
    }
1647
1761
 
 
1762
    if (SCAN_ALL && viruses_found)
 
1763
        return CL_VIRUS;
1648
1764
    return CL_CLEAN;
1649
1765
}
1650
1766
 
1651
 
static int cli_scanembpe(int desc, cli_ctx *ctx)
 
1767
static int cli_scanembpe(cli_ctx *ctx, off_t offset)
1652
1768
{
1653
1769
        int fd, bytes, ret = CL_CLEAN;
1654
 
        unsigned long int size = 0;
1655
 
        char buff[512];
 
1770
        unsigned long int size = 0, todo;
 
1771
        char *buff;
1656
1772
        char *tmpname;
 
1773
        fmap_t *map = *ctx->fmap;
 
1774
        unsigned int corrupted_input;
1657
1775
 
1658
1776
    tmpname = cli_gentemp(ctx->engine->tmpdir);
1659
1777
    if(!tmpname)
1665
1783
        return CL_ECREAT;
1666
1784
    }
1667
1785
 
1668
 
    while((bytes = read(desc, buff, sizeof(buff))) > 0) {
 
1786
    todo = map->len - offset;
 
1787
    while(1) {
 
1788
        bytes = MIN(todo, map->pgsz);
 
1789
        if(!bytes)
 
1790
            break;
 
1791
 
 
1792
        if(!(buff = fmap_need_off_once(map, offset + size, bytes))) {
 
1793
            close(fd);
 
1794
            if(!ctx->engine->keeptmp) {
 
1795
                if (cli_unlink(tmpname)) {
 
1796
                    free(tmpname);
 
1797
                    return CL_EUNLINK;
 
1798
                }
 
1799
            }
 
1800
            free(tmpname);
 
1801
            return CL_EREAD;
 
1802
        }
1669
1803
        size += bytes;
 
1804
        todo -= bytes;
1670
1805
 
1671
 
        if(cli_checklimits("cli_scanembpe", ctx, size + sizeof(buff), 0, 0)!=CL_CLEAN)
 
1806
        if(cli_checklimits("cli_scanembpe", ctx, size, 0, 0)!=CL_CLEAN)
1672
1807
            break;
1673
1808
 
1674
1809
        if(cli_writen(fd, buff, bytes) != bytes) {
1680
1815
                    return CL_EUNLINK;
1681
1816
                }
1682
1817
            }
1683
 
            free(tmpname);      
 
1818
            free(tmpname);
1684
1819
            return CL_EWRITE;
1685
1820
        }
1686
1821
    }
1687
1822
 
1688
1823
    ctx->recursion++;
1689
1824
    lseek(fd, 0, SEEK_SET);
1690
 
    if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
1691
 
        cli_dbgmsg("cli_scanembpe: Infected with %s\n", *ctx->virname);
 
1825
    corrupted_input = ctx->corrupted_input;
 
1826
    ctx->corrupted_input = 1;
 
1827
    ret = cli_magic_scandesc(fd, ctx);
 
1828
    ctx->corrupted_input = corrupted_input;
 
1829
    if(ret == CL_VIRUS) {
 
1830
        cli_dbgmsg("cli_scanembpe: Infected with %s\n", cli_get_last_virus(ctx));
1692
1831
        close(fd);
1693
1832
        if(!ctx->engine->keeptmp) {
1694
1833
            if (cli_unlink(tmpname)) {
1714
1853
    return CL_CLEAN;
1715
1854
}
1716
1855
 
1717
 
static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype)
 
1856
static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype, unsigned char *refhash)
1718
1857
{
1719
1858
        int ret = CL_CLEAN, nret = CL_CLEAN;
1720
1859
        struct cli_matched_type *ftoffset = NULL, *fpt;
1721
1860
        uint32_t lastzip, lastrar;
1722
1861
        struct cli_exe_info peinfo;
1723
1862
        unsigned int acmode = AC_SCAN_VIR, break_loop = 0;
1724
 
        struct stat sb;
 
1863
        fmap_t *map = *ctx->fmap;
 
1864
        cli_file_t current_container_type = ctx->container_type;
 
1865
        size_t current_container_size = ctx->container_size;
1725
1866
 
1726
1867
 
1727
1868
    if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
1730
1871
    if(typercg)
1731
1872
        acmode |= AC_SCAN_FT;
1732
1873
 
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);
 
1874
    ret = cli_fmap_scandesc(ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode, NULL, refhash);
1739
1875
 
1740
1876
    if(ret >= CL_TYPENO) {
1741
1877
        ctx->recursion++;
1742
 
 
1743
 
/*
1744
 
        if(type == CL_TYPE_TEXT_ASCII) {
1745
 
            lseek(desc, 0, SEEK_SET);
1746
 
 
1747
 
            nret = cli_scandesc(desc, ctx, 0, ret, 1, NULL);
1748
 
            if(nret == CL_VIRUS)
1749
 
                cli_dbgmsg("%s found in descriptor %d when scanning file type %u\n", *ctx->virname, desc, ret);
1750
 
        }
1751
 
*/
1752
 
 
1753
1878
        if(nret != CL_VIRUS) {
1754
1879
            lastzip = lastrar = 0xdeadbeef;
1755
1880
            fpt = ftoffset;
1756
1881
            while(fpt) {
1757
1882
                if(fpt->offset) switch(fpt->type) {
1758
1883
                    case CL_TYPE_RARSFX:
1759
 
                            cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1760
1884
                        if(type != CL_TYPE_RAR && have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR)) {
 
1885
                            ctx->container_type = CL_TYPE_RAR;
 
1886
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1761
1887
                            cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1762
 
                            nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar);
 
1888
                            nret = cli_scanrar(map->fd, ctx, fpt->offset, &lastrar);
1763
1889
                        }
1764
1890
                        break;
1765
1891
 
1766
1892
                    case CL_TYPE_ZIPSFX:
1767
1893
                        if(type != CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
 
1894
                            ctx->container_type = CL_TYPE_ZIP;
 
1895
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1768
1896
                            cli_dbgmsg("ZIP/ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
1769
 
                            nret = cli_unzip_single(desc, ctx, fpt->offset);
 
1897
                            nret = cli_unzip_single(ctx, fpt->offset);
1770
1898
                        }
1771
1899
                        break;
1772
1900
 
1773
1901
                    case CL_TYPE_CABSFX:
1774
1902
                        if(type != CL_TYPE_MSCAB && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB)) {
 
1903
                            ctx->container_type = CL_TYPE_MSCAB;
 
1904
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1775
1905
                            cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
1776
 
                            nret = cli_scanmscab(desc, ctx, fpt->offset);
 
1906
                            nret = cli_scanmscab(map->fd, ctx, fpt->offset);
1777
1907
                        }
1778
1908
                        break;
1779
1909
                    case CL_TYPE_ARJSFX:
1780
1910
                        if(type != CL_TYPE_ARJ && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ)) {
 
1911
                            ctx->container_type = CL_TYPE_ARJ;
 
1912
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1781
1913
                            cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
1782
 
                            nret = cli_scanarj(desc, ctx, fpt->offset, &lastrar);
 
1914
                            nret = cli_scanarj(map->fd, ctx, fpt->offset, &lastrar);
1783
1915
                        }
1784
1916
                        break;
1785
1917
 
1786
1918
                    case CL_TYPE_NULSFT:
1787
1919
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_NSIS) && fpt->offset > 4) {
 
1920
                            ctx->container_type = CL_TYPE_NULSFT;
 
1921
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1788
1922
                            cli_dbgmsg("NSIS signature found at %u\n", (unsigned int) fpt->offset-4);
1789
 
                            nret = cli_scannulsft(desc, ctx, fpt->offset - 4);
 
1923
                            nret = cli_scannulsft(map->fd, ctx, fpt->offset - 4);
1790
1924
                        }
1791
1925
                        break;
1792
1926
 
1793
1927
                    case CL_TYPE_AUTOIT:
1794
1928
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_AUTOIT)) {
 
1929
                            ctx->container_type = CL_TYPE_AUTOIT;
 
1930
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1795
1931
                            cli_dbgmsg("AUTOIT signature found at %u\n", (unsigned int) fpt->offset);
1796
 
                            nret = cli_scanautoit(desc, ctx, fpt->offset + 23);
 
1932
                            nret = cli_scanautoit(ctx, fpt->offset + 23);
 
1933
                        }
 
1934
                        break;
 
1935
 
 
1936
                    case CL_TYPE_ISHIELD_MSI:
 
1937
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ISHIELD)) {
 
1938
                            ctx->container_type = CL_TYPE_AUTOIT;
 
1939
                            ctx->container_size = map->len - fpt->offset; /* not precise */
 
1940
                            cli_dbgmsg("ISHIELD-MSI signature found at %u\n", (unsigned int) fpt->offset);
 
1941
                            nret = cli_scanishield_msi(ctx, fpt->offset + 14);
1797
1942
                        }
1798
1943
                        break;
1799
1944
 
1800
1945
                    case CL_TYPE_PDF:
1801
1946
                        if(type != CL_TYPE_PDF && SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
 
1947
                            ctx->container_type = CL_TYPE_PDF;
 
1948
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1802
1949
                            cli_dbgmsg("PDF signature found at %u\n", (unsigned int) fpt->offset);
1803
 
                            nret = cli_scanpdf(desc, ctx, fpt->offset);
 
1950
                            nret = cli_scanpdf(ctx, fpt->offset);
1804
1951
                        }
1805
1952
                        break;
1806
1953
 
1807
1954
                    case CL_TYPE_MSEXE:
1808
1955
                        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)
 
1956
                            if(map->len > 10485760)
1811
1957
                                break;
 
1958
                            ctx->container_type = CL_TYPE_MSEXE; /* PE is a container for another executable here */
 
1959
                            ctx->container_size = map->len - fpt->offset; /* not precise */
1812
1960
                            memset(&peinfo, 0, sizeof(struct cli_exe_info));
1813
1961
                            peinfo.offset = fpt->offset;
1814
 
                            lseek(desc, fpt->offset, SEEK_SET);
1815
 
                            if(cli_peheader(desc, &peinfo) == 0) {
 
1962
                            if(cli_peheader(map, &peinfo) == 0) {
1816
1963
                                cli_dbgmsg("*** Detected embedded PE file at %u ***\n", (unsigned int) fpt->offset);
1817
1964
                                if(peinfo.section)
1818
1965
                                    free(peinfo.section);
 
1966
                                cli_hashset_destroy(&peinfo.vinfo);
1819
1967
 
1820
 
                                lseek(desc, fpt->offset, SEEK_SET);
1821
 
                                nret = cli_scanembpe(desc, ctx);
 
1968
                                nret = cli_scanembpe(ctx, fpt->offset);
1822
1969
                                break_loop = 1; /* we can stop here and other
1823
1970
                                                 * embedded executables will
1824
1971
                                                 * be found recursively
1837
1984
 
1838
1985
                fpt = fpt->next;
1839
1986
            }
 
1987
            ctx->container_type = current_container_type;
 
1988
            ctx->container_size = current_container_size;
1840
1989
        }
1841
1990
 
1842
1991
        if(nret != CL_VIRUS) switch(ret) {
1843
1992
            case CL_TYPE_HTML:
1844
1993
                if(SCAN_HTML && type == CL_TYPE_TEXT_ASCII && (DCONF_DOC & DOC_CONF_HTML)) {
1845
1994
                    *dettype = CL_TYPE_HTML;
1846
 
                    nret = cli_scanhtml(desc, ctx);
 
1995
                    nret = cli_scanhtml(ctx);
1847
1996
                }
1848
1997
                break;
1849
1998
 
1850
1999
            case CL_TYPE_MAIL:
1851
 
                if(SCAN_MAIL && type == CL_TYPE_TEXT_ASCII && (DCONF_MAIL & MAIL_CONF_MBOX))
1852
 
                    nret = cli_scanmail(desc, ctx);
 
2000
                ctx->container_type = CL_TYPE_MAIL;
 
2001
                ctx->container_size = map->len;
 
2002
                if(SCAN_MAIL && type == CL_TYPE_TEXT_ASCII && (DCONF_MAIL & MAIL_CONF_MBOX)) {
 
2003
                    *dettype = CL_TYPE_MAIL;
 
2004
                    nret = cli_scanmail(map->fd, ctx);
 
2005
                }
 
2006
                ctx->container_type = current_container_type;
 
2007
                ctx->container_size = current_container_size;
1853
2008
                break;
1854
2009
 
1855
2010
            default:
1866
2021
    }
1867
2022
 
1868
2023
    if(ret == CL_VIRUS)
1869
 
        cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
 
2024
        cli_dbgmsg("%s found\n", cli_get_last_virus(ctx));
1870
2025
 
1871
2026
    return ret;
1872
2027
}
1873
2028
 
1874
 
int cli_magic_scandesc(int desc, cli_ctx *ctx)
 
2029
 
 
2030
static void emax_reached(cli_ctx *ctx) {
 
2031
    fmap_t **ctx_fmap = ctx->fmap;
 
2032
    if (!ctx_fmap)
 
2033
        return;
 
2034
    while(*ctx_fmap) {
 
2035
        fmap_t *map = *ctx_fmap;
 
2036
        map->dont_cache_flag = 1;
 
2037
        ctx_fmap--;
 
2038
    }
 
2039
    cli_dbgmsg("emax_reached: marked parents as non cacheable\n");
 
2040
}
 
2041
 
 
2042
#define LINESTR(x) #x
 
2043
#define LINESTR2(x) LINESTR(x)
 
2044
#define __AT__  " at line "LINESTR2(__LINE__)
 
2045
#define ret_from_magicscan(retcode) do {                                                        \
 
2046
    cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__);                       \
 
2047
    if(ctx->engine->cb_post_scan) {                                                             \
 
2048
        switch(ctx->engine->cb_post_scan(desc, retcode, retcode == CL_VIRUS ? cli_get_last_virus(ctx) : NULL, ctx->cb_ctx)) { \
 
2049
        case CL_BREAK:                                                                          \
 
2050
            cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n");                   \
 
2051
            return CL_CLEAN;                                                                    \
 
2052
        case CL_VIRUS:                                                                          \
 
2053
            cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n");                   \
 
2054
            cli_append_virus(ctx, "Detected.By.Callback");                                      \
 
2055
            return CL_VIRUS;                                                                    \
 
2056
        case CL_CLEAN:                                                                          \
 
2057
            break;                                                                              \
 
2058
        default:                                                                                \
 
2059
            cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n");        \
 
2060
        }                                                                                       \
 
2061
    }\
 
2062
    return retcode;                                                                             \
 
2063
    } while(0)
 
2064
 
 
2065
static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
1875
2066
{
1876
 
        int ret = CL_CLEAN;
1877
 
        cli_file_t type, dettype = 0;
 
2067
        int ret = CL_CLEAN, res;
 
2068
        cli_file_t dettype = 0;
1878
2069
        struct stat sb;
1879
2070
        uint8_t typercg = 1;
1880
 
 
 
2071
        cli_file_t current_container_type = ctx->container_type;
 
2072
        size_t current_container_size = ctx->container_size, hashed_size;
 
2073
        unsigned char hash[16];
 
2074
        bitset_t *old_hook_lsig_matches;
 
2075
        unsigned int viruses_found = 0;
 
2076
 
 
2077
#ifdef HAVE__INTERNAL__SHA_COLLECT
 
2078
    if(ctx->sha_collect>0) ctx->sha_collect = 0;
 
2079
#endif
 
2080
 
 
2081
    cli_dbgmsg("in cli_magic_scandesc (reclevel: %u/%u)\n", ctx->recursion, ctx->engine->maxreclevel);
1881
2082
    if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
1882
2083
        cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
1883
 
        return CL_CLEAN;
 
2084
        emax_reached(ctx);
 
2085
        ret_from_magicscan(CL_CLEAN);
1884
2086
    }
1885
2087
 
1886
2088
    if(fstat(desc, &sb) == -1) {
1887
2089
        cli_errmsg("magic_scandesc: Can't fstat descriptor %d\n", desc);
1888
 
        return CL_ESTAT;
 
2090
        ret_from_magicscan(CL_ESTAT);
1889
2091
    }
1890
2092
 
1891
2093
    if(sb.st_size <= 5) {
1892
2094
        cli_dbgmsg("Small data (%u bytes)\n", (unsigned int) sb.st_size);
1893
 
        return CL_CLEAN;
 
2095
        ret_from_magicscan(CL_CLEAN);
1894
2096
    }
1895
2097
 
1896
2098
    if(!ctx->engine) {
1897
2099
        cli_errmsg("CRITICAL: engine == NULL\n");
1898
 
        return CL_ENULLARG;
 
2100
        ret_from_magicscan(CL_ENULLARG);
1899
2101
    }
1900
2102
 
1901
2103
    if(!(ctx->engine->dboptions & CL_DB_COMPILED)) {
1902
2104
        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;
1908
 
 
1909
 
    if(!ctx->options || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
 
2105
        ret_from_magicscan(CL_EMALFDB);
 
2106
    }
 
2107
 
 
2108
    if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN) {
 
2109
        emax_reached(ctx);
 
2110
        ret_from_magicscan(CL_CLEAN);
 
2111
    }
 
2112
 
 
2113
    ctx->fmap++;
 
2114
    if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
 
2115
        cli_errmsg("CRITICAL: fmap() failed\n");
 
2116
        ctx->fmap--;
 
2117
        ret_from_magicscan(CL_EMEM);
 
2118
    }
 
2119
 
 
2120
    if(ctx->engine->cb_pre_scan) {
 
2121
        switch(ctx->engine->cb_pre_scan(desc, ctx->cb_ctx)) {
 
2122
        case CL_BREAK:
 
2123
            cli_dbgmsg("cli_magic_scandesc: file whitelisted by callback\n");
 
2124
            funmap(*ctx->fmap);
 
2125
            ctx->fmap--;
 
2126
            ret_from_magicscan(CL_CLEAN);
 
2127
        case CL_VIRUS:
 
2128
            cli_dbgmsg("cli_magic_scandesc: file blacklisted by callback\n");
 
2129
            cli_append_virus(ctx, "Detected.By.Callback");
 
2130
            funmap(*ctx->fmap);
 
2131
            ctx->fmap--;
 
2132
            ret_from_magicscan(CL_VIRUS);
 
2133
        case CL_CLEAN:
 
2134
            break;
 
2135
        default:
 
2136
            cli_warnmsg("cli_magic_scandesc: ignoring bad return code from callback\n");
 
2137
        }
 
2138
    }
 
2139
 
 
2140
    res = cache_check(hash, ctx);
 
2141
    if(res != CL_VIRUS) {
 
2142
        funmap(*ctx->fmap);
 
2143
        ctx->fmap--;
 
2144
        ret_from_magicscan(res);
 
2145
    }
 
2146
    hashed_size = (*ctx->fmap)->len;
 
2147
    old_hook_lsig_matches = ctx->hook_lsig_matches;
 
2148
    ctx->hook_lsig_matches = NULL;
 
2149
 
 
2150
    if(!(ctx->options&~CL_SCAN_ALLMATCHES) || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
1910
2151
        if(ctx->recursion == ctx->engine->maxreclevel)
1911
2152
            cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n");
1912
2153
        else
1913
2154
            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)
1915
 
            cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
1916
 
        return ret;
 
2155
 
 
2156
        if((ret = cli_fmap_scandesc(ctx, 0, 0, NULL, AC_SCAN_VIR, NULL, hash)) == CL_VIRUS)
 
2157
            cli_dbgmsg("%s found in descriptor %d\n", cli_get_last_virus(ctx), desc);
 
2158
        else if(ret == CL_CLEAN) {
 
2159
            if(ctx->recursion != ctx->engine->maxreclevel)
 
2160
                cache_add(hash, hashed_size, ctx); /* Only cache if limits are not reached */
 
2161
            else 
 
2162
                emax_reached(ctx);
 
2163
        }
 
2164
 
 
2165
        ctx->hook_lsig_matches = old_hook_lsig_matches;
 
2166
        funmap(*ctx->fmap);
 
2167
        ctx->fmap--;
 
2168
        ret_from_magicscan(ret);
1917
2169
    }
1918
2170
 
1919
 
    lseek(desc, 0, SEEK_SET);
1920
 
    type = cli_filetype2(desc, ctx->engine);
 
2171
    if(type == CL_TYPE_ANY)
 
2172
        type = cli_filetype2(*ctx->fmap, ctx->engine); /* FIXMEFMAP: port to fmap */
1921
2173
    if(type == CL_TYPE_ERROR) {
1922
2174
        cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
1923
 
        return CL_EREAD;
1924
 
    }
1925
 
    lseek(desc, 0, SEEK_SET);
 
2175
        funmap(*ctx->fmap);
 
2176
        ctx->fmap--;
 
2177
        ctx->hook_lsig_matches = old_hook_lsig_matches;
 
2178
        ret_from_magicscan(CL_EREAD);
 
2179
    }
 
2180
 
 
2181
#ifdef HAVE__INTERNAL__SHA_COLLECT
 
2182
    if(!ctx->sha_collect && type==CL_TYPE_MSEXE) ctx->sha_collect = 1;
 
2183
#endif
 
2184
    lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
 
2185
 
 
2186
    ctx->hook_lsig_matches = cli_bitset_init();
 
2187
    if (!ctx->hook_lsig_matches) {
 
2188
        ctx->hook_lsig_matches = old_hook_lsig_matches;
 
2189
        ctx->fmap--;
 
2190
        ret_from_magicscan(CL_EMEM);
 
2191
    }
1926
2192
 
1927
2193
    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);
 
2194
        if((ret = cli_scanraw(ctx, type, 0, &dettype, hash)) == CL_VIRUS) {
 
2195
            ret = cli_checkfp(hash, hashed_size, ctx);
 
2196
            funmap(*ctx->fmap);
 
2197
            ctx->fmap--;
 
2198
            cli_bitset_free(ctx->hook_lsig_matches);
 
2199
            ctx->hook_lsig_matches = old_hook_lsig_matches;
 
2200
            ret_from_magicscan(ret);
 
2201
        }
 
2202
        lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
1931
2203
    }
1932
2204
 
1933
2205
    ctx->recursion++;
1934
 
 
1935
2206
    switch(type) {
1936
2207
        case CL_TYPE_IGNORED:
1937
2208
            break;
1938
2209
 
1939
2210
        case CL_TYPE_RAR:
 
2211
            ctx->container_type = CL_TYPE_RAR;
 
2212
            ctx->container_size = sb.st_size;
1940
2213
            if(have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
1941
2214
                ret = cli_scanrar(desc, ctx, 0, NULL);
1942
2215
            break;
1943
2216
 
1944
2217
        case CL_TYPE_ZIP:
 
2218
            ctx->container_type = CL_TYPE_ZIP;
 
2219
            ctx->container_size = sb.st_size;
1945
2220
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
1946
 
                ret = cli_unzip(desc, ctx);
 
2221
                ret = cli_unzip(ctx);
1947
2222
            break;
1948
2223
 
1949
2224
        case CL_TYPE_GZ:
1950
2225
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GZ))
1951
 
                ret = cli_scangzip(desc, ctx);
 
2226
                ret = cli_scangzip(ctx);
1952
2227
            break;
1953
2228
 
1954
2229
        case CL_TYPE_BZ:
1955
2230
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BZ))
1956
2231
                ret = cli_scanbzip(desc, ctx);
1957
2232
            break;
 
2233
 
1958
2234
        case CL_TYPE_ARJ:
 
2235
            ctx->container_type = CL_TYPE_ARJ;
 
2236
            ctx->container_size = sb.st_size;
1959
2237
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ))
1960
2238
                ret = cli_scanarj(desc, ctx, 0, NULL);
1961
2239
            break;
1962
2240
 
1963
2241
        case CL_TYPE_NULSFT:
1964
 
          if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_NSIS))
 
2242
            ctx->container_type = CL_TYPE_NULSFT;
 
2243
            ctx->container_size = sb.st_size;
 
2244
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_NSIS))
1965
2245
                ret = cli_scannulsft(desc, ctx, 0);
1966
2246
            break;
1967
2247
 
1968
2248
        case CL_TYPE_AUTOIT:
 
2249
            ctx->container_type = CL_TYPE_AUTOIT;
 
2250
            ctx->container_size = sb.st_size;
1969
2251
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_AUTOIT))
1970
 
                ret = cli_scanautoit(desc, ctx, 23);
 
2252
                ret = cli_scanautoit(ctx, 23);
1971
2253
            break;
1972
2254
 
1973
2255
        case CL_TYPE_MSSZDD:
1976
2258
            break;
1977
2259
 
1978
2260
        case CL_TYPE_MSCAB:
 
2261
            ctx->container_type = CL_TYPE_MSCAB;
 
2262
            ctx->container_size = sb.st_size;
1979
2263
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB))
1980
2264
                ret = cli_scanmscab(desc, ctx, 0);
1981
2265
            break;
1982
2266
 
1983
2267
        case CL_TYPE_HTML:
1984
2268
            if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
1985
 
                ret = cli_scanhtml(desc, ctx);
 
2269
                ret = cli_scanhtml(ctx);
1986
2270
            break;
1987
2271
 
1988
2272
        case CL_TYPE_HTML_UTF16:
1989
2273
            if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
1990
 
                ret = cli_scanhtml_utf16(desc, ctx);
 
2274
                ret = cli_scanhtml_utf16(ctx);
1991
2275
            break;
1992
2276
 
1993
2277
        case CL_TYPE_SCRIPT:
1994
2278
            if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
1995
 
                ret = cli_scanscript(desc, ctx);
 
2279
                ret = cli_scanscript(ctx);
1996
2280
            break;
1997
2281
 
1998
2282
        case CL_TYPE_RTF:
 
2283
            ctx->container_type = CL_TYPE_RTF;
 
2284
            ctx->container_size = sb.st_size;
1999
2285
            if(SCAN_ARCHIVE && (DCONF_DOC & DOC_CONF_RTF))
2000
2286
                ret = cli_scanrtf(desc, ctx);
2001
2287
            break;
2002
2288
 
2003
2289
        case CL_TYPE_MAIL:
 
2290
            ctx->container_type = CL_TYPE_MAIL;
 
2291
            ctx->container_size = sb.st_size;
2004
2292
            if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX))
2005
2293
                ret = cli_scanmail(desc, ctx);
2006
2294
            break;
2012
2300
 
2013
2301
        case CL_TYPE_UUENCODED:
2014
2302
            if(DCONF_OTHER & OTHER_CONF_UUENC)
2015
 
                ret = cli_scanuuencoded(desc, ctx);
 
2303
                ret = cli_scanuuencoded(ctx);
2016
2304
            break;
2017
2305
 
2018
2306
        case CL_TYPE_MSCHM:
 
2307
            ctx->container_type = CL_TYPE_MSCHM;
 
2308
            ctx->container_size = sb.st_size;
2019
2309
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CHM))
2020
2310
                ret = cli_scanmschm(desc, ctx);
2021
2311
            break;
2022
2312
 
2023
2313
        case CL_TYPE_MSOLE2:
 
2314
            ctx->container_type = CL_TYPE_MSOLE2;
 
2315
            ctx->container_size = sb.st_size;
2024
2316
            if(SCAN_OLE2 && (DCONF_ARCH & ARCH_CONF_OLE2))
2025
 
                ret = cli_scanole2(desc, ctx);
 
2317
                ret = cli_scanole2(ctx);
 
2318
            break;
 
2319
 
 
2320
        case CL_TYPE_7Z:
 
2321
            ctx->container_type = CL_TYPE_7Z;
 
2322
            ctx->container_size = sb.st_size;
 
2323
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_7Z))
 
2324
                ret = cli_7unz(desc, ctx);
2026
2325
            break;
2027
2326
 
2028
2327
        case CL_TYPE_POSIX_TAR:
 
2328
            ctx->container_type = CL_TYPE_POSIX_TAR;
 
2329
            ctx->container_size = sb.st_size;
2029
2330
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
2030
2331
                ret = cli_scantar(desc, ctx, 1);
2031
2332
            break;
2032
2333
 
2033
2334
        case CL_TYPE_OLD_TAR:
 
2335
            ctx->container_type = CL_TYPE_OLD_TAR;
 
2336
            ctx->container_size = sb.st_size;
2034
2337
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
2035
2338
                ret = cli_scantar(desc, ctx, 0);
2036
2339
            break;
2037
2340
 
 
2341
        case CL_TYPE_CPIO_OLD:
 
2342
            ctx->container_type = CL_TYPE_CPIO_OLD;
 
2343
            ctx->container_size = sb.st_size;
 
2344
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
 
2345
                ret = cli_scancpio_old(desc, ctx);
 
2346
            break;
 
2347
 
 
2348
        case CL_TYPE_CPIO_ODC:
 
2349
            ctx->container_type = CL_TYPE_CPIO_ODC;
 
2350
            ctx->container_size = sb.st_size;
 
2351
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
 
2352
                ret = cli_scancpio_odc(desc, ctx);
 
2353
            break;
 
2354
 
 
2355
        case CL_TYPE_CPIO_NEWC:
 
2356
            ctx->container_type = CL_TYPE_CPIO_NEWC;
 
2357
            ctx->container_size = sb.st_size;
 
2358
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
 
2359
                ret = cli_scancpio_newc(desc, ctx, 0);
 
2360
            break;
 
2361
 
 
2362
        case CL_TYPE_CPIO_CRC:
 
2363
            ctx->container_type = CL_TYPE_CPIO_CRC;
 
2364
            ctx->container_size = sb.st_size;
 
2365
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
 
2366
                ret = cli_scancpio_newc(desc, ctx, 1);
 
2367
            break;
 
2368
 
2038
2369
        case CL_TYPE_BINHEX:
2039
2370
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BINHEX))
2040
 
                ret = cli_scanbinhex(desc, ctx);
 
2371
                ret = cli_binhex(ctx);
2041
2372
            break;
2042
2373
 
2043
2374
        case CL_TYPE_SCRENC:
2056
2387
            break;
2057
2388
 
2058
2389
        case CL_TYPE_PDF: /* FIXMELIMITS: pdf should be an archive! */
 
2390
            ctx->container_type = CL_TYPE_PDF;
 
2391
            ctx->container_size = sb.st_size;
2059
2392
            if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF))
2060
 
                ret = cli_scanpdf(desc, ctx, 0);
 
2393
                ret = cli_scanpdf(ctx, 0);
2061
2394
            break;
2062
2395
 
2063
2396
        case CL_TYPE_CRYPTFF:
2067
2400
 
2068
2401
        case CL_TYPE_ELF:
2069
2402
            if(SCAN_ELF && ctx->dconf->elf)
2070
 
                ret = cli_scanelf(desc, ctx);
 
2403
                ret = cli_scanelf(ctx);
 
2404
            break;
 
2405
 
 
2406
        case CL_TYPE_MACHO:
 
2407
            if(ctx->dconf->macho)
 
2408
                ret = cli_scanmacho(ctx, NULL);
 
2409
            break;
 
2410
 
 
2411
        case CL_TYPE_MACHO_UNIBIN:
 
2412
            if(ctx->dconf->macho)
 
2413
                ret = cli_scanmacho_unibin(ctx);
2071
2414
            break;
2072
2415
 
2073
2416
        case CL_TYPE_SIS:
 
2417
            ctx->container_type = CL_TYPE_SIS;
 
2418
            ctx->container_size = sb.st_size;
2074
2419
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_SIS))
2075
2420
                ret = cli_scansis(desc, ctx);
2076
2421
            break;
2092
2437
            break;
2093
2438
    }
2094
2439
    ctx->recursion--;
 
2440
    ctx->container_type = current_container_type;
 
2441
    ctx->container_size = current_container_size;
2095
2442
 
2096
 
    if(ret == CL_VIRUS)
2097
 
        return CL_VIRUS;
 
2443
    if(ret == CL_VIRUS) {
 
2444
        ret = cli_checkfp(hash, hashed_size, ctx);
 
2445
        funmap(*ctx->fmap);
 
2446
        ctx->fmap--;
 
2447
        cli_bitset_free(ctx->hook_lsig_matches);
 
2448
        ctx->hook_lsig_matches = old_hook_lsig_matches;
 
2449
        ret_from_magicscan(ret);
 
2450
    }
2098
2451
 
2099
2452
    if(type == CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
2100
2453
        if(sb.st_size > 1048576) {
2105
2458
 
2106
2459
    /* CL_TYPE_HTML: raw HTML files are not scanned, unless safety measure activated via DCONF */
2107
2460
    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;
 
2461
        res = cli_scanraw(ctx, type, typercg, &dettype, hash);
 
2462
        if(res != CL_CLEAN) {
 
2463
            switch(res) {
 
2464
                /* List of scan halts, runtime errors only! */
 
2465
                case CL_EUNLINK:
 
2466
                case CL_ESTAT:
 
2467
                case CL_ESEEK:
 
2468
                case CL_EWRITE:
 
2469
                case CL_EDUP:
 
2470
                case CL_ETMPFILE:
 
2471
                case CL_ETMPDIR:
 
2472
                case CL_EMEM:
 
2473
                case CL_ETIMEOUT:
 
2474
                    cli_dbgmsg("Descriptor[%d]: cli_scanraw error %s\n", desc, cl_strerror(res));
 
2475
                    funmap(*ctx->fmap);
 
2476
                    ctx->fmap--;
 
2477
                    cli_bitset_free(ctx->hook_lsig_matches);
 
2478
                    ctx->hook_lsig_matches = old_hook_lsig_matches;
 
2479
                    ret_from_magicscan(res);
 
2480
                /* CL_VIRUS = malware found, check FP and report */
 
2481
                case CL_VIRUS:
 
2482
                    ret = cli_checkfp(hash, hashed_size, ctx);
 
2483
                    if (SCAN_ALL)
 
2484
                        break;
 
2485
                    funmap(*ctx->fmap);
 
2486
                    ctx->fmap--;
 
2487
                    cli_bitset_free(ctx->hook_lsig_matches);
 
2488
                    ctx->hook_lsig_matches = old_hook_lsig_matches;
 
2489
                    ret_from_magicscan(ret);
 
2490
                /* "MAX" conditions should still fully scan the current file */
 
2491
                case CL_EMAXREC:
 
2492
                case CL_EMAXSIZE:
 
2493
                case CL_EMAXFILES:
 
2494
                    ret = res;
 
2495
                    cli_dbgmsg("Descriptor[%d]: Continuing after cli_scanraw reached %s\n",
 
2496
                        desc, cl_strerror(res));
 
2497
                    break;
 
2498
                /* Other errors must not block further scans below
 
2499
                 * This specifically includes CL_EFORMAT & CL_EREAD & CL_EUNPACK
 
2500
                 * Malformed/truncated files could report as any of these three.
 
2501
                 */
 
2502
                default:
 
2503
                    ret = res;
 
2504
                    cli_dbgmsg("Descriptor[%d]: Continuing after cli_scanraw error %s\n",
 
2505
                        desc, cl_strerror(res));
 
2506
            }
 
2507
        }
2110
2508
    }
2111
2509
 
2112
2510
    ctx->recursion++;
2113
2511
    lseek(desc, 0, SEEK_SET);
2114
2512
    switch(type) {
 
2513
        /* bytecode hooks triggered by a lsig must be a hook
 
2514
         * called from one of the functions here */
2115
2515
        case CL_TYPE_TEXT_ASCII:
2116
2516
        case CL_TYPE_TEXT_UTF16BE:
2117
2517
        case CL_TYPE_TEXT_UTF16LE:
2118
2518
        case CL_TYPE_TEXT_UTF8:
2119
 
            if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
2120
 
                ret = cli_scanscript(desc, ctx);
 
2519
            if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML && ret != CL_VIRUS)
 
2520
                ret = cli_scanscript(ctx);
 
2521
            if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX) && ret != CL_VIRUS && (ctx->container_type == CL_TYPE_MAIL || dettype == CL_TYPE_MAIL)) {
 
2522
                ret = cli_fmap_scandesc(ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR, NULL, NULL);
 
2523
            }
2121
2524
            break;
2122
2525
        /* Due to performance reasons all executables were first scanned
2123
2526
         * in raw mode. Now we will try to unpack them
2124
2527
         */
2125
2528
        case CL_TYPE_MSEXE:
2126
 
            if(SCAN_PE && ctx->dconf->pe)
2127
 
                ret = cli_scanpe(desc, ctx);
 
2529
            if(SCAN_PE && ctx->dconf->pe) {
 
2530
                unsigned int corrupted_input = ctx->corrupted_input;
 
2531
                ret = cli_scanpe(ctx);
 
2532
                ctx->corrupted_input = corrupted_input;
 
2533
            }
2128
2534
            break;
2129
 
 
2130
2535
        default:
2131
2536
            break;
2132
2537
    }
 
2538
 
 
2539
    if(ret == CL_VIRUS)
 
2540
        ret = cli_checkfp(hash, hashed_size, ctx);
2133
2541
    ctx->recursion--;
 
2542
    funmap(*ctx->fmap);
 
2543
    ctx->fmap--;
 
2544
    cli_bitset_free(ctx->hook_lsig_matches);
 
2545
    ctx->hook_lsig_matches = old_hook_lsig_matches;
2134
2546
 
2135
2547
    switch(ret) {
 
2548
        /* Malformed file cases */
2136
2549
        case CL_EFORMAT:
 
2550
        case CL_EREAD:
 
2551
        case CL_EUNPACK:
 
2552
        /* Limits exceeded */
2137
2553
        case CL_EMAXREC:
2138
2554
        case CL_EMAXSIZE:
2139
2555
        case CL_EMAXFILES:
2140
2556
            cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(ret));
2141
 
            return CL_CLEAN;
 
2557
            ret_from_magicscan(CL_CLEAN);
 
2558
        case CL_CLEAN:
 
2559
            cache_add(hash, hashed_size, ctx);
 
2560
            ret_from_magicscan(CL_CLEAN);
2142
2561
        default:
2143
 
            return ret;
 
2562
            ret_from_magicscan(ret);
2144
2563
    }
2145
2564
}
2146
2565
 
 
2566
int cli_magic_scandesc(int desc, cli_ctx *ctx)
 
2567
{
 
2568
    return magic_scandesc(desc, ctx, CL_TYPE_ANY);
 
2569
}
 
2570
 
 
2571
int cli_magic_scandesc_type(int desc, cli_ctx *ctx, cli_file_t type)
 
2572
{
 
2573
    return magic_scandesc(desc, ctx, type);
 
2574
}
 
2575
 
2147
2576
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
2148
2577
{
 
2578
    return cl_scandesc_callback(desc, virname, scanned, engine, scanoptions, NULL);
 
2579
}
 
2580
 
 
2581
int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context)
 
2582
{
2149
2583
    cli_ctx ctx;
2150
2584
    int rc;
2151
2585
 
2155
2589
    ctx.scanned = scanned;
2156
2590
    ctx.options = scanoptions;
2157
2591
    ctx.found_possibly_unwanted = 0;
 
2592
    ctx.container_type = CL_TYPE_ANY;
 
2593
    ctx.container_size = 0;
2158
2594
    ctx.dconf = (struct cli_dconf *) engine->dconf;
2159
 
 
 
2595
    ctx.cb_ctx = context;
 
2596
    ctx.fmap = cli_calloc(sizeof(fmap_t *), ctx.engine->maxreclevel + 2);
 
2597
    if(!ctx.fmap)
 
2598
        return CL_EMEM;
 
2599
    if (!(ctx.hook_lsig_matches = cli_bitset_init())) {
 
2600
        free(ctx.fmap);
 
2601
        return CL_EMEM;
 
2602
    }
 
2603
 
 
2604
#ifdef HAVE__INTERNAL__SHA_COLLECT
 
2605
    if(scanoptions & CL_SCAN_INTERNAL_COLLECT_SHA) {
 
2606
        char link[32];
 
2607
        ssize_t linksz;
 
2608
 
 
2609
        snprintf(link, sizeof(link), "/proc/self/fd/%u", desc);
 
2610
        link[sizeof(link)-1]='\0';
 
2611
        if((linksz=readlink(link, ctx.entry_filename, sizeof(ctx.entry_filename)))==-1) {
 
2612
            cli_errmsg("failed to resolve filename for descriptor %d (%s)\n", desc, link);
 
2613
            strcpy(ctx.entry_filename, "NO_IDEA");
 
2614
        } else
 
2615
            ctx.entry_filename[linksz]='\0';
 
2616
    } while(0);
 
2617
#endif
 
2618
 
 
2619
    cli_logg_setup(&ctx);
2160
2620
    rc = cli_magic_scandesc(desc, &ctx);
 
2621
 
 
2622
    if (ctx.options & CL_SCAN_ALLMATCHES) {
 
2623
        *virname = (char *)ctx.virname; /* temp hack for scanall mode until api augmentation */
 
2624
        if (rc == CL_CLEAN && ctx.num_viruses)
 
2625
            rc = CL_VIRUS;
 
2626
    }
 
2627
 
 
2628
    cli_bitset_free(ctx.hook_lsig_matches);
 
2629
    free(ctx.fmap);
2161
2630
    if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
2162
 
        rc = CL_VIRUS;
 
2631
        rc = CL_VIRUS;
 
2632
    cli_logg_unsetup();
2163
2633
    return rc;
2164
2634
}
2165
2635
 
2166
2636
int cli_found_possibly_unwanted(cli_ctx* ctx)
2167
2637
{
2168
 
        if(ctx->virname) {
2169
 
                cli_dbgmsg("found Possibly Unwanted: %s\n",*ctx->virname);
2170
 
                if(ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE) {
2171
 
                        /* we found a heuristic match, don't scan further,
2172
 
                         * but consider it a virus. */
2173
 
                        cli_dbgmsg("cli_found_possibly_unwanted: CL_VIRUS\n");
2174
 
                        return CL_VIRUS;
2175
 
                }
2176
 
                /* heuristic scan isn't taking precedence, keep scanning.
2177
 
                 * If this is part of an archive, and 
2178
 
                 * we find a real malware we report that instead of the 
2179
 
                 * heuristic match */
2180
 
                ctx->found_possibly_unwanted = 1;
2181
 
        } else {
2182
 
                cli_warnmsg("cli_found_possibly_unwanted called, but virname is not set\n");
 
2638
    if(cli_get_last_virus(ctx)) {
 
2639
        cli_dbgmsg("found Possibly Unwanted: %s\n", cli_get_last_virus(ctx));
 
2640
        if(ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE) {
 
2641
            /* we found a heuristic match, don't scan further,
 
2642
             * but consider it a virus. */
 
2643
            cli_dbgmsg("cli_found_possibly_unwanted: CL_VIRUS\n");
 
2644
            return CL_VIRUS;
2183
2645
        }
2184
 
        return CL_CLEAN;
 
2646
        /* heuristic scan isn't taking precedence, keep scanning.
 
2647
         * If this is part of an archive, and 
 
2648
         * we find a real malware we report that instead of the 
 
2649
         * heuristic match */
 
2650
        ctx->found_possibly_unwanted = 1;
 
2651
    } else {
 
2652
        cli_warnmsg("cli_found_possibly_unwanted called, but virname is not set\n");
 
2653
    }
 
2654
    emax_reached(ctx);
 
2655
    return CL_CLEAN;
2185
2656
}
2186
2657
 
2187
2658
static int cli_scanfile(const char *filename, cli_ctx *ctx)
2189
2660
        int fd, ret;
2190
2661
 
2191
2662
    /* internal version of cl_scanfile with arec/mrec preserved */
2192
 
    if((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
 
2663
    if((fd = safe_open(filename, O_RDONLY|O_BINARY)) == -1)
2193
2664
        return CL_EOPEN;
2194
2665
 
2195
2666
    ret = cli_magic_scandesc(fd, ctx);
2200
2671
 
2201
2672
int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
2202
2673
{
 
2674
    return cl_scanfile_callback(filename, virname, scanned, engine, scanoptions, NULL);
 
2675
}
 
2676
 
 
2677
int cl_scanfile_callback(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context)
 
2678
{
2203
2679
        int fd, ret;
2204
2680
 
2205
 
 
2206
 
    if((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
 
2681
    if((fd = safe_open(filename, O_RDONLY|O_BINARY)) == -1)
2207
2682
        return CL_EOPEN;
2208
2683
 
2209
 
    ret = cl_scandesc(fd, virname, scanned, engine, scanoptions);
 
2684
    ret = cl_scandesc_callback(fd, virname, scanned, engine, scanoptions, context);
2210
2685
    close(fd);
2211
2686
 
2212
2687
    return ret;