com.tesora.dve.db.mysql.portal.protocol.MSPAuthenticateV10MessageMessage.java Source code

Java tutorial

Introduction

Here is the source code for com.tesora.dve.db.mysql.portal.protocol.MSPAuthenticateV10MessageMessage.java

Source

package com.tesora.dve.db.mysql.portal.protocol;

/*
 * #%L
 * Tesora Inc.
 * Database Virtualization Engine
 * %%
 * Copyright (C) 2011 - 2014 Tesora Inc.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 * 
 * This program 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */

import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import org.apache.commons.codec.digest.DigestUtils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;

public class MSPAuthenticateV10MessageMessage extends BaseMSPMessage<MSPAuthenticateV10MessageMessage.ParsedData> {
    public static final MSPAuthenticateV10MessageMessage PROTOTYPE = new MSPAuthenticateV10MessageMessage();
    private static final int MAX_PACKET_SIZE = 0xffffff;

    static class ParsedData {
        ClientCapabilities caps;
        int maxPacketSize;
        byte charsetID;
        String username;
        String password;
        String initialDatabase;
    }

    protected MSPAuthenticateV10MessageMessage() {
        super();
    }

    protected MSPAuthenticateV10MessageMessage(ByteBuf backing) {
        super(backing);
    }

    public static MSPAuthenticateV10MessageMessage newMessage(ByteBuf backing) {
        return new MSPAuthenticateV10MessageMessage(backing.slice());
    }

    @Override
    public MSPAuthenticateV10MessageMessage newPrototype(ByteBuf source) {
        source = source.slice();
        return new MSPAuthenticateV10MessageMessage(source);
    }

    @Override
    public byte getMysqlMessageType() {
        return (byte) 0xc0;
    }

    @Override
    protected ParsedData unmarshall(ByteBuf source) {
        ParsedData parseValues = new ParsedData();
        parseValues.caps = new ClientCapabilities(source.readUnsignedInt());
        parseValues.maxPacketSize = source.readInt();
        parseValues.charsetID = source.readByte();

        source.skipBytes(23); // login request has a 23 byte filler
        parseValues.username = source.readSlice(source.bytesBefore((byte) 0)).toString(CharsetUtil.UTF_8);
        source.skipBytes(1); // skip the NULL terminator
        byte passwordLength = source.readByte();
        parseValues.password = source.readSlice(passwordLength).toString(CharsetUtil.ISO_8859_1);

        // if the clientCapabilities flag has the CLIENT_CONNECT_WITH_DB bit set,
        // then this message contains an initial database to connect to
        if (parseValues.caps.connectWithDB()) {
            parseValues.initialDatabase = source.readSlice(source.bytesBefore((byte) 0))
                    .toString(CharsetUtil.UTF_8);
            source.skipBytes(1); // skip the NULL terminator
        } else {
            parseValues.initialDatabase = "";
        }
        return parseValues;
    }

    public ClientCapabilities getClientCapabilities() {
        return readState().caps;
    }

    public int getMaxPacketSize() {
        return readState().maxPacketSize;
    }

    public byte getCharsetID() {
        return readState().charsetID;
    }

    public String getUsername() {
        return readState().username;
    }

    public String getPassword() {
        return readState().password;
    }

    public String getInitialDatabase() {
        return readState().initialDatabase;
    }

    public static void write(ByteBuf out, String userName, String userPassword, String salt, Charset charset,
            int mysqlCharsetID, int capabilitiesFlag) {
        ByteBuf leBuf = out.order(ByteOrder.LITTLE_ENDIAN);

        int payloadSizeIndex = leBuf.writerIndex();
        leBuf.writeMedium(0);
        leBuf.writeByte(1);
        int payloadStartIndex = leBuf.writerIndex();
        leBuf.writeInt(capabilitiesFlag);
        leBuf.writeInt(MAX_PACKET_SIZE);
        //      leBuf.writeByte(serverGreeting.getServerCharsetId());
        leBuf.writeByte(mysqlCharsetID);
        leBuf.writeZero(23);
        leBuf.writeBytes(userName.getBytes(charset));
        leBuf.writeZero(1);

        if ((capabilitiesFlag & ClientCapabilities.CLIENT_SECURE_CONNECTION) > 0) {

            byte[] securePassword = computeSecurePassword(userPassword, salt);
            leBuf.writeByte(securePassword.length);
            leBuf.writeBytes(securePassword);
        } else {
            leBuf.writeBytes(userPassword.getBytes(charset));
            leBuf.writeZero(1);
        }

        leBuf.setMedium(payloadSizeIndex, leBuf.writerIndex() - payloadStartIndex);
    }

    public static byte[] computeSecurePassword(String password, String salt) {
        byte[] sha1password = DigestUtils.sha1(password);
        byte[] seedbytes = salt.getBytes();
        ByteBuffer bb = ByteBuffer.allocate(sha1password.length + seedbytes.length);
        bb.put(seedbytes);
        bb.put(DigestUtils.sha1(sha1password));
        byte[] sha1parttwo = DigestUtils.sha1(bb.array());
        byte[] securePassword = new byte[sha1password.length];
        for (int i = 0; i < securePassword.length; ++i)
            securePassword[i] = (byte) (sha1password[i] ^ sha1parttwo[i]);
        return securePassword;
    }

    public static String computeSecurePasswordString(String password, String salt) {
        return new String(computeSecurePassword(password, salt), CharsetUtil.ISO_8859_1);
    }

}