void VoiceChatClientSocket::OnRead() { WorldPacket *data; // uint16 op // uint16 size // <data> for(;;) { // no more data if( GetReadBufferSize() < 4 ) break; Read(2, (uint8*)&op); Read(2, (uint8*)&remaining); if( GetReadBufferSize() < remaining ) break; data = new WorldPacket(op, remaining); data->resize(remaining); Read(remaining, (uint8*)data->contents()); // handle the packet sVoiceChatHandler.OnRead(data); delete data; remaining = op = 0; } }
void WSClient::OnRead() { for(;;) { if(!_cmd) { if(GetReadBufferSize() < 6) break; Read(2, (uint8*)&_cmd); Read(4, (uint8*)&_remaining); } if(_remaining && GetReadBufferSize() < _remaining) break; if(_cmd == ISMSG_WOW_PACKET) { /* optimized version for packet passing, to reduce latency! ;) */ uint32 sid = *(uint32*)&m_readBuffer[0]; uint16 op = *(uint16*)&m_readBuffer[4]; uint32 sz = *(uint32*)&m_readBuffer[6]; WorldSession * session = sClusterInterface.GetSession(sid); if(session != NULL) { WorldPacket * pck = new WorldPacket(op, sz); pck->resize(sz); memcpy((void*)pck->contents(), &m_readBuffer[10], sz); session->QueuePacket(pck); } RemoveReadBufferBytes(sz + 10/*header*/, false); _cmd = 0; continue; } WorldPacket * pck = new WorldPacket(_cmd, _remaining); _cmd = 0; pck->resize(_remaining); Read(_remaining, (uint8*)pck->contents()); /* we could handle auth here */ switch(_cmd) { case ISMSG_AUTH_REQUEST: sClusterInterface.HandleAuthRequest(*pck); delete pck; break; default: sClusterInterface.QueuePacket(pck); } } }
void AuthSocket::HandleReconnectProof() { /* printf("Len: %u\n", this->GetReadBufferSize()); ByteBuffer buf(58); buf.resize(58); Read(58, const_cast<uint8*>(buf.contents())); buf.hexlike();*/ // 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); 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 LogonCommClientSocket::OnRead() { while(true) { if(!remaining) { if(GetReadBufferSize() < 4) return; // no header // read header Read(2, (uint8*)&opcode); Read(4, (uint8*)&remaining); // decrypt the first two bytes if(use_crypto) { _recvCrypto.Process((uint8*)&opcode, (uint8*)&opcode, 2); _recvCrypto.Process((uint8*)&remaining, (uint8*)&remaining, 4); } // convert network byte order remaining = ntohl(remaining); } // do we have a full packet? if(GetReadBufferSize() < remaining) return; // create the buffer WorldPacket buff(opcode, remaining); if(remaining) { buff.resize(remaining); Read(remaining, (uint8*)buff.contents()); } // decrypt the rest of the packet 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::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 WorldSocket::OnRead() { for(;;) { // Check for the header if we don't have any bytes to wait for. if(mRemaining == 0) { if(GetReadBufferSize() < 6) { // No header in the packet, let's wait. return; } // Copy from packet buffer into header local var ClientPktHeader Header; Read(6, (uint8*)&Header); // Decrypt the header _crypt.DecryptSixRecv((uint8*)&Header); #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( GetReadBufferSize() < 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()); } 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: { _HandlePing(Packet); delete Packet; }break; case CMSG_AUTH_SESSION: { _HandleAuthSession(Packet); }break; default: { if(mSession) mSession->QueuePacket(Packet); else delete Packet; }break; } } }
if (getpeername(m_sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { throw CSocketException("Fetch of foreign port failed (getpeername())", true); } return ntohs(addr.sin_port); } CSocket& CSocket::operator<<(const string& sStr ) { Send(sStr.c_str(), sStr.length()); return *this; } CSocket& CSocket::operator>>( string& sStr ) { char *buff = new char[GetReadBufferSize()]; Recv(buff, GetReadBufferSize()); sStr.append(buff); delete [] buff; return *this; } int CSocket::OnDataRead(unsigned long timeToWait) { /* master file descriptor list */ fd_set master; struct timeval *ptimeout = NULL; /* temp file descriptor list for select() */ fd_set read_fds;
void AuthSocket::HandleChallenge() { // No header if(GetReadBufferSize() < 4) return; // Check the rest of the packet is complete. uint8 * ReceiveBuffer = this->GetReadBuffer(0); #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(GetReadBufferSize() < 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); //#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); 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; } // Null-terminate the account string m_challenge.I[m_challenge.I_len] = 0; // 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; } // 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); }
void AuthSocket::HandleReconnectChallenge() { // No header if(GetReadBufferSize() < 4) return; // Check the rest of the packet is complete. uint8 * ReceiveBuffer = GetReadBuffer(0); uint16 full_size = *(uint16*)&ReceiveBuffer[2]; sLog.outDetail("[AuthChallenge] got header, body is 0x%02X bytes", full_size); if(GetReadBufferSize() < (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, false); // 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; } // Null-terminate the account string m_challenge.I[m_challenge.I_len] = 0; // 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(GetReadBufferSize() < sizeof(sAuthLogonProof_C)) return ; // patch if(m_patch&&!m_account) { RemoveReadBufferBytes(75,false); sLog.outDebug("[AuthLogonProof] Intitiating PatchJob"); uint8 bytes[2] = {0x01,0x0a}; Send(bytes,2); PatchMgr::getSingleton().InitiatePatch(m_patch, this); return; } if(!m_account) return; sLog.outDebug("[AuthLogonProof] Interleaving and checking proof..."); sAuthLogonProof_C lp; Read(sizeof(sAuthLogonProof_C), (uint8*)&lp); 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); sLog.outDebug("[AuthLogonProof] M1 values don't match."); return; } // Store sessionkey m_account->SetSessionKey(m_sessionkey.AsByteArray()); // let the client know sha.Initialize(); sha.UpdateBigNumbers(&A, &M, &m_sessionkey, 0); sha.Finalize(); SendProofError(0, sha.GetDigest()); sLog.outDebug("[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 sLogonSQL->Execute("UPDATE accounts SET lastlogin=NOW(), lastip='%s' WHERE acct=%u;", GetRemoteIP().c_str(), m_account->AccountId); }
void AuthSocket::HandleChallenge() { // No header if(GetReadBufferSize() < 4) return; // Check the rest of the packet is complete. uint8 * ReceiveBuffer = this->GetReadBuffer(0); uint16 full_size = *(uint16*)&ReceiveBuffer[2]; sLog.outDetail("[AuthChallenge] got header, body is 0x%02X bytes", full_size); if(GetReadBufferSize() < 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); // 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_PERMANANT_BAN: SendChallengeError(CE_ACCOUNT_CLOSED); return; case BAN_STATUS_TIME_LEFT_ON_BAN: SendChallengeError(CE_ACCOUNT_FREEZED); return; } // Null-terminate the account string m_challenge.I[m_challenge.I_len] = 0; // 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; } 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); }