Coverage for mindsdb / api / mysql / mysql_proxy / data_types / mysql_packets / handshake_response_packet.py: 12%

52 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-21 00:36 +0000

1""" 

2******************************************************* 

3 * Copyright (C) 2017 MindsDB Inc. <copyright@mindsdb.com> 

4 * 

5 * This file is part of MindsDB Server. 

6 * 

7 * MindsDB Server can not be copied and/or distributed without the express 

8 * permission of MindsDB Inc 

9 ******************************************************* 

10""" 

11 

12# https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse 

13 

14from mindsdb.api.mysql.mysql_proxy.data_types.mysql_packet import Packet 

15from mindsdb.api.mysql.mysql_proxy.data_types.mysql_datum import Datum 

16from mindsdb.api.mysql.mysql_proxy.classes.client_capabilities import ClentCapabilities 

17from mindsdb.api.mysql.mysql_proxy.libs.constants.mysql import CAPABILITIES 

18from mindsdb.api.mysql.mysql_proxy.classes.server_capabilities import server_capabilities 

19 

20 

21class HandshakeResponsePacket(Packet): 

22 ''' 

23 Implementation based on description: 

24 https://mariadb.com/kb/en/library/1-connecting-connecting/#initial-handshake-packet 

25 ''' 

26 

27 def setup(self, length=0, count_header=1, body=''): 

28 length = len(body) 

29 

30 if length == 0: 

31 return 

32 

33 self.salt = self.proxy.salt 

34 

35 self._length = length 

36 self._seq = count_header 

37 self._body = body 

38 

39 self.capabilities = Datum('int<4>') 

40 self.max_packet_size = Datum('int<4>') 

41 self.reserved = Datum('string<23>') 

42 self.username = Datum('string<NUL>') 

43 

44 self.enc_password = Datum('string<NUL>') 

45 self.database = Datum('string<NUL>') 

46 

47 self.charset = Datum('int<1>') 

48 

49 self.client_auth_plugin = Datum('string<NUL>') 

50 

51 buffer = body 

52 

53 if len(body) == 32 and body[9:] == (b'\x00' * 23): 

54 self.type = 'SSLRequest' 

55 buffer = self.capabilities.setFromBuff(buffer) 

56 buffer = self.max_packet_size.setFromBuff(buffer) 

57 buffer = self.charset.setFromBuff(buffer) 

58 else: 

59 self.type = 'HandshakeResponse' 

60 buffer = self.capabilities.setFromBuff(buffer) 

61 capabilities = ClentCapabilities(self.capabilities.value) 

62 buffer = self.max_packet_size.setFromBuff(buffer) 

63 buffer = self.charset.setFromBuff(buffer) 

64 buffer = self.reserved.setFromBuff(buffer) 

65 buffer = self.username.setFromBuff(buffer) 

66 

67 if server_capabilities.has(CAPABILITIES.CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) \ 

68 and capabilities.PLUGIN_AUTH_LENENC_CLIENT_DATA: 

69 self.enc_password = Datum('string<lenenc>') 

70 buffer = self.enc_password.setFromBuff(buffer) 

71 elif server_capabilities.has(CAPABILITIES.CLIENT_SECURE_CONNECTION) \ 

72 and capabilities.SECURE_CONNECTION: 

73 self.auth_resp_len = Datum('int<1>') 

74 buffer = self.auth_resp_len.setFromBuff(buffer) 

75 self.enc_password = Datum(f'string<{self.auth_resp_len.value}>') 

76 buffer = self.enc_password.setFromBuff(buffer) 

77 else: 

78 pass_byte = Datum('int<1>') 

79 buffer = pass_byte.setFromBuff(buffer) 

80 

81 if capabilities.CONNECT_WITH_DB: 

82 buffer = self.database.setFromBuff(buffer) 

83 if capabilities.PLUGIN_AUTH: 

84 buffer = self.client_auth_plugin.setFromBuff(buffer) 

85 

86 # at the end is CLIENT_CONNECT_ATTRS, but we dont use it and dont parse 

87 

88 self.session.username = self.username.value 

89 

90 def __str__(self): 

91 return str({ 

92 'header': {'length': self.length, 'seq': self.seq}, 

93 'username': self.username.value, 

94 'password': self.enc_password.value, 

95 'database': self.database.value 

96 })