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

« back to all changes in this revision

Viewing changes to libclamav/scanners.c

  • Committer: Bazaar Package Importer
  • Author(s): Jamie Strandboge
  • Date: 2010-02-23 10:20:16 UTC
  • mfrom: (0.28.9 sid)
  • Revision ID: james.westby@ubuntu.com-20100223102016-oyc56y6ddhrsznh6
Tags: 0.95.3+dfsg-1ubuntu0.09.04~hardy2.2
No change rebuild from hardy-backports per microrelease exception

Show diffs side-by-side

added added

removed removed

Lines of Context:
91
91
#include <zlib.h>
92
92
#include "unzip.h"
93
93
#include "dlp.h"
 
94
#include "default.h"
94
95
 
95
96
#ifdef HAVE_BZLIB_H
96
97
#include <bzlib.h>
97
98
#endif
98
99
 
99
 
#ifdef ENABLE_UNRAR
100
 
#include "libclamunrar_iface/unrar_iface.h"
101
 
#endif
102
 
 
103
100
#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
104
101
#include <limits.h>
105
102
#include <stddef.h>
164
161
                                if(container == CL_TYPE_MAIL) {
165
162
                                    fd = open(fname, O_RDONLY|O_BINARY);
166
163
                                    if(fd == -1) {
167
 
                                            cli_warnmsg("Cannot open file %s: %s, mode: %x\n", fname, strerror(errno), statbuf.st_mode);
 
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);
168
166
                                            free(fname);
169
167
                                            continue;
170
168
                                    }
196
194
    return CL_CLEAN;
197
195
}
198
196
 
199
 
