WIP: clamav integration #1223
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from contextlib import contextmanager
|
||||
import io
|
||||
import socket
|
||||
import struct
|
||||
import sys
|
||||
|
||||
class ClamdClient(object):
|
||||
def __init__(self, sock_path="/var/run/clamav/clamd.ctl"):
|
||||
self.sock_path = sock_path
|
||||
|
||||
@contextmanager
|
||||
def _socket(self):
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
sock.connect(self.sock_path)
|
||||
sock.settimeout(10)
|
||||
try:
|
||||
yield sock
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
def _send_command(self, cmd):
|
||||
with self._socket() as sock:
|
||||
if type(cmd) is str:
|
||||
sock.send(b"z%s\x00" % cmd.encode("utf8"))
|
||||
else:
|
||||
sock.send(b"z%s\x00" % cmd)
|
||||
return sock.recv(250).decode("utf8")
|
||||
|
||||
def version(self):
|
||||
return self._send_command("VERSION")
|
||||
|
||||
def scan_file(self, filename):
|
||||
return self._send_command("SCAN %s" % filename)
|
||||
|
||||
def scan_stream(self, stream):
|
||||
with self._socket() as sock:
|
||||
sock.send(b"zINSTREAM\x00")
|
||||
chunk_size = 1024
|
||||
buf = stream.read(chunk_size)
|
||||
while buf:
|
||||
sizebuf = struct.pack(b'!L', len(buf)) + buf
|
||||
sock.send(sizebuf)
|
||||
buf = stream.read(chunk_size)
|
||||
sock.send(struct.pack(b'!L', 0))
|
||||
return sock.recv(250).decode("utf8")
|
||||
|
||||
def scan_data(self, data):
|
||||
return self.scan_stream(io.BytesIO(data))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
c = ClamdClient()
|
||||
print(c.version())
|
||||
if sys.argv[1] == "-":
|
||||
print(c.scan_stream(sys.stdin.buffer))
|
||||
else:
|
||||
print(c.scan_file(sys.argv[1]))
|
||||
|
|
@ -120,18 +120,26 @@ class FileField(WidgetField):
|
|||
def convert_value_from_anything(cls, value):
|
||||
if not value:
|
||||
return None
|
||||
from wcs.clamd import ClamdClient
|
||||
from wcs.variables import LazyFieldVarFile
|
||||
|
||||
if isinstance(value, LazyFieldVarFile):
|
||||
value = value.get_value() # unbox
|
||||
if hasattr(value, 'base_filename'):
|
||||
upload = PicklableUpload(value.base_filename, value.content_type or 'application/octet-stream')
|
||||
# TODO : scan file !
|
||||
data = None
|
||||
if hasattr(value, 'get_content'):
|
||||
upload.receive([value.get_content()])
|
||||
data = value.get_content()
|
||||
else:
|
||||
# native quixote Upload object
|
||||
upload.receive([value.fp.read()])
|
||||
data = value.fp.read()
|
||||
value.fp.seek(0)
|
||||
clam = ClamdClient()
|
||||
res = clam.scan_data(data)
|
||||
if res != b"OK":
|
||||
raise ValueError("Found a VIRUS, run away, run away !")
|
||||
upload.receive([data])
|
||||
return upload
|
||||
from wcs.workflows import NamedAttachmentsSubstitutionProxy
|
||||
|
||||
|
|
Loading…
Reference in New Issue