Example #1
0
    def _read_packet(self):
        """
        Reads a packet from a socket
        """
        socket_in = self._connection
        # Read the size of the packet
        psize = bytearray(3)
        socket_in.recv_into(psize, 3)

        size = getSize(psize) + 1

        # Read the rest of the packet
        packet_payload = bytearray(size)
        socket_in.recv_into(packet_payload, size)

        # Combine the chunks
        psize.extend(packet_payload)
        packetType = getType(psize)

        if packetType == Flags.ERR:
            buf = ERR.loadFromPacket(psize)
            logger.error("error:", buf.errorCode, buf.sqlState, buf.errorMessage)
            self.close()
            exit(1)

        return psize
Example #2
0
    def init_upstream(self):
        conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        host = self.server.settings["server_host"]
        port = self.server.settings.getint("server_port")
        user = self.server.settings["server_user"]
        password = self.server.settings["server_password"]

        schema = ""
        conn.connect((host, port))
        self.upstream = conn

        challenge = Challenge.loadFromPacket(self.upstream.recv(10240))
        logger.debug("== Greeting ==")
        dump(challenge.toPacket())

        challenge1 = challenge.challenge1
        challenge2 = challenge.challenge2

        scramble_password = scramble_native_password(password,
                                                     challenge1 + challenge2)
        response = Response()
        response.sequenceId = 1
        response.capabilityFlags = 33531397
        response.characterSet = 33
        response.maxPacketSize = 16777216
        response.clientAttributes["_client_name"] = 'pymysql'
        response.clientAttributes["_pid"] = str(os.getpid())
        response.clientAttributes["_client_version"] = '5.7'
        response.clientAttributes["program_name"] = 'mysql'
        response.pluginName = 'mysql_native_password'
        response.username = user
        response.schema = schema
        response.authResponse = scramble_password
        response.removeCapabilityFlag(Flags.CLIENT_COMPRESS)
        response.removeCapabilityFlag(Flags.CLIENT_SSL)
        response.removeCapabilityFlag(Flags.CLIENT_LOCAL_FILES)

        logger.debug("== Auth ==")
        dump(response.toPacket())

        self.upstream.send(response.toPacket())

        _packet = self.upstream.recv(10240)

        logger.debug("== Result ==")
        dump(_packet)
        packetType = getType(_packet)

        if packetType == Flags.ERR:
            buf = ERR.loadFromPacket(_packet)
            logger.error("Upstream error:", buf.errorCode, buf.sqlState,
                         buf.errorMessage)
            self.upstream.close()
            self.finish()
            exit(1)
Example #3
0
    def handle(self):

        # 认证
        challenge1 = '12345678'
        challenge2 = '123456789012'
        challenge = self.create_challenge(challenge1, challenge2)
        self.send_packet(challenge.toPacket())

        packet = self.read_packet()
        response = Response()
        response = response.loadFromPacket(packet)

        username = response.username
        self.logger.info("login user:"******"proxy_password"]
        self.user_id = username

        # 验证密码
        native_password = scramble_native_password(password,
                                                   challenge1 + challenge2)

        if self.server.settings[
                "proxy_user"] != username or response.authResponse.encode(
                    "iso-8859-1") != native_password:
            err = ERR(9001, '28000', '[%s] Access denied.' % username)
            buff = err.toPacket()
            self.send_packet(buff)
            self.finish()
            return

        buff = file2packet("auth_result.cap")
        self.send_packet(buff)

        # 初始化后端服务器
        self.init_upstream()

        # 查询
        while True:

            packet = self.read_packet()
            if len(packet) < 4:
                continue
            packet_type = getType(packet)

            if packet_type == Flags.COM_QUIT:
                self.upstream.close()
                self.finish()

            elif packet_type == Flags.COM_QUERY:
                self.handle_query(packet)
            else:
                self.dispatch_packet(packet)
def read_packet(skt):
    while True:
        packet = read_server_packet(skt)
        sequenceId = getSequenceId(packet)
        print("read packet [%s]:" % (sequenceId, ))
        dump_my_packet(packet)
        packetType = getType(packet)

        if packetType == Flags.ERR:
            buf = ERR.loadFromPacket(packet)
            print("error:", buf.errorCode, buf.sqlState, buf.errorMessage)
            skt.close()
            exit(1)
            break

        if packetType == Flags.EOF or packetType == Flags.OK:
            break
Example #5
0
    def get_conn(self):
        conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        host = self._connection_settings["host"]
        port = self._connection_settings.getint("port")
        user = self._connection_settings["user"]
        password = self._connection_settings["password"]
        schema = ""
        conn.connect((host, port))
        self._connection = conn

        challenge = Challenge.loadFromPacket(self._read_packet())

        challenge1 = challenge.challenge1
        challenge2 = challenge.challenge2

        scramble_password = scramble_native_password(password, challenge1 + challenge2)
        response = Response()
        response.sequenceId = 1
        response.capabilityFlags = 33531397
        response.characterSet = 33
        response.maxPacketSize = 16777216
        response.clientAttributes["_client_name"] = 'pymysql'
        response.clientAttributes["_pid"] = str(os.getpid())
        response.clientAttributes["_client_version"] = '5.7'
        response.clientAttributes["program_name"] = 'mysql'
        response.pluginName = 'mysql_native_password'
        response.username = user
        response.schema = schema
        response.authResponse = scramble_password
        response.removeCapabilityFlag(Flags.CLIENT_COMPRESS)
        response.removeCapabilityFlag(Flags.CLIENT_SSL)
        response.removeCapabilityFlag(Flags.CLIENT_LOCAL_FILES)

        self._send_packet(response.toPacket())

        _packet = self._read_packet()
        packetType = getType(_packet)

        if packetType == Flags.ERR:
            buf = ERR.loadFromPacket(_packet)
            logger.error("error:", buf.errorCode, buf.sqlState, buf.errorMessage)
            self.close()
            exit(1)
