~ubuntu-branches/ubuntu/wily/clamav/wily

« back to all changes in this revision

Viewing changes to libclamav/blob.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen Gran
  • Date: 2008-09-05 17:25:34 UTC
  • mfrom: (0.35.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080905172534-yi3f8fkye1o7u1r3
* New upstream version (closes: #497662, #497773)
  - lots of new options for clamd.conf
  - fixes CVEs CVE-2008-3912, CVE-2008-3913, CVE-2008-3914, and
    CVE-2008-1389
* No longer supports --unzip option, so typo is gone (closes: #496276)
* Translations:
  - sv (thanks Martin Bagge <brother@bsnet.se>) (closes: #491760)

Show diffs side-by-side

added added

removed removed

Lines of Context:
439
439
        if(fb->fp && fb->fullname) {
440
440
                fclose(fb->fp);
441
441
                cli_dbgmsg("fileblobDestructiveDestroy: %s\n", fb->fullname);
442
 
                if(unlink(fb->fullname) < 0)
443
 
                        cli_warnmsg("fileblobDestructiveDestroy: Can't delete file %s\n", fb->fullname);
 
442
                cli_unlink(fb->fullname);
444
443
                free(fb->fullname);
445
444
                fb->fp = NULL;
446
445
                fb->fullname = NULL;
468
467
                        cli_dbgmsg("fileblobDestroy: %s\n", fb->fullname);
469
468
                        if(!fb->isNotEmpty) {
470
469
                                cli_dbgmsg("fileblobDestroy: not saving empty file\n");
471
 
                                if(unlink(fb->fullname) < 0)
472
 
                                        cli_warnmsg("fileblobDestroy: Can't delete empty file %s\n", fb->fullname);
 
470
                                cli_unlink(fb->fullname); 
473
471
                        }
474
472
                }
475
473
                free(fb->b.name);
494
492
}
495
493
 
496
494
void
 
495
fileblobPartialSet(fileblob *fb, const char *fullname, const char *arg)
 
496
{
 
497
        if(fb->b.name)
 
498
                return;
 
499
 
 
500
        assert(fullname != NULL);
 
501
 
 
502
        cli_dbgmsg("fileblobPartialSet: saving to %s\n", fullname);
 
503
 
 
504
        fb->fd = open(fullname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY|O_EXCL, 0600);
 
505
        if(fb->fd < 0) {
 
506
                cli_errmsg("fileblobPartialSet: unable to create file: %s\n",fullname);
 
507
                return;
 
508
        }
 
509
        fb->fp = fdopen(fb->fd, "wb");
 
510
 
 
511
        if(fb->fp == NULL) {
 
512
                cli_errmsg("fileblobSetFilename: fdopen failed (%s)\n", strerror(errno));
 
513
                close(fb->fd);
 
514
                return;
 
515
        }
 
516
        blobSetFilename(&fb->b, NULL, fullname);
 
517
        if(fb->b.data)
 
518
                if(fileblobAddData(fb, fb->b.data, fb->b.len) == 0) {
 
519
                        free(fb->b.data);
 
520
                        fb->b.data = NULL;
 
521
                        fb->b.len = fb->b.size = 0;
 
522
                        fb->isNotEmpty = 1;
 
523
                }
 
524
        fb->fullname = cli_strdup(fullname);
 
525
}
 
526
 
 
527
void
497
528
fileblobSetFilename(fileblob *fb, const char *dir, const char *filename)
498
529
{
499
 
        int fd;
500
 
        char fullname[NAME_MAX + 1];
 
530
        char *fullname;
501
531
 
502
532
        if(fb->b.name)
503
533
                return;
514
544
        filename = blobGetFilename(&fb->b);
515
545
 
516
546
        assert(filename != NULL);
517
 
 
518
 
#ifdef  C_QNX6
519
 
        /*
520
 
         * QNX6 support from mikep@kaluga.org to fix bug where mkstemp
521
 
         * can return ETOOLONG even when the file name isn't too long
522
 
         */
523
 
        snprintf(fullname, sizeof(fullname), "%s/clamavtmpXXXXXXXXXXXXX", dir);
524
 
#elif   defined(C_WINDOWS)
525
 
        sprintf_s(fullname, sizeof(fullname) - 1, "%s\\%.*sXXXXXX", dir,
526
 
                (int)(sizeof(fullname) - 9 - strlen(dir)), filename);
527
 
#else
528
 
        sprintf(fullname, "%s/%.*sXXXXXX", dir,
529
 
                (int)(sizeof(fullname) - 9 - strlen(dir)), filename);
530
 
#endif
531
 
 
532
 
#if     defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) || defined(C_CYGWIN) || defined(C_QNX6)
533
 
        cli_dbgmsg("fileblobSetFilename: mkstemp(%s)\n", fullname);
534
 
        /*
535
 
         * On older Cygwin, mkstemp opened in O_TEXT mode, rather than
536
 
         *      O_BINARY. I understand this is now fixed, but I don't know in
537
 
         *      what version
538
 
         * See http://cygwin.com/ml/cygwin-patches/2006-q2/msg00014.html
539
 
         */
540
 
        fd = mkstemp(fullname);
541
 
        if((fd < 0) && (errno == EINVAL)) {
542
 
                /*
543
 
                 * This happens with some Linux flavours when (mis)handling
544
 
                 * filenames with foreign characters
545
 
                 */
546
 
                snprintf(fullname, sizeof(fullname), "%s/clamavtmpXXXXXXXXXXXXX", dir);
547
 
                cli_dbgmsg("fileblobSetFilename: retry as mkstemp(%s)\n", fullname);
548
 
                fd = mkstemp(fullname);
549
 
        }
550
 
#elif   defined(C_WINDOWS)
551
 
        cli_dbgmsg("fileblobSetFilename: _mktemp_s(%s)\n", fullname);
552
 
        if(_mktemp_s(fullname, strlen(fullname) + 1) != 0) {
553
 
                char *name;
554
 
 
555
 
                /* _mktemp_s only allows 26 files */
556
 
                cli_dbgmsg("fileblobSetFilename: _mktemp_s(%s) failed: %s\n", fullname, strerror(errno));
557
 
                name = cli_gentemp(dir);
558
 
                if(name == NULL)
559
 
                        return;
560
 
                fd = open(name, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
561
 
                if(fd >= 0)
562
 
                        strncpy(fullname, name, sizeof(fullname) - 1);
563
 
                free(name);
564
 
        } else
565
 
                fd = open(fullname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
566
 
#else
567
 
        cli_dbgmsg("fileblobSetFilename: mktemp(%s)\n", fullname);
568
 
        (void)mktemp(fullname);
569
 
        fd = open(fullname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
570
 
#endif
571
 
 
572
 
        if(fd < 0) {
573
 
                cli_errmsg("Can't create temporary file %s: %s\n", fullname, strerror(errno));
574
 
                cli_dbgmsg("%lu %lu\n", (unsigned long)sizeof(fullname),
575
 
                        (unsigned long)strlen(fullname));
576
 
                return;
577
 
        }
578
 
 
579
 
        cli_dbgmsg("Creating %s\n", fullname);
580
 
 
581
 
        fb->fp = fdopen(fd, "wb");
 
547
        
 
548
        if (cli_gentempfd(dir, &fullname, &fb->fd)!=CL_SUCCESS) return;
 
549
 
 
550
        cli_dbgmsg("fileblobSetFilename: file %s saved to %s\n", filename, fullname);
 
551
 
 
552
        fb->fp = fdopen(fb->fd, "wb");
582
553
 
583
554
        if(fb->fp == NULL) {
584
 
                cli_errmsg("Can't create file %s: %s\n", fullname, strerror(errno));
585
 
                cli_dbgmsg("%lu %lu\n", (unsigned long)sizeof(fullname),
586
 
                        (unsigned long)strlen(fullname));
587
 
                close(fd);
588
 
 
 
555
                cli_errmsg("fileblobSetFilename: fdopen failed (%s)\n", strerror(errno));
 
556
                close(fb->fd);
 
557
                free(fullname);
589
558
                return;
590
559
        }
591
560
        if(fb->b.data)
595
564
                        fb->b.len = fb->b.size = 0;
596
565
                        fb->isNotEmpty = 1;
597
566
                }
598
 
 
599
 
        /*
600
 
         * If this strdup fails, then if the file is empty it won't be removed
601
 
         * until later. Since this is only a trivial issue, there is no need
602
 
         * to error if it fails to allocate
603
 
         */
604
 
        fb->fullname = cli_strdup(fullname);
 
567
        fb->fullname = fullname;
605
568
}
606
569
 
607
570
int
671
634
int
672
635
fileblobScan(const fileblob *fb)
673
636
{
674
 
#ifndef C_WINDOWS
675
 
        int rc, fd;
 
637
        int rc;
676
638
        cli_file_t ftype;
677
 
#endif
678
639
 
679
640
        if(fb->isInfected)
680
641
                return CL_VIRUS;
681
 
        if(fb->fullname == NULL) {
 
642
        if(fb->fp == NULL || fb->fullname == NULL) {
682
643
                /* shouldn't happen, scan called before fileblobSetFilename */
683
644
                cli_warnmsg("fileblobScan, fullname == NULL\n");
684
645
                return CL_ENULLARG;     /* there is no CL_UNKNOWN */
688
649
                cli_dbgmsg("fileblobScan, ctx == NULL\n");
689
650
                return CL_CLEAN;        /* there is no CL_UNKNOWN */
690
651
        }
691
 
#ifndef C_WINDOWS
692
 
        /*
693
 
         * FIXME: On Windows, cli_readn gives "bad file descriptor" when called
694
 
         * by cli_check_mydoom_log from the call to cli_magic_scandesc here
695
 
         * which implies that the file descriptor is getting closed somewhere,
696
 
         * but I can't see where.
697
 
         * One possible fix would be to duplicate cli_scanfile here.
698
 
         */
 
652
 
699
653
        fflush(fb->fp);
700
 
        fd = dup(fileno(fb->fp));
701
 
        if(fd == -1) {
702
 
                cli_warnmsg("%s: dup failed\n", fb->fullname);
703
 
                return CL_CLEAN;
704
 
        }
705
 
        /* cli_scanfile is static :-( */
706
 
        /*if(cli_scanfile(fb->fullname, fb->ctx) == CL_VIRUS) {
707
 
                cli_dbgmsg("%s is infected\n", fb->fullname);
708
 
                return CL_VIRUS;
709
 
        }*/
710
 
 
711
 
        rc = cli_magic_scandesc(fd, fb->ctx);
 
654
        lseek(fb->fd, 0, SEEK_SET);
 
655
        rc = cli_magic_scandesc(fb->fd, fb->ctx);
712
656
 
713
657
        if(rc == CL_CLEAN) {
714
 
                lseek(fd, 0, SEEK_SET);
715
 
                ftype = cli_filetype2(fd, fb->ctx->engine);
 
658
                lseek(fb->fd, 0, SEEK_SET);
 
659
                ftype = cli_filetype2(fb->fd, fb->ctx->engine);
716
660
                if(ftype >= CL_TYPE_TEXT_ASCII && ftype <= CL_TYPE_TEXT_UTF16BE) {
717
 
                        lseek(fd, 0, SEEK_SET);
718
 
                        rc = cli_scandesc(fd, fb->ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR);
 
661
                        lseek(fb->fd, 0, SEEK_SET);
 
662
                        rc = cli_scandesc(fb->fd, fb->ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR);
719
663
                }
720
664
        }
721
665
 
722
 
        close(fd);
723
 
 
724
666
        if(rc == CL_VIRUS) {
725
667
                cli_dbgmsg("%s is infected\n", fb->fullname);
726
668
                return CL_VIRUS;
727
669
        }
728
670
        cli_dbgmsg("%s is clean\n", fb->fullname);
729
671
        return CL_BREAK;
730
 
#else   /*C_WINDOWS*/
731
 
        /* Ensure that the file is saved and scanned */
732
 
        return CL_CLEAN;        /* there is no CL_UNKNOWN :-( */
733
 
#endif  /*C_WINDOWS*/
734
672
}
735
673
 
736
674
/*
761
699
                 * I don't know if spaces are legal in OS/2.
762
700
                 */
763
701
                if(strchr("%/*?<>|\\\"+=,;:\t ~", *name))
764
 
#elif   defined(C_CYGWIN) || defined(C_WINDOWS)
 
702
#elif defined(C_WINDOWS)
765
703
                if(strchr("%/*?<>|\\\"+=,;:\t~", *name))
766
704
#else
767
705
                if(*name == '/')