2626
2727/**
2828 * 基于mysql socket协议的链接实现
29- *
29+ *
3030 * @author jianghang 2013-2-18 下午09:22:30
3131 * @version 1.0.1
3232 */
@@ -220,55 +220,45 @@ private void negotiate(SocketChannel channel) throws IOException {
220220 packet .fromBytes (body );
221221 authData = packet .authData ;
222222 pluginName = packet .authName ;
223+ logger .info ("auth switch pluginName is {}." , pluginName );
223224 }
224225
225- boolean isSha2Password = false ;
226226 byte [] encryptedPassword = null ;
227227 if ("mysql_clear_password" .equals (pluginName )) {
228228 encryptedPassword = getPassword ().getBytes ();
229+ header = authSwitchAfterAuth (encryptedPassword , header );
230+ body = PacketManager .readBytes (channel , header .getPacketBodyLength (), timeout );
229231 } else if ("mysql_native_password" .equals (pluginName )) {
230232 try {
231233 encryptedPassword = MySQLPasswordEncrypter .scramble411 (getPassword ().getBytes (), authData );
232234 } catch (NoSuchAlgorithmException e ) {
233235 throw new RuntimeException ("can't encrypt password that will be sent to MySQL server." , e );
234236 }
237+ header = authSwitchAfterAuth (encryptedPassword , header );
238+ body = PacketManager .readBytes (channel , header .getPacketBodyLength (), timeout );
235239 } else if ("caching_sha2_password" .equals (pluginName )) {
236- isSha2Password = true ;
240+ byte [] scramble = authData ;
237241 try {
238- encryptedPassword = MySQLPasswordEncrypter .scrambleCachingSha2 (getPassword ().getBytes (), authData );
242+ encryptedPassword = MySQLPasswordEncrypter .scrambleCachingSha2 (getPassword ().getBytes (), scramble );
239243 } catch (DigestException e ) {
240244 throw new RuntimeException ("can't encrypt password that will be sent to MySQL server." , e );
241245 }
242- }
243- assert encryptedPassword != null ;
244- AuthSwitchResponsePacket responsePacket = new AuthSwitchResponsePacket ();
245- responsePacket .authData = encryptedPassword ;
246- byte [] auth = responsePacket .toBytes ();
247-
248- h = new HeaderPacket ();
249- h .setPacketBodyLength (auth .length );
250- h .setPacketSequenceNumber ((byte ) (header .getPacketSequenceNumber () + 1 ));
251- PacketManager .writePkg (channel , h .toBytes (), auth );
252- logger .info ("auth switch response packet is sent out." );
253-
254- header = null ;
255- header = PacketManager .readHeader (channel , 4 );
256- body = null ;
257- body = PacketManager .readBytes (channel , header .getPacketBodyLength (), timeout );
258- assert body != null ;
259- if (isSha2Password ) {
246+ header = authSwitchAfterAuth (encryptedPassword , header );
247+ body = PacketManager .readBytes (channel , header .getPacketBodyLength (), timeout );
248+ assert body != null ;
260249 if (body [0 ] == 0x01 && body [1 ] == 0x04 ) {
261- // password auth failed
262- throw new IOException ("caching_sha2_password Auth failed" );
250+ header = cachingSha2PasswordFullAuth (channel , header , getPassword ().getBytes (), scramble );
251+ body = PacketManager .readBytes (channel , header .getPacketBodyLength (), timeout );
252+ } else {
253+ header = PacketManager .readHeader (channel , 4 );
254+ body = PacketManager .readBytes (channel , header .getPacketBodyLength (), timeout );
263255 }
264-
265- header = null ;
266- header = PacketManager .readHeader (channel , 4 );
267- body = null ;
256+ } else {
257+ header = authSwitchAfterAuth (encryptedPassword , header );
268258 body = PacketManager .readBytes (channel , header .getPacketBodyLength (), timeout );
269259 }
270260 }
271-
261+ assert body != null ;
272262 if (body [0 ] < 0 ) {
273263 if (body [0 ] == -1 ) {
274264 ErrorPacket err = new ErrorPacket ();
@@ -280,6 +270,62 @@ private void negotiate(SocketChannel channel) throws IOException {
280270 }
281271 }
282272
273+ private HeaderPacket cachingSha2PasswordFullAuth (SocketChannel channel , HeaderPacket header , byte [] pass ,
274+ byte [] seed ) throws IOException {
275+ AuthSwitchResponsePacket responsePacket = new AuthSwitchResponsePacket ();
276+ responsePacket .authData = new byte [] { 2 };
277+ byte [] auth = responsePacket .toBytes ();
278+ HeaderPacket h = new HeaderPacket ();
279+ h .setPacketBodyLength (auth .length );
280+ h .setPacketSequenceNumber ((byte ) (header .getPacketSequenceNumber () + 1 ));
281+ PacketManager .writePkg (channel , h .toBytes (), auth );
282+ logger .info ("caching sha2 password fullAuth request public key packet is sent out." );
283+
284+ header = PacketManager .readHeader (channel , 4 );
285+ byte [] body = PacketManager .readBytes (channel , header .getPacketBodyLength (), timeout );
286+ AuthSwitchRequestMoreData packet = new AuthSwitchRequestMoreData ();
287+ packet .fromBytes (body );
288+ if (packet .status != 0x01 ) {
289+ throw new IOException ("caching_sha2_password get public key failed" );
290+ }
291+ logger .info ("caching sha2 password fullAuth get server public key succeed." );
292+ byte [] publicKeyBytes = packet .authData ;
293+
294+ byte [] encryptedPassword = null ;
295+ try {
296+ encryptedPassword = MySQLPasswordEncrypter .scrambleRsa (publicKeyBytes , pass , seed );
297+ } catch (Exception e ) {
298+ logger .error ("rsa encrypt failed {}" , publicKeyBytes );
299+ throw new IOException ("caching_sha2_password auth failed" , e );
300+ }
301+
302+ // send auth
303+ responsePacket = new AuthSwitchResponsePacket ();
304+ responsePacket .authData = encryptedPassword ;
305+ auth = responsePacket .toBytes ();
306+ h = new HeaderPacket ();
307+ h .setPacketBodyLength (auth .length );
308+ h .setPacketSequenceNumber ((byte ) (header .getPacketSequenceNumber () + 1 ));
309+ PacketManager .writePkg (channel , h .toBytes (), auth );
310+ logger .info ("caching sha2 password fullAuth response auth data packet is sent out." );
311+ return PacketManager .readHeader (channel , 4 );
312+ }
313+
314+ private HeaderPacket authSwitchAfterAuth (byte [] encryptedPassword , HeaderPacket header ) throws IOException {
315+ assert encryptedPassword != null ;
316+ AuthSwitchResponsePacket responsePacket = new AuthSwitchResponsePacket ();
317+ responsePacket .authData = encryptedPassword ;
318+ byte [] auth = responsePacket .toBytes ();
319+
320+ HeaderPacket h = new HeaderPacket ();
321+ h .setPacketBodyLength (auth .length );
322+ h .setPacketSequenceNumber ((byte ) (header .getPacketSequenceNumber () + 1 ));
323+ PacketManager .writePkg (channel , h .toBytes (), auth );
324+ logger .info ("auth switch response packet is sent out." );
325+ header = PacketManager .readHeader (channel , 4 );
326+ return header ;
327+ }
328+
283329 private void auth323 (SocketChannel channel , byte packetSequenceNumber , byte [] seed ) throws IOException {
284330 // auth 323
285331 Reply323Packet r323 = new Reply323Packet ();
0 commit comments