diff --git a/Dockerfile b/Dockerfile index 239326c..7db5013 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,6 +5,7 @@ MAINTAINER Antti Virtanen # update maximum stream length to much smaller than default # automated tests run smoother this way RUN sed -i 's/^StreamMaxLength .*$/StreamMaxLength 50100/g' /etc/clamav/clamd.conf - +# For testing scan files +ADD src/test/resources / # av daemon bootstrapping CMD ["/bootstrap.sh"] diff --git a/src/main/java/fi/solita/clamav/ClamAVClient.java b/src/main/java/fi/solita/clamav/ClamAVClient.java index 7f14e11..8db2a03 100644 --- a/src/main/java/fi/solita/clamav/ClamAVClient.java +++ b/src/main/java/fi/solita/clamav/ClamAVClient.java @@ -7,7 +7,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; -import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -113,6 +112,28 @@ public byte[] scan(InputStream is) throws IOException { } } + /** + * Scan file by the path on the filesystem + * @param filepath the path to file to scan. Example: /share/attachments/virus.txt + * @return server reply + */ + public byte[] scan(String filepath) throws IOException { + try (Socket socket = new Socket(hostName, port); + OutputStream outs = new BufferedOutputStream(socket.getOutputStream())) { + socket.setSoTimeout(timeout); + + // handshake + final String multiScanCmd = "MULTISCAN" + " " + filepath; + outs.write(multiScanCmd.getBytes(StandardCharsets.US_ASCII)); + outs.flush(); + + try (InputStream response = socket.getInputStream()) { + return readAll(response); + } + + } + } + /** * Scans bytes for virus by passing the bytes to clamav * diff --git a/src/test/java/fi/solita/clamav/InstreamTest.java b/src/test/java/fi/solita/clamav/InstreamTest.java index 6177df6..185f98f 100644 --- a/src/test/java/fi/solita/clamav/InstreamTest.java +++ b/src/test/java/fi/solita/clamav/InstreamTest.java @@ -1,38 +1,40 @@ package fi.solita.clamav; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import org.junit.Test; import java.io.IOException; import java.io.InputStream; -import java.net.UnknownHostException; -import org.junit.Test; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * These tests assume clamd is running and responding in the virtual machine. */ public class InstreamTest { + private final ClamAVClient client = new ClamAVClient( + TestConfiguration.CLAMAV_HOST, TestConfiguration.CLAMAV_PORT); - private static String CLAMAV_HOST = "localhost"; - - private byte[] scan(byte[] input) throws UnknownHostException, IOException { - ClamAVClient cl = new ClamAVClient(CLAMAV_HOST, 3310); - return cl.scan(input); + private byte[] scan(byte[] input) throws IOException { + return client.scan(input); } - private byte[] scan(InputStream input) throws UnknownHostException, IOException { - ClamAVClient cl = new ClamAVClient(CLAMAV_HOST, 3310); - return cl.scan(input); + private byte[] scan(InputStream input) throws IOException { + return client.scan(input); } + + private byte[] scan(String filepath) throws IOException { + return client.scan(filepath); + } + @Test - public void testRandomBytes() throws UnknownHostException, IOException { + public void testRandomBytes() throws IOException { byte[] r = scan("alsdklaksdla".getBytes("ASCII")); assertTrue(ClamAVClient.isCleanReply(r)); } @Test - public void testPositive() throws UnknownHostException, IOException { + public void testPositive() throws IOException { // http://www.eicar.org/86-0-Intended-use.html byte[] EICAR = "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*".getBytes("ASCII"); byte[] r = scan(EICAR); @@ -40,27 +42,34 @@ public void testPositive() throws UnknownHostException, IOException { } @Test - public void testStreamChunkingWorks() throws UnknownHostException, IOException { + public void testStreamChunkingWorks() throws IOException { byte[] multipleChunks = new byte[50000]; byte[] r = scan(multipleChunks); assertTrue(ClamAVClient.isCleanReply(r)); } @Test - public void testChunkLimit() throws UnknownHostException, IOException { + public void testChunkLimit() throws IOException { byte[] maximumChunk = new byte[2048]; byte[] r = scan(maximumChunk); assertTrue(ClamAVClient.isCleanReply(r)); } @Test - public void testZeroBytes() throws UnknownHostException, IOException { + public void testZeroBytes() throws IOException { byte[] r = scan(new byte[]{}); assertTrue(ClamAVClient.isCleanReply(r)); } @Test(expected = ClamAVSizeLimitException.class) - public void testSizeLimit() throws UnknownHostException, IOException { + public void testSizeLimit() throws IOException { scan(new SlowInputStream()); } + + @Test + public void testHealthyFile() throws IOException { + byte[] response = scan("/healthy.file"); + assertTrue(ClamAVClient.isCleanReply(response)); + } + } diff --git a/src/test/java/fi/solita/clamav/PingTest.java b/src/test/java/fi/solita/clamav/PingTest.java index 29b9f72..523aa9d 100644 --- a/src/test/java/fi/solita/clamav/PingTest.java +++ b/src/test/java/fi/solita/clamav/PingTest.java @@ -1,11 +1,10 @@ package fi.solita.clamav; -import static org.junit.Assert.assertTrue; +import org.junit.Test; import java.io.IOException; -import java.net.UnknownHostException; -import org.junit.Test; +import static org.junit.Assert.assertTrue; /** * These tests assume clamd is running and responding in the virtual machine. @@ -13,8 +12,8 @@ public class PingTest { @Test - public void testPingPong() throws UnknownHostException, IOException { - ClamAVClient cl = new ClamAVClient("localhost", 3310); + public void testPingPong() throws IOException { + ClamAVClient cl = new ClamAVClient(TestConfiguration.CLAMAV_HOST, TestConfiguration.CLAMAV_PORT); assertTrue(cl.ping()); } } diff --git a/src/test/java/fi/solita/clamav/TestConfiguration.java b/src/test/java/fi/solita/clamav/TestConfiguration.java new file mode 100644 index 0000000..f3f327b --- /dev/null +++ b/src/test/java/fi/solita/clamav/TestConfiguration.java @@ -0,0 +1,6 @@ +package fi.solita.clamav; + +public class TestConfiguration { + public static String CLAMAV_HOST = "localhost"; + public static int CLAMAV_PORT = 3310; +} diff --git a/src/test/resources/healthy.file b/src/test/resources/healthy.file new file mode 100644 index 0000000..62d4d39 --- /dev/null +++ b/src/test/resources/healthy.file @@ -0,0 +1 @@ +It's the healthy file \ No newline at end of file