Пример #1
0
        public ActionResult <string> Get()
        {
            try
            {
                ClamClient clam = new ClamClient("localhost", 3310);
                //string fileName1 = "C:\\Users\\ColtonHester\\Downloads\\eicar.com.txt";
                //string fileName2 = "C:\\Users\\ColtonHester\\Pictures\\AssurantTest\\Test.pdf";
                //string fileName1 = "C:\\Users\\ColtonHester\\Downloads\\nihongo_grammar_guide.pdf";
                string fileName1 = "C:\\Users\\ColtonHester\\Downloads\\1126072019 Council Meeting Package_Externals.pdf";
                string fileName2 = "C:\\Users\\ColtonHester\\Downloads\\eicar.com.txt";
                Task <ClamScanResult> scanResult1 = clam.SendAndScanFileAsync(fileName1);
                Task <ClamScanResult> scanResult2 = clam.SendAndScanFileAsync(fileName2);

                string output = "FileScan on " + fileName1 + " results:" + scanResult1.Result.RawResult.Replace("stream:", "") + "\n" +
                                "FileScan on " + fileName2 + " results:" + scanResult2.Result.RawResult.Replace("stream:", "");

                //using (System.IO.StreamWriter file =
                //			new System.IO.StreamWriter(@"C:\\Users\\ColtonHester\\Downloads\\load_test\\log.txt", true))
                //{
                //	file.WriteLine(logoutput);
                //}

                // test commit 1 - patch test 1 - round 4
                // test commit 2 - patch test 2 - round 5

                return(output);
            }
            catch (Exception ex) {
                return(ex.ToString());
            }
        }
Пример #2
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);
        }
Пример #3
0
        public static async Task <bool> FileScan(HttpPostedFileBase image)
        {
            return(true);

            try
            {
                var clam       = new ClamClient("localhost", 3310);
                var scanResult = await clam.SendAndScanFileAsync(image.InputStream).ConfigureAwait(false);


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

                    break;

                case ClamScanResults.VirusDetected:
                    return(false);

                    break;

                case ClamScanResults.Error:
                    return(false);

                    break;
                }

                return(true);
            }
            catch
            {
                return(false);
            }
        }
        /// <inheritdoc cref="IFileManager.ScanFileAsync(byte[])" />
        public async Task <bool> ScanFileAsync(byte[] fileBytes)
        {
            ClamAV clamAvSettings = _appSettings.ClamAV;

            if (!clamAvSettings.Enable)
            {
                return(true);
            }
            else if (!string.IsNullOrEmpty(clamAvSettings.Host))
            {
                var clamClient = new ClamClient(clamAvSettings.Host, clamAvSettings.Port);

                var result = await clamClient.SendAndScanFileAsync(fileBytes);

                if (result.Result == ClamScanResults.Clean)
                {
                    return(true);
                }
                else
                {
                    string message = result.Result switch
                    {
                        ClamScanResults.VirusDetected => "Virus detected",
                        ClamScanResults.Error => "Error in the file",
                        ClamScanResults.Unknown => "Unknown file",
                        _ => "No case available"
                    };

                    _logger.LogWarning(message);
                }
            }

            return(false);
        }
Пример #5
0
        public async Task <IActionResult> UploadFiles(List <IFormFile> files)
        {
            var log = new List <ScanResult>();

            foreach (var formFile in files)
            {
                if (formFile.Length > 0)
                {
                    var clam = new ClamClient("clamav-server", 3310);
                    var ping = await clam.PingAsync();

                    var result = await clam.SendAndScanFileAsync(formFile.OpenReadStream());

                    log.Add(new ScanResult()
                    {
                        FileName  = formFile.FileName,
                        Result    = result.Result.ToString(),
                        Message   = result.InfectedFiles?.FirstOrDefault()?.VirusName,
                        RawResult = result.RawResult
                    });
                }
            }

            var model = new UploadFilesViewModel();

            model.Results = log;

            return(View(model));
        }
