def add_comment(self, id): if comments_enabled(): f = File(get_or_404(current_user.files, _id=id)) if current_user.has_permission('add_probable_name'): probable_name = request.form.get('probable_name') else: probable_name = None comment = request.form.get('comment') analysis_id = request.form.get('analysis') notify = request.form.get('notify') if comment: # If there is an analysis ID, make sure it is accessible if analysis_id: get_or_404(current_user.analyses, _id=analysis_id) f.add_comment(current_user['_id'], comment, analysis_id, probable_name) if notify: self.notify_new_comment(f, analysis_id, current_user['_id'], comment) else: flash('Comment should not be empty', 'danger') return redirect(request.referrer)
def default_sharing(self, id): """Change a user's default sharing. .. :quickref: User; Change default sharing When used on another user account, requires the `manage_users` permission. :param id: user id. :>json User user: modified user. """ self.ensure_permission(id) user = User(get_or_404(User.get_collection(), _id=id)) groups = request.form.get('groups', '').split(',') for group in groups: if group in user['groups']: break else: flash('You have to at least keep one of your groups.', 'danger') return redirect(request.referrer) user.update_value('default_sharing', groups) return redirect({'user': clean_users(user)}, request.referrer)
def get(self, id): """Get a user. .. :quickref: User; Get a user The user is returned in the ``user`` field. :param id: user id :>json ObjectId _id: user's ObjectId. :>json string name: full name. :>json string: email address. :>json boolean enabled: ``True`` if the user is enabled. :>json list groups: list of groups the user belongs to. :>json list default_sharing: list of groups used by the user as default sharing preferences. :>json list permissions: list of user's permissions """ self.ensure_permission(id) user = User(get_or_404(User.get_collection(), _id=id)) return render( { 'user': clean_users(user), 'permissions': dispatcher.permissions }, 'users/profile.html')
def change_type(self, id): f = File(get_or_404(current_user.files, _id=id)) new_type = request.form.get('type') f.update_value("type", new_type) return redirect(request.referrer)
def update(self, id): """Update a user. .. :quickref: User; Update existing user Requires the `manage_users` permission. When succesful, the new user will be returned in the ``user`` field. Otherwise, an ``errors`` field will list errors. :form name: full name :form email: email address :form groups: comma-delimited list of groups :form permission_VALUE: specify a value different than ``0`` or ``False`` for all permissions the user should have. """ name = request.form.get('name') email = request.form.get('email').lower() groups = [g for g in request.form.get('groups', '').split(',') if g] user = User(get_or_404(User.get_collection(), _id=id)) if not self._valid_form(name, email, groups, user['email']): return validation_error() user['name'] = name user['email'] = email user['groups'] = groups user['permissions'] = self.get_permissions(user['permissions']) user.save() return redirect({'user': clean_users(user)}, url_for('UsersView:get', id=user['_id']))
def get(self, id): """Get the object with `id`. .. :quickref: File; Get an object Resulting object is in the ``file`` field. :param id: id of the object. :>json dict _id: ObjectId dict. :>json string md5: MD5 hash. :>json string sha1: SHA1 hash. :>json string sha256: SHA256 hash. :>json string type: FAME type. :>json string mime: mime type. :>json string detailed_type: detailed type. :>json list groups: list of groups (as strings) that have access to this file. :>json list owners: list of groups (as strings) that submitted this file. :>json list probable_names: list of probable names (as strings). :>json list analysis: list of analyses' ObjectIds. :>json list parent_analyses: list of analyses (as ObjectIds) that extracted this object. :>json dict antivirus: dict with antivirus names as keys. """ file = {'file': enrich_comments(clean_files(get_or_404(current_user.files, _id=id)))} return return_file(file)
def configuration(self, id): """Configure a named configuration. .. :quickref: Module; Configure a named configuration Requires the `manage_modules` permission. For each configuration available, you should set the value in a form parameter named ``config_NAME``. For boolean values, any value not ``0`` or ``False`` is considered to be ``True``. If successful, will return the named configuration in ``config``. Otherwise, errors will be available in ``errors``. :param id: id of the named configuration. """ config = Config(get_or_404(Config.get_collection(), _id=id)) if request.method == "POST": errors = update_config(config['config']) if errors is not None: return errors config.save() dispatcher.reload() return redirect({'config': config}, url_for('ModulesView:index')) else: return render({'config': config}, 'modules/configuration.html')
def download_support_file(self, id, module, filename): """Download a support file. .. :quickref: Analysis; Download a support file. :param id: id of the analysis. :param module: name of the module. :param filename: name of the file to download. """ analysis = get_or_404(current_user.analyses, _id=id) filepath = os.path.join(fame_config.storage_path, 'support_files', module, str(analysis['_id']), secure_filename(filename)) if os.path.isfile(filepath): return file_download(filepath) else: # This code is here for compatibility # with older analyses filepath = os.path.join(fame_config.storage_path, 'support_files', str(analysis['_id']), secure_filename(filename)) if os.path.isfile(filepath): return file_download(filepath) else: abort(404)
def add_group(self, id): f = File(get_or_404(current_user.files, _id=id)) group = request.form.get('group') f.add_groups([group]) return redirect(request.referrer)
def download(self, id): """Download the file with `id`. .. :quickref: File; Download a file :param id: id of the file to download. """ f = File(get_or_404(current_user.files, _id=id)) return file_download(f['filepath'])
def get(self, id): """Get the analysis with `id`. .. :quickref: Analysis; Get an analysis Resulting object is in the ``analysis`` field. :param id: id of the analysis. :>json dict _id: ObjectId dict. :>json dict analyst: analyst's ObjectId. :>json dict date: date dict. :>json list executed_modules: list of executed modules. :>json list pending_modules: list of pending modules. :>json list waiting_modules: list of waiting modules. :>json list canceled_modules: list of canceled modules. :>json list executed_modules: list of executed modules. :>json string module: the name of the target module. :>json string status: status of the analysis (one of `pending`, `running`, `finished` or `error`). :>json list tags: the list of tags. :>json list probable_names: the list of probable names. :>json list iocs: list of dict describing observables. :>json dict results: detailed results for each module, with the module name being the key. :>json dict generated_files: a dict of generated files, the key being the file type. :>json list extracted_files: a list of extracted files. :>json dict support_files: a dict of support files, the key being the module name. """ analysis = { 'analysis': clean_analyses(get_or_404(current_user.analyses, _id=id)) } file = current_user.files.find_one( {'_id': analysis['analysis']['file']}) analysis['analysis']['file'] = clean_files(file) ti_modules = [ m.name for m in dispatcher.get_threat_intelligence_modules() ] av_modules = [m.name for m in dispatcher.get_antivirus_modules()] if 'extracted_files' in analysis['analysis']: files = [] for id in analysis['analysis']['extracted_files']: files.append(current_user.files.find_one({'_id': id})) analysis['analysis']['extracted_files'] = clean_files(files) modules = dict() for module in ModuleInfo.get_collection().find(): modules[module['name']] = ModuleInfo(module) return render(analysis, 'analyses/show.html', ctx={ 'analysis': analysis, 'modules': modules, 'av_modules': av_modules, 'ti_modules': ti_modules })
def get_sha1(self, sha1): """Get the object with `sha1`. .. :quickref: File; Get an object by SHA1 :param sha1: sha1 of the object. :>json file file: list of files (see :http:get:`/files/(id)` for details on the format of a file). """ file = {'file': clean_files(get_or_404(current_user.files, sha1=sha1))} return return_file(file)
def refresh_iocs(self, id): """Refresh IOCs with Threat Intel modules .. :quickref: Analysis; Refresh IOCs with Threat Intel modules. :param id: id of the analysis. """ analysis = Analysis(get_or_404(current_user.analyses, _id=id)) analysis.refresh_iocs() return redirect(analysis, url_for('AnalysesView:get', id=analysis["_id"]))
def get_md5(self, md5): """Get the object with `md5`. .. :quickref: File; Get an object by MD5 :param md5: md5 of the object. :>json file file: list of files (see :http:get:`/files/(id)` for details on the format of a file). """ file = {'file': clean_files(get_or_404(current_user.files, md5=md5))} return return_file(file)
def get_sha256(self, sha256): """Get the object with `sha256`. .. :quickref: File; Get an object by SHA256 :param sha256: sha256 of the object. :>json file file: list of files (see :http:get:`/files/(id)` for details on the format of a file). """ file = {'file': enrich_comments(clean_files(get_or_404(current_user.files, sha256=sha256)))} return return_file(file)
def remove_group(self, id): f = File(get_or_404(current_user.files, _id=id)) group = request.form.get('group') if group in f['owners']: flash('This group submitted this file themselves. You cannot neuralize them.', 'danger') else: f.remove_group(group) return redirect(request.referrer)
def update_queue(module, new_queue): if new_queue == '': flash('queue cannot be empty', 'danger') return validation_error() elif module['queue'] != new_queue: module.update_setting_value('queue', new_queue) updates = Internals( get_or_404(Internals.get_collection(), name="updates")) updates.update_value("last_update", time()) flash( 'Workers will reload once they are done with their current tasks', 'success')
def download_support_file(self, id, filename): """Download a support file. .. :quickref: Analysis; Download a support file. :param id: id of the analysis. :param filename: name of the file to download. """ analysis = get_or_404(current_user.analyses, _id=id) filepath = os.path.join(fame_config.storage_path, 'support_files', str(analysis['_id']), secure_filename(filename)) return file_download(filepath)
def get_md5(self, md5): """Get the object with `md5`. .. :quickref: File; Get an object by MD5 :param md5: md5 of the object. :>json file file: list of files (see :http:get:`/files/(id)` for details on the format of a file). """ return return_file({ "file": enrich_comments( clean_files(get_or_404(current_user.files, md5=md5.lower()))) })
def get_file(self, id, filehash): analysis = Analysis(get_or_404(current_user.analyses, _id=id)) for file_type in analysis['generated_files']: for filepath in analysis['generated_files'][file_type]: filepath = filepath.encode('utf-8') if filehash == md5(filepath).hexdigest(): return file_download(filehash) filepath = analysis._file['filepath'].encode('utf-8') if filehash == md5(filepath).hexdigest(): return file_download(analysis.get_main_file()) return abort(404)
def add_comment(self, id): if comments_enabled(): f = File(get_or_404(current_user.files, _id=id)) if current_user.has_permission("add_probable_name"): probable_name = request.form.get("probable_name") else: probable_name = None comment = request.form.get("comment") analysis_id = request.form.get("analysis") notify = request.form.get("notify") if comment: # If there is an analysis ID, make sure it is accessible if analysis_id: get_or_404(current_user.analyses, _id=analysis_id) f.add_comment(current_user["_id"], comment, analysis_id, probable_name, notify) else: flash("Comment should not be empty", "danger") return redirect(request.referrer)
def enable(self, id): """Enable a module .. :quickref: Module; Enable a module Requires the `manage_modules` permission. If successful, will return the module in ``module``. Otherwise, errors will be available in ``errors``. :param id: id of the module to enable. """ module = ModuleInfo(get_or_404(ModuleInfo.get_collection(), _id=id)) if 'error' in module: flash( "Cannot enable '{}' because of errors installing dependencies." .format(module['name']), 'danger') return validation_error(url_for('ModulesView:index')) # See if module is properly configured module_class = get_class(module['path'], module['class']) module_class.info = module try: module_class() except MissingConfiguration as e: if e.name: flash( "You must configure '{}' before trying to enable '{}'". format(e.name, module['name']), 'warning') return validation_error( url_for('ModulesView:configuration', id=e.id)) else: flash( "You must configure '{}' before trying to enable it.". format(module['name']), 'warning') return validation_error( url_for('ModulesView:configure', id=module['_id'])) module.update_value('enabled', True) dispatcher.reload() readme = module.get_readme() if readme: flash(readme, 'persistent') return redirect({'module': clean_modules(module)}, url_for('ModulesView:index'))
def repository_delete(self, id): """Delete a repository .. :quickref: Module; Delete repository Requires the `manage_modules` permission. Returns "ok". :param id: id of the repository. """ repository = Repository(get_or_404(Repository.get_collection(), _id=id)) repository.delete() dispatcher.reload() return redirect('ok', url_for('ModulesView:index'))
def disable(self, id): """Disable a module .. :quickref: Module; Disable a module Requires the `manage_modules` permission. :param id: id of the module to disable. :>json Module module: resulting module. """ module = ModuleInfo(get_or_404(ModuleInfo.get_collection(), _id=id)) module.update_value('enabled', False) dispatcher.reload() return redirect({'module': clean_modules(module)}, url_for('ModulesView:index'))
def disable(self, id): """Disable a user. .. :quickref: User; Disable a user Requires the `manage_users` permission. :param id: user id. :>json User user: modified user. """ user = User(get_or_404(User.get_collection(), _id=id)) user.update_value('enabled', False) return redirect({'user': clean_users(user)}, url_for('UsersView:index'))
def _save_analysis_file(self, id, path): file = request.files['file'] analysis = Analysis(get_or_404(current_user.analyses, _id=id)) dirpath = os.path.join(path, str(analysis['_id'])) filepath = os.path.join(dirpath, secure_filename(file.filename)) # Create parent dirs if they don't exist try: os.makedirs(dirpath) except: pass with open(filepath, "wb") as fd: copyfileobj(file.stream, fd) return filepath
def repository_update(self, id): """Update a repository .. :quickref: Module; Update repository Requires the `manage_modules` permission. :param id: id of the repository. :>json Repository repository: the repository. """ repository = Repository(get_or_404(Repository.get_collection(), _id=id)) repository.pull() return redirect({'repository': clean_repositories(repository)}, url_for('ModulesView:index'))
def reset_api(self, id): """Reset a user's API key. .. :quickref: User; Reset API key When used on another user account, requires the `manage_users` permission. :param id: user id. :>json User user: modified user. """ self.ensure_permission(id) user = User(get_or_404(User.get_collection(), _id=id)) user.update_value('api_key', User.generate_api_key()) return redirect({'user': clean_users(user)}, request.referrer)
def get(self, id): """Get the object with `id`. .. :quickref: File; Get an object Resulting object is in the ``file`` field. :param id: id of the object. :>json dict _id: ObjectId dict. :>json string md5: MD5 hash. :>json string sha1: SHA1 hash. :>json string sha256: SHA256 hash. :>json string type: FAME type. :>json string mime: mime type. :>json string detailed_type: detailed type. :>json list groups: list of groups (as strings) that have access to this file. :>json list owners: list of groups (as strings) that submitted this file. :>json list probable_names: list of probable names (as strings). :>json list analysis: list of analyses' ObjectIds. :>json list parent_analyses: list of analyses (as ObjectIds) that extracted this object. :>json dict antivirus: dict with antivirus names as keys. """ file = {'file': clean_files(get_or_404(current_user.files, _id=id))} analyses = list( current_user.analyses.find( {'_id': { '$in': file['file']['analysis'] }})) file['av_modules'] = [ m.name for m in dispatcher.get_antivirus_modules() ] for analysis in analyses: if 'analyst' in analysis: analyst = store.users.find_one({'_id': analysis['analyst']}) analysis['analyst'] = clean_users(analyst) file['file']['analysis'] = clean_analyses(analyses) return render(file, 'files/show.html', ctx={ 'data': file, 'options': dispatcher.options })
def reload(self): """Reload the workers .. :quickref: Module; Reload workers Requires the `manage_modules` permission. Returns "ok". """ for repository in Repository.get_collection().find(): dispatcher.update_modules(Repository(repository)) updates = Internals( get_or_404(Internals.get_collection(), name="updates")) updates.update_value("last_update", time()) flash( 'Workers will reload once they are done with their current tasks', 'success') return redirect('ok', url_for('ModulesView:index'))