def test_get_exception(self):
        ok_packet = '\x07\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00'
        err_packet = '\x47\x00\x00\x02\xff\x15\x04\x23\x32\x38\x30\x30\x30'\
                     '\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69\x65\x64'\
                     '\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x68\x61'\
                     '\x6d\x27\x40\x27\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74'\
                     '\x27\x20\x28\x75\x73\x69\x6e\x67\x20\x70\x61\x73\x73'\
                     '\x77\x6f\x72\x64\x3a\x20\x59\x45\x53\x29'
        self.assertTrue(
            isinstance(errors.get_exception(err_packet),
                       errors.ProgrammingError))

        self.assertRaises(ValueError, errors.get_exception, ok_packet)

        res = errors.get_exception('\x47\x00\x00\x02\xff\x15')
        self.assertTrue(isinstance(res, errors.InterfaceError))
    def test_get_exception(self):
        ok_packet = '\x07\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00'
        err_packet = '\x47\x00\x00\x02\xff\x15\x04\x23\x32\x38\x30\x30\x30'\
                     '\x41\x63\x63\x65\x73\x73\x20\x64\x65\x6e\x69\x65\x64'\
                     '\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x68\x61'\
                     '\x6d\x27\x40\x27\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74'\
                     '\x27\x20\x28\x75\x73\x69\x6e\x67\x20\x70\x61\x73\x73'\
                     '\x77\x6f\x72\x64\x3a\x20\x59\x45\x53\x29'
        self.assertTrue(isinstance(errors.get_exception(err_packet),
                                   errors.ProgrammingError))

        self.assertRaises(ValueError,
                          errors.get_exception, ok_packet)
        
        res = errors.get_exception('\x47\x00\x00\x02\xff\x15')
        self.assertTrue(isinstance(res, errors.InterfaceError))
示例#3
0
    def _do_handshake(self):
        """Get the handshake from the MySQL server"""
        packet = yield from self._socket.recv()
        if packet[4] == 255:
            raise errors.get_exception(packet)

        try:
            handshake = self._protocol.parse_handshake(packet)
        except Exception as err:
            raise errors.InterfaceError(
                'Failed parsing handshake; {0}'.format(err))

        regex_ver = re.compile(br"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)")
        match = regex_ver.match(handshake['server_version_original'])
        if not match:
            raise errors.InterfaceError("Failed parsing MySQL version")

        version = tuple([int(v) for v in match.groups()[0:3]])
        if b'fabric' in match.group(4).lower():
            if version < (1, 4):
                raise errors.InterfaceError(
                    "MySQL Fabric '{0}'' is not supported".format(
                        handshake['server_version_original']))
        elif version < (4, 1):
            raise errors.InterfaceError(
                "MySQL Version '{0}' is not supported.".format(
                    handshake['server_version_original']))

        if handshake['capabilities'] & ClientFlag.PLUGIN_AUTH:
            self.set_client_flags([ClientFlag.PLUGIN_AUTH])

        self._handshake = handshake
        self._server_version = version
示例#4
0
    def _handle_binary_result(self, packet):
        """Handle a MySQL Result

        This method handles a MySQL result, for example, after sending the
        query command. OK and EOF packets will be handled and returned. If
        the packet is an Error packet, an errors.Error-exception will be
        raised.

        The tuple returned by this method consist of:
        - the number of columns in the result,
        - a list of tuples with information about the columns,
        - the EOF packet information as a dictionary.

        Returns tuple() or dict()
        """
        if not packet or len(packet) < 4:
            raise errors.InterfaceError('Empty response')
        elif packet[4] == 0:
            return self._handle_ok(packet)
        elif packet[4] == 254:
            return self._handle_eof(packet)
        elif packet[4] == 255:
            raise errors.get_exception(packet)

        # We have a binary result set
        column_count = self._protocol.parse_column_count(packet)
        if not column_count or not isinstance(column_count, int):
            raise errors.InterfaceError('Illegal result set.')

        columns = [None] * column_count
        for i in range(0, column_count):
            columns[i] = self._protocol.parse_column((yield from self._socket.recv()))
        eof = self._handle_eof((yield from self._socket.recv()))
        return (column_count, columns, eof)
示例#5
0
    def _auth_switch_request(self, username=None, password=None):
        """Handle second part of authentication

        Raises NotSupportedError when we get the old, insecure password
        reply back. Raises any error coming from MySQL.
        """
        packet = yield from self._socket.recv()
        if packet[4] == 254 and len(packet) == 5:
            raise errors.NotSupportedError(
                "Authentication with old (insecure) passwords "
                "is not supported. For more information, lookup "
                "Password Hashing in the latest MySQL manual")
        elif packet[4] == 254:
            # AuthSwitchRequest
            (new_auth_plugin,
             auth_data) = self._protocol.parse_auth_switch_request(packet)
            auth = get_auth_plugin(new_auth_plugin)(
                auth_data, password=password, ssl_enabled=self._ssl_active)
            response = auth.auth_response()
            yield from self._socket.drain()
            if response == b'\x00':
                self._socket.send(b'')
            else:
                self._socket.send(response)
            packet = yield from self._socket.recv()
            if packet[4] != 1:
                return self._handle_ok(packet)
            else:
                auth_data = self._protocol.parse_auth_more_data(packet)
        elif packet[4] == 255:
            raise errors.get_exception(packet)
