예제 #1
0
        /// <summary>
        /// Sends the specified bytes to the ClamAv server to be scanned for viruses
        /// </summary>
        /// <param name="fileBytes">The file bytes to scanned</param>
        /// <returns>True if a virus is detected false if file is clean</returns>
        public async Task <bool> FileContainsVirus(byte[] fileBytes)
        {
            var            clam       = new ClamClient(_config[ConfigParameters.ClamAvServerUrl]);
            ClamScanResult scanResult = await clam.SendAndScanFileAsync(fileBytes);

            return(scanResult.Result == ClamScanResults.VirusDetected);
        }
예제 #2
0
        private ScanResult MapScanResult(ClamScanResult clamAvScanResult)
        {
            var status = clamAvScanResult.Result;
            var result = new ScanResult();

            switch (clamAvScanResult.Result)
            {
            case ClamScanResults.Unknown:
                result.Message     = "Could Not Scan File";
                result.IsVirusFree = false;
                break;

            case ClamScanResults.Clean:
                result.Message     = "No Virus File";
                result.IsVirusFree = true;
                break;

            case ClamScanResults.VirusDetected:
                result.Message     = "Virus Found " + clamAvScanResult.InfectedFiles.FirstOrDefault().VirusName;
                result.IsVirusFree = false;
                break;

            case ClamScanResults.Error:
                result.Message     = string.Format("Virus Scan Error! {0}", clamAvScanResult.RawResult);
                result.IsVirusFree = false;
                break;

            default:
                break;
            }

            return(result);
        }
예제 #3
0
        public static async Task <IActionResult> RunAsync(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req)
        {
            IActionResult _ActionResult = new BadRequestObjectResult(INVALID_REQUEST_MESSAGE);;

            ScanRequest _RequestModel = await GetModelFromRequestBodyAsync(req.Body);

            if (!string.IsNullOrEmpty(_RequestModel.Base64EncodedBytes))
            {
                _ActionResult = new UnprocessableEntityResult();

                ClamScanResult _Result = await new FileScanManager(new ClamClient(Environment.GetEnvironmentVariable("CLAM_AV_SERVER"))).Scan(_RequestModel.Base64EncodedBytes);

                if (_Result != null)
                {
                    ScanResponse _Respone = new ScanResponse()
                    {
                        Result = Enum.GetName(typeof(ClamScanResults), _Result.Result),
                        Threat = _Result.InfectedFiles?.First().VirusName ?? string.Empty
                    };

                    _ActionResult = new JsonResult(_Respone);
                }
            }

            return(_ActionResult);
        }
예제 #4
0
        /// <summary>
        /// helper method to map scan results
        /// </summary>
        private ScanResult MapScanResult(ClamScanResult scanresult)
        {
            var result = new ScanResult();

            switch (scanresult.Result)
            {
            case ClamScanResults.Unknown:
                result.Message     = "Could not scan file";
                result.IsVirusFree = false;
                break;

            case ClamScanResults.Clean:
                result.Message     = "No Virus found";
                result.IsVirusFree = true;
                break;

            case ClamScanResults.VirusDetected:
                result.Message     = "Virus found: " + scanresult.InfectedFiles.First().VirusName;
                result.IsVirusFree = false;
                break;

            case ClamScanResults.Error:
                result.Message     = string.Format("VIRUS SCAN ERROR! {0}", scanresult.RawResult);
                result.IsVirusFree = false;
                break;
            }
            return(result);
        }
예제 #5
0
        public void VirusDetected_Response()
        {
            var result = new ClamScanResult(@"\\?\C:\test.txt: Eicar-Test-Signature FOUND");

            Assert.Equal(ClamScanResults.VirusDetected, result.Result);

            Assert.Single(result.InfectedFiles);

            Assert.Equal(@"\\?\C:\test.txt", result.InfectedFiles[0].FileName);
            Assert.Equal(" Eicar-Test-Signature", result.InfectedFiles[0].VirusName);
        }
