void VoiceChatClientSocket::OnRead() { WorldPacket *data; // uint16 op // uint16 size // <data> for(;;) { // no more data if( GetReadBuffer().GetSize() < 4 ) break; GetReadBuffer().Read((uint8*)&op, 2); GetReadBuffer().Read((uint8*)&remaining, 2); if( GetReadBuffer().GetSize() < remaining ) break; data = new WorldPacket(op, remaining); data->resize(remaining); GetReadBuffer().Read((uint8*)data->contents(), remaining); // handle the packet sVoiceChatHandler.OnRead(data); delete data; remaining = op = 0; } }
void AuthSocket::HandleReconnectProof() { if( m_account == NULL ) return; // Load sessionkey from account database. QueryResult * result = sLogonSQL->Query ("SELECT SessionKey FROM accounts WHERE acct = %u", m_account->AccountId); if(result) { Field * field = result->Fetch(); K.SetHexStr(field[0].GetString ()); delete result; } else { // Disconnect if the sessionkey invalid or not found DEBUG_LOG("AuthReConnectProof","No matching SessionKey found while user %s tried to login.", AccountName.c_str()); Disconnect(); return; } if(GetReadBuffer().GetSize() < sizeof(sAuthLogonProofKey_C)) return; sAuthLogonProofKey_C lp; GetReadBuffer().Read(&lp, sizeof(sAuthLogonProofKey_C)); BigNumber A; A.SetBinary(lp.R1, 16); Sha1Hash sha; sha.Initialize(); sha.UpdateData(AccountName); sha.UpdateBigNumbers(&A, &rs, &K, 0); sha.Finalize(); if (!memcmp(sha.GetDigest(), lp.R2, SHA_DIGEST_LENGTH)) { ///- Sending response ByteBuffer pkt; pkt << (uint8) 0x03; //ReconnectProof pkt << (uint8) 0x00; pkt << (uint16) 0x00; // 2 bytes zeros Send(pkt.contents(), pkt.size()); // we're authenticated now :) m_authenticated = true; DEBUG_LOG("AuthReConnectProof","Authentication Success."); } else DEBUG_LOG("AuthReConnectProof","Authentication Failed."); }
void AuthSocket::OnRecvData() { if(GetReadBuffer()->GetSize() < 1) return; uint8 Command = *(uint8*)GetReadBuffer()->GetBufferOffset(); last_recv = UNIXTIME; if(Command < MAX_AUTH_CMD && Handlers[Command] != NULL) (this->*Handlers[Command])(); else Log.Notice("AuthSocket", "Unknown cmd %u", Command); }
void AuthSocket::OnRead() { if(GetReadBuffer().GetContiguiousBytes() < 1) return; uint8 Command = *(uint8*)GetReadBuffer().GetBufferStart(); last_recv = UNIXTIME; if(Command < MAX_AUTH_CMD && Handlers[Command] != NULL) (this->*Handlers[Command])(); else Log.Debug("AuthSocket", "Unknown cmd %u", Command); }
void Battlenet::Session::ReadHandler() { BitStream stream(std::move(GetReadBuffer())); _crypt.DecryptRecv(stream.GetBuffer(), stream.GetSize()); while (!stream.IsRead()) { try { PacketHeader header; header.Opcode = stream.Read<uint32>(6); if (stream.Read<bool>(1)) header.Channel = stream.Read<int32>(4); if (header.Channel != AUTHENTICATION && (header.Channel != CONNECTION || header.Opcode != Connection::CMSG_PING) && !_authed) { TC_LOG_DEBUG("session.packets", "%s Received not allowed %s. Client has not authed yet.", GetClientInfo().c_str(), header.ToString().c_str()); CloseSocket(); return; } if (ClientPacket* packet = sPacketManager.CreateClientPacket(header, stream)) { if (sPacketManager.IsHandled(header)) TC_LOG_DEBUG("session.packets", "%s Received %s", GetClientInfo().c_str(), PacketToStringHelper(packet).c_str()); packet->CallHandler(this); delete packet; } else if (sPacketManager.GetClientPacketName(header)) { LogUnhandledPacket(header); break; } else { TC_LOG_DEBUG("session.packets", "%s Received unknown %s", GetClientInfo().c_str(), header.ToString().c_str()); break; } stream.AlignToNextByte(); } catch (BitStreamPositionException const& e) { TC_LOG_ERROR("session.packets", "%s Exception thrown during packet processing %s", GetClientInfo().c_str(), e.what()); CloseSocket(); return; } } GetReadBuffer().Resize(size_t(BufferSizes::Read)); AsyncRead(); }
void AuthSocket::HandleTransferResume() { DEBUG_LOG("AuthSocket","Resuming transfer"); if(!m_patch) return; GetReadBuffer()->Remove(1); uint64 size; GetReadBuffer()->Read(&size, 8); if(size>=m_patch->FileSize) return; PatchMgr::getSingleton().BeginPatchJob(m_patch,this,(uint32)size); }
void AuthSocket::HandleTransferResume() { sLog.outDebug("Resuming transfer"); if(!m_patch) return; //RemoveReadBufferBytes(1,false); GetReadBuffer().Remove(1); uint64 size; //Read(8,(uint8*)&size); GetReadBuffer().Read(&size, 8); if(size>=m_patch->FileSize) return; PatchMgr::getSingleton().BeginPatchJob(m_patch,this,(uint32)size); }
void AuthSocket::HandleReconnectProof() { /* printf("Len: %u\n", this->GetReadBufferSize()); ByteBuffer buf(58); buf.resize(58); Read(58, const_cast<uint8*>(buf.contents())); buf.hexlike();*/ if (!m_account) return; // Don't update when IP banned, but update anyway if it's an account ban sLogonSQL->Execute("UPDATE accounts SET lastlogin=NOW(), lastip='%s' WHERE acct=%u;", GetRemoteIP().c_str(), m_account->AccountId); //RemoveReadBufferBytes(GetReadBufferSize(), true); GetReadBuffer().Remove(GetWriteBuffer().GetSize()); if(!m_account->SessionKey) { uint8 buffer[4]; buffer[0] = 3; buffer[1] = 0; buffer[2] = 1; buffer[3] = 0; Send(buffer, 4); } else { uint32 x = 3; Send((const uint8*)&x, 4); } }
void AuthSocket::OnRead() { if(GetReadBufferSize() < 1) return; uint8 Command = GetReadBuffer(0)[0]; // Handle depending on command switch(Command) { case 0: // AUTH_CHALLENGE last_recv = time(NULL); HandleChallenge(); break; case 1: // AUTH_PROOF last_recv = time(NULL); HandleProof(); break; case 0x10: // REALM_LIST last_recv = time(NULL); HandleRealmlist(); break; } }
void LogonCommServerSocket::OnRecvData() { while(true) { if(!remaining) { if(GetReadBuffer()->GetSize() < 6) return; // no header // read header Read((uint8*)&opcode, 2); Read((uint8*)&remaining, 4); if(use_crypto) { // decrypt the packet recvCrypto.Process((unsigned char*)&opcode, (unsigned char*)&opcode, 2); recvCrypto.Process((unsigned char*)&remaining, (unsigned char*)&remaining, 4); } EndianConvert(opcode); /* reverse byte order */ EndianConvertReverse(remaining); } // do we have a full packet? if(GetReadBuffer()->GetSize() < remaining) return; // create the buffer WorldPacket buff(opcode, remaining); if(remaining) { buff.resize(remaining); Read((uint8*)buff.contents(), remaining); } if(use_crypto && remaining) recvCrypto.Process((unsigned char*)buff.contents(), (unsigned char*)buff.contents(), remaining); // handle the packet HandlePacket(buff); remaining = 0; opcode = 0; } }
void AuthSocket::HandleTransferAccept() { DEBUG_LOG("AuthSocket","Accepted transfer"); if(!m_patch) return; GetReadBuffer()->Remove(1); PatchMgr::getSingleton().BeginPatchJob(m_patch,this,0); }
void AuthSocket::HandleTransferAccept() { sLog.outDebug("Accepted transfer"); if(!m_patch) return; //RemoveReadBufferBytes(1,false); GetReadBuffer().Remove(1); PatchMgr::getSingleton().BeginPatchJob(m_patch,this,0); }
void Socket::ReadHandler() { if (!IsOpen()) return; MessageBuffer& packet = GetReadBuffer(); while (packet.GetActiveSize() > 0) { if (_headerBuffer.GetRemainingSpace() > 0) { // need to receive the header std::size_t readHeaderSize = std::min(packet.GetActiveSize(), _headerBuffer.GetRemainingSpace()); _headerBuffer.Write(packet.GetReadPointer(), readHeaderSize); packet.ReadCompleted(readHeaderSize); if (_headerBuffer.GetRemainingSpace() > 0) break; // We just received nice new header if (!ReadHeaderHandler()) { CloseSocket(); return; } } // We have full read header, now check the data payload if (_packetBuffer.GetRemainingSpace() > 0) { // need more data in the payload std::size_t readDataSize = std::min(packet.GetActiveSize(), _packetBuffer.GetRemainingSpace()); _packetBuffer.Write(packet.GetReadPointer(), readDataSize); packet.ReadCompleted(readDataSize); if (_packetBuffer.GetRemainingSpace() > 0) { // Couldn't receive the whole data this time. break; } } // just received fresh new payload if (!ReadDataHandler()) { CloseSocket(); _headerBuffer.Reset(); return; } _headerBuffer.Reset(); } AsyncRead(); }
void AuthSocket::OnRead() { if(GetReadBufferSize() < 1) return; uint8 Command = GetReadBuffer(0)[0]; last_recv = UNIXTIME; if(Command < MAX_AUTH_CMD && Handlers[Command] != NULL) (this->*Handlers[Command])(); else Log.Notice("AuthSocket", "Unknown cmd %u", Command); }
void Battlenet::Session::ReadHandler() { if (!IsOpen()) return; MessageBuffer& packet = GetReadBuffer(); while (packet.GetActiveSize() > 0) { if (!PartialProcessPacket<&Battlenet::Session::ReadHeaderLengthHandler, &Battlenet::Session::_headerLengthBuffer>(this, packet)) break; if (!PartialProcessPacket<&Battlenet::Session::ReadHeaderHandler, &Battlenet::Session::_headerBuffer>(this, packet)) break; if (!PartialProcessPacket<&Battlenet::Session::ReadDataHandler, &Battlenet::Session::_packetBuffer>(this, packet)) break; _headerLengthBuffer.Reset(); _headerBuffer.Reset(); } AsyncRead(); }
void AuthSocket::HandleTransferCancel() { //RemoveReadBufferBytes(1,false); GetReadBuffer().Remove(1); Disconnect(); }
void WSClient::OnRecvData() { for(;;) { if(!_cmd) { if(GetReadBuffer()->GetSize() < 6) break; Read((uint8*)&_cmd, 2); Read((uint8*)&_remaining, 4); } if(_remaining && GetReadBuffer()->GetSize() < _remaining) return; if(_cmd == SMSGR_WOW_PACKET) { uint32 sid = 0; uint16 op = 0; uint32 sz = 0; Read(&sid, 4); Read(&op, 2); Read(&sz, 4); WorldSession * session = sClusterInterface.GetSession(sid); if(session != NULL) { WorldPacket * pck = new WorldPacket(op, sz); if (sz > 0) { pck->resize(sz); Read((void*)pck->contents(), sz); } if(session) session->QueuePacket(pck); else delete pck; } _cmd = 0; continue; } WorldPacket * pck = new WorldPacket(_cmd, _remaining); _cmd = 0; if(_remaining) { pck->resize(_remaining); Read((uint8*)pck->contents(), _remaining); } /* we could handle auth here */ switch(_cmd) { case SMSGR_AUTH_REQUEST: sClusterInterface.HandleAuthRequest(*pck); delete pck; break; default: sClusterInterface.QueuePacket(pck); } } }
void WorldSocket::OnRead() { for(;;) { // Check for the header if we don't have any bytes to wait for. if(mRemaining == 0) { if(GetReadBuffer().GetSize() < 6) { // No header in the packet, let's wait. return; } // Copy from packet buffer into header local var ClientPktHeader Header; GetReadBuffer().Read(&Header, 6); // Decrypt the header _crypt.DecryptSixRecv((uint8*)&Header); mRemaining = mSize = ntohs(Header.size) - 4; mOpcode = Header.cmd; } WorldPacket * Packet; if(mRemaining > 0) { if( GetReadBuffer().GetSize() < mRemaining ) { // We have a fragmented packet. Wait for the complete one before proceeding. return; } } Packet = new WorldPacket(mOpcode, mSize); Packet->resize(mSize); if(mRemaining > 0) { // Copy from packet buffer into our actual buffer. //Read(mRemaining, (uint8*)Packet->contents()); GetReadBuffer().Read((uint8*)Packet->contents(), mRemaining); } /*sWorldLog.LogPacket(mSize, mOpcode, mSize ? Packet->contents() : NULL, 0);*/ mRemaining = mSize = mOpcode = 0; // Check for packets that we handle switch(Packet->GetOpcode()) { case CMSG_PING: { if(!m_session->m_currentPlayer) { _HandlePing(Packet); delete Packet; } else m_session->m_readQueue.Push(Packet); }break; case CMSG_AUTH_SESSION: { _HandleAuthSession(Packet); }break; default: { if(m_session) m_session->m_readQueue.Push(Packet); else delete Packet; }break; } } }
void WorldSocket::OnRecvData() { for(;;) { // Check for the header if we don't have any bytes to wait for. if(mRemaining == 0) { if(GetReadBuffer()->GetSize() < 6) { // No header in the packet, let's wait. return; } // Copy from packet buffer into header local var ClientPktHeader Header; Read(&Header, 6); // Decrypt the header _crypt.DecryptRecv((uint8*)&Header, sizeof (ClientPktHeader)); mRemaining = mSize = ntohs(Header.size) - 4; mOpcode = Header.cmd; } if(mRemaining > 0) { if( GetReadBuffer()->GetSize() < mRemaining ) { // We have a fragmented packet. Wait for the complete one before proceeding. return; } } WorldPacket *Packet = new WorldPacket(mOpcode, mSize); if(mRemaining > 0) { Packet->resize(mRemaining); Read((uint8*)Packet->contents(), mRemaining); if(!bServerShutdown) sWorld.NetworkStressIn += float(float(mSize+6)/1024); } mRemaining = mSize = mOpcode = 0; // Check for packets that we handle switch(Packet->GetOpcode()) { case CMSG_PING: { _HandlePing(Packet); delete Packet; }break; case CMSG_AUTH_SESSION: { _HandleAuthSession(Packet); }break; default: { if(mSession) mSession->QueuePacket(Packet); else { delete Packet; Packet = NULL; } }break; } } }
void ConsoleSocket::OnRecvData() { uint32 readlen = (uint32)GetReadBuffer()->GetSize(); uint32 rlen; char * p; if( ( readlen + m_pBufferPos ) >= m_pBufferLen ) { Disconnect(); return; } Read((uint8*)&m_pBuffer[m_pBufferPos], readlen); m_pBufferPos += readlen; // let's look for any newline bytes. p = strchr(m_pBuffer, '\n'); while( p != NULL ) { // windows is stupid. :P rlen = (uint32)((p+1) - m_pBuffer); if( *(p-1) == '\r' ) *(p-1) = '\0'; *p = '\0'; // handle the command if( *m_pBuffer != '\0' ) { switch(m_state) { case STATE_USER: m_username = string(m_pBuffer); m_pConsole->Write("password: "******"\r\nAttempting to authenticate. Please wait.\r\n"); m_state = STATE_WAITING; m_requestNo = ConsoleAuthMgr::getSingleton().GenerateRequestId(); ConsoleAuthMgr::getSingleton().SetRequest(m_requestNo, this); TestConsoleLogin(m_username, m_password, m_requestNo); break; case STATE_LOGGED: if( !strnicmp( m_pBuffer, "quit", 4 ) ) { Disconnect(); break; } HandleConsoleInput(m_pConsole, m_pBuffer); break; } } // move the bytes back if( rlen == m_pBufferPos ) { m_pBuffer[0] = '\0'; m_pBufferPos = 0; } else { memcpy(m_pBuffer, &m_pBuffer[rlen], m_pBufferPos - rlen); m_pBufferPos -= rlen; } p = strchr(m_pBuffer, '\n'); } }
void AuthSocket::HandleTransferCancel() { GetReadBuffer()->Remove(1); Disconnect(); }
void AuthSocket::HandleChallenge() { // No header if(GetReadBuffer()->GetSize() < 4) return; if(sInfoCore.GetRealmMap().empty()) { // If we lack a realm to connect to, block em, it's better then making them sit and get locked into an empty list. SendChallengeError(CE_IPBAN); return; } // Check the rest of the packet is complete. uint8 * ReceiveBuffer = (uint8*)GetReadBuffer()->GetBufferOffset(); uint16 full_size = *(uint16*)&ReceiveBuffer[2]; DEBUG_LOG("AuthChallenge","got header, body is 0x%02X bytes", full_size); if(GetReadBuffer()->GetSize() < uint32(full_size+4)) return; // Copy the data into our cached challenge structure if(full_size > sizeof(sAuthLogonChallenge_C)) { Disconnect(); return; } DEBUG_LOG("AuthChallenge","got full packet."); GetReadBuffer()->Read(&m_challenge, full_size + 4); // Check client build. if(GetBuild() > LogonServer::getSingleton().max_build) { SendChallengeError(CE_WRONG_BUILD_NUMBER); return; } if(GetBuild() < LogonServer::getSingleton().min_build) { // can we patch? char flippedloc[5] = {0,0,0,0,0}; flippedloc[0] = m_challenge.country[3]; flippedloc[1] = m_challenge.country[2]; flippedloc[2] = m_challenge.country[1]; flippedloc[3] = m_challenge.country[0]; m_patch = PatchMgr::getSingleton().FindPatchForClient(GetBuild(), flippedloc); if(m_patch == NULL) { // could not find a valid patch SendChallengeError(CE_WRONG_BUILD_NUMBER); return; } DEBUG_LOG("Patch", "Selected patch %u%s for client.", m_patch->Version,m_patch->Locality); BigNumber unk; unk.SetRand(128); uint8 response[119] = { 0x00, 0x00, 0x00, 0x72, 0x50, 0xa7, 0xc9, 0x27, 0x4a, 0xfa, 0xb8, 0x77, 0x80, 0x70, 0x22, 0xda, 0xb8, 0x3b, 0x06, 0x50, 0x53, 0x4a, 0x16, 0xe2, 0x65, 0xba, 0xe4, 0x43, 0x6f, 0xe3, 0x29, 0x36, 0x18, 0xe3, 0x45, 0x01, 0x07, 0x20, 0x89, 0x4b, 0x64, 0x5e, 0x89, 0xe1, 0x53, 0x5b, 0xbd, 0xad, 0x5b, 0x8b, 0x29, 0x06, 0x50, 0x53, 0x08, 0x01, 0xb1, 0x8e, 0xbf, 0xbf, 0x5e, 0x8f, 0xab, 0x3c, 0x82, 0x87, 0x2a, 0x3e, 0x9b, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x32, 0xa3, 0x49, 0x76, 0x5c, 0x5b, 0x35, 0x9a, 0x93, 0x3c, 0x6f, 0x3c, 0x63, 0x6d, 0xc0, 0x00 }; Send(response, 119); return; } // Check for a possible IP ban on this client. BAN_STATUS ipb = IPBanner::getSingleton().CalculateBanStatus(GetRemoteAddress()); switch(ipb) { case BAN_STATUS_PERMANENT_BAN: SendChallengeError(CE_ACCOUNT_CLOSED); return; case BAN_STATUS_TIME_LEFT_ON_BAN: SendChallengeError(CE_ACCOUNT_FREEZED); return; default: break; } // Null-terminate the account string if(m_challenge.I_len >= 0x50) { Disconnect(); return; } m_challenge.I[m_challenge.I_len] = 0; AccountName = (char*)&m_challenge.I; string::size_type i = AccountName.rfind("#"); if( i != string::npos ) { printf("# ACCOUNTNAME!\n"); return; } // Look up the account information m_account = AccountMgr::getSingleton().GetAccount(AccountName); if(m_account == 0) { DEBUG_LOG("AuthChallenge","Account Name: \"%s\" - Account state: INVALID", AccountName.c_str()); // Non-existant account SendChallengeError(CE_NO_ACCOUNT); return; } // Check that the account isn't banned. if(m_account->Banned == 1) { SendChallengeError(CE_ACCOUNT_CLOSED); Log.Notice("AuthChallenge","Account Name: \"%s\" - Account state: CLOSED", AccountName.c_str()); return; } else if(m_account->Banned > 0) { SendChallengeError(CE_ACCOUNT_FREEZED); Log.Notice("AuthChallenge","Account Name: \"%s\" - Account state: FROZEN (%u)", AccountName.c_str(), m_account->Banned); return; } else Log.Notice("AuthChallenge","Account Name: \"%s\" - Account state: OK", AccountName.c_str()); // update cached locale if(!m_account->forcedLocale) { char temp[4]; temp[0] = m_challenge.country[3]; temp[1] = m_challenge.country[2]; temp[2] = m_challenge.country[1]; temp[3] = m_challenge.country[0]; *(uint32*)&m_account->Locale[0] = *(uint32*)temp; } Sha1Hash sha; //uint32 tc = s.GetNumBytes(); sha.UpdateData( s.AsByteArray(), 32 ); sha.UpdateData( m_account->SrpHash, 20 ); sha.Finalize(); BigNumber x; x.SetBinary( sha.GetDigest(), sha.GetLength() ); v = g.ModExp(x, N); b.SetRand(152); BigNumber gmod = g.ModExp(b, N); B = ((v * 3) + gmod) % N; ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk; unk.SetRand(128); uint8 response[200]; uint32 c = 0; response[c] = 0; c += 1; response[c] = 0; c += 1; response[c] = CE_SUCCESS; c += 1; memcpy(&response[c], B.AsByteArray(), 32); c += 32; response[c] = 1; c += 1; response[c] = g.AsByteArray()[0]; c += 1; response[c] = 32; c += 1; memcpy(&response[c], N.AsByteArray(), 32); c += 32; memcpy(&response[c], s.AsByteArray(), s.GetNumBytes()); c += s.GetNumBytes(); memcpy(&response[c], unk.AsByteArray(), 16); c += 16; response[c] = 0; c += 1; Send(response, c); DEBUG_LOG("AuthSocket","Sending Success Response"); }
void WSSocket::OnRead() { for(;;) { if(!_cmd) { if(readBuffer.GetSize() < 6) break; readBuffer.Read(&_cmd, 2); readBuffer.Read(&_remaining, 4); } if(_remaining && readBuffer.GetSize() < _remaining) break; if(_cmd == ICMSG_WOW_PACKET) { uint32 sid; uint16 op; uint32 sz; GetReadBuffer().Read(&sid, 4); GetReadBuffer().Read(&op, 2); GetReadBuffer().Read(&sz, 4); Session * session = sClientMgr.GetSession(sid); if(session != NULL && session->GetSocket() != NULL) { uint8* buf = new uint8[sz]; GetReadBuffer().Read(buf, sz); session->GetSocket()->OutPacket(op, sz, buf); delete [] buf; } else GetReadBuffer().Remove(sz); _cmd = 0; continue; } WorldPacket * pck = new WorldPacket(_cmd, _remaining); _cmd = 0; pck->resize(_remaining); readBuffer.Read((uint8*)pck->contents(), _remaining); if(_authenticated) { // push to queue if(!_ws) { if(pck->GetOpcode() == ICMSG_REGISTER_WORKER) { // handle register worker HandleRegisterWorker(*pck); } /* I deliberately don't delete pck here for a reason :P */ } else { _ws->QueuePacket(pck); } } else { if(pck->GetOpcode() != ICMSG_AUTH_REPLY) Disconnect(); else HandleAuthRequest(*pck); delete pck; } } }
void KOSocket::OnRead() { Packet pkt; for (;;) { if (m_remaining == 0) { if (GetReadBuffer().GetSize() < 5) return; //check for opcode as well uint16 header = 0; GetReadBuffer().Read(&header, 2); if (header != 0x55aa) { TRACE("%s: Got packet without header 0x55AA, got 0x%X\n", GetRemoteIP().c_str(), header); goto error_handler; } GetReadBuffer().Read(&m_remaining, 2); if (m_remaining == 0) { TRACE("%s: Got packet without an opcode, this should never happen.\n", GetRemoteIP().c_str()); goto error_handler; } } if (m_remaining > GetReadBuffer().GetAllocatedSize()) { TRACE("%s: Packet received which was %u bytes in size, maximum of %u.\n", GetRemoteIP().c_str(), m_remaining, GetReadBuffer().GetAllocatedSize()); goto error_handler; } if (m_remaining > GetReadBuffer().GetSize()) { if (m_readTries > 4) { TRACE("%s: packet fragmentation count is over 4, disconnecting as they're probably up to something bad\n", GetRemoteIP().c_str()); goto error_handler; } m_readTries++; return; } uint8 *in_stream = new uint8[m_remaining]; m_readTries = 0; GetReadBuffer().Read(in_stream, m_remaining); uint16 footer = 0; GetReadBuffer().Read(&footer, 2); if (footer != 0xaa55 || !DecryptPacket(in_stream, pkt)) { TRACE("%s: Footer invalid (%X) or failed to decrypt.\n", GetRemoteIP().c_str(), footer); delete [] in_stream; goto error_handler; } delete [] in_stream; if (!HandlePacket(pkt)) { TRACE("%s: Handler for packet %X returned false\n", GetRemoteIP().c_str(), pkt.GetOpcode()); #ifndef _DEBUG goto error_handler; #endif } m_remaining = 0; } return; error_handler: GetReadBuffer().Remove(GetReadBuffer().GetSize()); Disconnect(); }
void AuthSocket::HandleReconnectChallenge() { // No header if(GetReadBuffer()->GetSize() < 4) return; // Check the rest of the packet is complete. uint8 * ReceiveBuffer = (uint8*)GetReadBuffer()->GetBufferOffset(); uint16 full_size = *(uint16*)&ReceiveBuffer[2]; DEBUG_LOG("ReconnectChallenge","got header, body is 0x%02X bytes", full_size); if(GetReadBuffer()->GetSize() < (uint32)full_size+4) return; // Copy the data into our cached challenge structure if((size_t)(full_size+4) > sizeof(sAuthLogonChallenge_C)) { Disconnect(); return; } DEBUG_LOG("ReconnectChallenge", "got full packet."); memcpy(&m_challenge, ReceiveBuffer, full_size + 4); GetReadBuffer()->Read(&m_challenge, full_size + 4); // Check client build. if(m_challenge.build > LogonServer::getSingleton().max_build || m_challenge.build < LogonServer::getSingleton().min_build) { SendChallengeError(CE_WRONG_BUILD_NUMBER); return; } // Check for a possible IP ban on this client. BAN_STATUS ipb = IPBanner::getSingleton().CalculateBanStatus(GetRemoteAddress()); switch(ipb) { case BAN_STATUS_PERMANENT_BAN: SendChallengeError(CE_ACCOUNT_CLOSED); return; case BAN_STATUS_TIME_LEFT_ON_BAN: SendChallengeError(CE_ACCOUNT_FREEZED); return; default: break; } // Null-terminate the account string if( m_challenge.I_len >= 50 ) { Disconnect(); return; } m_challenge.I[m_challenge.I_len] = 0; // Look up the account information AccountName = (char*)&m_challenge.I; Log.Notice("ReconnectChallenge","Account Name: \"%s\"", AccountName.c_str()); m_account = AccountMgr::getSingleton().GetAccount(AccountName); if(m_account == 0) { DEBUG_LOG("ReconnectChallenge","Invalid account."); // Non-existant account SendChallengeError(CE_NO_ACCOUNT); return; } // Check that the account isn't banned. if(m_account->Banned == 1) { SendChallengeError(CE_ACCOUNT_CLOSED); Log.Notice("ReconnectChallenge","Account banned state = %u", m_account->Banned); return; } else if(m_account->Banned > 0) { SendChallengeError(CE_ACCOUNT_FREEZED); Log.Notice("ReconnectChallenge","Account banned state = %u", m_account->Banned); return; } else DEBUG_LOG("ReconnectChallenge","Account banned state = %u", m_account->Banned); if(!m_account->SessionKey) { SendChallengeError(CE_SERVER_FULL); return; } /** Mangos figured this out, thanks for the structure. */ ///- Sending response if(GetBuild() <= 6005) { MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, m_account->SessionKey, 40); uint8 buffer[20]; MD5_Final(buffer, &ctx); ByteBuffer buf; buf << uint16(2); buf.append(buffer, 20); buf << uint64(0); buf << uint64(0); Send(buf.contents(), 34); } else { ByteBuffer pkt; pkt << (uint8) 0x02; //ReconnectChallenge pkt << (uint8) 0x00; rs.SetRand(16*8); pkt.append(rs.AsByteBuffer()); // 16 bytes random pkt << uint64(0x00) << uint64(0x00); // 16 bytes zeros Send(pkt.contents(), uint32(pkt.size())); } }
void AuthSocket::HandleReconnectChallenge() { // No header if(GetReadBuffer().GetContiguiousBytes() < 4) return; // Check the rest of the packet is complete. uint8 * ReceiveBuffer = /*GetReadBuffer(0)*/(uint8*)GetReadBuffer().GetBufferStart(); uint16 full_size = *(uint16*)&ReceiveBuffer[2]; sLog.outDetail("[AuthChallenge] got header, body is 0x%02X bytes", full_size); if(GetReadBuffer().GetSize() < (uint32)full_size+4) return; // Copy the data into our cached challenge structure if((size_t)(full_size+4) > sizeof(sAuthLogonChallenge_C)) { Disconnect(); return; } sLog.outDebug("[AuthChallenge] got full packet."); memcpy(&m_challenge, ReceiveBuffer, full_size + 4); //RemoveReadBufferBytes(full_size + 4, false); GetReadBuffer().Read(&m_challenge, full_size + 4); // Check client build. if(m_challenge.build > LogonServer::getSingleton().max_build || m_challenge.build < LogonServer::getSingleton().min_build) { SendChallengeError(CE_WRONG_BUILD_NUMBER); return; } // Check for a possible IP ban on this client. BAN_STATUS ipb = IPBanner::getSingleton().CalculateBanStatus(GetRemoteAddress()); switch(ipb) { case BAN_STATUS_PERMANENT_BAN: SendChallengeError(CE_ACCOUNT_CLOSED); return; case BAN_STATUS_TIME_LEFT_ON_BAN: SendChallengeError(CE_ACCOUNT_FREEZED); return; default: break; } // Null-terminate the account string m_challenge.I[m_challenge.I_len] = 0; // Clear the shitty hash (for server) /* size_t i = 0; for( i = m_challenge.I_len; i >= 0; --i ) { if( m_challenge.I[i] == '#' ) { m_challenge.I[i] = '\0'; break; } }*/ // Look up the account information string AccountName = (char*)&m_challenge.I; sLog.outDebug("[AuthChallenge] Account Name: \"%s\"", AccountName.c_str()); m_account = AccountMgr::getSingleton().GetAccount(AccountName); if(m_account == 0) { sLog.outDebug("[AuthChallenge] Invalid account."); // Non-existant account SendChallengeError(CE_NO_ACCOUNT); return; } sLog.outDebug("[AuthChallenge] Account banned state = %u", m_account->Banned); // Check that the account isn't banned. if(m_account->Banned == 1) { SendChallengeError(CE_ACCOUNT_CLOSED); return; } else if(m_account->Banned > 0) { SendChallengeError(CE_ACCOUNT_FREEZED); return; } if(!m_account->SessionKey) { SendChallengeError(CE_SERVER_FULL); return; } /** burlex: this is pure speculation, I really have no idea what this does :p * just guessed the md5 because it was 16 byte blocks. */ MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, m_account->SessionKey, 40); uint8 buffer[20]; MD5_Final(buffer, &ctx); ByteBuffer buf; buf << uint16(2); buf.append(buffer, 20); buf << uint64(0); buf << uint64(0); Send(buf.contents(), 34); }
void AuthSocket::HandleProof() { if(GetReadBuffer()->GetSize() < sizeof(sAuthLogonProof_C)) return; // patch if(m_patch&&!m_account) { //RemoveReadBufferBytes(75,false); GetReadBuffer()->Remove(75); DEBUG_LOG("AuthLogonProof","Intitiating PatchJob"); uint8 bytes[2] = {0x01,0x0a}; Send(bytes,2); PatchMgr::getSingleton().InitiatePatch(m_patch, this); return; } if(!m_account) return; DEBUG_LOG("AuthLogonProof","Interleaving and checking proof..."); sAuthLogonProof_C lp; GetReadBuffer()->Read(&lp, sizeof(sAuthLogonProof_C)); BigNumber A; A.SetBinary(lp.A, 32); Sha1Hash sha; sha.UpdateBigNumbers(&A, &B, 0); sha.Finalize(); BigNumber u; u.SetBinary(sha.GetDigest(), 20); BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N); uint8 t[32]; uint8 t1[16]; uint8 vK[40]; memcpy(t, S.AsByteArray(), 32); for (int i = 0; i < 16; i++) { t1[i] = t[i*2]; } sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); for (int i = 0; i < 20; i++) { vK[i*2] = sha.GetDigest()[i]; } for (int i = 0; i < 16; i++) { t1[i] = t[i*2+1]; } sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); for (int i = 0; i < 20; i++) { vK[i*2+1] = sha.GetDigest()[i]; } m_sessionkey.SetBinary(vK, 40); uint8 hash[20]; sha.Initialize(); sha.UpdateBigNumbers(&N, NULL); sha.Finalize(); memcpy(hash, sha.GetDigest(), 20); sha.Initialize(); sha.UpdateBigNumbers(&g, NULL); sha.Finalize(); for (int i = 0; i < 20; i++) { hash[i] ^= sha.GetDigest()[i]; } BigNumber t3; t3.SetBinary(hash, 20); sha.Initialize(); sha.UpdateData((const uint8*)m_account->UsernamePtr->c_str(), (int)m_account->UsernamePtr->size()); sha.Finalize(); BigNumber t4; t4.SetBinary(sha.GetDigest(), 20); sha.Initialize(); sha.UpdateBigNumbers(&t3, &t4, &s, &A, &B, &m_sessionkey, NULL); sha.Finalize(); BigNumber M; M.SetBinary(sha.GetDigest(), 20); // Compare M1 values. if(memcmp(lp.M1, M.AsByteArray(), 20) != 0) { // Authentication failed. //SendProofError(4, 0); SendChallengeError(CE_NO_ACCOUNT); DEBUG_LOG("AuthLogonProof","M1 values don't match."); return; } // Store sessionkey m_account->SetSessionKey(m_sessionkey.AsByteArray()); // OUT_DEBUG("========================\nSession key: "); // for(uint32 z = 0; z < 40; ++z) // OUT_DEBUG("%.2X ", m_account->SessionKey[z]); // OUT_DEBUG("\n========================\n"); // let the client know sha.Initialize(); sha.UpdateBigNumbers(&A, &M, &m_sessionkey, 0); sha.Finalize(); if(GetBuild() <= 6005) { sAuthLogonProof_S proof; proof.cmd = 0x01; proof.error = 0; memcpy(proof.M2, sha.GetDigest(), 20); proof.unk2 = 0; SendPacket( (uint8*) &proof, sizeof(proof) ); } else SendProofError(0, sha.GetDigest()); DEBUG_LOG("AuthLogonProof","Authentication Success."); // we're authenticated now :) m_authenticated = true; // Don't update when IP banned, but update anyway if it's an account ban const char* m_sessionkey_hex = m_sessionkey.AsHexStr(); sLogonSQL->Execute("UPDATE accounts SET lastlogin=NOW(), SessionKey = '%s', lastip='%s' WHERE acct=%u;", m_sessionkey_hex, GetIP(), m_account->AccountId); }
void WorldSocket::OnRead() { for(;;) { // Check for the header if we don't have any bytes to wait for. if(mRemaining == 0) { if(GetReadBuffer().GetSize() < 6) { // No header in the packet, let's wait. return; } // Copy from packet buffer into header local var ClientPktHeader Header; GetReadBuffer().Read((uint8*)&Header, 6); // Decrypt the header _crypt.DecryptRecv((uint8*)&Header, sizeof (ClientPktHeader)); #ifdef USING_BIG_ENDIAN mRemaining = mSize = Header.size - 4; mOpcode = swap32(Header.cmd); #else mRemaining = mSize = ntohs(Header.size) - 4; mOpcode = Header.cmd; #endif } WorldPacket * Packet; if(mRemaining > 0) { if( GetReadBuffer().GetSize() < mRemaining ) { // We have a fragmented packet. Wait for the complete one before proceeding. return; } } Packet = new WorldPacket( static_cast<uint16>( mOpcode ), mSize); Packet->resize(mSize); if(mRemaining > 0) { // Copy from packet buffer into our actual buffer. ///Read(mRemaining, (uint8*)Packet->contents()); GetReadBuffer().Read((uint8*)Packet->contents(), mRemaining); } sWorldLog.LogPacket(mSize, static_cast<uint16>( mOpcode ), mSize ? Packet->contents() : NULL, 0, (mSession ? mSession->GetAccountId() : 0) ); mRemaining = mSize = mOpcode = 0; // Check for packets that we handle switch(Packet->GetOpcode()) { case CMSG_PING: { _HandlePing(Packet); delete Packet; }break; case CMSG_AUTH_SESSION: { _HandleAuthSession(Packet); }break; default: { if(mSession) mSession->QueuePacket(Packet); else delete Packet; }break; } } }
void AuthSocket::HandleChallenge() { // No header if(GetReadBuffer().GetContiguiousBytes() < 4) return; // Check the rest of the packet is complete. uint8 * ReceiveBuffer = (uint8*)GetReadBuffer().GetBufferStart(); #ifdef USING_BIG_ENDIAN uint16 full_size = swap16(*(uint16*)&ReceiveBuffer[2]); #else uint16 full_size = *(uint16*)&ReceiveBuffer[2]; #endif sLog.outDetail("[AuthChallenge] got header, body is 0x%02X bytes", full_size); if(GetReadBuffer().GetSize() < uint32(full_size+4)) return; // Copy the data into our cached challenge structure if(full_size > sizeof(sAuthLogonChallenge_C)) { Disconnect(); return; } sLog.outDebug("[AuthChallenge] got full packet."); //memcpy(&m_challenge, ReceiveBuffer, full_size + 4); //RemoveReadBufferBytes(full_size + 4, true); GetReadBuffer().Read(&m_challenge, full_size + 4); //#ifdef USING_BIG_ENDIAN // uint16 build = swap16(m_challenge.build); // printf("Build: %u\n", build); //#endif // Check client build. #ifdef USING_BIG_ENDIAN uint16 build = swap16(m_challenge.build); #else uint16 build = m_challenge.build; #endif // Check client build. if(build > LogonServer::getSingleton().max_build) { // wtf? SendChallengeError(CE_WRONG_BUILD_NUMBER); return; } if(build < LogonServer::getSingleton().min_build) { // can we patch? char flippedloc[5] = {0,0,0,0,0}; flippedloc[0] = m_challenge.country[3]; flippedloc[1] = m_challenge.country[2]; flippedloc[2] = m_challenge.country[1]; flippedloc[3] = m_challenge.country[0]; m_patch = PatchMgr::getSingleton().FindPatchForClient(build, flippedloc); if(m_patch == NULL) { // could not find a valid patch SendChallengeError(CE_WRONG_BUILD_NUMBER); return; } Log.Debug("Patch", "Selected patch %u%s for client.", m_patch->Version,m_patch->Locality); uint8 response[119] = { 0x00, 0x00, 0x00, 0x72, 0x50, 0xa7, 0xc9, 0x27, 0x4a, 0xfa, 0xb8, 0x77, 0x80, 0x70, 0x22, 0xda, 0xb8, 0x3b, 0x06, 0x50, 0x53, 0x4a, 0x16, 0xe2, 0x65, 0xba, 0xe4, 0x43, 0x6f, 0xe3, 0x29, 0x36, 0x18, 0xe3, 0x45, 0x01, 0x07, 0x20, 0x89, 0x4b, 0x64, 0x5e, 0x89, 0xe1, 0x53, 0x5b, 0xbd, 0xad, 0x5b, 0x8b, 0x29, 0x06, 0x50, 0x53, 0x08, 0x01, 0xb1, 0x8e, 0xbf, 0xbf, 0x5e, 0x8f, 0xab, 0x3c, 0x82, 0x87, 0x2a, 0x3e, 0x9b, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x32, 0xa3, 0x49, 0x76, 0x5c, 0x5b, 0x35, 0x9a, 0x93, 0x3c, 0x6f, 0x3c, 0x63, 0x6d, 0xc0, 0x00 }; Send(response, 119); return; } // Check for a possible IP ban on this client. BAN_STATUS ipb = IPBanner::getSingleton().CalculateBanStatus(GetRemoteAddress()); switch(ipb) { case BAN_STATUS_PERMANENT_BAN: SendChallengeError(CE_ACCOUNT_CLOSED); return; case BAN_STATUS_TIME_LEFT_ON_BAN: SendChallengeError(CE_ACCOUNT_FREEZED); return; default: break; } // Null-terminate the account string if(m_challenge.I_len >= 0x50) { Disconnect(); return; } m_challenge.I[m_challenge.I_len] = 0; // Clear the shitty hash (for server) string AccountName = (char*)&m_challenge.I; string::size_type i = AccountName.rfind("#"); if( i != string::npos ) { printf("# ACCOUNTNAME!\n"); return; //AccountName.erase( i ); } // Look up the account information sLog.outDebug("[AuthChallenge] Account Name: \"%s\"", AccountName.c_str()); m_account = AccountMgr::getSingleton().GetAccount(AccountName); if(m_account == 0) { sLog.outDebug("[AuthChallenge] Invalid account."); // Non-existant account SendChallengeError(CE_NO_ACCOUNT); return; } sLog.outDebug("[AuthChallenge] Account banned state = %u", m_account->Banned); // Check that the account isn't banned. if(m_account->Banned == 1) { SendChallengeError(CE_ACCOUNT_CLOSED); return; } else if(m_account->Banned > 0) { SendChallengeError(CE_ACCOUNT_FREEZED); return; } // update cached locale if(!m_account->forcedLocale) { char temp[4]; temp[0] = m_challenge.country[3]; temp[1] = m_challenge.country[2]; temp[2] = m_challenge.country[1]; temp[3] = m_challenge.country[0]; *(uint32*)&m_account->Locale[0] = *(uint32*)temp; } Sha1Hash sha; //uint32 tc = s.GetNumBytes(); sha.UpdateData( s.AsByteArray(), 32 ); sha.UpdateData( m_account->SrpHash, 20 ); sha.Finalize(); BigNumber x; x.SetBinary( sha.GetDigest(), sha.GetLength() ); v = g.ModExp(x, N); b.SetRand(152); BigNumber gmod = g.ModExp(b, N); B = ((v * 3) + gmod) % N; ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk; unk.SetRand(128); uint8 response[200]; uint32 c = 0; response[c] = 0; c += 1; response[c] = 0; c += 1; response[c] = CE_SUCCESS; c += 1; memcpy(&response[c], B.AsByteArray(), 32); c += 32; response[c] = 1; c += 1; response[c] = g.AsByteArray()[0]; c += 1; response[c] = 32; c += 1; memcpy(&response[c], N.AsByteArray(), 32); c += 32; memcpy(&response[c], s.AsByteArray(), s.GetNumBytes()); c += s.GetNumBytes(); memcpy(&response[c], unk.AsByteArray(), 16); c += 16; response[c] = 0; c += 1; Send(response, c); }