Пример #6
0
        public static void Run([BlobTrigger("upload/{name}", Connection = "stgblobscan_STORAGE")] Stream myBlob, string name, ILogger log)
        {
            log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
            var clam = new ClamClient(GetEnvironmentVariable("clamavserver"), Convert.ToInt32(GetEnvironmentVariable("clamavport")));

            // Scanning for viruses...
            var scanResult = clam.SendAndScanFileAsync(myBlob).Result;

            switch (scanResult.Result)
            {
            case ClamScanResults.Clean:
                log.LogInformation("The file is clean!");
                MoveFileFromBlob(name, log);
                log.LogInformation("Move File {0}", name);
                break;

            case ClamScanResults.VirusDetected:
                log.LogInformation("Virus Found!");
                log.LogInformation("Virus name: {0}", scanResult.InfectedFiles.Count > 0 ? scanResult.InfectedFiles[0].FileName.ToString() : string.Empty);
                MoveFileFromBlob(name, log);
                break;

            case ClamScanResults.Error:
                log.LogInformation("Error scanning file: {0}", scanResult.RawResult);
                break;
            }
        }
Пример #7
0
        private async void scantest()
        {
            var clam = new ClamClient("13.76.89.213", 3310);
            //var scanResult = await clam.ScanFileOnServerAsync("C:\\Users\\Desmond\\Downloads\\TeamViewer_Setup.exe");  //any file you would like!
            var scanResult = await clam.SendAndScanFileAsync("C:\\Users\\Desmond\\Downloads\\TeamViewer_Setup.exe");

            switch (scanResult.Result)
            {
            case ClamScanResults.Clean:
                Console.WriteLine("The file is clean!");
                MessageBox.Show("The file is clean");
                break;

            case ClamScanResults.VirusDetected:
                Console.WriteLine("Virus Found!");
                Console.WriteLine("Virus name: {0}", scanResult.InfectedFiles.First().VirusName);
                MessageBox.Show("Virus name: {0}", scanResult.InfectedFiles.First().VirusName);
                break;

            case ClamScanResults.Error:
                Console.WriteLine("Woah an error occured! Error: {0}", scanResult.RawResult);
                MessageBox.Show("Woah an error occured! Error: {0}", scanResult.RawResult);
                break;
            }
        }
Пример #8
0
        /// <summary>
        /// Scans an array of Base64 encoded bytes
        /// </summary>
        /// <param name="fileData">The Data to be scanned</param>
        /// <param name="fileGUID">The Results GUID used to index for scan result</param>
        /// <returns></returns>
        public static async Task ScanBytes(byte[] fileData, Guid fileGUID)
        {
            try
            {
                ClamClient clam = new ClamClient(ClamAVServer, ClamAVPort);

                var scanResult = await clam.SendAndScanFileAsync(fileData);

                ScanResults result = ScanHistory.Find(x => x.FileGUID == fileGUID);

                result.ScanResult = scanResult;
            }
            catch (Exception exception)
            {
                ScanResults result = ScanHistory.Find(x => x.FileGUID == fileGUID);

                if (result == null)
                {
                    result = new ScanResults(fileGUID, exception.Message);
                }
                else
                {
                    result.ScanResult = new ClamScanResult(exception.Message);
                }
            }
        }
Пример #9
0
        private async Task ScanNClamResult(byte[] content)
        {
            var            serverUrl = _rootConfiguration.isFileScanConfiguration.ServerUrl;
            var            port      = int.Parse(_rootConfiguration.isFileScanConfiguration.Port);
            var            clam      = new ClamClient(serverUrl, port);
            ClamScanResult scanResult;

            try
            {
                scanResult = await clam.SendAndScanFileAsync(content);
            }
            catch (Exception ex)
            { _logger.LogError("File Scan Error : " + ex.Message + "\n" + ex.StackTrace); throw new BusinessRuleException("Exception raised while scanning file"); }
            switch (scanResult.Result)
            {
            case ClamScanResults.Clean:
                break;

            case ClamScanResults.VirusDetected:
                throw new BusinessRuleException(string.Format("Virus Found! Virus name: {0}", scanResult.InfectedFiles.First().VirusName));

            case ClamScanResults.Error:
                throw new BusinessRuleException(string.Format("An error occured! Error: {0}", scanResult.RawResult));
            }
        }
Пример #10
0
        public void TestSendIPAsyncTest()
        {
            string Eicartestcase = @"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*";
            var    client        = new ClamClient(IPAddress.Parse("127.0.0.1"));
            var    result        = client.SendAndScanFileAsync(new MemoryStream(System.Text.Encoding.Default.GetBytes(Eicartestcase)));

            Assert.Equal(ClamScanResults.VirusDetected, result.Result.Result);
        }