예제 #6
0
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            ClamClient client = new ClamClient(SERVER_URL, SERVER_PORT);
            bool       ping   = Task.Run(() => client.PingAsync()).Result;

            Console.WriteLine($"Ping Successful? {ping}");

            ClamScanResult result = Task.Run(() => client.ScanFileOnServerAsync(Path.Combine(Environment.CurrentDirectory, fileName))).Result;

            Console.WriteLine($"Scan Successful? {result.RawResult}");
        }
예제 #7
0
        public void Before_Tests()
        {
            Assert.Equal(
                "test:test1",
                ClamScanResult.before("test:test1:test2")
                );

            Assert.Equal(
                "",
                ClamScanResult.before("test")
                );

            Assert.Equal(
                "test",
                ClamScanResult.before("test:test1")
                );
        }
예제 #8
0
        public void After_Tests()
        {
            //current released behavior to have initial space
            //(probably a bug)

            Assert.Equal(
                " test1",
                ClamScanResult.after("test test1")
                );

            Assert.Equal(
                " test2",
                ClamScanResult.after("test test1 test2")
                );

            Assert.Equal(
                "",
                ClamScanResult.after("test")
                );
        }
예제 #9
0
        private async Task <bool> PerformClamAVScan()
        {
            var isInfected = false;

            var clamAVServiceURI = Environment.GetEnvironmentVariable("ClamAVServiceURI");

            var clam = new ClamClient(clamAVServiceURI, 3310);

            ClamScanResult scanResult = null;

            var timeTaken = await TimedExecutionAsync(async() =>
            {
                scanResult = await clam.SendAndScanFileAsync(blobStream.ReadAllBytes());
            });

            logger.LogInformation($"Time taken to perform virus scan {timeTaken} ms");

            switch (scanResult.Result)
            {
            case ClamScanResults.Clean:
                logger.LogInformation("The file is clean!");
                break;

            case ClamScanResults.VirusDetected:
                logger.LogInformation("Virus Found!");
                logger.LogInformation("Virus name: {0}", scanResult.InfectedFiles.First().VirusName);
                isInfected = true;
                break;

            case ClamScanResults.Error:
                logger.LogInformation("Error scanning file: {0}", scanResult.RawResult);
                break;
            }

            return(isInfected);
        }
예제 #10
0
        public void Non_Matching()
        {
            var result = new ClamScanResult(Guid.NewGuid().ToString());

            Assert.Equal(ClamScanResults.Unknown, result.Result);
        }
예제 #11
0
        public void Error_Response()
        {
            var result = new ClamScanResult("error");

            Assert.Equal(ClamScanResults.Error, result.Result);
        }
예제 #12
0
        public void OK_Response()
        {
            var result = new ClamScanResult(@"C:\test.txt: OK");

            Assert.Equal(ClamScanResults.Clean, result.Result);
        }
예제 #13
0
 public ScanResults(Guid fileGUID, string error)
 {
     ScanResult = new ClamScanResult(error);
 }