def read_binlog(skt):
    while True:
        packet = read_server_packet(skt)
        sequenceId = getSequenceId(packet)
        packetType = getType(packet)

        # OK value
        # timestamp
        # event_type
        # server_id
        # log_pos
        # flags
        unpack = struct.unpack('<cIcIIIH', packet[6:26])

        # Header
        timestamp = unpack[1]
        event_type = byte2int(unpack[2])
        server_id = unpack[3]
        event_size = unpack[4]
        # position of the next event
        log_pos = unpack[5]
        flags = unpack[6]

        print('timestamp', 'event_type', 'server_id', 'event_size', 'log_pos')
        print(timestamp, event_type, server_id, event_size, log_pos)
        dump_my_packet(packet)

        if event_type == 16:
            ack = SemiAck("mysql-bin.000001", log_pos)
            ack.sequenceId = 0
            packet = ack.toPacket()
            send_socket(skt, packet)

        if packetType == Flags.ERR:
            buf = ERR.loadFromPacket(packet)
            print("error:", buf.errorCode, buf.sqlState, buf.errorMessage)
            skt.close()
            exit(1)
            break

        if packetType == Flags.EOF or packetType == Flags.OK:
            break
Example #7
0
    def fetchone(self):
        while True:

            self._register_slave()
            packet = self._read_packet()
            sequenceId = getSequenceId(packet)
            packetType = getType(packet)

            unpack = struct.unpack('<IcIIIH',
                                   packet[self.__binlog_header_fix_length:self.__binlog_header_fix_length + 19])
            # Header
            timestamp = unpack[0]
            event_type = byte2int(unpack[1])
            server_id = unpack[2]
            event_size = unpack[3]
            log_pos = unpack[4]
            flags = unpack[5]

            # 跳过HEARTBEAT_EVENT
            if event_type == HEARTBEAT_EVENT:
                continue

            # 跳过重启后的第一个 FORMAT_DESCRIPTION_EVENT
            if event_type == FORMAT_DESCRIPTION_EVENT and log_pos == 0:
                continue

            # Send SemiAck after xid event
            if self._connection_settings["semi_sync"]:
                if event_type in (XID_EVENT, QUERY_EVENT):
                    ack = SemiAck(self.__log_file, log_pos)
                    ack.sequenceId = 0
                    acp_packet = ack.toPacket()
                    self._send_packet(acp_packet)

            if packetType == Flags.ERR:
                buf = ERR.loadFromPacket(packet)
                logger.error("error:", buf.errorCode, buf.sqlState, buf.errorMessage)
                self.close()
                exit(1)

            return (timestamp, event_type, event_size, log_pos), packet[self.__binlog_header_fix_length:]
    def handle(self):

        # 认证
        challenge1 = '12345678'
        challenge2 = '123456789012'
        challenge = self.create_challenge(challenge1, challenge2)
        self.send_packet(challenge.toPacket())

        packet = self.read_packet()
        response = Response()
        response = response.loadFromPacket(packet)

        username = response.username
        self.logger.info("login user:"******"password"]
        self.user_id = username

        # 验证密码
        native_password = scramble_native_password(password,
                                                   challenge1 + challenge2)

        if self.server.settings[
                "user"] != username or response.authResponse.encode(
                    "iso-8859-1") != native_password:
            err = ERR(9001, '28000', '[%s] Access denied.' % username)
            buff = err.toPacket()
            self.send_packet(buff)
            self.finish()
            return

        buff = file2packet("auth_result.cap")
        self.send_packet(buff)
        # self.send_packet(bytes.fromhex("07 00 00 02 00 00 00 02 00 00 00"))

        # 查询
        while True:

            packet = self.read_packet()
            if len(packet) < 4:
                continue
            packet_type = getType(packet)

            # dump_my_packet(packet)
            # print('packet_type', packet_type, com_type_name(packet_type))

            if packet_type == Flags.COM_QUIT:
                self.finish()
            elif packet_type == Flags.COM_REGISTER_SLAVE:
                logger.info("Received COM_REGISTER_SLAVE")
                self.send_packet(OK().toPacket())

            elif packet_type == Flags.COM_BINLOG_DUMP_GTID:
                logger.info("Received COM_BINLOG_DUMP_GTID")
                dump(packet)
                # https://dev.mysql.com/doc/internals/en/com-binlog-dump-gtid.html
                filename_len = struct.unpack("<I", packet[11:15])[0]
                payload = packet[27 + filename_len:]
                gtid_set = GtidSet.decode(BytesIO(payload))

                self.dump_binlog_gtid(gtid_set)

            elif packet_type == Flags.COM_QUERY:
                self.handle_query(packet)