/******************************************************************************* * Copyright (C) 2013 JMaNGOS <http://jmangos.org/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package org.jmangos.realm.controller; import java.nio.charset.Charset; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import javolution.util.FastMap; import org.jmangos.commons.model.AccountInfo; import org.jmangos.commons.network.model.NettyNetworkChannel; import org.jmangos.commons.network.model.NetworkChannel; import org.jmangos.commons.network.model.State; import org.jmangos.commons.network.sender.AbstractPacketSender; import org.jmangos.realm.network.handler.RealmToClientChannelHandler; import org.jmangos.realm.network.packet.auth.server.SMD_SESSION_KEY; import org.jmangos.realm.network.packet.wow.server.SMSG_ADDON_INFO; import org.jmangos.realm.network.packet.wow.server.SMSG_AUTH_RESPONSE; import org.jmangos.realm.network.packet.wow.server.SMSG_CLIENTCACHE_VERSION; import org.jmangos.realm.network.packet.wow.server.SMSG_TUTORIAL_FLAGS; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; /** * * @author MinimaJack * */ @Controller public class AccountQueueController { /** The Constant logger. */ private static final Logger logger = LoggerFactory.getLogger(AccountQueueController.class); /** */ private final FastMap<String, AccountInfo> accountQueue = new FastMap<String, AccountInfo>().shared(); /** The sender. */ @Autowired @Qualifier("serverPacketSender") private AbstractPacketSender authSender; @Autowired @Qualifier("nettyPacketSender") private AbstractPacketSender clientsender; /** */ private NetworkChannel authNetworkChannel; private static final Charset charset = Charset.forName("UTF-8"); @Autowired RealmController realmController; /** */ public void loadKeyAndValidateAccount(final AccountInfo aci) { if (this.accountQueue.containsKey(aci.getName())) { logger.debug("Account {} exist in queue", aci.getName()); return; } logger.debug("Add account :{} to queue", aci.getName()); this.accountQueue.put(aci.getName(), aci); this.authSender.send(this.authNetworkChannel, new SMD_SESSION_KEY(aci.getName())); } public void recieveAccountData(final AccountInfo account) { if (this.accountQueue.containsKey(account.getName()) && validateAccountInfo(account)) { logger.debug("Recieve AccountInfo for account: {}", account.getName()); final AccountInfo cAccountInfo = this.accountQueue.get(account.getName()); this.clientsender.send(cAccountInfo.getChannel(), new SMSG_AUTH_RESPONSE()); this.clientsender.send(cAccountInfo.getChannel(), new SMSG_ADDON_INFO(cAccountInfo.getAddonLists())); this.clientsender.send(cAccountInfo.getChannel(), new SMSG_CLIENTCACHE_VERSION()); this.clientsender.send(cAccountInfo.getChannel(), new SMSG_TUTORIAL_FLAGS()); this.accountQueue.remove(account.getName()); } else { logger.debug("Auth server sent wrong data: {}", account.getName()); } } private boolean validateAccountInfo(final AccountInfo account) { final AccountInfo cAccountInfo = this.accountQueue.get(account.getName()); MessageDigest sha; try { sha = MessageDigest.getInstance("SHA-1"); } catch (final NoSuchAlgorithmException e) { return false; } // TODO replace final RealmToClientChannelHandler channelHandler = (RealmToClientChannelHandler) ((NettyNetworkChannel) cAccountInfo.getChannel()).getChannel().getPipeline().getLast(); final byte[] t = { 0, 0, 0, 0 }; sha.update(account.getName().toUpperCase().getBytes(charset)); sha.update(t); sha.update(cAccountInfo.getClientSeed()); sha.update(channelHandler.getSeed()); sha.update(account.getSessionKey().asByteArray(40)); if (!Arrays.equals(sha.digest(), cAccountInfo.getvK())) { cAccountInfo.getChannel().getChannel().close(); return false; } /** * Now Set right object id And set crypto seed */ cAccountInfo.setObjectId(account.getObjectId()); channelHandler.getCrypt().init(account.getSessionKey().asByteArray(40)); cAccountInfo.getChannel().setChannelState(State.AUTHED); this.realmController.addAccount(cAccountInfo); return true; } public void removeFromQueue(final String accountName) { this.accountQueue.remove(accountName); } public void setAuthNetworkChannel(final NetworkChannel authNetworkChannel) { this.authNetworkChannel = authNetworkChannel; } }