예제 #14
0
        public async Task <IActionResult> Upload([FromForm] UploadFileViewModel uploadFile)
        {
            try
            {
                if (_config.UploadConfig.UploadEnabled)
                {
                    long maxUploadSize = _config.UploadConfig.MaxUploadSize;
                    if (User.Identity.IsAuthenticated)
                    {
                        maxUploadSize = _config.UploadConfig.MaxUploadSizeBasic;
                        IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);

                        if (userInfo.AccountType == AccountType.Premium)
                        {
                            maxUploadSize = _config.UploadConfig.MaxUploadSizePremium;
                        }
                    }
                    else
                    {
                        // Non-logged in users are defaulted to 1 day expiration
                        uploadFile.options.ExpirationUnit   = ExpirationUnit.Days;
                        uploadFile.options.ExpirationLength = 1;
                    }
                    if (uploadFile.file.Length <= maxUploadSize)
                    {
                        // convert file to bytes
                        long contentLength = uploadFile.file.Length;

                        // Scan the file to detect a virus
                        if (_config.UploadConfig.VirusScanEnable)
                        {
                            using (Stream fs = uploadFile.file.OpenReadStream())
                            {
                                ClamClient clam = new ClamClient(_config.UploadConfig.ClamServer, _config.UploadConfig.ClamPort);
                                clam.MaxStreamSize = maxUploadSize;
                                ClamScanResult scanResult = await clam.SendAndScanFileAsync(fs);

                                switch (scanResult.Result)
                                {
                                case ClamScanResults.Clean:
                                    break;

                                case ClamScanResults.VirusDetected:
                                    return(Json(new { error = new { message = string.Format("Virus Detected: {0}. As per our <a href=\"{1}\">Terms of Service</a>, Viruses are not permited.", scanResult.InfectedFiles.First().VirusName, Url.SubRouteUrl("tos", "TOS.Index")) } }));

                                case ClamScanResults.Error:
                                    return(Json(new { error = new { message = string.Format("Error scanning the file upload for viruses.  {0}", scanResult.RawResult) } }));

                                case ClamScanResults.Unknown:
                                    return(Json(new { error = new { message = string.Format("Unknown result while scanning the file upload for viruses.  {0}", scanResult.RawResult) } }));
                                }
                            }
                        }

                        // Check content type restrictions (Only for encrypting server side
                        if (!uploadFile.options.Encrypt)
                        {
                            if (_config.UploadConfig.RestrictedContentTypes.Contains(uploadFile.fileType) || _config.UploadConfig.RestrictedExtensions.Contains(uploadFile.fileExt))
                            {
                                return(Json(new { error = new { message = "File Type Not Allowed" } }));
                            }
                        }

                        using (Stream fs = uploadFile.file.OpenReadStream())
                        {
                            Models.Upload upload = UploadHelper.SaveFile(_dbContext,
                                                                         _config,
                                                                         fs,
                                                                         uploadFile.fileType,
                                                                         contentLength,
                                                                         !uploadFile.options.Encrypt,
                                                                         uploadFile.options.ExpirationUnit,
                                                                         uploadFile.options.ExpirationLength,
                                                                         uploadFile.fileExt,
                                                                         uploadFile.iv, null,
                                                                         uploadFile.keySize,
                                                                         uploadFile.blockSize);
                            if (upload != null)
                            {
                                if (User.Identity.IsAuthenticated)
                                {
                                    Users.Models.User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
                                    if (user != null)
                                    {
                                        upload.UserId = user.UserId;
                                        _dbContext.Entry(upload).State = EntityState.Modified;
                                        _dbContext.SaveChanges();
                                    }
                                }
                                return(Json(new { result = new
                                                  {
                                                      name = upload.Url,
                                                      url = Url.SubRouteUrl("u", "Upload.Download", new { file = upload.Url }),
                                                      contentType = upload.ContentType,
                                                      contentLength = StringHelper.GetBytesReadable(upload.ContentLength),
                                                      deleteUrl = Url.SubRouteUrl("u", "Upload.DeleteByKey", new { file = upload.Url, key = upload.DeleteKey }),
                                                      expirationUnit = uploadFile.options.ExpirationUnit.ToString(),
                                                      expirationLength = uploadFile.options.ExpirationLength
                                                  } }));
                            }
                        }
                        return(Json(new { error = new { message = "Unable to upload file" } }));
                    }
                    else
                    {
                        return(Json(new { error = new { message = "File Too Large" } }));
                    }
                }
                return(Json(new { error = new { message = "Uploads are disabled" } }));
            }
            catch (Exception ex)
            {
                return(Json(new { error = new { message = "Exception while uploading file: " + ex.GetFullMessage(true) } }));
            }
        }
