mirror of
https://github.com/claunia/apprepodbmgr.git
synced 2025-12-16 19:24:42 +00:00
220 lines
9.3 KiB
C#
220 lines
9.3 KiB
C#
|
|
//
|
|||
|
|
// Author:
|
|||
|
|
// Natalia Portillo claunia@claunia.com
|
|||
|
|
//
|
|||
|
|
// Copyright (c) 2017, © Claunia.com
|
|||
|
|
//
|
|||
|
|
// All rights reserved.
|
|||
|
|
//
|
|||
|
|
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|||
|
|
//
|
|||
|
|
// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|||
|
|
// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
|
|||
|
|
// the documentation and/or other materials provided with the distribution.
|
|||
|
|
// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|||
|
|
//
|
|||
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|||
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|||
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|||
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|||
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|||
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|||
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|||
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|||
|
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|||
|
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|||
|
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
|
//
|
|||
|
|
using System;
|
|||
|
|
using nClam;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
using System.IO;
|
|||
|
|
using SharpCompress.Compressors.LZMA;
|
|||
|
|
using SharpCompress.Compressors.Deflate;
|
|||
|
|
using SharpCompress.Compressors.BZip2;
|
|||
|
|
using System.Threading;
|
|||
|
|
|
|||
|
|
namespace osrepodbmgr.Core
|
|||
|
|
{
|
|||
|
|
public static partial class Workers
|
|||
|
|
{
|
|||
|
|
static ClamClient clam;
|
|||
|
|
|
|||
|
|
public static void InitClamd()
|
|||
|
|
{
|
|||
|
|
if(!Settings.Current.UseClamd || !Settings.Current.UseAntivirus)
|
|||
|
|
{
|
|||
|
|
Context.clamdVersion = null;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
TestClamd();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void TestClamd()
|
|||
|
|
{
|
|||
|
|
Task.Run(async () =>
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
clam = new ClamClient(Settings.Current.ClamdHost, Settings.Current.ClamdPort);
|
|||
|
|
Context.clamdVersion = await clam.GetVersionAsync();
|
|||
|
|
}
|
|||
|
|
catch(System.Net.Sockets.SocketException)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}).Wait();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void ClamScanFileFromRepo(DBFile file)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if(Context.clamdVersion == null)
|
|||
|
|
{
|
|||
|
|
if(Failed != null)
|
|||
|
|
Failed("clamd is not usable");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(clam == null)
|
|||
|
|
{
|
|||
|
|
if(Failed != null)
|
|||
|
|
Failed("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(Failed != null)
|
|||
|
|
Failed(string.Format("Cannot find file with hash {0} in the repository", file.Sha256));
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ClamScanResult result = null;
|
|||
|
|
Stream zStream = null;
|
|||
|
|
|
|||
|
|
if(Settings.Current.ClamdIsLocal)
|
|||
|
|
{
|
|||
|
|
// clamd supports gzip and bzip2 but not lzma
|
|||
|
|
if(algorithm == AlgoEnum.LZMA)
|
|||
|
|
{
|
|||
|
|
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);
|
|||
|
|
|
|||
|
|
byte[] properties = new byte[5];
|
|||
|
|
inFs.Read(properties, 0, 5);
|
|||
|
|
inFs.Seek(8, SeekOrigin.Current);
|
|||
|
|
zStream = new LzmaStream(properties, inFs);
|
|||
|
|
|
|||
|
|
zStream.CopyTo(outFs);
|
|||
|
|
zStream.Close();
|
|||
|
|
outFs.Close();
|
|||
|
|
|
|||
|
|
Task.Run(async () =>
|
|||
|
|
{
|
|||
|
|
result = await clam.ScanFileOnServerMultithreadedAsync(tmpFile);
|
|||
|
|
}).Wait();
|
|||
|
|
|
|||
|
|
File.Delete(tmpFile);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
Task.Run(async () =>
|
|||
|
|
{
|
|||
|
|
result = await clam.ScanFileOnServerMultithreadedAsync(repoPath);
|
|||
|
|
}).Wait();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
FileStream inFs = new FileStream(repoPath, FileMode.Open, FileAccess.Read);
|
|||
|
|
|
|||
|
|
switch(algorithm)
|
|||
|
|
{
|
|||
|
|
case AlgoEnum.GZip:
|
|||
|
|
zStream = new GZipStream(inFs, SharpCompress.Compressors.CompressionMode.Decompress);
|
|||
|
|
break;
|
|||
|
|
case AlgoEnum.BZip2:
|
|||
|
|
zStream = new BZip2Stream(inFs, SharpCompress.Compressors.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);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Task.Run(async () =>
|
|||
|
|
{
|
|||
|
|
result = await clam.SendAndScanFileAsync(zStream);
|
|||
|
|
}).Wait();
|
|||
|
|
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);
|
|||
|
|
|
|||
|
|
if(ScanFinished != null)
|
|||
|
|
ScanFinished(file);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
catch(Exception ex)
|
|||
|
|
{
|
|||
|
|
if(Failed != null)
|
|||
|
|
Failed(string.Format("Exception {0} when calling clamd", ex.Message));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|