/* * Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software;Designed and Developed mainly by many Chinese * opensource volunteers. you can redistribute it and/or modify it under the * terms of the GNU General Public License version 2 only, as published by the * Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Any questions about this component can be directed to it's project Web address * https://code.google.com/p/opencloudb/. * */ package com.talent.mysql.packet.request; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import java.nio.ByteOrder; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.talent.balance.conf.BackendConf; import com.talent.balance.conf.BackendServerConf; import com.talent.mysql.packet.MysqlRequestPacket; import com.talent.mysql.packet.factory.MysqlHeaderFactory; import com.talent.mysql.packet.factory.MysqlHeaderFactory.MysqlHeader; import com.talent.mysql.packet.response.HandshakePacket; import com.talent.mysql.utils.Capabilities; import com.talent.mysql.utils.SecurityUtil; import com.talent.nio.communicate.intf.DecoderIntf.DecodeException; /** * 40 00 00 //数据长度,3字节,0x40=64字节<br> 01 //序号,1字节,同一个动作的所有请求与响应会递增此值<br> 8D A6 03 00 //客户端支持的属性,4字节,枚举参见网站<br> FF FF FF 00 //最大数据包长度,4字节,0xffffff=16777215=约16MB<br> 21 //字符集,1字节,0x21=33=utf8<br> 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字节<br> 74 65 73 74 00 //用户名,\0结尾的字符串,内容为test<br> 14 //密码串长度,1字节,0x14=20字节<br> B4 2F BB 65 7A D4 55 BA 9E E4 4B 34 A3 2C F6 58 92 7A A7 A2 //密码的加密串,20字节(算法见后)<br> 76 6D 6E 70 6E 00 //初始数据库,\0结尾的字符串,内容为vmnpn<br> * * @see http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse * @filename: com.talent.mysql.packet.request.AuthPacket * @copyright: Copyright (c)2010 * @company: talent * @author: 谭耀武 * @version: 1.0 * @create time: 2013年12月26日 下午5:19:13 * @record * <table cellPadding="3" cellSpacing="0" style="width:600px"> * <thead style="font-weight:bold;background-color:#e3e197"> * <tr> <td>date</td> <td>author</td> <td>version</td> <td>description</td></tr> * </thead> * <tbody style="background-color:#ffffeb"> * <tr><td>2013年12月26日</td> <td>谭耀武</td> <td>1.0</td> <td>create</td></tr> * </tbody> * </table> */ public class AuthPacket extends MysqlRequestPacket { /** * */ private static final long serialVersionUID = -474477733084620969L; private static final long CLIENT_FLAGS = initClientFlags(); private static Logger log = LoggerFactory.getLogger(AuthPacket.class); public long clientFlags = CLIENT_FLAGS; //172939;// public long maxPacketSize = 15 * 1024 * 1024; //1073741824;// public byte charsetIndex; public byte[] extra = new byte[23]; //固定填充0,23字节<br> public byte[] user; public byte passwordLen; public byte[] password; public byte[] database; private static long initClientFlags() { long flag = 0; flag |= Capabilities.CLIENT_LONG_PASSWORD; flag |= Capabilities.CLIENT_FOUND_ROWS; flag |= Capabilities.CLIENT_LONG_FLAG; flag |= Capabilities.CLIENT_CONNECT_WITH_DB; // flag |= Capabilities.CLIENT_NO_SCHEMA; // flag |= Capabilities.CLIENT_COMPRESS; flag |= Capabilities.CLIENT_ODBC; // flag |= Capabilities.CLIENT_LOCAL_FILES; flag |= Capabilities.CLIENT_IGNORE_SPACE; flag |= Capabilities.CLIENT_PROTOCOL_41; flag |= Capabilities.CLIENT_INTERACTIVE; // flag |= Capabilities.CLIENT_SSL; flag |= Capabilities.CLIENT_IGNORE_SIGPIPE; flag |= Capabilities.CLIENT_TRANSACTIONS; // flag |= Capabilities.CLIENT_RESERVED; flag |= Capabilities.CLIENT_SECURE_CONNECTION; // client extension // flag |= Capabilities.CLIENT_MULTI_STATEMENTS; // flag |= Capabilities.CLIENT_MULTI_RESULTS; return flag; } public int bodyLenth() { // return 4 + 4 + 1 + 23 + user.length + 1 + 1 + 20 + database.length + 1; return 55 + user.length + database.length; } /** * */ public AuthPacket() { } /** * @param args */ public static void main(String[] args) { AuthPacket authPacket1 = new AuthPacket(); authPacket1.decodeBody(null); byte[] bs = new byte[] { 82, 0, 0, 0, 10, 49, 48, 46, 48, 46, 49, 45, 77, 97, 114, 105, 97, 68, 66, 0, -98, 1, 0, 0, 110, 104, 61, 56, 64, 122, 101, 107, 0, -1, -9, 8, 2, 0, 15, -96, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 78, 41, 35, 111, 43, 39, 124, 98, 82, 87, 60, 0, 109, 121, 115, 113, 108, 95, 110, 97, 116, 105, 118, 101, 95, 112, 97, 115, 115, 119, 111, 114, 100, 0 }; ByteBuf byteBuf = Unpooled.buffer(bs.length); byteBuf = byteBuf.order(ByteOrder.LITTLE_ENDIAN); byteBuf.setBytes(0, bs); HandshakePacket handshakePacket = new HandshakePacket(); try { handshakePacket.decode(byteBuf); byteBuf.readerIndex(0); } catch (DecodeException e) { e.printStackTrace(); } BackendConf backendConf = BackendConf.getInstance(); BackendServerConf backendServerConf = backendConf.getServers()[0]; AuthPacket authPacket = new AuthPacket(); authPacket.charsetIndex = (byte) (handshakePacket.charset & 0xff); authPacket.user = backendServerConf.getProps().get("user").getBytes(); try { authPacket.password = getPass(backendServerConf.getProps().get("pwd"), handshakePacket); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } authPacket.passwordLen = (byte) authPacket.password.length; authPacket.database = backendServerConf.getProps().get("db").getBytes(); ByteBuf byteBuf1 = authPacket.encode(); System.out.println(Arrays.toString(byteBuf1.array())); } public static final byte[] getPass(String pass, HandshakePacket hs) throws NoSuchAlgorithmException { if (pass == null || pass.length() == 0) { return null; } byte[] passwd = pass.getBytes(); int sl1 = hs.encrypt1.length; int sl2 = hs.encrypt2.length; byte[] seed = new byte[sl1 + sl2]; System.arraycopy(hs.encrypt1, 0, seed, 0, sl1); System.arraycopy(hs.encrypt2, 0, seed, sl1, sl2); return SecurityUtil.scramble411(passwd, seed); // if (src == null || src.length() == 0) // { // return null; // } // byte[] passwd = src.getBytes(); // int sl1 = handshakePacket.encrypt1.length; // int sl2 = handshakePacket.authPluginName.length; // byte[] seed = new byte[sl1 + sl2]; // System.arraycopy(handshakePacket.encrypt1, 0, seed, 0, sl1); // System.arraycopy(handshakePacket.authPluginName, 0, seed, sl1, sl2); // return SecurityUtil.scramble411(passwd, seed); } @Override public void encodeBody(ByteBuf byteBuf) { int index = byteBuf.readerIndex(); String xx = Long.toBinaryString(clientFlags); byteBuf.setLong(index, clientFlags); index += 4; byteBuf.setLong(index, maxPacketSize); index += 4; byteBuf.setByte(index, charsetIndex); index++; byteBuf.setBytes(index, extra); index += extra.length; byteBuf.setBytes(index, user); index += user.length; byteBuf.setByte(index, 0); index++; byteBuf.setByte(index, passwordLen); index++; byteBuf.setBytes(index, password); index += password.length; byteBuf.setBytes(index, database); index += database.length; byteBuf.setByte(index, 0); index++; } public void decodeBody(ByteBuf _byteBuf) { byte[] bs = new byte[] { -117, -93, 2, 0, 0, 0, 0, 64, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 111, 111, 116, 0, 20, -19, -111, -3, 39, -46, -116, -128, -44, -112, -26, -48, 42, 70, -85, 8, 83, 83, 100, 103, 68, 116, 97, 108, 101, 110, 116, 95, 98, 97, 115, 101, 119, 101, 98, 50, 48, 49, 0 }; ByteBuf byteBuf = Unpooled.buffer(bs.length); byteBuf = byteBuf.order(ByteOrder.LITTLE_ENDIAN); byteBuf.setBytes(0, bs, 0, bs.length); int _index = byteBuf.readerIndex(); int index = _index; clientFlags = byteBuf.getInt(index); //172939 index += 4; maxPacketSize = byteBuf.getInt(index); //1073741824 index += 4; charsetIndex = byteBuf.getByte(index); //33 index += 1; index += extra.length; int len = 0; while (byteBuf.getByte(index+len) != 0) { len++; } user = new byte[len]; byteBuf.getBytes(index, user, 0, len); index += len; index++; passwordLen = byteBuf.getByte(index); index += 1; password = new byte[passwordLen]; byteBuf.getBytes(index, password, 0, passwordLen); len = 0; while (byteBuf.getByte(index+len) != 0) { len++; } database = new byte[len]; byteBuf.getBytes(index, database, 0, len); index += len; index++; } @Override public MysqlHeader createHeader() { MysqlHeader mysqlHeader = MysqlHeaderFactory.borrow(bodyLenth(), (byte) 1); return mysqlHeader; } }