Пример #11
0
        public async Task <IActionResult> Scan([FromForm] FileUpload fileUpload)
        {
            var ms = new MemoryStream();

            fileUpload.file.OpenReadStream().CopyTo(ms);
            byte[] fileBytes   = ms.ToArray();
            bool   isFileClean = false;

            try
            {
                this._logger.LogInformation("ClamAV scan begin for file {0}", fileUpload.file.FileName);
                // var clam = new ClamClient(this._configuration["ClamAVServer:URL"],
                //   Convert.ToInt32(this._configuration["ClamAVServer:Port"]));

                //var clam = new ClamClient("0.0.0.0", 3310);

                // First parameter could be the container ip (if link via network) or container name.
                var clam = new ClamClient("172.17.0.2", 3310);


                var scanResult = await clam.SendAndScanFileAsync(fileBytes);

                switch (scanResult.Result)
                {
                case ClamScanResults.Clean:
                    this._logger.LogInformation("The file is clean! ScanResult:{1}", scanResult.RawResult);
                    break;

                case ClamScanResults.VirusDetected:
                    this._logger.LogError("Virus Found! Virus name: {1}", scanResult.InfectedFiles.FirstOrDefault().VirusName);
                    break;

                case ClamScanResults.Error:
                    this._logger.LogError("An error occured while scaning the file! ScanResult: {1}", scanResult.RawResult);
                    break;

                case ClamScanResults.Unknown:
                    this._logger.LogError("Unknown scan result while scaning the file! ScanResult: {0}", scanResult.RawResult);
                    break;
                }

                if (scanResult.Result == ClamScanResults.Clean)
                {
                    isFileClean = true;
                }
            }
            catch (Exception ex)
            {
                this._logger.LogError("ClamAV Scan Exception: {0}", ex.ToString());
            }
            this._logger.LogInformation("ClamAV scan completed for file {0}", fileUpload.file.FileName);

            return(Ok(isFileClean));
        }
Пример #12
0
        public bool IsVirus(byte[] byteArray)
        {
            switch (_scanner.SendAndScanFileAsync(byteArray).Result.Result)
            {
            case ClamScanResults.Clean: return(false);

            case ClamScanResults.VirusDetected: return(true);

            case ClamScanResults.Error: throw new Exception("Error during virus scan");

            default: return(false);
            }
        }
