mirror of
https://github.com/volodymyrsmirnov/MalwareMultiScan.git
synced 2025-08-24 05:22:22 +00:00
111 lines
3.9 KiB
C#
111 lines
3.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Net.Http;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Hangfire;
|
|
using MalwareMultiScan.Backends.Backends.Implementations;
|
|
using MalwareMultiScan.Shared.Data.Enums;
|
|
using MalwareMultiScan.Shared.Data.Responses;
|
|
using MalwareMultiScan.Shared.Interfaces;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace MalwareMultiScan.Worker.Jobs
|
|
{
|
|
public class ScanJob
|
|
{
|
|
private readonly IScanBackend _backend;
|
|
private readonly IHttpClientFactory _httpClientFactory;
|
|
private readonly ILogger<ScanJob> _logger;
|
|
private readonly int _scanTimeout;
|
|
|
|
public ScanJob(IConfiguration configuration, ILogger<ScanJob> logger,
|
|
IHttpClientFactory httpClientFactory)
|
|
{
|
|
_logger = logger;
|
|
_httpClientFactory = httpClientFactory;
|
|
_scanTimeout = configuration.GetValue<int>("ScanTimeout");
|
|
|
|
_backend = configuration.GetValue<BackendType>("BackendType") switch
|
|
{
|
|
BackendType.Defender => new WindowsDefenderScanBackend(logger),
|
|
BackendType.Clamav => new ClamavScanBackend(logger),
|
|
BackendType.DrWeb => new DrWebScanBackend(logger),
|
|
BackendType.Kes => new KesScanBackend(logger),
|
|
BackendType.Comodo => new ComodoScanBackend(logger),
|
|
BackendType.Sophos => new SophosScanBackend(logger),
|
|
BackendType.McAfee => new McAfeeScanBackend(logger),
|
|
_ => throw new NotImplementedException()
|
|
};
|
|
}
|
|
|
|
private async Task PostResult(ResultResponse response, Uri callbackUrl, CancellationToken cancellationToken)
|
|
{
|
|
var serializedResponse = JsonSerializer.Serialize(
|
|
response, typeof(ResultResponse), new JsonSerializerOptions
|
|
{
|
|
WriteIndented = true
|
|
});
|
|
|
|
_logger.LogInformation(
|
|
$"Sending following payload to {callbackUrl}: {serializedResponse}");
|
|
|
|
using var httpClient = _httpClientFactory.CreateClient();
|
|
|
|
var callbackResponse = await httpClient.PostAsync(callbackUrl,
|
|
new StringContent(serializedResponse, Encoding.UTF8, "application/json"), cancellationToken);
|
|
|
|
_logger.LogInformation($"Callback URL {callbackUrl} returned a status {callbackResponse.StatusCode}");
|
|
}
|
|
|
|
private async Task Scan(Func<CancellationToken, Task<string[]>> scanMethod, Uri callbackUrl)
|
|
{
|
|
var cancellationTokenSource = new CancellationTokenSource();
|
|
|
|
cancellationTokenSource.CancelAfter(_scanTimeout * 1000);
|
|
|
|
var cancellationToken = cancellationTokenSource.Token;
|
|
|
|
var response = new ResultResponse
|
|
{
|
|
Backend = _backend.Id
|
|
};
|
|
|
|
try
|
|
{
|
|
response.Success = true;
|
|
response.Threats = await scanMethod(cancellationToken);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
response.Success = false;
|
|
|
|
_logger.LogError(exception, "Scanning failed with exception");
|
|
}
|
|
|
|
await PostResult(response, callbackUrl, cancellationToken);
|
|
}
|
|
|
|
[AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
|
public async Task ScanUrl(Uri url, Uri callbackUrl)
|
|
{
|
|
await Scan(async t => await _backend.ScanAsync(url, t), callbackUrl);
|
|
}
|
|
|
|
[AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
|
public async Task ScanFile(string file, Uri callbackUrl)
|
|
{
|
|
try
|
|
{
|
|
await Scan(async t => await _backend.ScanAsync(file, t), callbackUrl);
|
|
}
|
|
finally
|
|
{
|
|
File.Delete(file);
|
|
}
|
|
}
|
|
}
|
|
} |