예제 #15
0
        public async Task <IActionResult> Upload(UploadAPIv1Model model)
        {
            try
            {
                if (_config.UploadConfig.UploadEnabled)
                {
                    if (model.file != null)
                    {
                        long maxUploadSize = _config.UploadConfig.MaxUploadSize;
                        if (User.Identity.IsAuthenticated)
                        {
                            maxUploadSize = _config.UploadConfig.MaxUploadSizeBasic;
                            IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);

                            if (userInfo.AccountType == AccountType.Premium)
                            {
                                maxUploadSize = _config.UploadConfig.MaxUploadSizePremium;
                            }
                        }
                        else
                        {
                            // Non-logged in users are defaulted to 1 day expiration
                            model.expirationUnit   = ExpirationUnit.Days;
                            model.expirationLength = 1;
                        }
                        if (model.file.Length <= maxUploadSize)
                        {
                            // convert file to bytes
                            string fileExt       = FileHelper.GetFileExtension(model.file.FileName);
                            long   contentLength = model.file.Length;

                            // Scan the file to detect a virus
                            if (_config.UploadConfig.VirusScanEnable)
                            {
                                ClamClient clam = new ClamClient(_config.UploadConfig.ClamServer, _config.UploadConfig.ClamPort);
                                clam.MaxStreamSize = maxUploadSize;
                                ClamScanResult scanResult = await clam.SendAndScanFileAsync(model.file.OpenReadStream());

                                switch (scanResult.Result)
                                {
                                case ClamScanResults.Clean:
                                    break;

                                case ClamScanResults.VirusDetected:
                                    return(Json(new { error = new { message = string.Format("Virus Detected: {0}. As per our <a href=\"{1}\">Terms of Service</a>, Viruses are not permited.", scanResult.InfectedFiles.First().VirusName, Url.SubRouteUrl("tos", "TOS.Index")) } }));

                                case ClamScanResults.Error:
                                    break;

                                case ClamScanResults.Unknown:
                                    break;
                                }
                            }

                            // Need to grab the contentType if it's empty
                            if (string.IsNullOrEmpty(model.contentType))
                            {
                                model.contentType = model.file.ContentType;

                                if (string.IsNullOrEmpty(model.contentType))
                                {
                                    using (Stream fileStream = model.file.OpenReadStream())
                                    {
                                        fileStream.Seek(0, SeekOrigin.Begin);
                                        FileType fileType = fileStream.GetFileType();
                                        if (fileType != null)
                                        {
                                            model.contentType = fileType.Mime;
                                        }
                                        if (string.IsNullOrEmpty(model.contentType))
                                        {
                                            model.contentType = "application/octet-stream";
                                        }
                                    }
                                }
                            }

                            // Check content type restrictions (Only for encrypting server side
                            if (model.encrypt || !string.IsNullOrEmpty(model.key))
                            {
                                if (_config.UploadConfig.RestrictedContentTypes.Contains(model.contentType) || _config.UploadConfig.RestrictedExtensions.Contains(fileExt))
                                {
                                    return(Json(new { error = new { message = "File Type Not Allowed" } }));
                                }
                            }

                            // Initialize the key size and block size if empty
                            if (model.keySize <= 0)
                            {
                                model.keySize = _config.UploadConfig.KeySize;
                            }
                            if (model.blockSize <= 0)
                            {
                                model.blockSize = _config.UploadConfig.BlockSize;
                            }

                            // Save the file data
                            Upload.Models.Upload upload = UploadHelper.SaveFile(_dbContext, _config, model.file.OpenReadStream(), model.contentType, contentLength, model.encrypt, model.expirationUnit, model.expirationLength, fileExt, model.iv, model.key, model.keySize, model.blockSize);

                            if (upload != null)
                            {
                                string fileKey = upload.Key;

                                // Associate this with the user if they provided an auth key
                                if (User.Identity.IsAuthenticated)
                                {
                                    User foundUser = UserHelper.GetUser(_dbContext, User.Identity.Name);
                                    if (foundUser != null)
                                    {
                                        upload.UserId = foundUser.UserId;
                                        _dbContext.Entry(upload).State = EntityState.Modified;
                                        _dbContext.SaveChanges();
                                    }
                                }

                                // Generate delete key only if asked to
                                if (!model.genDeletionKey)
                                {
                                    upload.DeleteKey = string.Empty;
                                    _dbContext.Entry(upload).State = EntityState.Modified;
                                    _dbContext.SaveChanges();
                                }

                                // remove the key if we don't want to save it
                                if (!model.saveKey)
                                {
                                    upload.Key = null;
                                    _dbContext.Entry(upload).State = EntityState.Modified;
                                    _dbContext.SaveChanges();
                                }

                                // Pull all the information together
                                string fullUrl    = Url.SubRouteUrl("u", "Upload.Download", new { file = upload.Url });
                                var    returnData = new
                                {
                                    url            = (model.saveKey || string.IsNullOrEmpty(fileKey)) ? fullUrl : fullUrl + "#" + fileKey,
                                    fileName       = upload.Url,
                                    contentType    = upload.ContentType,
                                    contentLength  = upload.ContentLength,
                                    key            = fileKey,
                                    keySize        = upload.KeySize,
                                    iv             = upload.IV,
                                    blockSize      = upload.BlockSize,
                                    maxDownloads   = upload.MaxDownloads,
                                    expirationDate = upload.ExpireDate,
                                    deletionKey    = upload.DeleteKey
                                };
                                return(Json(new { result = returnData }));
                            }
                            return(Json(new { error = new { message = "Unable to save file" } }));
                        }
                        else
                        {
                            return(Json(new { error = new { message = "File Too Large" } }));
                        }
                    }
                    return(Json(new { error = new { message = "Invalid Upload Request" } }));
                }
                return(Json(new { error = new { message = "Uploads are Disabled" } }));
            }
            catch (Exception ex)
            {
                return(Json(new { error = new { message = "Exception: " + ex.Message } }));
            }
        }