Пример #13
0
        public (bool detected, Detection detection) Scan(FileItem file)
        {
            ClamScanResult result;

            if (this.Status == DetectorStatus.UNUSED)
            {
                logger.Error("{0} detector in use when it should have been pruned", this.Name);
                return(false, null);
            }

            if (this.Status == DetectorStatus.UNINITIALIZED)
            {
                string message = string.Format(
                    "Trying to use the {0} detector while it is uninitialized",
                    this.Name);

                logger.Error(message);
                throw new Exception(message);
            }

            try
            {
                using (var stream = new FileStream(file.AbsolutePath, FileMode.Open))
                {
                    logger.Trace("Submitting {0} for ClamAV scan", file.AbsolutePath);
                    result = clam.SendAndScanFileAsync(stream).Result;
                    logger.Trace("ClamAV result for {0}: {1}", file.AbsolutePath, result.Result);

                    if (result.Result == ClamScanResults.VirusDetected)
                    {
                        string virusName = result.InfectedFiles.Count > 0 ? result.InfectedFiles[0].VirusName : "Unknown";
                        logger.Error("ClamAV reports {0} is infected with {1}", file.AbsolutePath, virusName);
                        return(true, new Detection(this.Type, this.Name, string.Format("Virus: {0}", virusName)));
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Warn(ex, "Error scanning {0} using ClamAV", file.AbsolutePath);
                return(false, null);
            }

            return(false, null);
        }
Пример #14
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            ScanResultModel scr    = new ScanResultModel();
            Stream          stream = new MemoryStream();

            if (req.Body == null)
            {
                stream = GenerateStreamFromString("a,b \n c,d");
            }
            else
            {
                await req.Body.CopyToAsync(stream);

                stream.Seek(0, SeekOrigin.Begin);
            }

            string clamip = Environment.GetEnvironmentVariable("clamip", EnvironmentVariableTarget.Process);
            //var clam = new ClamClient("13.86.246.40", 3310); // "clamav -server",
            // clam = new ClamClient("172.17.0.2", 3310); // "clamav -server",
            var clam = new ClamClient(clamip, 3310);

            scr.InfectedFilesCount = 0;
            var scanResult = await clam.SendAndScanFileAsync(stream);

            if (scanResult.InfectedFiles != null)
            {
                scr.InfectedFilesCount = scanResult.InfectedFiles.Count;
            }


            scr.RawResult = scanResult.RawResult;
            scr.Result    = scanResult.Result.ToString();

            scr.IsComplete = true;

            //return CreatedAtAction("xyz", scr);
            string jsonData = JsonConvert.SerializeObject(scr);

            return(new OkObjectResult(jsonData));
        }
Пример #15
0
        public async Task <IActionResult> UploadFile(IFormFile file)
        {
            if (file == null || file.Length == 0)
            {
                return(Content("file not selected"));
            }

            var ms = new MemoryStream();

            file.OpenReadStream().CopyTo(ms);
            byte[] fileBytes = ms.ToArray();
            string Result    = string.Empty;

            try
            {
                // Scan with Docker image
                var clam = new ClamClient(this._configuration["ClamAVServer:URL"],
                                          Convert.ToInt32(this._configuration["ClamAVServer:Port"]));

                // Scan with Clam Av server
                //var clam = new ClamClient(IPAddress.Parse("127.0.0.1"), 3310);
                var scanResult = await clam.SendAndScanFileAsync(fileBytes);

                // Switch Expression C# 8.0
                Result = scanResult.Result switch
                {
                    ClamScanResults.Clean => "Clean",
                    ClamScanResults.VirusDetected => "Virus Detected",
                    ClamScanResults.Error => "Error in File",
                    ClamScanResults.Unknown => "Unknown File",
                    _ => "No case available"
                };
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return(Ok(Result));
        }
Пример #16
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);
        }
Пример #17
0
 public async Task <ScanResultModel> ScanFileAsync(byte[] bytes, CancellationToken cancellationToken = default)
 {
     return(await SendAsync(async() => await _clamClient.SendAndScanFileAsync(bytes, cancellationToken)));
 }
Пример #18
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
            }
        }
Пример #19
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);
        }
        // a method to scan the file for viruses on a ClamAV (anitvirus software) server
        // this server is located in a separate container (and connected via docker-compose)
        private static Task <ClamScanResult> AntiVirusScan(IFormFile formFile)
        {
            var clam = new ClamClient("clamav-server", 3310);

            return(clam.SendAndScanFileAsync(formFile.OpenReadStream()));
        }
Пример #21
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) } }));
            }
        }
