def test_config_validation(config): """Read and validate config files.""" assert read_config(config.good_filepath) assert read_config(config.bad_filepath) is None os.environ['config_path'] = config.good_filepath assert read_config_from_env('config_path') os.environ['config_path'] = config.bad_filepath assert read_config_from_env('config_path') is None
def __init__(self): self.AP_SSID = False self.AP_PASS = False self.iface_in = read_config(("network", "in")) self.iface_out = read_config(("network", "out")) self.enable_interface(self.iface_in) self.enable_interface(self.iface_out) self.enable_forwarding() self.reset_dnsmasq_leases() self.random_choice_alphabet = "abcdef1234567890"
def get_config(): """ Get configuration keys relative to the GUI """ return jsonify({ "virtual_keyboard": read_config(("frontend", "virtual_keyboard")), "hide_mouse": read_config(("frontend", "hide_mouse")), "download_links": read_config(("frontend", "download_links")), "sparklines": read_config(("frontend", "sparklines")), })
def check_creds(user, password): """ Check the credentials :return: :bool: if the authentication succeed. """ if user == read_config(("backend", "login")) and check_password(password): return True
def check_version(self): """ Check if a new version of TinyCheck is available by quering the Github api and comparing the last tag inside the VERSION file. :return: dict containing the available versions. """ if read_config(("frontend", "update")): try: res = requests.get(self.project_url) res = json.loads(res.content.decode("utf8")) with open(os.path.join(self.app_path, "VERSION")) as f: cv = f.read() if cv != res[0]["name"]: return {"status": True, "message": "A new version is available", "current_version": cv, "next_version": res[0]["name"]} else: return {"status": True, "message": "This is the latest version", "current_version": cv} except: return {"status": False, "message": "Something went wrong (no API access nor version file)"} else: return {"status": False, "message": "You don't have rights to do this operation."}
def get_config(): """ Get configuration keys relative to the GUI """ return jsonify({ "virtual_keyboard": read_config(("frontend", "virtual_keyboard")), "hide_mouse": read_config(("frontend", "hide_mouse")), "download_links": read_config(("frontend", "download_links")), "sparklines": read_config(("frontend", "sparklines")), "quit_option": read_config(("frontend", "quit_option")), "shutdown_option": read_config(("frontend", "shutdown_option")), "reboot_option": read_config(("frontend", "reboot_option")), "iface_out": read_config(("network", "out")), "user_lang": read_config(("frontend", "user_lang")), "choose_net": read_config(("frontend", "choose_net")) })
def watch_whitelists(): """ Retrieve whitelist elements from the remote URLs defined in config/watchers. For each (new ?) element, add it to the DB. """ urls = read_config(("watchers", "whitelists")) watchers = [{"url": url, "status": False} for url in urls] while True: for w in watchers: if w["status"] == False: whitelist = WhiteList() elements = [] try: res = requests.get(w["url"], verify=False) if res.status_code == 200: elements = json.loads(res.content)["elements"] else: w["status"] = False except: w["status"] = False for elem in elements: try: whitelist.add(elem["type"], elem["element"], "watcher") w["status"] = True except: continue if False in [w["status"] for w in watchers]: time.sleep(60) else: break
def api_shutdown(): """ Reboot the device """ if read_config(("frontend", "shutdown_option")): sp.Popen("shutdown -h now", shell=True) return jsonify({"message": "Let's shutdown", "status": True}) else: return jsonify({"message": "Option disabled", "status": False})
def check_password(password): """ Password hashes comparison (submitted and the config one) :return: True if there is a match between the two hases """ if read_config( ("backend", "password")) == hashlib.sha256(password.encode()).hexdigest(): return True
def api_quit(): """ Quit the interface (Chromium browser) """ if read_config(("frontend", "quit_option")): sp.Popen('pkill -INT -f "chromium-browser"', shell=True) return jsonify({"message": "Let's quit", "status": True}) else: return jsonify({"message": "Option disabled", "status": False})
def start_ap(self): """ The start_ap method generates an Access Point by using HostApd and provide to the GUI the associated ssid, password and qrcode. :return: dict containing the status of the AP """ # Re-ask to enable interface, sometimes it just go away. if not self.enable_interface(self.iface_out): return {"status": False, "message": "Interface not present."} # Generate the hostapd configuration if read_config(("network", "tokenized_ssids")): token = "".join( [random.choice(self.random_choice_alphabet) for i in range(4)]) self.AP_SSID = random.choice(read_config( ("network", "ssids"))) + "-" + token else: self.AP_SSID = random.choice(read_config(("network", "ssids"))) self.AP_PASS = "".join( [random.choice(self.random_choice_alphabet) for i in range(8)]) # Launch hostapd if self.write_hostapd_config(): if self.lauch_hostapd() and self.reset_dnsmasq_leases(): return { "status": True, "message": "AP started", "ssid": self.AP_SSID, "password": self.AP_PASS, "qrcode": self.generate_qr_code() } else: return {"status": False, "message": "Error while creating AP."} else: return { "status": False, "message": "Error while writing hostapd configuration file." }
def check_internet(self): """ Check the internet link just with a small http request to an URL present in the configuration :return: bool - if the request succeed or not. """ try: url = read_config(("network", "internet_check")) requests.get(url, timeout=10) return True except: return False
def watch_iocs(): """ Retrieve IOCs from the remote URLs defined in config/watchers. For each IOC, add it to the DB. """ # Retrieve the URLs from the configuration urls = read_config(("watchers", "iocs")) watchers = [{"url": url, "status": False} for url in urls] while True: for w in watchers: if w["status"] == False: iocs = IOCs() iocs_list = [] to_delete = [] try: res = requests.get(w["url"], verify=False) if res.status_code == 200: content = json.loads(res.content) iocs_list = content[ "iocs"] if "iocs" in content else [] to_delete = content[ "to_delete"] if "to_delete" in content else [] else: w["status"] = False except: w["status"] = False for ioc in iocs_list: try: iocs.add(ioc["type"], ioc["tag"], ioc["tlp"], ioc["value"], "watcher") w["status"] = True except: continue for ioc in to_delete: try: iocs.delete_by_value(ioc["value"]) w["status"] = True except: continue # If at least one URL haven't be parsed, let's retry in 1min. if False in [w["status"] for w in watchers]: time.sleep(60) else: break
def get_current_version(self): """ Get the current version of the TinyCheck instance :return: dict containing the current version or error. """ if read_config(("frontend", "update")): try: with open(os.path.join(self.app_path, "VERSION")) as f: return {"status": True, "current_version": f.read()} except: return {"status": False, "message": "Something went wrong - no version file ?"} else: return {"status": False, "message": "You don't have rights to do this operation."}
async def pool(request, config, event_loop): """Create a db conneciton from a given config.""" pool = await init_db(config=read_config(config.good_filepath)) def tear_down(): async def cleanup(): # Event loop was not available here, so this little hack # https://github.com/pytest-dev/pytest-asyncio/issues/59 async with pool.acquire() as conn: await delete_tables(conn) await pool.close() event_loop.run_until_complete(cleanup()) request.addfinalizer(tear_down) return pool
def cli_with_drop_table(loop, aiohttp_client, config): """.""" app = web.Application() app['config'] = read_config(config.good_filepath) handler = Handler() app.add_routes([ web.get('/forecast', handler.get_all_records), web.post('/forecast', handler.post_record), web.get('/forecast/{date}', handler.get_record), web.delete('/forecast/{date}', handler.delete_record), web.put('/forecast/{date}', handler.put_record) ]) app.on_startup.append(init_db) app.on_startup.append(load_forecasts_to_db) app.on_cleanup.append(delete_table) app.on_cleanup.append(close_db) return loop.run_until_complete(aiohttp_client(app))
def update_instance(self): """ Update the instance by executing the update script. :return: dict containing the update status. """ if read_config(("frontend", "update")): try: os.chdir(self.app_path) sp.Popen(["bash", os.path.join(self.app_path, "update.sh")]) return {"status": True, "message": "Update successfully launched"} except: return {"status": False, "message": "Issue during the update"} else: return {"status": False, "message": "You don't have rights to do this operation."}
def start_capture(self): """ Start a tshark capture on the created AP interface and save it in a temporary directory under /tmp/. :return: dict containing capture token and status. """ # Kill potential tshark zombies instances, if any. terminate_process("tshark") # Few context variable assignment self.capture_token = "".join( [random.choice(self.random_choice_alphabet) for i in range(8)]) self.capture_dir = "/tmp/{}/".format(self.capture_token) self.assets_dir = "/tmp/{}/assets/".format(self.capture_token) self.pcap = self.capture_dir + "capture.pcap" self.iface = read_config(("network", "in")) # For packets monitoring self.list_pkts = [] self.last_pkts = 0 # Make the capture and the assets directory mkdir(self.capture_dir) mkdir(self.assets_dir) try: sp.Popen([ "tshark", "-i", self.iface, "-w", self.pcap, "-f", "tcp or udp" ]) return { "status": True, "message": "Capture started", "capture_token": self.capture_token } except: return { "status": False, "message": "Unexpected error: %s" % sys.exc_info()[0] }
return render_template("index.html") @app.route("/<p>/<path:path>", methods=["GET"]) def get_file(p, path): """ Return the frontend assets (css, js files, fonts etc.) """ rp = "../../app/frontend/dist/{}".format(p) return send_from_directory(rp, path) if p in ["css", "fonts", "js", "img"] else redirect("/") @app.errorhandler(404) def page_not_found(e): return redirect("/") # API Blueprints. app.register_blueprint(network_bp, url_prefix='/api/network') app.register_blueprint(capture_bp, url_prefix='/api/capture') app.register_blueprint(device_bp, url_prefix='/api/device') app.register_blueprint(analysis_bp, url_prefix='/api/analysis') app.register_blueprint(save_bp, url_prefix='/api/save') app.register_blueprint(misc_bp, url_prefix='/api/misc') if __name__ == '__main__': if read_config(("frontend", "remote_access")): app.run(host="0.0.0.0", port=80) else: app.run(port=80)
@app.route("/<p>/<path:path>", methods=["GET"]) @auth.login_required def get_file(p, path): """ Return the backend assets (css, js files, fonts etc.) """ rp = "../../app/backend/dist/{}".format(p) return send_from_directory(rp, path) if p in ["css", "fonts", "js", "img" ] else redirect("/") @app.errorhandler(404) def page_not_found(e): return redirect("/") # API Blueprints. app.register_blueprint(ioc_bp, url_prefix='/api/ioc') app.register_blueprint(whitelist_bp, url_prefix='/api/whitelist') app.register_blueprint(config_bp, url_prefix='/api/config') if __name__ == '__main__': ssl_cert = "{}/{}".format(path[0], 'cert.pem') ssl_key = "{}/{}".format(path[0], 'key.pem') if read_config(("backend", "remote_access")): app.run(host="0.0.0.0", port=443, ssl_context=(ssl_cert, ssl_key)) else: app.run(port=443, ssl_context=(ssl_cert, ssl_key))