Beispiel #1
0
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);
	}
}
Beispiel #2
0
void AuthSocket::HandleTransferAccept()
{
	sLog.outDebug("Accepted transfer");
	if(!m_patch)
		return;

	RemoveReadBufferBytes(1,false);
	PatchMgr::getSingleton().BeginPatchJob(m_patch,this,0);
}
Beispiel #3
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);
		}		
	}
}
Beispiel #4
0
void AuthSocket::HandleTransferResume()
{
	sLog.outDebug("Resuming transfer");
	if(!m_patch)
		return;

	RemoveReadBufferBytes(1,false);
	uint64 size;
	Read(8,(uint8*)&size);
	if(size>=m_patch->FileSize)
		return;

	PatchMgr::getSingleton().BeginPatchJob(m_patch,this,(uint32)size);
}
Beispiel #5
0
void Socket::Read(uint32 size, uint8 * buffer)
{
	assert(size <= m_readByteCount);
	memcpy(buffer, m_readBuffer, size);
	RemoveReadBufferBytes(size, false);
}
Beispiel #6
0
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);
}
Beispiel #7
0
void AuthSocket::HandleTransferCancel()
{
	RemoveReadBufferBytes(1,false);
	Disconnect();
}
Beispiel #8
0
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);
}
Beispiel #9
0
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);
}
Beispiel #10
0
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);
}