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}"
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")
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.")
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)
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')
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.')
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
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." )
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')
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
] ) 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