今天看登录认证,需要指出的是MySQL支持多种登录方式,而且支持SSL,我们只看最简单的,基础流程如下:


Client               Server
  |      handshake     |
  |<-------------------|
  |   authentication   |
  |------------------->|
  |     auth result    |
  |<-------------------|
  |                    |


1、handshake

格式:(Initial Handshake Packet)

1              [0a] protocol version
string[NUL]    server version
4              connection id
string[8]      auth-plugin-data-part-1
1              [00] filler
2              capability flags (lower 2 bytes)
  if more data in the packet:
1              character set
2              status flags
2              capability flags (upper 2 bytes)
  if capabilities & CLIENT_PLUGIN_AUTH {
1              length of auth-plugin-data
  } else {
1              [00]
  }
string[10]     reserved (all [00])
  if capabilities & CLIENT_SECURE_CONNECTION {
string[$len]   auth-plugin-data-part-2 ($len=MAX(13, length of auth-plugin-data - 8))
  if capabilities & CLIENT_PLUGIN_AUTH {
    if version >= (5.5.7 and < 5.5.10) or (>= 5.6.0 and < 5.6.2) {
string[EOF]    auth-plugin name
    } elseif version >= 5.5.10 or >= 5.6.2 {
string[NUL]    auth-plugin name
    }
  }


抓包:

00000000  42 00 00 00 0A 35 2E 31  2E 34 39 2D 63 6F 6D 6D   B....5.1 .49-comm
00000010  75 6E 69 74 79 2D 6C 6F  67 00 14 00 00 00 49 69   unity-lo g.....Ii
00000020  57 55 27 5E 26 42 00 FF  F7 1C 02 00 00 00 00 00   WU'^&B.. ........
00000030  00 00 00 00 00 00 00 00  00 5A 7C 24 39 32 2E 2F   ........ .Z|$92./
00000040  43 40 5A 25 46 00                                  C@Z%F.


解析:

42 00 00                    //数据长度,3字节,0x42=66字节
00                          //序号,1字节
0A                          //协议,1字节,0x0A=10,表示第10版协议
35 2E 31 2E 34 39 2D 63 6F 6D 6D 75 6E 69 74 79 2D 6C 6F 67 00  //版本信息,字符串,以\0结尾,内容为5.1.49-community-log
14 00 00 00                 //连接ID,4字节,0x14=20
5e 63 59 72 54 2c 7b 4a     //加密串的前半部分,定长8字节
00                          //固定填充0
FF F7                       //服务端属性的低16位,2字节,枚举参见网站
1C                          //字符集,1字节,0x1c=28=gbk_chinese_ci
02 00                       //服务端状态,2字节,枚举参见网站
00 00                       //服务端属性的高16位,2字节
00                          //固定填充0
00 00 00 00 00 00 00 00 00 00   //固定填充0,10字节
5A 7C 24 39 32 2E 2F 43 40 5A 25 46 00      //加密串的后半部分,以\0结尾,加密串总共8+12=20字节


2、authentication

格式:(Handshake Response Packet)

4              capability flags, CLIENT_PROTOCOL_41 always set
4              max-packet size
1              character set
string[23]     reserved (all [0])
string[NUL]    username
  if capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA {
lenenc-int     length of auth-response
string[n]      auth-response
  } else if capabilities & CLIENT_SECURE_CONNECTION {
1              length of auth-response
string[n]      auth-response
  } else {
string[NUL]    auth-response
  }
  if capabilities & CLIENT_CONNECT_WITH_DB {
string[NUL]    database
  }
  if capabilities & CLIENT_PLUGIN_AUTH {
string[NUL]    auth plugin name
  }
  if capabilities & CLIENT_CONNECT_ATTRS {
lenenc-int     length of all key-values
lenenc-str     key
lenenc-str     value
   if-more data in 'length of all key-values', more keys and value pairs
  }


抓包:

00000000  40 00 00 01 8D A6 03 00  FF FF FF 00 21 00 00 00   @....... ....!...
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
00000020  00 00 00 00 74 65 73 74  00 14 B4 2F BB 65 7A D4   ....test .../.ez.
00000030  55 BA 9E E4 4B 34 A3 2C  F6 58 92 7A A7 A2 76 6D   U...K4., .X.z..vm
00000040  6E 70 6E 00                                        npn.


解析:

40 00 00                    //数据长度,3字节,0x40=64字节
01                          //序号,1字节,同一个动作的所有请求与响应会递增此值
8D A6 03 00                 //客户端支持的属性,4字节,枚举参见网站
FF FF FF 00                 //最大数据包长度,4字节,0xffffff=16777215=约16MB
21                          //字符集,1字节,0x21=33=utf8
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   //固定填充0,23字节
74 65 73 74 00              //用户名,\0结尾的字符串,内容为test
14                          //密码串长度,1字节,0x14=20字节
B4 2F BB 65 7A D4 55 BA 9E E4 4B 34 A3 2C F6 58 92 7A A7 A2   //密码的加密串,20字节(算法见后)
76 6D 6E 70 6E 00           //初始数据库,\0结尾的字符串,内容为vmnpn


加密算法:

SHA1(password) XOR SHA1("20-bytes random data from server" <concat> SHA1(SHA1(password)))


3、auth ok

格式:(OK Packet)

1              [00] the OK header
lenenc-int     affected rows
lenenc-int     last-insert-id
  if capabilities & CLIENT_PROTOCOL_41 {
2              status_flags
2              warnings
  } elseif capabilities & CLIENT_TRANSACTIONS {
2              status_flags
  }
string[EOF]    info


抓包:

00000000  07 00 00 02 00 00 00 02  00 00 00                  ........ ........


解析:

07 00 00                    //数据长度,3字节,0x07=7字节
02                          //序号,1字节,在上一个包的基础上又+1了
00                          //状态标识,1字节,0x00表示成功
00                          //影响行数,变长数值
00                          //LastInsertId,变长数值
02 00                       //状态,2字节,枚举参见网站
00 00                       //消息


4、auth fail

格式:(ERR Packet)

1              [ff] the ERR header
2              error code
  if capabilities & CLIENT_PROTOCOL_41 {
string[1]      '#' the sql-state marker
string[5]      sql-state
  }
string[EOF]    error-message


抓包:

00000000  48 00 00 02 FF 15 04 23  32 38 30 30 30 41 63 63   .......# 28000Acc
00000010  65 73 73 20 64 65 6E 69  65 64 20 66 6F 72 20 75   ess deni ed for u
00000020  73 65 72 20 27 74 65 73  74 27 40 27 54 69 61 6E   ser 'tes t'@'Tian
00000030  59 75 2D 50 43 27 20 28  75 73 69 6E 67 20 70 61   Yu-PC' ( using pa
00000040  73 73 77 6F 72 64 3A 20  59 45 53 29               ssword:  YES)


解析:

48 00 00                    //数据长度,3字节,0x48=72字节
02                          //序号,1字节,在上一个包的基础上又+1了
FF                          //状态标识,1字节,0xff表示错误
15 04                       //错误码,2字节,0x415=1045
23                          //固定1字节,#
32 38 30 30 30              //SQL状态,固定5字节,内容=28000
41 63 63 65 ... 59 45 53 29 //出错信息,字符串,内容=Access denied for user 'test'@'TianYu-PC' (using password: YES)


未完待续……