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()); } }
/// <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); }
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); }
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)); }
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; } }
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; } }
/// <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); } } }
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)); } }
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); }
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)); }
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); } }
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); }
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)); }
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)); }
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); }
public async Task <ScanResultModel> ScanFileAsync(byte[] bytes, CancellationToken cancellationToken = default) { return(await SendAsync(async() => await _clamClient.SendAndScanFileAsync(bytes, cancellationToken))); }
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 } }
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())); }
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) } })); } }
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) { } }
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)); }
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 } })); } }