Esempio n. 1
0
def post_http():
    method_name = request.headers.get('ce-methodname')
    resource_name = request.headers.get('ce-resourcename')
    print(f"{method_name} : {resource_name}")
    if method_name != 'storage.objects.create':
        return "BYE"

    blob = parse_resource_name(resource_name)
    if not blob:
        print(f"{resource_name} is null")
        return "NULL"

    print(f"SCAN {blob}")
    cd = clamd.ClamdNetworkSocket(host="127.0.0.1", port=3310)
    cd.ping()
    status = "CLEAN" 
    signataure = "N/A"
    with blob.open("rb", chunk_size=1024) as f:
        cd_response = cd.instream(f)
        cd_status = cd_response['stream']
        if 'FOUND' in cd_status:
            status = "INFECTED"
            signature = cd_status[1]

    metadata = { "timesetamp": get_timestamp(), "status": status, "signature": signataure}
    print(f"Update METADATA {blob}: {metadata}")
    blob.metadata = metadata
    blob.patch()
    return f"DONE {blob}"
Esempio n. 2
0
def upload_file():
    if 'file' not in request.files:
        app.logger.warning("No file uploaded")
        flash('No file found in uploaded form')
        return redirect(request.url)

    upload_file = request.files['file']
    app.logger.info('File upload: %s', upload_file.filename)

    try:
        av = clamd.ClamdNetworkSocket("clamav-server")
    except:
        app.logger.error("Unable to establish network connection")
        flash('The AV server is unavailable. No uploads are being accepted until the server is back online.')
        return redirect(request.url)

    if av.ping() != 'PONG':
        app.logger.error("No Clam AV deamon responding")
        flash('The AV server is unavailable. No uploads are being accepted until the server is back online.')
        return redirect(request.url)

    result = av.instream(request.files['file'])['stream']
    app.logger.info("Upload scanned: %s - %s", result[0], result[1])

    if result[0] != 'OK':
        app.logger.warning("Virus detected in upload: %s", result[1])
        flash("Virus detected in upload: {}".format(result[1]))
        return redirect(request.url)

    blob_client = container_client.get_blob_client(upload_file.filename)
    blob_client.upload_blob(request.files['file'].read())

    return redirect("/files")
Esempio n. 3
0
def connect_to_clamav(connection_string: str) -> clamd.ClamdNetworkSocket:
    if connection_string.startswith("unix://"):
        return clamd.ClamdUnixSocket(connection_string.replace("unix://", ""))
    elif ":" in connection_string:
        host, port = connection_string.split(":")
        return clamd.ClamdNetworkSocket(host, int(port))
    else:
        raise Exception("ClamAV connection string is invalid. It must be unix socket path with 'unix://' prefix or IP:PORT.")
Esempio n. 4
0
def get_scanner():
    """Lazy get scanner configured scanner when needed"""
    import clamd
    from . import conf

    if conf.CLAMAV_USE_TCP:
        return clamd.ClamdNetworkSocket(conf.CLAMAV_TCP_ADDR,
                                        conf.CLAMAV_TCP_PORT)

    return clamd.ClamdUnixSocket(conf.CLAMAV_UNIX_SOCKET)
Esempio n. 5
0
def _make_clamd(type, **kwargs):
    timeout = kwargs.get('timeout', 10.0)
    if type == 'socket':
        socketpath = kwargs.get('socketpath', '/var/run/clamd')
        return clamd.ClamdUnixSocket(path=socketpath, timeout=timeout)
    elif type == 'net':
        host = kwargs.get('host', 'localhost')
        port = kwargs.get('port', 3310)
        return clamd.ClamdNetworkSocket(host=host, port=port, timeout=timeout)
    else:
        raise ScanError('Invalid call')
Esempio n. 6
0
    def __init__(self, polyswarmd_addr, keyfile, password, api_key=None):
        """Initialize a ClamAV microengine

        Args:
            polyswarmd_addr (str): Address of polyswarmd
            keyfile (str): Path to private key file to use to sign transactions
            password (str): Password to decrypt the encrypted private key
            api_key (str): API key to use with polyswarmd
        """
        super().__init__(polyswarmd_addr, keyfile, password, api_key)
        self.clamd = clamd.ClamdNetworkSocket(CLAMD_HOST, CLAMD_PORT, CLAMD_TIMEOUT)
def get_scanner(socket, timeout=None):
    if socket.startswith('unix://'):
        return clamd.ClamdUnixSocket(socket[7:], timeout)
    elif socket.startswith('tcp://'):
        uri = urlparse(socket)

        return clamd.ClamdNetworkSocket(uri.hostname, uri.port or 3310,
                                        timeout)
    else:
        raise NotImplementedError(
            'Missed or unsupported ClamAV connection string schema. '
            'Only tcp:// or unix:// is allowed.')
