예제 #1
0
    def write(self, data):
        """Write data to socket"""

        if not self.refresh_stun():
            return False

        try:
            if self.connected:
                payload = encrypt(data, self.key)
                msg = ip_message.build(
                    dict(header=dict(length=len(data),
                                     unknown0=0x04,
                                     flags=0x09,
                                     command=0x00,
                                     encrypt=1),
                         payload=payload))
                if cfg.LOGGING_DUMP_PACKETS:
                    logger.debug("PC -> IP {}".format(binascii.hexlify(msg)))
                self.socket.send(msg)
                return True
            else:
                return False
        except Exception as e:
            logger.exception("Error writing to socket.")
            raise ConnectionError()
예제 #2
0
    async def handle_panel_message(self, data):
        """
        Handle message from panel, which must be sent to the client
        """
        if isinstance(data, Awaitable):
            try:
                data = await data
            except asyncio.TimeoutError:
                return False

        if data is not None:
            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("PNL -> IPI (payload) {}".format(
                    binascii.hexlify(data)))

            payload_len = len(data)

            payload = encrypt(data, self.connection_key)
            flags = 0x73

            m = ip_message.build(
                dict(header=dict(length=payload_len,
                                 unknown0=2,
                                 flags=flags,
                                 command=0),
                     payload=payload))

            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("IPI -> APP (raw) {}".format(binascii.hexlify(m)))

            self.client_writer.write(m)

        return False  # Block further message processing
예제 #3
0
    def send_message(self, message):
        if cfg.LOGGING_DUMP_PACKETS:
            logger.debug("PAI -> IPC {}".format(binascii.hexlify(message)))

        payload = encrypt(message, self.key)
        msg = ip_message.build(
            dict(header=dict(length=len(message), unknown0=0x04, flags=0x09, command=0x00, encrypt=1), payload=payload))
        if cfg.LOGGING_DUMP_PACKETS:
            logger.debug("IPC -> Mod {}".format(binascii.hexlify(msg)))
        self.transport.write(msg)
예제 #4
0
파일: ip_interface.py 프로젝트: skeary/pai
    def process_client_message(self, client, data):
        message = ip_message.parse(data)
        message_payload = data[16:]
        self.logger.debug("AP -> IP: {}".format(binascii.hexlify(data)))
        if len(message_payload) >= 16  and message.header.flags & 0x01 != 0 and len(message_payload) % 16 == 0:
            message_payload = decrypt(message_payload, self.key)[:37]

        force_plain_text = False
        response_code = 0x01
        if message.header.command == 0xf0:
            password = message_payload[:4]

            if password != cfg.IP_INTERFACE_PASSWORD:
                self.logger.warn("Authentication Error")
                return

            # Generate a new key
            self.key = binascii.hexlify(os.urandom(8)).upper()

            payload = ip_payload_connect_response.build(dict(key=self.key, major=0x0, minor=32, ip_major=4, ip_minor=48))
            force_plain_text = True

        elif message.header.command == 0xf2:
            payload = b'\x00'
        elif message.header.command == 0xf3:
            payload = binascii.unhexlify('0100000000000000000000000000000000')
        elif message.header.command == 0xf8:
            payload = b'\x01'
        elif message.header.command == 0x00:
            response_code = 0x02
            try:
                payload = self.alarm.send_wait_simple(message=message_payload[:37])
            except Exception:
                self.logger.exception("Send to panel")
                return
        else:
            self.logger.warn("UNKNOWN: {}".format(binascii.hexlify(data)))
            return

        if payload is not None:
            flags = 0x38
            payload_length = len(payload)

            if message.header.flags & 0x01 != 0 and not force_plain_text:
                payload = encrypt(payload, self.key)

                if message.header.command == 0x00:
                    flags = 0x73
                else:
                    flags = 0x39

            m = ip_message.build(dict(header=dict(length=payload_length, unknown0=response_code, flags=flags, command=message.header.command), payload=payload))
            self.logger.debug("IP -> AP: {}".format(binascii.hexlify(m)))
            client.send(m)
예제 #5
0
파일: ip_interface.py 프로젝트: skeary/pai
    def connection_watch(self):
        while self.client_socket is None:
            tstart = time.time()
            payload = self.alarm.send_wait()
            tend = time.time()
            payload_len = len(payload)
            if payload is not None:
                payload = encrypt(payload, self.key)
                flags = 0x73

                m = ip_message.build(dict(header=dict(length=payload_len, unknown0=2, flags=flags, command=0), payload=payload))
                self.logger.debug("IP -> AP: {}".format(binascii.hexlify(m)))
                self.client_socket.send(m)

            if tend - tstart < 0.1:
                time.sleep(0.1)
예제 #6
0
def test_encrypt():
    assert enc_text == encrypt(dec_text, password)
