def handle_message(self, endpoint, payload): args = struct.unpack("<16s10sfHH", payload[:34]) uuid_bytes, bsn, master_ts = args[:3] l_master_pkey, l_signuture = args[3:] self.serial = sn = bsn.decode("ascii") self.uuid = uuid = UUID(bytes=uuid_bytes) f = BytesIO(payload[34:]) masterkey_doc = f.read(l_master_pkey) signuture = f.read(l_signuture) if not validate_identify(uuid, signuture, serial=sn, masterkey_doc=masterkey_doc): print("Validate identify failed (uuid=%s)", uuid) return master_pkey = KeyObject.load_keyobj(masterkey_doc) stbuf = f.read(64) st_ts, st_id, st_prog, st_head, st_err = \ struct.unpack("dif16s32s", stbuf) head_module = st_head.decode("ascii", "ignore").strip("\x00") error_label = st_err.decode("ascii", "ignore").strip("\x00") self.device = Device(uuid, sn, master_pkey, 1) self.device.update_status(st_id=st_id, st_ts=st_ts, st_prog=st_prog, head_module=head_module, error_label=error_label)
def __init__(self, port, client_key=None, baudrate=115200): # Select does not work with windows.. try: if is_windows(): self.s = Serial(port=port, baudrate=115200, timeout=0.1) else: self.s = Serial(port=port, baudrate=115200, timeout=0) except SerialException as e: raise UsbTaskException("DEVICE_ERROR") from e self.s.write(b"\x00" * 16) if is_windows(): try: self.s.readall() # Normally returns with empty string except SerialTimeoutException: logger.error("Serial timeout") else: while True: rl = select((self.s, ), (), (), 0.1)[0] if rl: self.s.readall() else: break if client_key: self.keyobj = client_key else: self.keyobj = KeyObject.get_or_create_keyobj() self._discover()
def on_text_message(self, message): try: payload = json.loads(message) uuid = UUID(hex=payload["uuid"]) client_key = KeyObject.load_keyobj(payload["key"]) password = payload.get("password") self.touch_device(client_key, uuid, password) except Exception: logger.exception("Touch error") self.close()
def get_or_create_default_key(path=None): from fluxclient.encryptor import KeyObject if path is None: path = os.path.expanduser("~/.fluxclient_key.pem") if os.path.exists(path): try: with open(path, "rb") as f: buf = f.read() return KeyObject.load_keyobj(buf) except Exception: raise os.unlink(path) key = KeyObject.new_keyobj(1024) with open(path, "wb") as f: f.write(key.private_key_pem) return key
def _handle_discover(self, endpoint, payload): args = struct.unpack("<16s10sfHH", payload[:34]) uuid_bytes, bsn, master_ts = args[:3] l_master_pkey, l_signuture = args[3:] sn = bsn.decode("ascii") uuid = UUID(bytes=uuid_bytes) if not self.server.source_filter(uuid, endpoint): return f = BytesIO(payload[34:]) masterkey_doc = f.read(l_master_pkey) signuture = f.read(l_signuture) if not validate_identify(uuid, signuture, serial=sn, masterkey_doc=masterkey_doc): logger.error("Validate identify failed (uuid=%s)", uuid) return master_pkey = KeyObject.load_keyobj(masterkey_doc) uuid = UUID(bytes=uuid_bytes) if self._need_touch(uuid, master_ts): self.server.add_master_key(uuid, sn, master_pkey, 1) payload = struct.pack("<4sBB16s", b"FLUX", 1, 2, uuid.bytes) try: self.sock.sendto(payload, endpoint) except Exception: logger.exception("Error while poke %s", endpoint) else: try: stbuf = f.read(64) st_ts, st_id, st_prog, st_head, st_err = \ struct.unpack("dif16s32s", stbuf) head_module = st_head.decode("ascii", "ignore").strip("\x00") error_label = st_err.decode("ascii", "ignore").strip("\x00") device = self.server.devices[uuid] device.update_status(st_id=st_id, st_ts=st_ts, st_prog=st_prog, head_module=head_module, error_label=error_label) device.discover_endpoint = endpoint device.ipaddr = endpoint[0] return uuid except Exception: basic_info = self.server.devices[uuid] if basic_info.version > StrictVersion("0.13a"): logger.exception("Unpack status failed")
def on_text_message(self, message): if self.client_key: self.on_command(message) else: try: self.client_key = KeyObject.load_keyobj(message) except ValueError: self.send_fatal("BAD_PARAMS") except Exception: logger.error("RSA Key load error: %s", message) self.send_fatal("BAD_PARAMS") raise self.try_connect()
def on_text_message(self, message): if self.client_key: self.on_command(message) else: # self.client_key = True try: self.client_key = KeyObject.load_keyobj(message) except ValueError: self.send_fatal("BAD_PARAMS") except Exception: logger.error("RSA Key load error: %s", message) self.send_fatal("BAD_PARAMS") raise self.try_connect()
def _handle_discover(self, endpoint, payload): args = struct.unpack("<16s10sfHH", payload[:34]) uuid_bytes, bsn, master_ts = args[:3] l_master_pkey, l_signuture = args[3:] sn = bsn.decode("ascii") uuid = UUID(bytes=uuid_bytes) if not self.server.source_filter(uuid, endpoint): return f = BytesIO(payload[34:]) masterkey_doc = f.read(l_master_pkey) signuture = f.read(l_signuture) if not validate_identify( uuid, signuture, serial=sn, masterkey_doc=masterkey_doc): logger.error("Validate identify failed (uuid=%s)", uuid) return master_pkey = KeyObject.load_keyobj(masterkey_doc) uuid = UUID(bytes=uuid_bytes) if self._need_touch(uuid, master_ts): self.server.add_master_key(uuid, sn, master_pkey, 1) payload = struct.pack("<4sBB16s", b"FLUX", 1, 2, uuid.bytes) try: self.sock.sendto(payload, endpoint) except Exception: logger.exception("Error while poke %s", endpoint) else: try: stbuf = f.read(64) st_ts, st_id, st_prog, st_head, st_err = \ struct.unpack("dif16s32s", stbuf) head_module = st_head.decode("ascii", "ignore").strip("\x00") error_label = st_err.decode("ascii", "ignore").strip("\x00") device = self.server.devices[uuid] device.update_status(st_id=st_id, st_ts=st_ts, st_prog=st_prog, head_module=head_module, error_label=error_label) device.discover_endpoint = endpoint device.ipaddr = endpoint[0] return uuid except Exception: basic_info = self.server.devices[uuid] if basic_info.version > StrictVersion("0.13a"): logger.exception("Unpack status failed")
def _handle_touch(self, endpoint, payload): f = BytesIO(payload) buuid, master_ts, l1, l2 = struct.unpack("<16sfHH", f.read(24)) uuid = UUID(bytes=buuid) if not self.server.source_filter(uuid, endpoint): # Ingore this uuid return device = self.server.devices[uuid] slavekey_str = f.read(l1) slavekey_signuture = f.read(l2) temp_pkey = KeyObject.load_keyobj(slavekey_str) bmeta = f.read(struct.unpack("<H", f.read(2))[0]) smeta = bmeta.decode("utf8") rawdata = {} for item in smeta.split("\x00"): if "=" in item: k, v = item.split("=", 1) rawdata[k] = v doc_signuture = f.read() master_key = self.server.get_master_key(uuid) if master_key.verify(payload[16:20] + slavekey_str, slavekey_signuture): if temp_pkey.verify(bmeta, doc_signuture): device.slave_timestamp = master_ts device.slave_key = temp_pkey device.has_password = rawdata.get("pwd") == "T" device.timestamp = float(rawdata.get("time", 0)) device.timedelta = device.timestamp - time() device.model_id = rawdata.get("model", "UNKNOW_MODEL") device.version = StrictVersion(rawdata["ver"]) device.name = rawdata.get("name", "NONAME") device.discover_endpoint = endpoint device.ipaddr = endpoint[0] return uuid else: logger.error("Slave key signuture error (V1)") else: logger.error("Master key signuture error (V1)")
def _discover(self): resp = self._make_request(CODE_DISCOVER, timeout=0.25) info = {} for pair in resp.split(b"\x00"): spair = pair.decode("utf8", "ignore").split("=", 1) if len(spair) == 1: logger.error("Can not parse device info: %s" % pair) info[spair[0]] = spair[1] self.uuid = UUID(hex=info["uuid"]) self.serial = info["serial"] self.model_id = info["model"] self.version = StrictVersion(info["ver"]) self.nickname = info["name"] self.endpoint = "UART:%s" % self.port rsakey = self._make_request(CODE_RSAKEY) self.device_rsakey = KeyObject.load_keyobj(rsakey)
def on_text_message(self, message): if self.client_key: if self.manager.authorized: if message.startswith("set_network2 "): try: self.cmd_set_network_old(message[13:]) except Exception: logger.exception("ERR") elif message.startswith("set_nickname "): try: self.cmd_set_nickname(message[13:]) except Exception: logger.exception("ERR") else: self.on_command(*split(message)) else: if message.startswith("password "): try: self.manager.authorize_with_password(message[9:]) self.on_connected() except (ManagerError, ManagerException) as e: self.send_fatal(" ".join(e.err_symbol)) else: self.send_text(STAGE_REQUIRE_AUTHORIZE) else: try: self.client_key = KeyObject.load_keyobj(message) except ValueError: self.send_fatal("BAD_PARAMS") return except Exception: logger.error("RSA Key load error: %s", message) self.send_fatal("BAD_PARAMS") raise try: self.try_connect() except (ManagerException, ManagerError) as e: self.send_fatal(" ".join(e.err_symbol)) except RuntimeError as e: self.send_fatal(e.args[0]) except Exception: logger.exception("Error while manager connecting") self.send_fatal("L_UNKNOWN_ERROR")
def _discover(self): resp = self._make_request(CODE_DISCOVER, timeout=0.25) info = {} for pair in resp.split(b"\x00"): spair = pair.decode("utf8", "ignore").split("=", 1) if len(spair) == 1: logger.error("Can not parse device info: %s" % pair) info[spair[0]] = spair[1] self.uuid = UUID(hex=info["uuid"]) self.serial = info["serial"] self.model_id = info["model"] self.timedelta = time() - float(info["time"]) self.remote_version = info["ver"] self.has_password = True if int(info["pwd"]) == 1 else False self.name = info["name"] self.remote_addrs = None rsakey = self._make_request(CODE_RSAKEY) self.device_rsakey = KeyObject.load_keyobj(rsakey)
def on_text_message(self, message): try: if message == "list": self.list_ports() elif message.startswith("key "): pem = message.split(" ", 1)[-1] self.client_key = KeyObject.load_keyobj(pem) self.send_json(status="ok") elif message.startswith("connect "): self.connect_usb(message.split(" ", 1)[-1]) elif message == "auth": self.auth() elif message.startswith("auth "): self.auth(message[5:]) elif message.startswith("set general "): self.config_general(message.split(" ", 2)[-1]) elif message == "scan_wifi": self.scan_wifi() elif message.startswith("set network "): self.config_network(message.split(" ", 2)[-1]) elif message.startswith("get network"): self.get_network() elif message.startswith("set password "): self.set_password(message[13:]) else: self.send_error("L_UNKNOWN_COMMAND") except ManagerException as e: self.send_error(e.err_symbol, info=str(e)) logger.exception("UART request error") if self.task: self.task.close() self.task = NoneTask() except ManagerError as e: self.send_error(e.args) except Exception: logger.exception("Unhandle Error") self.send_traceback("L_UNKNOWN_ERROR")
def on_text_message(self, message): if self.client_key: self.on_command(message) else: try: self.client_key = KeyObject.load_keyobj(message) except ValueError: self.send_fatal("KEYOBJ_BAD_PARAMS") return except Exception: logger.error("RSA Key load error: %s", message) self.send_fatal("RSA_BAD_PARAMS") raise try: self.try_connect() except RuntimeError as e: self.send_fatal(e.args[0]) except Exception: logger.exception("Connection failed") self.send_fatal("DISCONNECTED") raise
def on_text_message(self, message): try: if message == "list": self.list_ports() elif message.startswith("key "): pem = message.split(" ", 1)[-1] self.client_key = KeyObject.load_keyobj(pem) self.send_json(status="ok") elif message.startswith("connect "): self.connect_usb(message.split(" ", 1)[-1]) elif message == "auth": self.auth() elif message.startswith("auth "): self.auth(message[5:]) elif message.startswith("set general "): self.config_general(message.split(" ", 2)[-1]) elif message == "scan_wifi": self.scan_wifi() elif message.startswith("set network "): self.config_network(message.split(" ", 2)[-1]) elif message.startswith("get network"): self.get_network() elif message.startswith("set password "): self.set_password(message[13:]) else: self.send_error("UNKNOWN_COMMAND") except UsbTaskException as e: self.send_error(" ".join(e.args), info=str(e)) if self.task: self.task.close() self.task = None except UsbTaskError as e: self.send_error(" ".join(e.args)) except Exception: logger.exception("Unhandle Error") self.send_error("UNKNOWN_ERROR")
def _handle_touch(self, endpoint, payload): f = BytesIO(payload) buuid, l1, l2 = struct.unpack("<16sHH", f.read(20)) uuid = UUID(bytes=buuid) if not self.server.source_filter(uuid, endpoint): # Ingore this uuid return pubkey_der = f.read(l1) pubkey_signuture = f.read(l2) dev_pubkey = KeyObject.load_keyobj(pubkey_der) bmeta = f.read(struct.unpack("<H", f.read(2))[0]) smeta = bmeta.decode("utf8") rawdata = {} for item in smeta.split("\x00"): if "=" in item: k, v = item.split("=", 1) rawdata[k] = v sn = rawdata.get("serial", None) if sn and validate_identify( uuid, pubkey_signuture, serial=sn, masterkey_doc=pubkey_der): device = self.server.add_master_key(uuid, sn, dev_pubkey, 2) device.model_id = rawdata.get("model", "UNKNOW_MODEL") device.has_password = rawdata.get("pwd") == "T" device.version = StrictVersion(rawdata["ver"]) device.name = rawdata.get("name", "NONAME") device.discover_endpoint = endpoint device.ipaddr = endpoint[0] self.session_cache[uuid] = self.session_swap.pop(uuid, None) return uuid else: logger.error("Validate identify failed (uuid=%s, serial=%s)", uuid, sn)
def _handle_touch(self, endpoint, payload): f = BytesIO(payload) buuid, l1, l2 = struct.unpack("<16sHH", f.read(20)) uuid = UUID(bytes=buuid) if not self.server.source_filter(uuid, endpoint): # Ingore this uuid return pubkey_der = f.read(l1) pubkey_signuture = f.read(l2) dev_pubkey = KeyObject.load_keyobj(pubkey_der) bmeta = f.read(struct.unpack("<H", f.read(2))[0]) smeta = bmeta.decode("utf8") rawdata = {} for item in smeta.split("\x00"): if "=" in item: k, v = item.split("=", 1) rawdata[k] = v sn = rawdata.get("serial", None) if sn and uuid in self.session_swap and \ validate_identify(uuid, pubkey_signuture, serial=sn, masterkey_doc=pubkey_der): device = self.server.add_master_key(uuid, sn, dev_pubkey, 2) device.model_id = rawdata.get("model", "UNKNOW_MODEL") device.has_password = rawdata.get("pwd") == "T" device.version = StrictVersion(rawdata["ver"]) device.name = rawdata.get("name", "NONAME") device.discover_endpoint = endpoint device.ipaddr = endpoint[0] self.session_cache[uuid] = self.session_swap.pop(uuid) return uuid else: logger.error("Validate identify failed (uuid=%s, serial=%s)", uuid, sn)
def upload_key(self, params): logger.debug('upload_key:' + params) pem = params self.client_key = KeyObject.load_keyobj(pem) self.send_json(status="ok")
from configparser import RawConfigParser from uuid import UUID import tempfile import os from fluxclient.encryptor import KeyObject from fluxclient.upnp import discover_device CLIENTKEY = KeyObject.new_keyobj(1024) CLIENTKEY_FILE = tempfile.NamedTemporaryFile() CLIENTKEY_FILE.write(CLIENTKEY.private_key_pem) CLIENTKEY_FILE.flush() DEFAULT_UUID = None DEFAULT_PASSWORD = None DEFAULT_DEVICE = None if os.path.exists("conftest.ini"): parser = RawConfigParser() parser.read("conftest.ini") if "default_device" in parser.sections(): devices = dict(parser.items("default_device")) DEFAULT_UUID = devices.get("uuid", None) DEFAULT_PASSWORD = devices.get("password", None) if DEFAULT_UUID: DEFAULT_DEVICE = discover_device(UUID(hex=DEFAULT_UUID), timeout=5)
def _to_keyobj_or_none(raw_pem): try: if raw_pem: return KeyObject.load_keyobj(raw_pem) except (ValueError, TypeError): pass