#ifdef ENABLE_UNRAR
200
197
static int cli_unrar_scanmetadata(int desc, unrar_metadata_t *metadata, cli_ctx *ctx, unsigned int files, uint32_t* sfx_check)
201
198
{
202
199
        int ret = CL_SUCCESS;
248
245
 
249
246
    if(mdata) {
250
247
        *ctx->virname = mdata->virname;
251
 
        return CL_VIRUS;           
 
248
        return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
252
249
    }
253
250
 
254
251
    if(DETECT_ENCRYPTED && metadata->encrypted) {
276
273
 
277
274
    if(sfx_offset)
278
275
        if(lseek(desc, sfx_offset, SEEK_SET) == -1)
279
 
            return CL_EIO;
 
276
            return CL_ESEEK;
280
277
 
281
278
    /* generate the temporary directory */
282
 
    if(!(dir = cli_gentemp(NULL)))
 
279
    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
283
280
        return CL_EMEM;
284
281
 
285
282
    if(mkdir(dir, 0700)) {
288
285
        return CL_ETMPDIR;
289
286
    }
290
287
 
291
 
    if((ret = unrar_open(desc, dir, &rar_state)) != UNRAR_OK) {
292
 
        if(!cli_leavetemps_flag)
 
288
    if((ret = cli_unrar_open(desc, dir, &rar_state)) != UNRAR_OK) {
 
289
        if(!ctx->engine->keeptmp)
293
290
            cli_rmdirs(dir);
294
291
        free(dir);
295
292
        if(ret == UNRAR_PASSWD) {
305
302
        } if(ret == UNRAR_EMEM) {
306
303
            return CL_EMEM;
307
304
        } else {
308
 
            return CL_ERAR;
 
305
            return CL_EUNPACK;
309
306
        }
310
307
    }
311
308
 
312
309
    do {
313
310
        int rc;
314
311
        rar_state.ofd = -1;
315
 
        ret = unrar_extract_next_prepare(&rar_state,dir);
 
312
        ret = cli_unrar_extract_next_prepare(&rar_state,dir);
316
313
        if(ret != UNRAR_OK) {
317
314
            if(ret == UNRAR_BREAK)
318
315
                ret = CL_BREAK;
319
316
            else if(ret == UNRAR_EMEM)
320
317
                ret = CL_EMEM;
321
318
            else
322
 
                ret = CL_ERAR;
 
319
                ret = CL_EUNPACK;
323
320
            break;
324
321
        }
325
 
        if((ret=cli_checklimits("RAR", ctx, rar_state.metadata_tail->unpack_size, rar_state.metadata_tail->pack_size, 0)!=CL_CLEAN)) {
 
322
        if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
326
323
            free(rar_state.file_header->filename);
327
324
            free(rar_state.file_header);
328
325
            ret = CL_CLEAN;
329
 
            continue;
 
326
            break;
330
327
        }
331
 
        ret = unrar_extract_next(&rar_state,dir);
 
328
        if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
 
329
            rar_state.maxfilesize = ctx->engine->maxscansize - ctx->scansize;
 
330
        else
 
331
            rar_state.maxfilesize = ctx->engine->maxfilesize;
 
332
 
 
333
        ret = cli_unrar_extract_next(&rar_state,dir);
332
334
        if(ret == UNRAR_OK)
333
335
            ret = CL_SUCCESS;
334
336
        else if(ret == UNRAR_EMEM)
335
337
            ret = CL_EMEM;
336
338
        else
337
 
            ret = CL_ERAR;
 
339
            ret = CL_EFORMAT;
338
340
 
339
341
        if(rar_state.ofd > 0) {
340
342
            lseek(rar_state.ofd,0,SEEK_SET);
341
343
            rc = cli_magic_scandesc(rar_state.ofd,ctx);
342
344
            close(rar_state.ofd);
343
 
            if(!cli_leavetemps_flag) 
344
 
                if (cli_unlink(rar_state.filename)) ret = CL_EIO;
 
345
            if(!ctx->engine->keeptmp) 
 
346
                if (cli_unlink(rar_state.filename)) ret = CL_EUNLINK;
345
347
            if(rc == CL_VIRUS ) {
346
348
                cli_dbgmsg("RAR: infected with %s\n",*ctx->virname);
347
349
                ret = CL_VIRUS;
362
364
    if(cli_scandir(rar_state.comment_dir, ctx, 0) == CL_VIRUS)
363
365
        ret = CL_VIRUS;
364
366
 
365
 
    unrar_close(&rar_state);
 
367
    cli_unrar_close(&rar_state);
366
368
 
367
 
    if(!cli_leavetemps_flag)
 
369
    if(!ctx->engine->keeptmp)
368
370
        cli_rmdirs(dir);
369
371
 
370
372
    free(dir);
380
382
 
381
383
    return ret;
382
384
}
383
 
#endif /* ENABLE_UNRAR */
384
385
 
385
386
static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
386
387
{
391
392
    cli_dbgmsg("in cli_scanarj()\n");
392
393
 
393
394
     /* generate the temporary directory */
394
 
    if(!(dir = cli_gentemp(NULL)))
 
395
    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
395
396
        return CL_EMEM;
396
397
 
397
398
    if(mkdir(dir, 0700)) {
405
406
 
406
407
    ret = cli_unarj_open(desc, dir);
407
408
    if (ret != CL_SUCCESS) {
408
 
        if(!cli_leavetemps_flag)
 
409
        if(!ctx->engine->keeptmp)
409
410
            cli_rmdirs(dir);
410
411
        free(dir);
411
412
        cli_dbgmsg("ARJ: Error: %s\n", cl_strerror(ret));
412
413
        return ret;
413
414
    }
414
415
    
415
 
   metadata.filename = NULL;
416
 
 
417
416
   do {
 
417
        metadata.filename = NULL;
418
418
        ret = cli_unarj_prepare_file(desc, dir, &metadata);
419
419
        if (ret != CL_SUCCESS) {
420
420
           break;
421
421
        }
422
422
        if ((ret = cli_checklimits("ARJ", ctx, metadata.orig_size, metadata.comp_size, 0))!=CL_CLEAN) {
423
423
            ret = CL_SUCCESS;
 
424
            if (metadata.filename)
 
425
                free(metadata.filename);
424
426
            continue;
425
427
        }
426
428
        ret = cli_unarj_extract_file(desc, dir, &metadata);
431
433
            if (rc == CL_VIRUS) {
432
434
                cli_dbgmsg("ARJ: infected with %s\n",*ctx->virname);
433
435
                ret = CL_VIRUS;
 
436
                if (metadata.filename) {
 
437
                    free(metadata.filename);
 
438
                    metadata.filename = NULL;
 
439
                }
434
440
                break;
435
441
            }
436
442
        }
441
447
 
442
448
    } while(ret == CL_SUCCESS);
443
449
    
444
 
    if(!cli_leavetemps_flag)
 
450
    if(!ctx->engine->keeptmp)
445
451
        cli_rmdirs(dir);
446
452
 
447
453
    free(dir);
469
475
 
470
476
    if((gd = gzdopen(dup(desc), "rb")) == NULL) {
471
477
        cli_dbgmsg("GZip: Can't open descriptor %d\n", desc);
472
 
        return CL_EGZIP;
 
478
        return CL_EOPEN;
473
479
    }
474
480
 
475
 
    if((ret = cli_gentempfd(NULL, &tmpname, &fd))) {
 
481
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
476
482
        cli_dbgmsg("GZip: Can't generate temporary file.\n");
477
483
        gzclose(gd);
478
484
        return ret;
482
488
        cli_dbgmsg("GZip: Unable to malloc %u bytes.\n", FILEBUFF);
483
489
        gzclose(gd);
484
490
        close(fd);
485
 
        if(!cli_leavetemps_flag) {
 
491
        if(!ctx->engine->keeptmp) {
486
492
            if(cli_unlink(tmpname)) {
487
493
                free(tmpname);
488
 
                return CL_EIO;
 
494
                return CL_EUNLINK;
489
495
            }
490
496
        }
491
497
        return CL_EMEM;
500
506
        if(cli_writen(fd, buff, bytes) != bytes) {
501
507
            cli_dbgmsg("GZip: Can't write to file.\n");
502
508
            close(fd);
503
 
            if(!cli_leavetemps_flag) {
 
509
            if(!ctx->engine->keeptmp) {
504
510
                if (cli_unlink(tmpname)) {
505
511
                    free(tmpname);
506
512
                    gzclose(gd);
507
513
                    free(buff);
508
 
                    return CL_EIO;
 
514
                    return CL_EUNLINK;
509
515
                }
510
516
            }
511
517
            free(tmpname);      
512
518
            gzclose(gd);
513
519
            free(buff);
514
 
            return CL_EGZIP;
 
520
            return CL_EWRITE;
515
521
        }
516
522
    }
517
523
 
520
526
 
521
527
    if(ret == CL_VIRUS) {
522
528
        close(fd);
523
 
        if(!cli_leavetemps_flag)
524
 
            if (cli_unlink(tmpname)) ret = CL_EIO;
 
529
        if(!ctx->engine->keeptmp)
 
530
            if (cli_unlink(tmpname)) ret = CL_EUNLINK;
525
531
        free(tmpname);  
526
532
        return ret;
527
533
    }
530
536
    if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
531
537
        cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
532
538
        close(fd);
533
 
        if(!cli_leavetemps_flag) {
 
539
        if(!ctx->engine->keeptmp) {
534
540
            if (cli_unlink(tmpname)) {
535
541
                free(tmpname);
536
 
                return CL_EIO;
 
542
                return CL_EUNLINK;
537
543
            }
538
544
        }
539
545
        free(tmpname);  
540
546
        return CL_VIRUS;
541
547
    }
542
548
    close(fd);
543
 
    if(!cli_leavetemps_flag)
544
 
        if (cli_unlink(tmpname)) ret = CL_EIO;
 
549
    if(!ctx->engine->keeptmp)
 
550
        if (cli_unlink(tmpname)) ret = CL_EUNLINK;
545
551
    free(tmpname);      
546
552
 
547
553
    return ret;
565
571
static int cli_scanbzip(int desc, cli_ctx *ctx)
566
572
{
567
573
        int fd, bytes, ret = CL_CLEAN, bzerror = 0;
568
 
        short memlim = 0;
569
574
        unsigned long int size = 0;
570
575
        char *buff;
571
576
        FILE *fs;
575
580
 
576
581
    if((fs = fdopen(dup(desc), "rb")) == NULL) {
577
582
        cli_dbgmsg("Bzip: Can't open descriptor %d.\n", desc);
578
 
        return CL_EBZIP;
 
583
        return CL_EOPEN;
579
584
    }
580
585
 
581
 
    if(ctx->limits)
582
 
        if(ctx->limits->archivememlim)
583
 
            memlim = 1;
584
 
 
585
 
    if((bfd = BZ2_bzReadOpen(&bzerror, fs, 0, memlim, NULL, 0)) == NULL) {
 
586
    if((bfd = BZ2_bzReadOpen(&bzerror, fs, 0, 0, NULL, 0)) == NULL) {
586
587
        cli_dbgmsg("Bzip: Can't initialize bzip2 library (descriptor: %d).\n", desc);
587
588
        fclose(fs);
588
 
        return CL_EBZIP;
 
589
        return CL_EOPEN;
589
590
    }
590
591
 
591
 
    if((ret = cli_gentempfd(NULL, &tmpname, &fd))) {
 
592
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
592
593
        cli_dbgmsg("Bzip: Can't generate temporary file.\n");
593
594
        BZ2_bzReadClose(&bzerror, bfd);
594
595
        fclose(fs);
598
599
    if(!(buff = (char *) cli_malloc(FILEBUFF))) {
599
600
        cli_dbgmsg("Bzip: Unable to malloc %u bytes.\n", FILEBUFF);
600
601
        close(fd);
601
 
        if(!cli_leavetemps_flag) {
 
602
        if(!ctx->engine->keeptmp) {
602
603
            if (cli_unlink(tmpname)) {
603
604
                free(tmpname);
604
605
                fclose(fs);
605
606
                BZ2_bzReadClose(&bzerror, bfd);
606
 
                return CL_EIO;
 
607
                return CL_EUNLINK;
607
608
            }
608
609
        }
609
610
        free(tmpname);  
622
623
            cli_dbgmsg("Bzip: Can't write to file.\n");
623
624
            BZ2_bzReadClose(&bzerror, bfd);
624
625
            close(fd);
625
 
            if(!cli_leavetemps_flag) {
 
626
            if(!ctx->engine->keeptmp) {
626
627
                if (cli_unlink(tmpname)) {
627
628
                    free(tmpname);
628
629
                    free(buff);
629
630
                    fclose(fs);
630
 
                    return CL_EIO;
 
631
                    return CL_EUNLINK;
631
632
                }
632
633
            }
633
634
            free(tmpname);      
634
635
            free(buff);
635
636
            fclose(fs);
636
 
            return CL_EGZIP;
 
637
            return CL_EWRITE;
637
638
        }
638
639
    }
639
640
 
642
643
 
643
644
    if(ret == CL_VIRUS) {
644
645
        close(fd);
645
 
        if(!cli_leavetemps_flag)
646
 
            if (cli_unlink(tmpname)) ret = CL_EIO;
 
646
        if(!ctx->engine->keeptmp)
 
647
            if (cli_unlink(tmpname)) ret = CL_EUNLINK;
647
648
        free(tmpname);  
648
649
        fclose(fs);
649
650
        return ret;
654
655
        cli_dbgmsg("Bzip: Infected with %s\n", *ctx->virname);
655
656
    }
656
657
    close(fd);
657
 
    if(!cli_leavetemps_flag)
658
 
        if (cli_unlink(tmpname)) ret = CL_EIO;
 
658
    if(!ctx->engine->keeptmp)
 
659
        if (cli_unlink(tmpname)) ret = CL_EUNLINK;
659
660
    free(tmpname);      
660
661
    fclose(fs);
661
662
 
671
672
 
672
673
    cli_dbgmsg("in cli_scanszdd()\n");
673
674
 
674
 
    if((ret = cli_gentempfd(NULL, &tmpname, &ofd))) {
 
675
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &ofd))) {
675
676
        cli_dbgmsg("MSEXPAND: Can't generate temporary file/descriptor\n");
676
677
        return ret;
677
678
    }
681
682
 
682
683
    if(ret != CL_SUCCESS) { /* CL_VIRUS or some error */
683
684
        close(ofd);
684
 
        if(!cli_leavetemps_flag)
685
 
            if (cli_unlink(tmpname)) ret = CL_EIO;
 
685
        if(!ctx->engine->keeptmp)
 
686
            if (cli_unlink(tmpname)) ret = CL_EUNLINK;
686
687
        free(tmpname);  
687
688
        return ret;
688
689
    }
691
692
    lseek(ofd, 0, SEEK_SET);
692
693
    ret = cli_magic_scandesc(ofd, ctx);
693
694
    close(ofd);
694
 
    if(!cli_leavetemps_flag)
695
 
        if (cli_unlink(tmpname)) ret = CL_EIO;
 
695
    if(!ctx->engine->keeptmp)
 
696
        if (cli_unlink(tmpname)) ret = CL_EUNLINK;
696
697
    free(tmpname);      
697
698
 
698
699
    return ret;
715
716
    for(file = cab.files; file; file = file->next) {
716
717
        files++;
717
718
 
718
 
        if(cli_checklimits("CAB", ctx, file->length, 0, 0)!=CL_CLEAN)
719
 
            continue;
720
 
 
721
 
        if(!(tempname = cli_gentemp(NULL))) {
 
719
        if(!(tempname = cli_gentemp(ctx->engine->tmpdir))) {
722
720
            ret = CL_EMEM;
723
721
            break;
724
722
        }
725
 
        cli_dbgmsg("CAB: Extracting file %s to %s, size %u\n", file->name, tempname, file->length);
726
 
        if((ret = cab_extract(file, tempname)))
 
723
 
 
724
        if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
 
725
            ret = CL_CLEAN;
 
726
            break;
 
727
        }
 
728
        if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
 
729
            file->max_size = ctx->engine->maxscansize - ctx->scansize;
 
730
        else
 
731
            file->max_size = ctx->engine->maxfilesize;
 
732
 
 
733
        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
        file->written_size = 0;
 
735
        if((ret = cab_extract(file, tempname))) {
727
736
            cli_dbgmsg("CAB: Failed to extract file: %s\n", cl_strerror(ret));
728
 
        else
 
737
        } else {
 
738
            if(file->length != file->written_size)
 
739
                cli_dbgmsg("CAB: Length from header %u but wrote %u bytes\n", (unsigned int) file->length, (unsigned int) file->written_size);
 
740
 
729
741
            ret = cli_scanfile(tempname, ctx);
730
 
 
731
 
        if(!cli_leavetemps_flag) {
 
742
        }
 
743
        if(!ctx->engine->keeptmp) {
732
744
            if (cli_unlink(tempname)) {
733
745
                free(tempname);
734
 
                ret = CL_EIO;
 
746
                ret = CL_EUNLINK;
735
747
                break;
736
748
            }
737
749
        }
784
796
                    /* cli_dbgmsg("Project content:\n%s", data); */
785
797
                    if(ctx->scanned)
786
798
                        *ctx->scanned += data_len / CL_COUNT_PRECISION;
787
 
                    if(cli_scanbuff(data, data_len, ctx, CL_TYPE_MSOLE2) == CL_VIRUS) {
 
799
                    if(cli_scanbuff(data, data_len, 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
788
800
                        free(data);
789
801
                        ret = CL_VIRUS;
790
802
                        break;
808
820
            vbaname[sizeof(vbaname)-1] = '\0';
809
821
            fd = open(vbaname, O_RDONLY|O_BINARY);
810
822
            if (fd == -1) continue;
811
 
            if ((fullname = cli_ppt_vba_read(fd))) {
 
823
            if ((fullname = cli_ppt_vba_read(fd, ctx))) {
812
824
                if(cli_scandir(fullname, ctx, 0) == CL_VIRUS) {
813
825
                    ret = CL_VIRUS;
814
826
                }
815
 
                if(!cli_leavetemps_flag)
 
827
                if(!ctx->engine->keeptmp)
816
828
                    cli_rmdirs(fullname);
817
829
                free(fullname);
818
830
            }
842
854
                        cli_dbgmsg("Project content:\n%s", data);
843
855
                        if(ctx->scanned)
844
856
                            *ctx->scanned += vba_project->length[i] / CL_COUNT_PRECISION;
845
 
                        if(cli_scanbuff(data, vba_project->length[i], ctx, CL_TYPE_MSOLE2) == CL_VIRUS) {
 
857
                        if(cli_scanbuff(data, vba_project->length[i], 0, ctx, CL_TYPE_MSOLE2, NULL) == CL_VIRUS) {
846
858
                                free(data);
847
859
                                ret = CL_VIRUS;
848
860
                                break;
939
951
 
940
952
    if(fstat(desc, &sb) == -1) {
941
953
        cli_errmsg("cli_scanhtml: fstat() failed for descriptor %d\n", desc);
942
 
        return CL_EIO;
 
954
        return CL_ESTAT;
943
955
    }
944
956
 
945
957
    /* Because HTML detection is FP-prone and html_normalise_fd() needs to
951
963
        return CL_CLEAN;
952
964
    }
953
965
 
954
 
    if(!(tempname = cli_gentemp(NULL)))
 
966
    if(!(tempname = cli_gentemp(ctx->engine->tmpdir)))
955
967
        return CL_EMEM;
956
968
 
957
969
    if(mkdir(tempname, 0700)) {
999
1011
        ret = cli_scandir(fullname, ctx, 0);
1000
1012
    }
1001
1013
 
1002
 
    if(!cli_leavetemps_flag)
 
1014
    if(!ctx->engine->keeptmp)
1003
1015
        cli_rmdirs(tempname);
1004
1016
 
1005
1017
    free(tempname);
1015
1027
        char *tmpname = NULL;
1016
1028
        int ofd = -1, ret;
1017
1029
        ssize_t nread;
1018
 
        const struct cli_matcher *root = ctx->engine->root[7];
1019
 
        uint32_t maxpatlen = root ? root->maxpatlen : 0;
 
1030
        const struct cli_matcher *troot = ctx->engine->root[7];
 
1031
        uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0;
 
1032
        struct cli_matcher *groot = ctx->engine->root[0];
 
1033
        struct cli_ac_data gmdata, tmdata;
 
1034
        struct cli_ac_data *mdata[2];
1020
1035
 
1021
1036
        cli_dbgmsg("in cli_scanscript()\n");
1022
1037
 
1023
1038
        if(fstat(desc, &sb) == -1) {
1024
1039
                cli_errmsg("cli_scanscript: fstat() failed for descriptor %d\n", desc);
1025
 
                return CL_EIO;
 
1040
                return CL_ESTAT;
1026
1041
        }
1027
1042
 
1028
1043
        /* don't normalize files that are too large */
1029
 
        if(sb.st_size > 524288) {
1030
 
                cli_dbgmsg("cli_scanscript: exiting (file larger than 400 kB)\n");
 
1044
        if(sb.st_size > 5242880) {
 
1045
                cli_dbgmsg("cli_scanscript: exiting (file larger than 5 MB)\n");
1031
1046
                return CL_CLEAN;
1032
1047
        }
1033
1048
 
1034
1049
        /* dump to disk only if explicitly asked to,
1035
1050
         * otherwise we can process just in-memory */
1036
 
        if(cli_leavetemps_flag) {
1037
 
                if((ret = cli_gentempfd(NULL, &tmpname, &ofd))) {
 
1051
        if(ctx->engine->keeptmp) {
 
1052
                if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &ofd))) {
1038
1053
                        cli_dbgmsg("cli_scanscript: Can't generate temporary file/descriptor\n");
1039
1054
                        return ret;
1040
1055
                }
1048
1063
        text_normalize_init(&state, normalized, SCANBUFF + maxpatlen);
1049
1064
        ret = CL_CLEAN;
1050
1065
 
 
1066
        if ((ret = cli_ac_initdata(&tmdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
 
1067
            return ret;
 
1068
 
 
1069
        if ((ret = cli_ac_initdata(&gmdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN))) {
 
1070
            cli_ac_freedata(&tmdata);
 
1071
            return ret;
 
1072
        }
 
1073
        mdata[0] = &tmdata;
 
1074
        mdata[1] = &gmdata;
 
1075
 
1051
1076
        do {
1052
1077
                nread = cli_readn(desc, buff, sizeof(buff));
1053
1078
                if(nread <= 0 || state.out_pos + nread > state.out_len) {
1059
1084
                                /* we can continue to scan in memory */
1060
1085
                        }
1061
1086
                        /* when we flush the buffer also scan */
1062
 
                        if(cli_scanbuff(state.out, state.out_pos, ctx, CL_TYPE_TEXT_ASCII) == CL_VIRUS) {
 
1087
                        if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
1063
1088
                                ret = CL_VIRUS;
 
1089
                                if(ofd != -1)
 
1090
                                    ret = cli_checkfp(ofd, ctx) ? CL_CLEAN : CL_VIRUS;
1064
1091
                                break;
1065
1092
                        }
 
1093
                        if(ctx->scanned)
 
1094
                            *ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
 
1095
                        offset += state.out_pos;
1066
1096
                        /* carry over maxpatlen from previous buffer */
1067
1097
                        if (state.out_pos > maxpatlen)
1068
 
                                memcpy(state.out, state.out + state.out_pos - maxpatlen, maxpatlen); 
 
1098
                                memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen); 
1069
1099
                        text_normalize_reset(&state);
1070
1100
                        state.out_pos = maxpatlen;
1071
1101
                }
1076
1106
                 * and using while(){} loop would mean code duplication */
1077
1107
        } while (nread > 0);
1078
1108
 
1079
 
        if(cli_leavetemps_flag) {
 
1109
        cli_ac_freedata(&tmdata);
 
1110
        cli_ac_freedata(&gmdata);
 
1111
        if(ctx->engine->keeptmp) {
1080
1112
                free(tmpname);
1081
1113
                close(ofd);
1082
1114
        }
1093
1125
 
1094
1126
    cli_dbgmsg("in cli_scanhtml_utf16()\n");
1095
1127
 
1096
 
    if(!(tempname = cli_gentemp(NULL)))
 
1128
    if(!(tempname = cli_gentemp(ctx->engine->tmpdir)))
1097
1129
        return CL_EMEM;
1098
1130
 
1099
1131
    if((fd = open(tempname, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
1100
1132
        cli_errmsg("cli_scanhtml_utf16: Can't create file %s\n", tempname);
1101
1133
        free(tempname);
1102
 
        return CL_EIO;
 
1134
        return CL_EOPEN;
1103
1135
    }
1104
1136
 
1105
1137
    cli_dbgmsg("cli_scanhtml_utf16: using tempfile %s\n", tempname);
1110
1142
            if(write(fd, decoded, strlen(decoded)) == -1) {
1111
1143
                cli_errmsg("cli_scanhtml_utf16: Can't write to file %s\n", tempname);
1112
1144
                free(decoded);
 
1145
                close(fd);
1113
1146
                cli_unlink(tempname);
1114
1147
                free(tempname);
1115
 
                close(fd);
1116
 
                return CL_EIO;
 
1148
                return CL_EWRITE;
1117
1149
            }
1118
1150
            free(decoded);
1119
1151
        }
1123
1155
    ret = cli_scanhtml(fd, ctx);
1124
1156
    close(fd);
1125
1157
 
1126
 
    if(!cli_leavetemps_flag) {
1127
 
        if (cli_unlink(tempname)) ret = CL_EIO;
 
1158
    if(!ctx->engine->keeptmp) {
 
1159
        if (cli_unlink(tempname)) ret = CL_EUNLINK;
1128
1160
    } else
1129
1161
        cli_dbgmsg("cli_scanhtml_utf16: Decoded HTML data saved in %s\n", tempname);
1130
1162
    free(tempname);
1140
1172
 
1141
1173
    cli_dbgmsg("in cli_scanole2()\n");
1142
1174
 
1143
 
    if(ctx->limits && ctx->limits->maxreclevel && ctx->recursion >= ctx->limits->maxreclevel)
 
1175
    if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
1144
1176
        return CL_EMAXREC;
1145
1177
 
1146
1178
    /* generate the temporary directory */
1147
 
    if(!(dir = cli_gentemp(NULL)))
 
1179
    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
1148
1180
        return CL_EMEM;
1149
1181
 
1150
1182
    if(mkdir(dir, 0700)) {
1156
1188
    ret = cli_ole2_extract(desc, dir, ctx, &vba);
1157
1189
    if(ret!=CL_CLEAN && ret!=CL_VIRUS) {
1158
1190
        cli_dbgmsg("OLE2: %s\n", cl_strerror(ret));
1159
 
        if(!cli_leavetemps_flag)
 
1191
        if(!ctx->engine->keeptmp)
1160
1192
            cli_rmdirs(dir);
1161
1193
        free(dir);
1162
1194
        return ret;
1173
1205
        ctx->recursion--;
1174
1206
    }
1175
1207
 
1176
 
    if(!cli_leavetemps_flag)
 
1208
    if(!ctx->engine->keeptmp)
1177
1209
        cli_rmdirs(dir);
1178
1210
    free(dir);
1179
1211
    return ret;
1188
1220
    cli_dbgmsg("in cli_scantar()\n");
1189
1221
 
1190
1222
    /* generate temporary directory */
1191
 
    if(!(dir = cli_gentemp(NULL)))
 
1223
    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
1192
1224
        return CL_EMEM;
1193
1225
 
1194
1226
    if(mkdir(dir, 0700)) {
1199
1231
 
1200
1232
    ret = cli_untar(dir, desc, posix, ctx);
1201
1233
 
1202
 
    if(!cli_leavetemps_flag)
 
1234
    if(!ctx->engine->keeptmp)
1203
1235
        cli_rmdirs(dir);
1204
1236
 
1205
1237
    free(dir);
1215
1247
    cli_dbgmsg("in cli_scanbinhex()\n");
1216
1248
 
1217
1249
    /* generate temporary directory */
1218
 
    if(!(dir = cli_gentemp(NULL)))
 
1250
    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
1219
1251
        return CL_EMEM;
1220
1252
 
1221
1253
    if(mkdir(dir, 0700)) {
1229
1261
    else
1230
1262
        ret = cli_scandir(dir, ctx, 0);
1231
1263
 
1232
 
    if(!cli_leavetemps_flag)
 
1264
    if(!ctx->engine->keeptmp)
1233
1265
        cli_rmdirs(dir);
1234
1266
 
1235
1267
    free(dir);
1245
1277
    cli_dbgmsg("in cli_scanmschm()\n");
1246
1278
 
1247
1279
     /* generate the temporary directory */
1248
 
    if(!(dir = cli_gentemp(NULL)))
 
1280
    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
1249
1281
        return CL_EMEM;
1250
1282
 
1251
1283
    if(mkdir(dir, 0700)) {
1254
1286
        return CL_ETMPDIR;
1255
1287
    }
1256
1288
 
1257
 
    ret = cli_chm_open(desc, dir, &metadata);
 
1289
    ret = cli_chm_open(desc, dir, &metadata, ctx);
1258
1290
    if (ret != CL_SUCCESS) {
1259
 
        if(!cli_leavetemps_flag)
 
1291
        if(!ctx->engine->keeptmp)
1260
1292
            cli_rmdirs(dir);
1261
1293
        free(dir);
1262
1294
        cli_dbgmsg("CHM: Error: %s\n", cl_strerror(ret));
1268
1300
        if (ret != CL_SUCCESS) {
1269
1301
           break;
1270
1302
        }
1271
 
        ret = cli_chm_extract_file(desc, dir, &metadata);
 
1303
        ret = cli_chm_extract_file(desc, dir, &metadata, ctx);
1272
1304
        if (ret == CL_SUCCESS) {
1273
1305
            lseek(metadata.ofd, 0, SEEK_SET);
1274
1306
            rc = cli_magic_scandesc(metadata.ofd, ctx);
1284
1316
 
1285
1317
    cli_chm_close(&metadata);
1286
1318
   
1287
 
    if(!cli_leavetemps_flag)
 
1319
    if(!ctx->engine->keeptmp)
1288
1320
        cli_rmdirs(dir);
1289
1321
 
1290
1322
    free(dir);
1303
1335
 
1304
1336
    cli_dbgmsg("in cli_scanscrenc()\n");
1305
1337
 
1306
 
    if(!(tempname = cli_gentemp(NULL)))
 
1338
    if(!(tempname = cli_gentemp(ctx->engine->tmpdir)))
1307
1339
        return CL_EMEM;
1308
1340
 
1309
1341
    if(mkdir(tempname, 0700)) {
1315
1347
    if (html_screnc_decode(desc, tempname))
1316
1348
        ret = cli_scandir(tempname, ctx, 0);
1317
1349
 
1318
 
    if(!cli_leavetemps_flag)
 
1350
    if(!ctx->engine->keeptmp)
1319
1351
        cli_rmdirs(tempname);
1320
1352
 
1321
1353
    free(tempname);
1322
1354
    return ret;
1323
1355
}
1324
1356
 
1325
 
static int cli_scanriff(int desc, const char **virname)
 
1357
static int cli_scanriff(int desc, cli_ctx *ctx)
1326
1358
{
1327
1359
        int ret = CL_CLEAN;
1328
1360
 
1329
1361
    if(cli_check_riff_exploit(desc) == 2) {
1330
 
        ret = CL_VIRUS;
1331
 
        *virname = "Exploit.W32.MS05-002";
 
1362
        if(!cli_checkfp(desc, ctx)) {
 
1363
            ret = CL_VIRUS;
 
1364
            *ctx->virname = "Exploit.W32.MS05-002";
 
1365
        }
1332
1366
    }
1333
1367
 
1334
1368
    return ret;
1339
1373
        int ret = CL_CLEAN;
1340
1374
 
1341
1375
    if(cli_check_jpeg_exploit(desc, ctx) == 1) {
1342
 
        ret = CL_VIRUS;
1343
 
        *ctx->virname = "Exploit.W32.MS04-028";
 
1376
        if(!cli_checkfp(desc, ctx)) {
 
1377
            ret = CL_VIRUS;
 
1378
            *ctx->virname = "Exploit.W32.MS04-028";
 
1379
        }
1344
1380
    }
1345
1381
 
1346
1382
    return ret;
1357
1393
 
1358
1394
    if(fstat(desc, &sb) == -1) {
1359
1395
        cli_errmsg("CryptFF: Can't fstat descriptor %d\n", desc);
1360
 
        return CL_EIO;
 
1396
        return CL_ESTAT;
1361
1397
    }
1362
1398
 
1363
1399
    /* Skip the CryptFF file header */
1383
1419
        cli_dbgmsg("CryptFF: Can't read from descriptor %d\n", desc);
1384
1420
        free(dest);
1385
1421
        free(src);
1386
 
        return CL_EIO;
 
1422
        return CL_EREAD;
1387
1423
    }
1388
1424
 
1389
1425
    for(i = 0; i < length; i++)
1391
1427
 
1392
1428
    free(src);
1393
1429
 
1394
 
    if(!(tempfile = cli_gentemp(NULL))) {
 
1430
    if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) {
1395
1431
        free(dest);
1396
1432
        return CL_EMEM;
1397
1433
    }
1400
1436
        cli_errmsg("CryptFF: Can't create file %s\n", tempfile);
1401
1437
        free(dest);
1402
1438
        free(tempfile);
1403
 
        return CL_EIO;
 
1439
        return CL_ECREAT;
1404
1440
    }
1405
1441
 
1406
1442
    if(write(ndesc, dest, length) == -1) {
1408
1444
        free(dest);
1409
1445
        close(ndesc);
1410
1446
        free(tempfile);
1411
 
        return CL_EIO;
 
1447
        return CL_EWRITE;
1412
1448
    }
1413
1449
 
1414
1450
    free(dest);
1422
1458
 
1423
1459
    close(ndesc);
1424
1460
 
1425
 
    if(cli_leavetemps_flag)
 
1461
    if(ctx->engine->keeptmp)
1426
1462
        cli_dbgmsg("CryptFF: Decompressed data saved in %s\n", tempfile);
1427
1463
    else
1428
 
        if (cli_unlink(tempfile)) ret = CL_EIO;
 
1464
        if (cli_unlink(tempfile)) ret = CL_EUNLINK;
1429
1465
 
1430
1466
    free(tempfile);
1431
1467
    return ret;
1434
1470
static int cli_scanpdf(int desc, cli_ctx *ctx, off_t offset)
1435
1471
{
1436
1472
        int ret;
1437
 
        char *dir = cli_gentemp(NULL);
 
1473
        char *dir = cli_gentemp(ctx->engine->tmpdir);
1438
1474
 
1439
1475
    if(!dir)
1440
1476
        return CL_EMEM;
1447
1483
 
1448
1484
    ret = cli_pdf(dir, desc, ctx, offset);
1449
1485
 
1450
 
    if(!cli_leavetemps_flag)
 
1486
    if(!ctx->engine->keeptmp)
1451
1487
        cli_rmdirs(dir);
1452
1488
 
1453
1489
    free(dir);
1457
1493
static int cli_scantnef(int desc, cli_ctx *ctx)
1458
1494
{
1459
1495
        int ret;
1460
 
        char *dir = cli_gentemp(NULL);
 
1496
        char *dir = cli_gentemp(ctx->engine->tmpdir);
1461
1497
 
1462
1498
    if(!dir)
1463
1499
        return CL_EMEM;
1468
1504
        return CL_ETMPDIR;
1469
1505
    }
1470
1506
 
1471
 
    ret = cli_tnef(dir, desc);
 
1507
    ret = cli_tnef(dir, desc, ctx);
1472
1508
 
1473
1509
    if(ret == CL_CLEAN)
1474
1510
        ret = cli_scandir(dir, ctx, 0);
1475
1511
 
1476
 
    if(!cli_leavetemps_flag)
 
1512
    if(!ctx->engine->keeptmp)
1477
1513
        cli_rmdirs(dir);
1478
1514
 
1479
1515
    free(dir);
1483
1519
static int cli_scanuuencoded(int desc, cli_ctx *ctx)
1484
1520
{
1485
1521
        int ret;
1486
 
        char *dir = cli_gentemp(NULL);
 
1522
        char *dir = cli_gentemp(ctx->engine->tmpdir);
1487
1523
 
1488
1524
    if(!dir)
1489
1525
        return CL_EMEM;
1499
1535
    if(ret == CL_CLEAN)
1500
1536
        ret = cli_scandir(dir, ctx, 0);
1501
1537
 
1502
 
    if(!cli_leavetemps_flag)
 
1538
    if(!ctx->engine->keeptmp)
1503
1539
        cli_rmdirs(dir);
1504
1540
 
1505
1541
    free(dir);
1515
1551
    cli_dbgmsg("Starting cli_scanmail(), recursion = %u\n", ctx->recursion);
1516
1552
 
1517
1553
    /* generate the temporary directory */
1518
 
    if(!(dir = cli_gentemp(NULL)))
 
1554
    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
1519
1555
        return CL_EMEM;
1520
1556
 
1521
1557
    if(mkdir(dir, 0700)) {
1528
1564
     * Extract the attachments into the temporary directory
1529
1565
     */
1530
1566
    if((ret = cli_mbox(dir, desc, ctx))) {
1531
 
        if(!cli_leavetemps_flag)
 
1567
        if(!ctx->engine->keeptmp)
1532
1568
            cli_rmdirs(dir);
1533
1569
        free(dir);
1534
1570
        return ret;
1536
1572
 
1537
1573
    ret = cli_scandir(dir, ctx, CL_TYPE_MAIL);
1538
1574
 
1539
 
    if(!cli_leavetemps_flag)
 
1575
    if(!ctx->engine->keeptmp)
1540
1576
        cli_rmdirs(dir);
1541
1577
 
1542
1578
    free(dir);
1550
1586
        unsigned int cc_count = 0;
1551
1587
        unsigned int ssn_count = 0;
1552
1588
        int done = 0;
1553
 
        const struct cl_limits *lim = NULL;
1554
1589
        int (*ccfunc)(const unsigned char *buffer, int length);
1555
1590
        int (*ssnfunc)(const unsigned char *buffer, int length);
1556
1591
 
1557
1592
 
1558
 
    if(ctx == NULL || ctx->limits == NULL)
 
1593
    if(ctx == NULL)
1559
1594
        return CL_ENULLARG;
1560
1595
 
1561
 
    lim = ctx->limits;
1562
 
 
1563
 
    if(lim->min_cc_count == 1)
 
1596
    if(ctx->engine->min_cc_count == 1)
1564
1597
        ccfunc = dlp_has_cc;
1565
1598
    else
1566
1599
        ccfunc = dlp_get_cc_count;
1568
1601
    switch((ctx->options & CL_SCAN_STRUCTURED_SSN_NORMAL) | (ctx->options & CL_SCAN_STRUCTURED_SSN_STRIPPED)) {
1569
1602
 
1570
1603
        case (CL_SCAN_STRUCTURED_SSN_NORMAL | CL_SCAN_STRUCTURED_SSN_STRIPPED):
1571
 
            if(lim->min_ssn_count == 1)
 
1604
            if(ctx->engine->min_ssn_count == 1)
1572
1605
                ssnfunc = dlp_has_ssn;
1573
1606
            else
1574
1607
                ssnfunc = dlp_get_ssn_count;
1575
1608
            break;
1576
1609
 
1577
1610
        case CL_SCAN_STRUCTURED_SSN_NORMAL:
1578
 
            if(lim->min_ssn_count == 1)
 
1611
            if(ctx->engine->min_ssn_count == 1)
1579
1612
                ssnfunc = dlp_has_normal_ssn;
1580
1613
            else
1581
1614
                ssnfunc = dlp_get_normal_ssn_count;
1582
1615
            break;
1583
1616
 
1584
1617
        case CL_SCAN_STRUCTURED_SSN_STRIPPED:
1585
 
            if(lim->min_ssn_count == 1)
 
1618
            if(ctx->engine->min_ssn_count == 1)
1586
1619
                ssnfunc = dlp_has_stripped_ssn;
1587
1620
            else
1588
1621
                ssnfunc = dlp_get_stripped_ssn_count;
1593
1626
    }
1594
1627
 
1595
1628
    while(!done && ((result = cli_readn(desc, buf, 8191)) > 0)) {
1596
 
        if((cc_count += ccfunc((const unsigned char *)buf, result)) >= lim->min_cc_count)
 
1629
        if((cc_count += ccfunc((const unsigned char *)buf, result)) >= ctx->engine->min_cc_count)
1597
1630
            done = 1;
1598
1631
 
1599
 
        if(ssnfunc && ((ssn_count += ssnfunc((const unsigned char *)buf, result)) >= lim->min_ssn_count))
 
1632
        if(ssnfunc && ((ssn_count += ssnfunc((const unsigned char *)buf, result)) >= ctx->engine->min_ssn_count))
1600
1633
            done = 1;
1601
1634
    }
1602
1635
 
1603
 
    if(cc_count != 0 && cc_count >= lim->min_cc_count) {
 
1636
    if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) {
1604
1637
        cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count);
1605
1638
        *ctx->virname = "Structured.CreditCardNumber";
1606
 
        return CL_VIRUS;
 
1639
        return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1607
1640
    }
1608
1641
 
1609
 
    if(ssn_count != 0 && ssn_count >= lim->min_ssn_count) {
 
1642
    if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) {
1610
1643
        cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count);
1611
1644
        *ctx->virname = "Structured.SSN";
1612
 
        return CL_VIRUS;
 
1645
        return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1613
1646
    }
1614
1647
 
1615
1648
    return CL_CLEAN;
1622
1655
        char buff[512];
1623
1656
        char *tmpname;
1624
1657
 
1625
 
 
1626
 
    tmpname = cli_gentemp(NULL);
 
1658
    tmpname = cli_gentemp(ctx->engine->tmpdir);
1627
1659
    if(!tmpname)
1628
1660
        return CL_EMEM;
1629
1661
 
1630
1662
    if((fd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
1631
1663
        cli_errmsg("cli_scanembpe: Can't create file %s\n", tmpname);
1632
1664
        free(tmpname);
1633
 
        return CL_EIO;
 
1665
        return CL_ECREAT;
1634
1666
    }
1635
1667
 
1636
1668
    while((bytes = read(desc, buff, sizeof(buff))) > 0) {
1642
1674
        if(cli_writen(fd, buff, bytes) != bytes) {
1643
1675
            cli_dbgmsg("cli_scanembpe: Can't write to temporary file\n");
1644
1676
            close(fd);
1645
 
            if(!cli_leavetemps_flag) {
 
1677
            if(!ctx->engine->keeptmp) {
1646
1678
                if (cli_unlink(tmpname)) {
1647
1679
                    free(tmpname);
1648
 
                    return CL_EIO;
 
1680
                    return CL_EUNLINK;
1649
1681
                }
1650
1682
            }
1651
1683
            free(tmpname);      
1652
 
            return CL_EIO;
 
1684
            return CL_EWRITE;
1653
1685
        }
1654
1686
    }
1655
1687
 
1658
1690
    if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) {
1659
1691
        cli_dbgmsg("cli_scanembpe: Infected with %s\n", *ctx->virname);
1660
1692
        close(fd);
1661
 
        if(!cli_leavetemps_flag) {
 
1693
        if(!ctx->engine->keeptmp) {
1662
1694
            if (cli_unlink(tmpname)) {
1663
1695
                free(tmpname);
1664
 
                return CL_EIO;
 
1696
                return CL_EUNLINK;
1665
1697
            }
1666
1698
        }
1667
1699
        free(tmpname);  
1670
1702
    ctx->recursion--;
1671
1703
 
1672
1704
    close(fd);
1673
 
    if(!cli_leavetemps_flag) {
 
1705
    if(!ctx->engine->keeptmp) {
1674
1706
        if (cli_unlink(tmpname)) {
1675
1707
            free(tmpname);
1676
 
            return CL_EIO;
 
1708
            return CL_EUNLINK;
1677
1709
        }
1678
1710
    }
1679
1711
    free(tmpname);
1689
1721
        uint32_t lastzip, lastrar;
1690
1722
        struct cli_exe_info peinfo;
1691
1723
        unsigned int acmode = AC_SCAN_VIR, break_loop = 0;
1692
 
 
1693
 
 
1694
 
    if(typercg) switch(type) {
1695
 
        case CL_TYPE_TEXT_ASCII:
1696
 
        case CL_TYPE_MSEXE:
1697
 
        case CL_TYPE_ZIP:
1698
 
        case CL_TYPE_MSOLE2:
1699
 
            acmode |= AC_SCAN_FT;
1700
 
        default:
1701
 
            break;
1702
 
    }
 
1724
        struct stat sb;
 
1725
 
 
1726
 
 
1727
    if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
 
1728
        return CL_EMAXREC;
 
1729
 
 
1730
    if(typercg)
 
1731
        acmode |= AC_SCAN_FT;
1703
1732
 
1704
1733
    if(lseek(desc, 0, SEEK_SET) < 0) {
1705
1734
        cli_errmsg("cli_scanraw: lseek() failed\n");
1706
 
        return CL_EIO;
 
1735
        return CL_ESEEK;
1707
1736
    }
1708
1737
 
1709
1738
    ret = cli_scandesc(desc, ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode);
1710
1739
 
1711
1740
    if(ret >= CL_TYPENO) {
 
1741
        ctx->recursion++;
1712
1742
 
1713
1743
/*
1714
1744
        if(type == CL_TYPE_TEXT_ASCII) {
1720
1750
        }
1721
1751
*/
1722
1752
 
1723
 
        if(nret != CL_VIRUS && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2)) {
 
1753
        if(nret != CL_VIRUS) {
1724
1754
            lastzip = lastrar = 0xdeadbeef;
1725
1755
            fpt = ftoffset;
1726
1756
            while(fpt) {
1727
 
                switch(fpt->type) {
 
1757
                if(fpt->offset) switch(fpt->type) {
1728
1758
                    case CL_TYPE_RARSFX:
1729
 
#ifdef ENABLE_UNRAR
1730
 
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_RAR)) {
1731
 
                            cli_dbgmsg("RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
 
1759
                            cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
 
1760
                        if(type != CL_TYPE_RAR && have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR)) {
 
1761
                            cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1732
1762
                            nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar);
1733
1763
                        }
1734
 
#endif
1735
1764
                        break;
1736
1765
 
1737
1766
                    case CL_TYPE_ZIPSFX:
1738
 
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ZIP) && fpt->offset) {
1739
 
                            cli_dbgmsg("ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
 
1767
                        if(type != CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
 
1768
                            cli_dbgmsg("ZIP/ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
1740
1769
                            nret = cli_unzip_single(desc, ctx, fpt->offset);
1741
1770
                        }
1742
1771
                        break;
1743
1772
 
1744
1773
                    case CL_TYPE_CABSFX:
1745
 
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_CAB)) {
1746
 
                            cli_dbgmsg("CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
 
1774
                        if(type != CL_TYPE_MSCAB && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB)) {
 
1775
                            cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
1747
1776
                            nret = cli_scanmscab(desc, ctx, fpt->offset);
1748
1777
                        }
1749
1778
                        break;
1750
1779
                    case CL_TYPE_ARJSFX:
1751
 
                        if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ARJ)) {
 
1780
                        if(type != CL_TYPE_ARJ && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ)) {
1752
1781
                            cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
1753
1782
                            nret = cli_scanarj(desc, ctx, fpt->offset, &lastrar);
1754
1783
                        }
1769
1798
                        break;
1770
1799
 
1771
1800
                    case CL_TYPE_PDF:
1772
 
                        if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
 
1801
                        if(type != CL_TYPE_PDF && SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
1773
1802
                            cli_dbgmsg("PDF signature found at %u\n", (unsigned int) fpt->offset);
1774
1803
                            nret = cli_scanpdf(desc, ctx, fpt->offset);
1775
1804
                        }
1776
1805
                        break;
1777
1806
 
1778
1807
                    case CL_TYPE_MSEXE:
1779
 
                        if(SCAN_PE && ctx->dconf->pe && fpt->offset) {
1780
 
                            cli_dbgmsg("PE signature found at %u\n", (unsigned int) fpt->offset);
 
1808
                        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)
 
1811
                                break;
1781
1812
                            memset(&peinfo, 0, sizeof(struct cli_exe_info));
1782
1813
                            peinfo.offset = fpt->offset;
1783
1814
                            lseek(desc, fpt->offset, SEEK_SET);
1784
1815
                            if(cli_peheader(desc, &peinfo) == 0) {
1785
 
                                cli_dbgmsg("*** Detected embedded PE file ***\n");
 
1816
                                cli_dbgmsg("*** Detected embedded PE file at %u ***\n", (unsigned int) fpt->offset);
1786
1817
                                if(peinfo.section)
1787
1818
                                    free(peinfo.section);
1788
1819
 
1808
1839
            }
1809
1840
        }
1810
1841
 
1811
 
        ctx->recursion++;
1812
 
 
1813
1842
        if(nret != CL_VIRUS) switch(ret) {
1814
1843
            case CL_TYPE_HTML:
1815
1844
                if(SCAN_HTML && type == CL_TYPE_TEXT_ASCII && (DCONF_DOC & DOC_CONF_HTML)) {
1849
1878
        struct stat sb;
1850
1879
        uint8_t typercg = 1;
1851
1880
 
 
1881
    if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
 
1882
        cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
 
1883
        return CL_CLEAN;
 
1884
    }
1852
1885
 
1853
1886
    if(fstat(desc, &sb) == -1) {
1854
1887
        cli_errmsg("magic_scandesc: Can't fstat descriptor %d\n", desc);
1855
 
        return CL_EIO;
 
1888
        return CL_ESTAT;
1856
1889
    }
1857
1890
 
1858
1891
    if(sb.st_size <= 5) {
1862
1895
 
1863
1896
    if(!ctx->engine) {
1864
1897
        cli_errmsg("CRITICAL: engine == NULL\n");
 
1898
        return CL_ENULLARG;
 
1899
    }
 
1900
 
 
1901
    if(!(ctx->engine->dboptions & CL_DB_COMPILED)) {
 
1902
        cli_errmsg("CRITICAL: engine not compiled\n");
1865
1903
        return CL_EMALFDB;
1866
1904
    }
1867
1905
 
1868
 
    if(!ctx->options) { /* raw mode (stdin, etc.) */
1869
 
        cli_dbgmsg("Raw mode: No support for special files\n");
 
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 */
 
1910
        if(ctx->recursion == ctx->engine->maxreclevel)
 
1911
            cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n");
 
1912
        else
 
1913
            cli_dbgmsg("Raw mode: No support for special files\n");
1870
1914
        if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS)
1871
1915
            cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
1872
1916
        return ret;
1873
1917
    }
1874
1918
 
1875
 
    if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
1876
 
        return CL_CLEAN;
1877
 
 
1878
 
    if((SCAN_MAIL || SCAN_ARCHIVE) && ctx->limits && ctx->limits->maxreclevel && ctx->recursion > ctx->limits->maxreclevel) {
1879
 
        cli_dbgmsg("Archive recursion limit exceeded (level = %u).\n", ctx->recursion);
1880
 
        return CL_CLEAN;
1881
 
    }
1882
 
 
1883
1919
    lseek(desc, 0, SEEK_SET);
1884
1920
    type = cli_filetype2(desc, ctx->engine);
1885
1921
    if(type == CL_TYPE_ERROR) {
1886
1922
        cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
1887
 
        return CL_EIO;
 
1923
        return CL_EREAD;
1888
1924
    }
1889
1925
    lseek(desc, 0, SEEK_SET);
1890
1926
 
1901
1937
            break;
1902
1938
 
1903
1939
        case CL_TYPE_RAR:
1904
 
#ifdef ENABLE_UNRAR
1905
 
            if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
 
1940
            if(have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
1906
1941
                ret = cli_scanrar(desc, ctx, 0, NULL);
1907
 
#else
1908
 
            cli_warnmsg("RAR code not compiled-in\n");
1909
 
#endif
1910
1942
            break;
1911
1943
 
1912
1944
        case CL_TYPE_ZIP:
2015
2047
 
2016
2048
        case CL_TYPE_RIFF:
2017
2049
            if(SCAN_ALGO && (DCONF_OTHER & OTHER_CONF_RIFF))
2018
 
                ret = cli_scanriff(desc, ctx->virname);
 
2050
                ret = cli_scanriff(desc, ctx);
2019
2051
            break;
2020
2052
 
2021
2053
        case CL_TYPE_GRAPHICS:
2045
2077
 
2046
2078
        case CL_TYPE_BINARY_DATA:
2047
2079
            if(SCAN_ALGO && (DCONF_OTHER & OTHER_CONF_MYDOOMLOG))
2048
 
                ret = cli_check_mydoom_log(desc, ctx->virname);
 
2080
                ret = cli_check_mydoom_log(desc, ctx);
2049
2081
            break;
2050
2082
 
2051
2083
        case CL_TYPE_TEXT_ASCII:
2112
2144
    }
2113
2145
}
2114
2146
 
2115
 
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
 
2147
int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
2116
2148
{
2117
2149
    cli_ctx ctx;
2118
 
    struct cl_limits l_limits;
2119
2150
    int rc;
2120
2151
 
2121
 
    if(!limits) {
2122
 
        cli_errmsg("cl_scandesc: limits == NULL\n");
2123
 
        return CL_ENULLARG;
2124
 
    }
2125
2152
    memset(&ctx, '\0', sizeof(cli_ctx));
2126
2153
    ctx.engine = engine;
2127
2154
    ctx.virname = virname;
2128
2155
    ctx.scanned = scanned;
2129
 
    ctx.options = options;
 
2156
    ctx.options = scanoptions;
2130
2157
    ctx.found_possibly_unwanted = 0;
2131
2158
    ctx.dconf = (struct cli_dconf *) engine->dconf;
2132
 
    ctx.limits = &l_limits;
2133
 
    memcpy(&l_limits, limits, sizeof(struct cl_limits));
2134
2159
 
2135
2160
    rc = cli_magic_scandesc(desc, &ctx);
2136
2161
    if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
2173
2198
    return ret;
2174
2199
}
2175
2200
 
2176
 
int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
 
2201
int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
2177
2202
{
2178
2203
        int fd, ret;
2179
2204
 
2181
2206
    if((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
2182
2207
        return CL_EOPEN;
2183
2208
 
2184
 
    ret = cl_scandesc(fd, virname, scanned, engine, limits, options);
 
2209
    ret = cl_scandesc(fd, virname, scanned, engine, scanoptions);
2185
2210
    close(fd);
2186
2211
 
2187
2212
    return ret;