Пример #22
0
        public static async Task Run([BlobTrigger("staging/{name}")] Stream blob, string name, Uri uri,
                                     BlobProperties properties, IDictionary <string, string> metadata, TraceWriter log)
        {
            try
            {
                var clam        = new ClamClient("localhost", 3310);
                var clamVersion = await clam.GetVersionAsync();

                //Make sure we can connect to the ClamAV Server
                var pingResult = await clam.PingAsync();

                if (!pingResult)
                {
                    throw new ApplicationException(
                              "The client failed to connect to the ClamAV Server.  Please check to see if the server is running and accessible on the configured port.");
                }

                //Dont exceed this value.  ClamAV server can be increased to 4GB, but you must have the resources available.
                var maxStreamSize = clam.MaxStreamSize;
                if (blob.Length > maxStreamSize)
                {
                    log.Info($"Blob {name} is too large to be scanned in memory.  Moving to deadletter container");
                    throw new InsufficientMemoryException(
                              $"Blob {name} is too large to be scanned in memory.  Moving to deadletter container");
                }

                //We are going to limit ourselves to block blobs, append blobs, and unspecified blobs.
                var cloudBlob = new CloudBlob(uri);
                if (cloudBlob.BlobType == BlobType.PageBlob)
                {
                    throw new ApplicationException(
                              $"Blob {cloudBlob.Name} has an unsupported type. BlobType = {cloudBlob.BlobType.ToString()}");
                }

                var scanResult = await clam.SendAndScanFileAsync(blob);

                switch (scanResult.Result)
                {
                case ClamScanResults.Clean:
                    //The blob is clean.  Move to production
                    log.Info($"Blob {name}. ScannResult = Clean, ClamVersion = {0}", clamVersion);
                    break;

                case ClamScanResults.VirusDetected:
                    //Bad blob.  Move to quarantine.
                    log.Warning($"Blob {name} has a virus! Name = {0}", scanResult.InfectedFiles.First().VirusName);
                    break;

                case ClamScanResults.Unknown:
                    //Unknown.  Moving to deadletter
                    log.Warning($"Blob {name} scan results unknown! Name = {0}",
                                scanResult.InfectedFiles.First().VirusName);
                    break;

                case ClamScanResults.Error:
                    //Unknown.  Moving to deadletter
                    log.Warning($"Blob {name} has a virus! Name = {0}", scanResult.InfectedFiles.First().VirusName);
                    break;
                }

                log.Info($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {blob.Length} Bytes");
            }
            catch (SocketException ex)
            {
                log.Error(ex.Message, ex);
            }
            catch (InsufficientMemoryException ex)
            {
                log.Error(ex.Message, ex);
                //Todo: Move to deadletter
            }
            catch (ApplicationException ex)
            {
                log.Error(ex.Message, ex);
            }
            catch (Exception ex)
            {
            }
        }
Пример #23
0
        public async Task <IActionResult> UploadFiles(List <IFormFile> files)
        {
            var log = new List <ScanResult>();

            foreach (var formFile in files)
            {
                if (formFile.Length > 0)
                {
                    var extension = formFile.FileName.Contains('.')
                        ? formFile.FileName.Substring(formFile.FileName.LastIndexOf('.'), formFile.FileName.Length - formFile.FileName.LastIndexOf('.'))
                        : string.Empty;
                    var file = new File
                    {
                        Name        = $"{Guid.NewGuid()}{extension}",
                        Alias       = formFile.FileName,
                        Region      = "us-east-1",
                        Bucket      = BUCKET_NAME,
                        ContentType = formFile.ContentType,
                        Size        = formFile.Length,
                        Uploaded    = DateTime.UtcNow,
                    };
                    var ping = await _clam.PingAsync();

                    if (ping)
                    {
                        _logger.LogInformation("Successfully pinged the ClamAV server.");
                        var result = await _clam.SendAndScanFileAsync(formFile.OpenReadStream());

                        file.ScanResult = result.Result.ToString();
                        file.Infected   = result.Result == ClamScanResults.VirusDetected;
                        file.Scanned    = DateTime.UtcNow;
                        if (result.InfectedFiles != null)
                        {
                            foreach (var infectedFile in result.InfectedFiles)
                            {
                                file.Viruses.Add(new Virus
                                {
                                    Name = infectedFile.VirusName
                                });
                            }
                        }
                        var metaData = new Dictionary <string, string>
                        {
                            { "av-status", result.Result.ToString() },
                            { "av-timestamp", DateTime.UtcNow.ToString() },
                            { "alias", file.Alias }
                        };

                        try
                        {
                            var found = await _minio.BucketExistsAsync(BUCKET_NAME);

                            if (!found)
                            {
                                await _minio.MakeBucketAsync(BUCKET_NAME);
                            }
                            await _minio.PutObjectAsync(BUCKET_NAME,
                                                        file.Name,
                                                        formFile.OpenReadStream(),
                                                        formFile.Length,
                                                        formFile.ContentType,
                                                        metaData);

                            await _context.Files.AddAsync(file);

                            await _context.SaveChangesAsync();
                        }
                        catch (MinioException e)
                        {
                            _logger.LogError($"File Upload Error: {e.Message}");
                        }


                        var scanResult = new ScanResult()
                        {
                            FileName  = formFile.FileName,
                            Result    = result.Result.ToString(),
                            Message   = result.InfectedFiles?.FirstOrDefault()?.VirusName,
                            RawResult = result.RawResult
                        };
                        log.Add(scanResult);
                    }
                    else
                    {
                        _logger.LogWarning("Wasn't able to connect to the ClamAV server.");
                    }
                }
            }

            var model = new UploadFilesViewModel
            {
                Results = log
            };

            return(View("UploadResults", model));
        }
Пример #24
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 } }));
            }
        }