예제 #16
0
        public static void ClamScanFileFromRepo(DbFile file)
        {
            try
            {
                if (Context.ClamdVersion == null)
                {
                    Failed?.Invoke("clamd is not usable");
                    return;
                }

                if (clam == null)
                {
                    Failed?.Invoke("clamd is not initalized");
                }

                string   repoPath;
                AlgoEnum algorithm;

                if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                             file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                             file.Sha256[3].ToString(), file.Sha256[4].ToString(), file.Sha256 + ".gz")))
                {
                    repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                            file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                            file.Sha256[3].ToString(), file.Sha256[4].ToString(), file.Sha256 + ".gz");
                    algorithm = AlgoEnum.GZip;
                }
                else if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                  file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                  file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                  file.Sha256 + ".bz2")))
                {
                    repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                            file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                            file.Sha256[3].ToString(), file.Sha256[4].ToString(), file.Sha256 + ".bz2");
                    algorithm = AlgoEnum.BZip2;
                }
                else if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                  file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                  file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                  file.Sha256 + ".lzma")))
                {
                    repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                            file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                            file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                            file.Sha256 + ".lzma");
                    algorithm = AlgoEnum.LZMA;
                }
                else if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                  file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                  file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                  file.Sha256 + ".lz")))
                {
                    repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                            file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                            file.Sha256[3].ToString(), file.Sha256[4].ToString(), file.Sha256 + ".lz");
                    algorithm = AlgoEnum.LZip;
                }
                else
                {
                    Failed?.Invoke($"Cannot find file with hash {file.Sha256} in the repository");
                    return;
                }

                ClamScanResult result  = null;
                Stream         zStream = null;

                if (Settings.Current.ClamdIsLocal)
                {
                    if (algorithm == AlgoEnum.LZMA || algorithm == AlgoEnum.LZip)
                    {
                        string     tmpFile = Path.Combine(Settings.Current.TemporaryFolder, Path.GetTempFileName());
                        FileStream outFs   = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
                        FileStream inFs    = new FileStream(repoPath, FileMode.Open, FileAccess.Read);

                        if (algorithm == AlgoEnum.LZMA)
                        {
                            byte[] properties = new byte[5];
                            inFs.Read(properties, 0, 5);
                            inFs.Seek(8, SeekOrigin.Current);
                            zStream = new LzmaStream(properties, inFs, inFs.Length - 13, file.Length);
                        }
                        else
                        {
                            zStream = new LZipStream(inFs, CompressionMode.Decompress);
                        }

                        UpdateProgress?.Invoke("Uncompressing file...", null, 0, 0);

                        #if DEBUG
                        stopwatch.Restart();
                        #endif
                        zStream.CopyTo(outFs);
                        zStream.Close();
                        outFs.Close();
                        #if DEBUG
                        stopwatch.Stop();
                        Console.WriteLine("Core.ClamScanFileFromRepo({0}): Uncompressing took {1} seconds", file,
                                          stopwatch.Elapsed.TotalSeconds);
                        #endif

                        UpdateProgress?.Invoke("Requesting local scan to clamd server...", null, 0, 0);

                        #if DEBUG
                        stopwatch.Restart();
                        #endif
                        Task.Run(async() => { result = await clam.ScanFileOnServerMultithreadedAsync(tmpFile); })
                        .Wait();
                        #if DEBUG
                        stopwatch.Stop();
                        Console.WriteLine("Core.ClamScanFileFromRepo({0}): Clamd took {1} seconds to scan", file,
                                          stopwatch.Elapsed.TotalSeconds);
                        #endif

                        File.Delete(tmpFile);
                    }
                    else
                    {
                        UpdateProgress?.Invoke("Requesting local scan to clamd server...", null, 0, 0);

                        #if DEBUG
                        stopwatch.Restart();
                        #endif
                        Task.Run(async() => { result = await clam.ScanFileOnServerMultithreadedAsync(repoPath); })
                        .Wait();
                        #if DEBUG
                        stopwatch.Stop();
                        Console.WriteLine("Core.ClamScanFileFromRepo({0}): Clamd took {1} seconds to scan", file,
                                          stopwatch.Elapsed.TotalSeconds);
                        #endif
                    }
                }
                else
                {
                    FileStream inFs = new FileStream(repoPath, FileMode.Open, FileAccess.Read);

                    switch (algorithm)
                    {
                    case AlgoEnum.GZip:
                        zStream = new GZipStream(inFs, CompressionMode.Decompress);
                        break;

                    case AlgoEnum.BZip2:
                        zStream = new BZip2Stream(inFs, CompressionMode.Decompress);
                        break;

                    case AlgoEnum.LZMA:
                        byte[] properties = new byte[5];
                        inFs.Read(properties, 0, 5);
                        inFs.Seek(8, SeekOrigin.Current);
                        zStream = new LzmaStream(properties, inFs, inFs.Length - 13, file.Length);
                        break;

                    case AlgoEnum.LZip:
                        zStream = new LZipStream(inFs, CompressionMode.Decompress);
                        break;
                    }

                    UpdateProgress?.Invoke("Uploading file to clamd server...", null, 0, 0);

                    #if DEBUG
                    stopwatch.Restart();
                    #endif
                    Task.Run(async() => { result = await clam.SendAndScanFileAsync(zStream); }).Wait();
                    #if DEBUG
                    stopwatch.Stop();
                    Console.WriteLine("Core.ClamScanFileFromRepo({0}): Clamd took {1} seconds to scan", file,
                                      stopwatch.Elapsed.TotalSeconds);
                    #endif
                    zStream.Close();
                }

                if (result.InfectedFiles != null && result.InfectedFiles.Count > 0)
                {
                    file.HasVirus = true;
                    file.Virus    = result.InfectedFiles[0].VirusName;
                }
                else if (file.HasVirus == null)
                {
                    // If no scan has been done, mark as false.
                    // If a positive has already existed don't overwrite it.
                    file.HasVirus = false;
                    file.Virus    = null;
                }

                file.ClamTime = DateTime.UtcNow;

                dbCore.DbOps.UpdateFile(file);

                ScanFinished?.Invoke(file);
            }
            catch (ThreadAbortException) { }
            catch (Exception ex)
            {
                Failed?.Invoke($"Exception {ex.Message} when calling clamd");
                #if DEBUG
                Console.WriteLine("Exception {0}\n{1}", ex.Message, ex.InnerException);
                #endif
            }
        }