예제 #7
0
    async def handle(self):
        next_connection_key = self.connection_key
        status = 'connecting'

        while True:
            try:
                data = await self.client_reader.read(1000)
            except:
                logger.info("Client disconnected")
                break

            if not data:
                continue

            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("APP -> IPI (raw) {}".format(
                    binascii.hexlify(data)))

            message = ip_message.parse(data)
            in_payload = message.payload

            if len(in_payload
                   ) >= 16 and message.header.flags & 0x01 != 0 and len(
                       in_payload) % 16 == 0:
                in_payload = decrypt(
                    in_payload, self.connection_key)[:message.header.length]

            in_payload = in_payload[:message.header.length]

            assert len(in_payload) == message.header.length, "Message payload length does not match with length in " \
                                                             "header "
            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("APP -> IPI (payload) {}".format(
                    binascii.hexlify(in_payload)))

            force_plain_text = False
            response_code = 0x01
            out_payload = None
            if message.header.command == 0xf0:
                password = in_payload

                if password != self.interface_password:
                    logger.warn("Authentication Error")
                    break
                else:
                    logger.info("Authentication Success")

                # Generate a new key
                next_connection_key = binascii.hexlify(os.urandom(8)).upper()

                out_payload = ip_payload_connect_response.build(
                    dict(key=next_connection_key,
                         major=0,
                         minor=32,
                         ip_major=1,
                         ip_minor=50,
                         unknown=113,
                         unknown2=6,
                         unknown3=0x15,
                         unknown4=44))

                flags = 0x39
            elif message.header.command == 0xf2:
                out_payload = b'\x00'
                flags = 0x39
            elif message.header.command == 0xf3:
                out_payload = binascii.unhexlify(
                    '0100000000000000000000000000000000')
                flags = 0x3b
            elif message.header.command == 0xf4:
                out_payload = b'\x01' if status == 'closing_connection' else b'\x00'
                flags = 0x39
            elif message.header.command == 0xf8:
                out_payload = b'\x01'
                flags = 0x39
            elif message.header.command == 0x00:
                response_code = 0x02
                flags = 0x73
                if in_payload[0] == 0x70 and in_payload[
                        2] == 0x05:  # Close connection
                    out_payload = self.alarm.panel.get_message(
                        'CloseConnection').build({})
                    status = 'closing_connection'
                else:
                    try:
                        self.alarm.connection.write(in_payload)
                    except Exception:
                        logger.exception("Send to panel")
                        break

                if in_payload[0] == 0x00:  # Just a status update
                    status = 'connected'

            else:
                logger.warn("UNKNOWN: raw: {}, payload: {}".format(
                    binascii.hexlify(data), binascii.hexlify(in_payload)))
                continue

            if out_payload is not None:
                payload_length = len(out_payload)

                if message.header.flags & 0x08 != 0:
                    out_payload = out_payload.ljust(
                        (payload_length // 16) * 16, bytes([0xee]))

                if cfg.LOGGING_DUMP_PACKETS:
                    logger.debug("IPI -> IPI (payload) {}".format(
                        binascii.hexlify(out_payload)))

                if message.header.flags & 0x01 != 0 and not force_plain_text:
                    out_payload = encrypt(out_payload, self.connection_key)

                m = ip_message.build(
                    dict(header=dict(length=payload_length,
                                     unknown0=response_code,
                                     flags=flags,
                                     command=message.header.command),
                         payload=out_payload))

                if cfg.LOGGING_DUMP_PACKETS:
                    logger.debug("IPI -> APP (raw) {}".format(
                        binascii.hexlify(m)))

                self.client_writer.write(m)
                await self.client_writer.drain()

                if self.connection_key != next_connection_key:
                    self.connection_key = next_connection_key

            if status == 'closing_connection':
                break
예제 #8
0
    def connect_to_panel(self):
        try:
            logger.debug("Authenticating with IP Module")

            self.key = self.password  # first request is with initial password, next with generated by panel key
            payload = encrypt(self.key, self.key)

            msg = ip_message.build(dict(header=dict(length=len(self.key), unknown0=0x03, flags=0x09, command=0xf0, unknown1=0, encrypt=1), payload=payload))
            #if cfg.LOGGING_DUMP_PACKETS:
            #    logger.debug("PC -> IP {}{}".format(binascii.hexlify(msg[:16]), 'xx' * 16))

            self.socket.send(msg)
            data = self.socket.recv(1024)
            #if cfg.LOGGING_DUMP_PACKETS:
            #    logger.debug("IP -> PC {}".format(binascii.hexlify(data)))

            message, message_payload = self.get_message_payload(data)

            response = ip_payload_connect_response.parse(message_payload)

            if response.login_status != 'success':
                logger.error("Error connecting to IP Module. Wrong IP Module password?")
                return False

            logger.info("Authentication Success. Panel version {:02x}, firmware: {}.{}".format(response.hardware_version,
                        response.ip_firmware_major,
                        response.ip_firmware_minor))

            self.key = response.key

            # F2
            logging.debug("Sending F2")
            msg = ip_message.build(dict(header=dict(length=0, unknown0=0x03, flags=0x09, command=0xf2, unknown1=0, encrypt=1), payload=encrypt(b'', self.key)))
            #if cfg.LOGGING_DUMP_PACKETS:
            #    logger.debug("PC -> IP {}".format(binascii.hexlify(msg)))

            self.socket.send(msg)
            data = self.socket.recv(1024)
            #if cfg.LOGGING_DUMP_PACKETS:
            #    logger.debug("IP -> PC {}".format(binascii.hexlify(data)))

            message, message_payload = self.get_message_payload(data)
            logger.debug("F2 answer: {}".format(binascii.hexlify(message_payload)))

            # F3
            logging.debug("Sending F3")
            msg = ip_message.build(dict(header=dict(length=0, unknown0=0x03, flags=0x09, command=0xf3, unknown1=0, encrypt=1), payload=encrypt(b'', self.key)))
            #if cfg.LOGGING_DUMP_PACKETS:
            #    logger.debug("PC -> IP {}".format(binascii.hexlify(msg)))

            self.socket.send(msg)
            data = self.socket.recv(1024)
            #if cfg.LOGGING_DUMP_PACKETS:
            #    logger.debug("IP -> PC {}".format(binascii.hexlify(data)))

            message, message_payload = self.get_message_payload(data)

            #logger.debug("F3 answer: {}".format(binascii.hexlify(message_payload)))

            # F8
            logger.debug("Sending F8")
            payload = binascii.unhexlify('0a500080000000000000000000000000000000000000000000000000000000000000000000d0')
            payload_len = len(payload)
            payload = encrypt(payload, self.key)
            msg = ip_message.build(dict(header=dict(length=payload_len, unknown0=0x03, flags=0x09, command=0xf8, unknown1=0, encrypt=1), payload=payload))

            #if cfg.LOGGING_DUMP_PACKETS:
            #    logger.debug("PC -> IP {}".format(binascii.hexlify(msg)))

            self.socket.send(msg)
            data = self.socket.recv(1024)
            #if cfg.LOGGING_DUMP_PACKETS:
            #    logger.debug("IP -> PC {}".format(binascii.hexlify(data)))

            message, message_payload = self.get_message_payload(data)
            #logger.debug("F8 answer: {}".format(binascii.hexlify(message_payload)))


            logger.info("Session Established with IP Module")

            self.connected = True
        except Exception:
            self.connected = False
            logger.exception("Unable to establish session with IP Module")

        return self.connected
예제 #9
0
    def connect_to_panel(self):
        logger.debug("Connecting to IP Panel")

        try:
            logger.debug("IP Connection established")

            self.key = self.password  # first request is with initial password, next with generated by panel key
            payload = encrypt(self.key, self.key)

            msg = ip_message.build(
                dict(header=dict(length=len(self.key),
                                 unknown0=0x03,
                                 flags=0x09,
                                 command=0xf0,
                                 unknown1=0,
                                 encrypt=1),
                     payload=payload))
            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("PC -> IP {}".format(binascii.hexlify(msg)))

            self.socket.send(msg)
            data = self.socket.recv(1024)
            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("IP -> PC {}".format(binascii.hexlify(data)))

            message, message_payload = self.get_message_payload(data)

            response = ip_payload_connect_response.parse(message_payload)

            if response.login_status != 'success':
                logger.error("Error connecting to IP Module: {}".format(
                    response.login_status))
                return False

            logger.info(
                "Connected to IP Module. Version {:02x}, Firmware: {}.{}, Serial: {}"
                .format(
                    response.hardware_version, response.ip_firmware_major,
                    response.ip_firmware_minor,
                    binascii.hexlify(
                        response.ip_module_serial).decode('utf-8')))

            self.key = response.key

            # F2
            msg = ip_message.build(
                dict(header=dict(length=0,
                                 unknown0=0x03,
                                 flags=0x09,
                                 command=0xf2,
                                 unknown1=0,
                                 encrypt=1),
                     payload=encrypt(b'', self.key)))
            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("PC -> IP {}".format(binascii.hexlify(msg)))

            self.socket.send(msg)
            data = self.socket.recv(1024)
            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("IP -> PC {}".format(binascii.hexlify(data)))

            message, message_payload = self.get_message_payload(data)
            logger.debug("F2 answer: {}".format(
                binascii.hexlify(message_payload)))

            # F3
            msg = ip_message.build(
                dict(header=dict(length=0,
                                 unknown0=0x03,
                                 flags=0x09,
                                 command=0xf3,
                                 unknown1=0,
                                 encrypt=1),
                     payload=encrypt(b'', self.key)))
            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("PC -> IP {}".format(binascii.hexlify(msg)))

            self.socket.send(msg)
            data = self.socket.recv(1024)
            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("IP -> PC {}".format(binascii.hexlify(data)))

            message, message_payload = self.get_message_payload(data)

            logger.debug("F3 answer: {}".format(
                binascii.hexlify(message_payload)))

            # F8
            payload = binascii.unhexlify(
                '0a500080000000000000000000000000000000000000000000000000000000000000000000d0'
            )
            payload_len = len(payload)
            payload = encrypt(payload, self.key)
            msg = ip_message.build(
                dict(header=dict(length=payload_len,
                                 unknown0=0x03,
                                 flags=0x09,
                                 command=0xf8,
                                 unknown1=0,
                                 encrypt=1),
                     payload=payload))

            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("PC -> IP {}".format(binascii.hexlify(msg)))

            self.socket.send(msg)
            data = self.socket.recv(1024)
            if cfg.LOGGING_DUMP_PACKETS:
                logger.debug("IP -> PC {}".format(binascii.hexlify(data)))

            message, message_payload = self.get_message_payload(data)
            logger.debug("F8 answer: {}".format(
                binascii.hexlify(message_payload)))

            logger.info("Connection fully established")

            self.connected = True
        except Exception:
            self.connected = False
            logger.exception("Unable to connect to IP Module")

        return self.connected
예제 #10
0
    async def connect_to_module(self):
        try:
            logger.debug("Authenticating with IP Module")

            self.key = self.password  # first request is with initial password, next with generated by panel key

            self.connection.key = self.password
            payload = encrypt(self.password, self.key)

            msg = ip_message.build(
                dict(header=dict(length=len(self.key), unknown0=0x03, flags=0x09, command=0xf0, unknown1=0, encrypt=1),
                     payload=payload))
            self.connection.send_raw(msg)
            message_payload = await self.read()

            response = ip_payload_connect_response.parse(message_payload)

            if response.login_status != 'success':
                logger.error("Error connecting to IP Module. Wrong IP Module password?")
                return False

            logger.info("Authentication Success. Panel version {:02x}, firmware: {}.{}, serial: {}".format(
                response.hardware_version,
                response.ip_firmware_major,
                response.ip_firmware_minor,
                binascii.hexlify(response.ip_module_serial).decode('utf-8')))

            self.key = response.key
            self.connection.key = response.key

            # F2
            logger.debug("Sending F2")
            msg = ip_message.build(
                dict(header=dict(length=0, unknown0=0x03, flags=0x09, command=0xf2, unknown1=0, encrypt=1),
                     payload=encrypt(b'', self.key)))
            self.connection.send_raw(msg)
            message_payload = await self.read()
            logger.debug("F2 answer: {}".format(binascii.hexlify(message_payload)))

            # # F4
            # logger.debug("Sending F4")
            # msg = binascii.unhexlify('aa00000309f400000001eeeeeeee0000')
            # self.connection.send_raw(msg)
            # message_payload = await self.read()
            #
            # logger.debug("F4 answer: {}".format(binascii.hexlify(message_payload)))

            # F3
            logger.debug("Sending F3")
            msg = ip_message.build(
                dict(header=dict(length=0, unknown0=0x03, flags=0x09, command=0xf3, unknown1=0, encrypt=1),
                     payload=encrypt(b'', self.key)))
            self.connection.send_raw(msg)
            message_payload = await self.read()

            #logger.debug("F3 answer: {}".format(binascii.hexlify(message_payload)))

            # F8
            logger.debug("Sending F8")
            payload = binascii.unhexlify('0a500080000000000000000000000000000000000000000000000000000000000000000000d0')
            payload_len = len(payload)
            payload = encrypt(payload, self.key)
            msg = ip_message.build(
                dict(header=dict(length=payload_len, unknown0=0x03, flags=0x09, command=0xf8, unknown1=0, encrypt=1),
                     payload=payload))
            self.connection.send_raw(msg)
            message_payload = await self.read()
            logger.debug("F8 answer: {}".format(binascii.hexlify(message_payload)))

            logger.info("Session Established with IP Module")

            self.connected = True
        except asyncio.TimeoutError:
            self.connected = False
            logger.error("Unable to establish session with IP Module. Timeout. Only one connection at a time is allowed.")
        except Exception:
            self.connected = False
            logger.exception("Unable to establish session with IP Module")

        return self.connected
예제 #11
0
 def _encode(self, obj, context, path):
     try:
         return encrypt(obj, context._.password)
     except AttributeError:
         raise