示例#6
0
    def _do_auth(self, username=None, password=None, database=None, client_flags=0, charset=33, ssl_options=None):
        """Authenticate with the MySQL server
        """
        if client_flags & ClientFlag.SSL and ssl_options:
            packet = self._protocol.make_auth_ssl(charset=charset, client_flags=client_flags)
            self._socket.send(packet)
            self._socket.switch_to_ssl(**ssl_options)

        packet = self._protocol.make_auth(
            seed=self._handshake["scramble"],
            username=username,
            password=password,
            database=database,
            charset=charset,
            client_flags=client_flags,
        )
        self._socket.send(packet)
        packet = self._socket.recv()

        if packet[4] == 254:
            raise errors.NotSupportedError(
                "Authentication with old (insecure) passwords "
                "is not supported. For more information, lookup "
                "Password Hashing in the latest MySQL manual"
            )
        elif packet[4] == 255:
            raise errors.get_exception(packet)

        try:
            if not (client_flags & ClientFlag.CONNECT_WITH_DB) and database:
                self.cmd_init_db(database)
        except:
            raise

        return True
示例#7
0
    def _handle_binary_ok(self, packet):
        """Handle a MySQL Binary Protocol OK packet

        This method handles a MySQL Binary Protocol OK packet. When the
        packet is found to be an Error packet, an error will be raised. If
        the packet is neither an OK or an Error packet, errors.InterfaceError
        will be raised.

        Returns a dict()
        """
        if packet[4] == 0:
            return self._protocol.parse_binary_prepare_ok(packet)
        elif packet[4] == 255:
            raise errors.get_exception(packet)
        raise errors.InterfaceError("Expected Binary OK packet")
示例#8
0
    def _handle_eof(self, packet):
        """Handle a MySQL EOF packet

        This method handles a MySQL EOF packet. When the packet is found to
        be an Error packet, an error will be raised. If the packet is neither
        and OK or an Error packet, errors.InterfaceError will be raised.

        Returns a dict()
        """
        if packet[4] == 254:
            eof = self._protocol.parse_eof(packet)
            self._handle_server_status(eof["status_flag"])
            return eof
        elif packet[4] == 255:
            raise errors.get_exception(packet)
        raise errors.InterfaceError("Expected EOF packet")
示例#9
0
    def _handle_ok(self, packet):
        """Handle a MySQL OK packet

        This method handles a MySQL OK packet. When the packet is found to
        be an Error packet, an error will be raised. If the packet is neither
        an OK or an Error packet, errors.InterfaceError will be raised.

        Returns a dict()
        """
        if packet[4] == 0:
            ok = self._protocol.parse_ok(packet)
            self._handle_server_status(ok["server_status"])
            return ok
        elif packet[4] == 255:
            raise errors.get_exception(packet)
        raise errors.InterfaceError("Expected OK packet")
示例#10
0
    def _handle_result(self, packet):
        """Handle a MySQL Result

        This method handles a MySQL result, for example, after sending the
        query command. OK and EOF packets will be handled and returned. If
        the packet is an Error packet, an errors.Error-exception will be
        raised.

        The dictionary returned of:
        - columns: column information
        - eof: the EOF-packet information

        Returns a dict()
        """
        if not packet or len(packet) < 4:
            raise errors.InterfaceError('Empty response')
        elif packet[4] == 0:
            return self._handle_ok(packet)
        elif packet[4] == 251:
            filename = packet[5:].decode()
            return self._handle_load_data_infile(filename)
        elif packet[4] == 254:
            return self._handle_eof(packet)
        elif packet[4] == 255:
            raise errors.get_exception(packet)

        # We have a text result set
        column_count = self._protocol.parse_column_count(packet)
        if not column_count or not isinstance(column_count, int):
            raise errors.InterfaceError('Illegal result set.')

        columns = [None,] * column_count
        for i in range(0, column_count):
            columns[i] = self._protocol.parse_column((yield from self._socket.recv()))
        eof = self._handle_eof((yield from self._socket.recv()))
        self.unread_result = True
        return {'columns': columns, 'eof': eof}
示例#11
0
    def _do_handshake(self):
        """Get the handshake from the MySQL server"""
        packet = self._socket.recv()
        if packet[4] == 255:
            raise errors.get_exception(packet)

        try:
            handshake = self._protocol.parse_handshake(packet)
        except Exception as err:
            raise errors.InterfaceError("Failed parsing handshake; {}".format(err))

        regex_ver = re.compile(b"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)")
        match = regex_ver.match(handshake["server_version_original"])
        if not match:
            raise errors.InterfaceError("Failed parsing MySQL version")

        version = tuple([int(v) for v in match.groups()[0:3]])
        if version < (4, 1):
            raise errors.InterfaceError(
                "MySQL Version '{}' is not supported.".format(handshake["server_version_original"])
            )

        self._handshake = handshake
        self._server_version = version