예제 #17
0
        private static async Task <bool> ScanUpload(Config config, TeknikEntities db, Upload upload, int totalCount, int currentCount)
        {
            bool   virusDetected = false;
            string subDir        = upload.FileName[0].ToString();
            string filePath      = Path.Combine(config.UploadConfig.UploadDirectory, subDir, upload.FileName);

            if (File.Exists(filePath))
            {
                // If the IV is set, and Key is set, then scan it
                if (!string.IsNullOrEmpty(upload.Key) && !string.IsNullOrEmpty(upload.IV))
                {
                    byte[] keyBytes = Encoding.UTF8.GetBytes(upload.Key);
                    byte[] ivBytes  = Encoding.UTF8.GetBytes(upload.IV);


                    long maxUploadSize = config.UploadConfig.MaxUploadSize;
                    if (upload.User != null)
                    {
                        maxUploadSize = config.UploadConfig.MaxUploadSizeBasic;
                        IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(config, upload.User.Username);

                        if (userInfo.AccountType == AccountType.Premium)
                        {
                            maxUploadSize = config.UploadConfig.MaxUploadSizePremium;
                        }
                    }

                    using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                        using (AesCounterStream aesStream = new AesCounterStream(fs, false, keyBytes, ivBytes))
                        {
                            ClamClient clam = new ClamClient(config.UploadConfig.ClamServer, config.UploadConfig.ClamPort);
                            clam.MaxStreamSize = maxUploadSize;
                            ClamScanResult scanResult = await clam.SendAndScanFileAsync(fs);

                            switch (scanResult.Result)
                            {
                            case ClamScanResults.Clean:
                                string cleanMsg = string.Format("[{0}] Clean Scan: {1}/{2} Scanned | {3} - {4}", DateTime.Now, currentCount, totalCount, upload.Url, upload.FileName);
                                Output(cleanMsg);
                                break;

                            case ClamScanResults.VirusDetected:
                                string msg = string.Format("[{0}] Virus Detected: {1} - {2} - {3}", DateTime.Now, upload.Url, upload.FileName, scanResult.InfectedFiles.First().VirusName);
                                Output(msg);
                                lock (scanStatsLock)
                                {
                                    virusDetected = true;
                                    File.AppendAllLines(virusFile, new List <string> {
                                        msg
                                    });
                                }

                                lock (dbLock)
                                {
                                    string urlName = upload.Url;
                                    // Delete from the DB
                                    db.Uploads.Remove(upload);

                                    // Delete the File
                                    if (File.Exists(filePath))
                                    {
                                        File.Delete(filePath);
                                    }

                                    // Add to transparency report if any were found
                                    Takedown report = new Takedown();
                                    report.Requester        = TAKEDOWN_REPORTER;
                                    report.RequesterContact = config.SupportEmail;
                                    report.DateRequested    = DateTime.Now;
                                    report.Reason           = "Malware Found";
                                    report.ActionTaken      = string.Format("Upload removed: {0}", urlName);
                                    report.DateActionTaken  = DateTime.Now;
                                    db.Takedowns.Add(report);

                                    // Save Changes
                                    db.SaveChanges();
                                }
                                break;

                            case ClamScanResults.Error:
                                string errorMsg = string.Format("[{0}] Scan Error: {1}", DateTime.Now, scanResult.RawResult);
                                File.AppendAllLines(errorFile, new List <string> {
                                    errorMsg
                                });
                                Output(errorMsg);
                                break;

                            case ClamScanResults.Unknown:
                                string unkMsg = string.Format("[{0}] Unknown Scan Result: {1}", DateTime.Now, scanResult.RawResult);
                                File.AppendAllLines(errorFile, new List <string> {
                                    unkMsg
                                });
                                Output(unkMsg);
                                break;
                            }
                        }
                }
            }
            return(virusDetected);
        }
예제 #18
0
 public ScanResults(Guid fileGUID, ClamScanResult scanResult)
 {
     FileGUID   = fileGUID;
     ScanResult = scanResult;
 }