Esempio n. 8
0
def validate_no_virus(afile):
    """ Checks a file field against a remote antivirus service
    """
    if not settings.CAMPAIGNS['SKIP_VIRUS_CHECK']:
        try:
            host, port = settings.CLAMD_HOST, settings.CLAMD_PORT
        except AttributeError:
            results = dns.resolver.query(settings.CLAMD_SERVICE_NAME, 'SRV')
            servers = [(rr.target.to_text(True), rr.port) for rr in results]
            host, port = servers[0]

        cd = clamd.ClamdNetworkSocket(host=host, port=port)
        check_result, check_msg = cd.instream(afile)['stream']
        # example virus result
        # {'stream': ('FOUND', 'Eicar-Test-Signature')}
        if check_result == 'FOUND':
            raise ValidationError(_(
                'File contains virus: "{}"').format(check_msg))
    return afile
Esempio n. 9
0
def validate_file_type(upload):
    upload.seek(0)
    file_type = magic.from_buffer(upload.read(), mime=True)
    allowed_types = settings.ALLOWED_FILE_TYPES
    if file_type not in allowed_types.viewvalues():
        raise ValidationError(
            'You cannot upload file type: {}. Allowed file types are: {}.'.
            format(str(file_type), ', '.join(allowed_types.viewkeys())))

    else:
        # setup unix socket and scan stream
        cd = clamd.ClamdNetworkSocket(settings.CLAMD_TCP_ADDR,
                                      settings.CLAMD_TCP_SOCKET)
        upload.seek(0)
        scan_results = cd.instream(upload)
        upload.seek(0)
        if (scan_results['stream'][0] == 'FOUND'):
            raise ValidationError(
                "Your file appears to be infected by a virus.Please check again before uploading."
            )
Esempio n. 10
0
def file_scan_validation(file):
    """
    This validator sends the file to ClamAV for scanning and returns returns to the form. By default, if antivirus
    service is not available or there are errors, the validation will fail.

    Usage:
        class UploadForm(forms.Form):
            file = forms.FileField(validators=[file_scan_validation])
    :param file:
    :return:
    """
    logger.debug("starting file scanning with clamav")
    if not settings.CLAMAV_ENABLED:
        logger.warning('File scanning has been disabled.')
        return

    # make sure we're at the beginning of the file stream
    file.seek(0)

    # we're just going to assume a network connection to clamav here .. no local unix socket support
    scanner = clamd.ClamdNetworkSocket(settings.CLAMAV_HOST,
                                       settings.CLAMAV_PORT)
    try:
        result = scanner.instream(file)
    except:
        # it doesn't really matter what the actual error is .. log it and raise validation error
        logger.error('Error occurred while trying to scan file. "{}"'.format(
            sys.exc_info()[0]))
        raise ValidationError('Unable to scan file.', code='scanerror')
    finally:
        # reset file stream
        file.seek(0)

    if result and result['stream'][0] == 'FOUND':
        logger.warning('Virus found: {}'.format(file.name))
        raise ValidationError('Infected file found.', code='infected')
Esempio n. 11
0
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
app.config['UPLOAD_FOLDER'] = 'upload_tmp/'
CORS(app)

app.logger.info('connecting to Redis queue')
q = Queue(connection=conn)

# clamd init
app.logger.info('initializing Clamav')
try:
    cd = clamd.ClamdUnixSocket()
    cd.ping()
except:
    app.logger.error(
        'could not open clamd unix socket. attemping network socket')
    cd = clamd.ClamdNetworkSocket()
    try:
        cd.ping()
    except clamd.ConnectionError:
        app.logger.error(
            'could not connect to clamd server either by unix or network socket. go big or go home I guess.'
        )
        cd = None

# dropbox init
app.logger.info('initializing Dropbox')
dbx = dropbox.Dropbox(config['DROPBOX_ACCESS_TOKEN'])


def isaudio(file):
    return 'audio/' in file.mimetype
Esempio n. 12
0
        ]
    )
except AttributeError:
    APPLICATION_USERS = {}
    logger.warning("No application users configured.")

sentry = Sentry(app, dsn=app.config.get("SENTRY_DSN", None))

auth = HTTPBasicAuth()

if "CLAMD_SOCKET" in app.config:
    cd = clamd.ClamdUnixSocket(path=app.config["CLAMD_SOCKET"])
else:
    try:
        cd = clamd.ClamdNetworkSocket(
            host=app.config["CLAMD_HOST"], port=app.config["CLAMD_PORT"]
        )
    except BaseException as exc:
        logger.exception(f"error bootstrapping clamd for network socket: {exc}")


@auth.verify_password
def verify_pw(username, password):
    app_password = APPLICATION_USERS.get(username, None)
    if not app_password:
        return False
    if hash.verify(password, app_password):
        g.current_user = username
        return True
    else:
        return False