Beispiel #1
0
void Battlenet::Session::HandleProofResponse(Authentication::ProofResponse const& proofResponse)
{
    if (_modulesWaitingForData.size() < proofResponse.Modules.size())
    {
        Authentication::LogonResponse* complete = new Authentication::LogonResponse();
        complete->SetAuthResult(AUTH_CORRUPTED_MODULE);
        AsyncWrite(complete);
        return;
    }

    ServerPacket* response = nullptr;
    for (size_t i = 0; i < proofResponse.Modules.size(); ++i)
    {
        if (!(this->*(ModuleHandlers[_modulesWaitingForData.front()]))(proofResponse.Modules[i], &response))
            break;

        _modulesWaitingForData.pop();
    }

    if (!response)
    {
        response = new Authentication::LogonResponse();
        static_cast<Authentication::LogonResponse*>(response)->SetAuthResult(AUTH_INTERNAL_ERROR);
    }

    AsyncWrite(response);
}
Beispiel #2
0
void Battlenet::Session::UpdateRealms(std::vector<Realm const*>& realms, std::vector<Battlenet::RealmHandle>& deletedRealms)
{
    for (Realm const* realm : realms)
        AsyncWrite(BuildListUpdate(realm));

    for (Battlenet::RealmHandle& deleted : deletedRealms)
    {
        WoWRealm::ListUpdate* listUpdate = new WoWRealm::ListUpdate();
        listUpdate->UpdateState = WoWRealm::ListUpdate::DELETED;
        listUpdate->Id = deleted;
        AsyncWrite(listUpdate);
    }
}
Beispiel #3
0
void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest)
{
    _accountName = resumeRequest.Login;
    _locale = resumeRequest.Locale;
    _os = resumeRequest.Platform;
    auto baseComponent = std::find_if(resumeRequest.Components.begin(), resumeRequest.Components.end(), [](Component const& c) { return c.Program == "base"; });
    if (baseComponent != resumeRequest.Components.end())
        _build = baseComponent->Build;

    Utf8ToUpperOnlyLatin(_accountName);
    PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO);
    stmt->setString(0, _accountName);
    stmt->setString(1, resumeRequest.GameAccountName);
    PreparedQueryResult result = LoginDatabase.Query(stmt);
    if (!result)
    {
        Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse();
        resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT);
        AsyncWrite(resumeResponse);
        return;
    }

    Field* fields = result->Fetch();

    _accountId = fields[0].GetUInt32();
    K.SetHexStr(fields[1].GetString().c_str());
    _gameAccountId = fields[2].GetUInt32();
    _gameAccountName = resumeRequest.GameAccountName;

    ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint");
    ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume");
    BitStream resumeData;
    uint8 state = 0;
    _reconnectProof.SetRand(16 * 8);

    resumeData.WriteBytes(&state, 1);
    resumeData.WriteBytes(_reconnectProof.AsByteArray().get(), 16);

    resume->DataSize = resumeData.GetSize();
    resume->Data = new uint8[resume->DataSize];
    memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize);

    _modulesWaitingForData.push(MODULE_RESUME);

    Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest();
    proofRequest->Modules.push_back(thumbprint);
    proofRequest->Modules.push_back(resume);
    AsyncWrite(proofRequest);
}
Beispiel #4
0
void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest)
{
    if (_queryCallback)
    {
        Authentication::ResumeResponse* logonResponse = new Authentication::ResumeResponse();
        logonResponse->SetAuthResult(AUTH_LOGON_TOO_FAST);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::ResumeRequest] %s attempted to log too quick after previous attempt!", GetClientInfo().c_str());
        return;
    }

    std::string login = resumeRequest.Login;
    _locale = resumeRequest.Locale;
    _os = resumeRequest.Platform;
    auto baseComponent = std::find_if(resumeRequest.Components.begin(), resumeRequest.Components.end(), [](Component const& c) { return c.Program == "base"; });
    if (baseComponent != resumeRequest.Components.end())
        _build = baseComponent->Build;

    Utf8ToUpperOnlyLatin(login);
    PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO);
    stmt->setString(0, login);
    stmt->setString(1, resumeRequest.GameAccountName);

    _queryCallback = std::bind(&Battlenet::Session::HandleResumeRequestCallback, this, std::placeholders::_1);
    _queryFuture = LoginDatabase.AsyncQuery(stmt);
}
Beispiel #5
0
void Battlenet::Session::HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& /*listSubscribeRequest*/)
{
    WoWRealm::ListSubscribeResponse* listSubscribeResponse = new WoWRealm::ListSubscribeResponse();

    PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS);
    stmt->setUInt32(0, _gameAccountId);

    if (PreparedQueryResult countResult = LoginDatabase.Query(stmt))
    {
        do
        {
            Field* fields = countResult->Fetch();
            uint32 build = fields[4].GetUInt32();
            listSubscribeResponse->CharacterCounts.push_back({ RealmId(fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32(), (_build != build ? build : 0)), fields[0].GetUInt8() });
        } while (countResult->NextRow());
    }

    for (RealmList::RealmMap::value_type const& i : sRealmList->GetRealms())
        listSubscribeResponse->RealmData.push_back(BuildListUpdate(&i.second));

    listSubscribeResponse->RealmData.push_back(new WoWRealm::ListComplete());

    AsyncWrite(listSubscribeResponse);
    _subscribedToRealmListUpdates = true;
}
void CNetwork::Execute(string cmd, ReadCallback_t callback)
{
	boost::lock_guard<boost::mutex> queue_lock_guard(m_CmdQueueMutex);
	m_CmdQueue.push(boost::make_tuple(boost::move(cmd), boost::move(callback)));
	if (m_CmdQueue.size() == 1)
		AsyncWrite(m_CmdQueue.front().get<0>());
}
Beispiel #7
0
VOID WINAPI CompletedWriteRoutine(
  DWORD err, DWORD written, LPOVERLAPPED overlap) {
  auto context = (Connection::IoCompletionRoutine*)overlap;
  auto self = context->self;
  if (err == ERROR_OPERATION_ABORTED) {
    SetEvent(self->cancel_io_event_.get());
    assert(("write operation should not be cancelled", false));
    return;
  }
  bool io = false;
  // The write operation has finished, so read() the next request (if
  // there is no error) or continue write if necessary.
  if ((err == 0) && (written == self->write_size_)) {
    bool pendding = false;
    std::string message;
    {
      std::unique_lock<std::mutex> lock(self->sending_queue_mutex_);
      pendding = !self->sending_queue_.empty();
      if (pendding) {
        message = self->sending_queue_.front();
        self->sending_queue_.pop_front();
        self->state_ = Connection::SEND_PENDDING;
      } else {
        self->state_ = Connection::CONNECTED;
      }
    }
    io = pendding ?
      self->AsyncWrite(message, CompletedWriteRoutine) :
      self->AsyncRead(CompletedReadRoutine);
  }

  if (!io) {
    self->Shutdown();
  }
}
Beispiel #8
0
void Battlenet::Session::CheckIpCallback(PreparedQueryResult result)
{
    if (result)
    {
        bool banned = false;
        do
        {
            Field* fields = result->Fetch();
            if (fields[0].GetUInt64() != 0)
                banned = true;

            if (!fields[1].GetString().empty())
                _ipCountry = fields[1].GetString();

        } while (result->NextRow());

        if (banned)
        {
            Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
            logonResponse->SetAuthResult(AUTH_INTERNAL_ERROR);
            AsyncWrite(logonResponse);
            TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Banned ip '%s:%d' tries to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort());
            return;
        }
    }

    AsyncRead();
}
Beispiel #9
0
void Battlenet::Session::HandleGetStreamItemsRequest(Cache::GetStreamItemsRequest const& getStreamItemsRequest)
{
    if (ModuleInfo* module = sModuleMgr->CreateModule(getStreamItemsRequest.Locale, getStreamItemsRequest.ItemName))
    {
        Cache::GetStreamItemsResponse* getStreamItemsResponse = new Cache::GetStreamItemsResponse();
        getStreamItemsResponse->Index = getStreamItemsRequest.Index;
        getStreamItemsResponse->Modules.push_back(module);
        AsyncWrite(getStreamItemsResponse);
    }
}
	/// <summary>
	/// Asynchronous write of a string message.
	/// NB if the length of the message is greater than MTU it will be split across datagrams.
	/// </summary>
	/// <param name="msg">The string message to send.</param>
	/// <param name="nullTerminate">Whether to null terminate the string or not.</param>
	void DgramListener::AsyncWrite(std::string&& msg, bool nullTerminate)
	{
		auto listener = _udpListener.lock();
		if (!listener)
		{
			throw runtime_error("Connection expired.");
		}

		listener->AsyncWrite(std::move(msg), nullTerminate);
	}
	/// <summary>
	/// Asynchronous write of a string message.
	/// NB if the length of the message is greater than MTU it will be split across datagrams.
	/// </summary>
	/// <param name="msg">The byte vector message to send.</param>
	void DgramListener::AsyncWrite(std::vector<uint8_t>&& msg)
	{
		auto listener = _udpListener.lock();
		if (!listener)
		{
			throw runtime_error("Connection expired.");
		}

		listener->AsyncWrite(std::move(msg));
	}
   void
   TCPConnection::ProcessOperationQueue_(int recurse_level)
   {
      if (recurse_level > 10)
      {
         throw std::logic_error(Formatter::FormatAsAnsi("Recurse level {0} was reached in TCPConnection::ProcessOperationQueue_ for session {1}", recurse_level, session_id_));
      }

      // Pick out the next item to process...
         std::shared_ptr<IOOperation> operation = operation_queue_.Front();

      if (!operation)
      {
         // We're no longer sending...
         return;
      }

      switch (operation->GetType())
      {
      case IOOperation::BCTHandshake:
        {
           AsyncHandshake();
           break;
        }
      case IOOperation::BCTWrite:
         {
               std::shared_ptr<ByteBuffer> pBuf = operation->GetBuffer();
            AsyncWrite(pBuf);
            break;
         }
      case IOOperation::BCTRead:
         {
            AsyncRead(operation->GetString());               
            break;
         }
      case IOOperation::BCTShutdownSend:
         {
            Shutdown(boost::asio::ip::tcp::socket::shutdown_send);
            operation_queue_.Pop(IOOperation::BCTShutdownSend);
            ProcessOperationQueue_(recurse_level + 1);
            break;
         }
      case IOOperation::BCTDisconnect:
         {
            Disconnect();
            operation_queue_.Pop(IOOperation::BCTDisconnect);
            ProcessOperationQueue_(recurse_level + 1);
            break;
         }

      }
   }
Beispiel #13
0
void Battlenet::Session::HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest)
{
    WoWRealm::JoinResponseV2* joinResponse = new WoWRealm::JoinResponseV2();
    Realm const* realm = sRealmList->GetRealm(joinRequest.Realm);
    if (!realm || realm->Flags & (REALM_FLAG_VERSION_MISMATCH | REALM_FLAG_OFFLINE))
    {
        joinResponse->Response = WoWRealm::JoinResponseV2::FAILURE;
        AsyncWrite(joinResponse);
        return;
    }

    joinResponse->ServerSeed = rand32();

    uint8 sessionKey[40];
    HmacSha1 hmac(K.GetNumBytes(), K.AsByteArray().get());
    hmac.UpdateData((uint8*)"WoW\0", 4);
    hmac.UpdateData((uint8*)&joinRequest.ClientSeed, 4);
    hmac.UpdateData((uint8*)&joinResponse->ServerSeed, 4);
    hmac.Finalize();

    memcpy(sessionKey, hmac.GetDigest(), hmac.GetLength());

    HmacSha1 hmac2(K.GetNumBytes(), K.AsByteArray().get());
    hmac2.UpdateData((uint8*)"WoW\0", 4);
    hmac2.UpdateData((uint8*)&joinResponse->ServerSeed, 4);
    hmac2.UpdateData((uint8*)&joinRequest.ClientSeed, 4);
    hmac2.Finalize();

    memcpy(sessionKey + hmac.GetLength(), hmac2.GetDigest(), hmac2.GetLength());

    LoginDatabase.DirectPExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = %u, failed_logins = 0, os = '%s' WHERE id = %u",
        ByteArrayToHexStr(sessionKey, 40, true).c_str(), GetRemoteIpAddress().to_string().c_str(), GetLocaleByName(_locale), _os.c_str(), _gameAccountInfo->Id);

    joinResponse->IPv4.emplace_back(realm->ExternalAddress, realm->Port);
    if (realm->ExternalAddress != realm->LocalAddress)
        joinResponse->IPv4.emplace_back(realm->LocalAddress, realm->Port);

    AsyncWrite(joinResponse);
}
Beispiel #14
0
bool Connection::AsyncWaitWrite() {
  if (CancelIo(pipe_.get())) {
    while (WAIT_OBJECT_0 != WaitForSingleObjectEx(
      cancel_io_event_.get(), INFINITE, TRUE)) {
      continue;
    }
  }
  std::string message;
  std::unique_lock<std::mutex> lock(transact_message_buffer_mutex_);
  message.swap(transact_message_buffer_);
  transact_message_buffer_cond.notify_all();
  return AsyncWrite(message, CompletedWriteRoutineForWait);
}
Beispiel #15
0
void Battlenet::Session::HandleListSubscribeRequestCallback(PreparedQueryResult result)
{
    WoWRealm::ListSubscribeResponse* listSubscribeResponse = new WoWRealm::ListSubscribeResponse();

    if (result)
    {
        do
        {
            Field* fields = result->Fetch();
            listSubscribeResponse->CharacterCounts.push_back({ Battlenet::RealmHandle(fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32()), fields[0].GetUInt8() });
        } while (result->NextRow());
    }

    AsyncWrite(listSubscribeResponse);

    for (RealmList::RealmMap::value_type const& i : sRealmList->GetRealms())
        AsyncWrite(BuildListUpdate(&i.second));

    AsyncWrite(new WoWRealm::ListComplete());

    _subscribedToRealmListUpdates = true;
}
Beispiel #16
0
void Battlenet::Session::HandleResumeRequestCallback(PreparedQueryResult result)
{
    if (!result)
    {
        Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse();
        resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT);
        AsyncWrite(resumeResponse);
        return;
    }

    Field* fields = result->Fetch();
    _accountInfo->LoadResult(fields);
    K.SetHexStr(fields[8].GetString().c_str());

    _gameAccounts.resize(1);
    _gameAccountInfo = &_gameAccounts[0];
    _gameAccountInfo->LoadResult(fields + 9);

    ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint");
    ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume");
    BitStream resumeData;
    uint8 state = 0;
    _reconnectProof.SetRand(16 * 8);

    resumeData.WriteBytes(&state, 1);
    resumeData.WriteBytes(_reconnectProof.AsByteArray().get(), 16);

    resume->DataSize = resumeData.GetSize();
    resume->Data = new uint8[resume->DataSize];
    memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize);

    _modulesWaitingForData.push(MODULE_RESUME);

    Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest();
    proofRequest->Modules.push_back(thumbprint);
    proofRequest->Modules.push_back(resume);
    AsyncWrite(proofRequest);
}
Beispiel #17
0
bool Connection::AsyncWrite() {
  // must cancel read operation first
  if (CancelIo(pipe_.get())) {
    while (WAIT_OBJECT_0 != WaitForSingleObjectEx(
      cancel_io_event_.get(), INFINITE, TRUE)) {
      continue;
    }
  }
  std::string message;
  {
    std::unique_lock<std::mutex> lock(sending_queue_mutex_);
    assert(("no more message to send", !sending_queue_.empty()));
    message = sending_queue_.front();
    sending_queue_.pop_front();
  }
  return AsyncWrite(message, CompletedWriteRoutine);
}
Beispiel #18
0
void Battlenet::Session::SendResponse(uint32 token, uint32 status)
{
    Header header;
    header.set_token(token);
    header.set_status(status);
    header.set_service_id(0xFE);

    uint16 headerSize = header.ByteSize();
    EndianConvertReverse(headerSize);

    MessageBuffer packet;
    packet.Write(&headerSize, sizeof(headerSize));
    uint8* ptr = packet.GetWritePointer();
    packet.WriteCompleted(header.ByteSize());
    header.SerializeToArray(ptr, header.ByteSize());

    AsyncWrite(&packet);
}
Beispiel #19
0
void Battlenet::Session::SendRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request)
{
    Header header;
    header.set_service_id(0);
    header.set_service_hash(serviceHash);
    header.set_method_id(methodId);
    header.set_size(request->ByteSize());
    header.set_token(_requestToken++);

    uint16 headerSize = header.ByteSize();
    EndianConvertReverse(headerSize);

    MessageBuffer packet;
    packet.Write(&headerSize, sizeof(headerSize));
    uint8* ptr = packet.GetWritePointer();
    packet.WriteCompleted(header.ByteSize());
    header.SerializeToArray(ptr, header.ByteSize());
    ptr = packet.GetWritePointer();
    packet.WriteCompleted(request->ByteSize());
    request->SerializeToArray(ptr, request->ByteSize());

    AsyncWrite(&packet);
}
Beispiel #20
0
void Battlenet::Session::Start()
{
    std::string ip_address = GetRemoteIpAddress().to_string();
    TC_LOG_TRACE("session", "Accepted connection from %s", ip_address.c_str());

    if (_queryCallback)
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_LOGON_TOO_FAST);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Session::Start] %s attempted to log too quick after previous attempt!", GetClientInfo().c_str());
        return;
    }

    // Verify that this IP is not in the ip_banned table
    LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));

    PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO);
    stmt->setString(0, ip_address);
    stmt->setUInt32(1, inet_addr(ip_address.c_str()));

    _queryCallback = std::bind(&Battlenet::Session::CheckIpCallback, this, std::placeholders::_1);
    _queryFuture = LoginDatabase.AsyncQuery(stmt);
}
/*
	- result data is sent as a string which ends with "\n\r"
	- the Teamspeak3 server can send multiple strings
	- the end of a result set is always an error result string
*/
void CNetwork::OnRead(const boost::system::error_code &error_code)
{
	if (error_code.value() == 0)
	{
		static vector<string> captured_data;
		std::istream tmp_stream(&m_ReadStreamBuf);
		string read_data;
		std::getline(tmp_stream, read_data, '\r');

#ifdef _DEBUG
		string dbg_read_data(read_data);
		bool first_line = true;
		do
		{
			logprintf("%s> %s", 
				first_line == true ? ">>>" : "   ",
				dbg_read_data.substr(0, 512).c_str());
			dbg_read_data.erase(0, 512);
			first_line = false;
		} while (dbg_read_data.empty() == false);
#endif

		//regex: parse error
		//if this is an error message, it means that no other result data will come
		static const boost::regex error_rx("error id=([0-9]+) msg=([^ \n]+)");
		boost::smatch error_rx_result;
		if (boost::regex_search(read_data, error_rx_result, error_rx))
		{
			if (error_rx_result[1].str() == "0")
			{
				for (auto i = captured_data.begin(); i != captured_data.end(); ++i)
				{
					string &data = *i;
					if (data.find('|') == string::npos) 
						continue;

					//we have multiple data rows with '|' as delimiter here,
					//split them up and re-insert every single row
					vector<string> result_set;
					size_t delim_pos = 0;
					do
					{
						size_t old_delim_pos = delim_pos;
						delim_pos = data.find('|', delim_pos);
						string row = data.substr(old_delim_pos, delim_pos - old_delim_pos);
						result_set.push_back(row);
					} while (delim_pos != string::npos && ++delim_pos);

					i = captured_data.erase(i);
					for (auto j = result_set.begin(), jend = result_set.end(); j != jend; ++j)
						i = captured_data.insert(i, *j);
				}
				
				//call callback and send next command
				m_CmdQueueMutex.lock();
				if (m_CmdQueue.empty() == false)
				{
					ReadCallback_t &callback = m_CmdQueue.front().get<1>();
					if (callback)
					{
						m_CmdQueueMutex.unlock();
						callback(captured_data); //calls the callback
						m_CmdQueueMutex.lock();
					}
					m_CmdQueue.pop();

					if (m_CmdQueue.empty() == false)
						AsyncWrite(m_CmdQueue.front().get<0>());
				}
				m_CmdQueueMutex.unlock();
			}
			else
			{
				string error_str(error_rx_result[2].str());
				unsigned int error_id = 0;

				CUtils::Get()->UnEscapeString(error_str);
				CUtils::Get()->ConvertStringToInt(error_rx_result[1].str(), error_id);

				m_CmdQueueMutex.lock();

				CCallbackHandler::Get()->ForwardError(
					EErrorType::TEAMSPEAK_ERROR, error_id,
					fmt::format("error while executing \"{}\": {}", m_CmdQueue.front().get<0>(), error_str));

				m_CmdQueue.pop();

				if (m_CmdQueue.empty() == false)
					AsyncWrite(m_CmdQueue.front().get<0>());

				m_CmdQueueMutex.unlock();
			}

			captured_data.clear();
		}
		else if (read_data.find("notify") == 0)
		{
			//check if notify is duplicate
			static string last_notify_data;
			static const vector<string> duplicate_notifies{ 
				"notifyclientmoved", 
				"notifycliententerview", 
				"notifyclientleftview" 
			};
			bool is_duplicate = false;
			
			for (auto &s : duplicate_notifies)
			{
				if (read_data.find(s) == 0)
				{
					if (last_notify_data == read_data)
						is_duplicate = true;
					
					break;
				}
			}
			
			if (is_duplicate == false)
			{
				//notify event
				boost::smatch event_result;
				for (auto &event : m_EventList)
				{
					if (boost::regex_search(read_data, event_result, event.get<0>()))
					{
						event.get<1>()(event_result);
						break;
					}
				}
			}

			last_notify_data = read_data;
		}
		else
		{
			//stack the result data if it is not an error or notification message
			captured_data.push_back(read_data);
		}

		AsyncRead();
	}
	else //error
	{
		CCallbackHandler::Get()->ForwardError(
			EErrorType::CONNECTION_ERROR, error_code.value(),
			fmt::format("error while reading: {}", error_code.message()));

		//"disable" the plugin, since calling Disconnect() or
		//destroying CNetwork here is not very smart
		CServer::CSingleton::Destroy();
		m_Connected = false; //we're not _really_ connected, are we?
	}
}
Beispiel #22
0
void Battlenet::Session::HandleSocialNetworkCheckConnected(Friends::SocialNetworkCheckConnected const& socialNetworkCheckConnected)
{
    Friends::SocialNetworkCheckConnectedResult* socialNetworkCheckConnectedResult = new Friends::SocialNetworkCheckConnectedResult();
    socialNetworkCheckConnectedResult->SocialNetworkId = socialNetworkCheckConnected.SocialNetworkId;
    AsyncWrite(socialNetworkCheckConnectedResult);
}
Beispiel #23
0
void Battlenet::Session::HandlePing(Connection::Ping const& /*ping*/)
{
    AsyncWrite(new Connection::Pong());
}
Beispiel #24
0
void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest3 const& logonRequest)
{
    // Verify that this IP is not in the ip_banned table
    LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));

    std::string ip_address = GetRemoteIpAddress().to_string();
    PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_BANNED);
    stmt->setString(0, ip_address);
    if (PreparedQueryResult result = LoginDatabase.Query(stmt))
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(LOGIN_BANNED);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Banned ip '%s:%d' tries to login!", ip_address.c_str(), GetRemotePort());
        return;
    }

    if (logonRequest.Program != "WoW")
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with game other than WoW (using %s)!", GetClientInfo().c_str(), logonRequest.Program.c_str());
        return;
    }

    if (!sComponentMgr->HasPlatform(logonRequest.Platform))
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_INVALID_OS);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in from an unsupported platform (using %s)!", GetClientInfo().c_str(), logonRequest.Platform.c_str());
        return;
    }

    if (!sComponentMgr->HasPlatform(logonRequest.Locale))
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with unsupported locale (using %s)!", GetClientInfo().c_str(), logonRequest.Locale.c_str());
        return;
    }

    for (Component const& component : logonRequest.Components)
    {
        if (!sComponentMgr->HasComponent(&component))
        {
            Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
            if (!sComponentMgr->HasProgram(component.Program))
            {
                logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM);
                TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component program %s!", GetClientInfo().c_str(), component.Program.c_str());
            }
            else if (!sComponentMgr->HasPlatform(component.Platform))
            {
                logonResponse->SetAuthResult(AUTH_INVALID_OS);
                TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component platform %s!", GetClientInfo().c_str(), component.Platform.c_str());
            }
            else
            {
                if (component.Program != "WoW" || AuthHelper::IsBuildSupportingBattlenet(component.Build))
                    logonResponse->SetAuthResult(AUTH_REGION_BAD_VERSION);
                else
                    logonResponse->SetAuthResult(AUTH_USE_GRUNT_LOGON);

                TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component version %u!", GetClientInfo().c_str(), component.Build);
            }

            AsyncWrite(logonResponse);
            return;
        }

        if (component.Platform == "base")
            _build = component.Build;
    }

    _accountName = logonRequest.Login;
    _locale = logonRequest.Locale;
    _os = logonRequest.Platform;

    Utf8ToUpperOnlyLatin(_accountName);
    stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO);
    stmt->setString(0, _accountName);

    PreparedQueryResult result = LoginDatabase.Query(stmt);
    if (!result)
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is trying to log in from unknown account!", GetClientInfo().c_str());
        return;
    }

    Field* fields = result->Fetch();

    _accountId = fields[1].GetUInt32();

    // If the IP is 'locked', check that the player comes indeed from the correct IP address
    if (fields[2].GetUInt8() == 1)                  // if ip is locked
    {
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountName.c_str(), fields[4].GetCString(), ip_address.c_str());

        if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0)
        {
            Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
            logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED);
            AsyncWrite(logonResponse);
            return;
        }
    }
    else
    {
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to ip", _accountName.c_str());
        std::string accountCountry = fields[3].GetString();
        if (accountCountry.empty() || accountCountry == "00")
            TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to country", _accountName.c_str());
        else if (!accountCountry.empty())
        {
            uint32 ip = inet_addr(ip_address.c_str());
            EndianConvertReverse(ip);

            stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY);
            stmt->setUInt32(0, ip);
            if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt))
            {
                std::string loginCountry = (*sessionCountryQuery)[0].GetString();
                TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to country: '%s' Player country is '%s'", _accountName.c_str(), accountCountry.c_str(), loginCountry.c_str());
                if (loginCountry != accountCountry)
                {
                    Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
                    logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED);
                    AsyncWrite(logonResponse);
                    return;
                }
            }
        }
    }

    //set expired bans to inactive
    LoginDatabase.DirectExecute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_BNET_EXPIRED_BANS));

    // If the account is banned, reject the logon attempt
    stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACTIVE_ACCOUNT_BAN);
    stmt->setUInt32(0, _accountId);
    PreparedQueryResult banresult = LoginDatabase.Query(stmt);
    if (banresult)
    {
        Field* fields = banresult->Fetch();
        if (fields[0].GetUInt32() == fields[1].GetUInt32())
        {
            Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
            logonResponse->SetAuthResult(LOGIN_BANNED);
            AsyncWrite(logonResponse);
            TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str());
            return;
        }
        else
        {
            Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
            logonResponse->SetAuthResult(LOGIN_SUSPENDED);
            AsyncWrite(logonResponse);
            TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Temporarily banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str());
            return;
        }
    }

    SHA256Hash sha;
    sha.UpdateData(_accountName);
    sha.Finalize();

    I.SetBinary(sha.GetDigest(), sha.GetLength());

    ModuleInfo* password = sModuleMgr->CreateModule(_os, "Password");
    ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint");

    std::string pStr = fields[0].GetString();

    std::string databaseV = fields[5].GetString();
    std::string databaseS = fields[6].GetString();

    if (databaseV.size() != size_t(BufferSizes::SRP_6_V) * 2 || databaseS.size() != size_t(BufferSizes::SRP_6_S) * 2)
        _SetVSFields(pStr);
    else
    {
        s.SetHexStr(databaseS.c_str());
        v.SetHexStr(databaseV.c_str());
    }

    b.SetRand(128 * 8);
    B = ((v * k) + g.ModExp(b, N)) % N;
    BigNumber unk;
    unk.SetRand(128 * 8);

    BitStream passwordData;
    uint8 state = 0;
    passwordData.WriteBytes(&state, 1);
    passwordData.WriteBytes(I.AsByteArray(32).get(), 32);
    passwordData.WriteBytes(s.AsByteArray(32).get(), 32);
    passwordData.WriteBytes(B.AsByteArray(128).get(), 128);
    passwordData.WriteBytes(unk.AsByteArray(128).get(), 128);

    password->DataSize = passwordData.GetSize();
    password->Data = new uint8[password->DataSize];
    memcpy(password->Data, passwordData.GetBuffer(), password->DataSize);

    _modulesWaitingForData.push(MODULE_PASSWORD);

    Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest();
    proofRequest->Modules.push_back(password);
    // if has authenticator, send Token module
    proofRequest->Modules.push_back(thumbprint);
    AsyncWrite(proofRequest);
}
Beispiel #25
0
void Battlenet::Session::HandleLogonRequestCallback(PreparedQueryResult result)
{
    if (!result)
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is trying to log in from unknown account!", GetClientInfo().c_str());
        return;
    }

    Field* fields = result->Fetch();
    _accountInfo->LoadResult(fields);

    std::string pStr = fields[8].GetString();
    std::string databaseV = fields[9].GetString();
    std::string databaseS = fields[10].GetString();

    _gameAccounts.resize(result->GetRowCount());
    uint32 i = 0;
    do
    {
        _gameAccounts[i++].LoadResult(result->Fetch() + 11);

    } while (result->NextRow());

    std::string ip_address = GetRemoteIpAddress().to_string();
    // If the IP is 'locked', check that the player comes indeed from the correct IP address
    if (_accountInfo->IsLockedToIP)
    {
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountInfo->Login.c_str(), _accountInfo->LastIP.c_str(), ip_address.c_str());

        if (_accountInfo->LastIP != ip_address)
        {
            Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
            logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED);
            AsyncWrite(logonResponse);
            return;
        }
    }
    else
    {
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to ip", _accountInfo->Login.c_str());
        if (_accountInfo->LockCountry.empty() || _accountInfo->LockCountry == "00")
            TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to country", _accountInfo->Login.c_str());
        else if (!_accountInfo->LockCountry.empty() && !_ipCountry.empty())
        {
            TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to country: '%s' Player country is '%s'", _accountInfo->Login.c_str(), _accountInfo->LockCountry.c_str(), _ipCountry.c_str());
            if (_ipCountry != _accountInfo->LockCountry)
            {
                Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
                logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED);
                AsyncWrite(logonResponse);
                return;
            }
        }
    }

    // If the account is banned, reject the logon attempt
    if (_accountInfo->IsBanned)
    {
        if (_accountInfo->IsPermanentlyBanned)
        {
            Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
            logonResponse->SetAuthResult(LOGIN_BANNED);
            AsyncWrite(logonResponse);
            TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountInfo->Login.c_str());
            return;
        }
        else
        {
            Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
            logonResponse->SetAuthResult(LOGIN_SUSPENDED);
            AsyncWrite(logonResponse);
            TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Temporarily banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountInfo->Login.c_str());
            return;
        }
    }

    SHA256Hash sha;
    sha.UpdateData(_accountInfo->Login);
    sha.Finalize();

    I.SetBinary(sha.GetDigest(), sha.GetLength());

    ModuleInfo* password = sModuleMgr->CreateModule(_os, "Password");
    ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint");

    if (databaseV.size() != size_t(BufferSizes::SRP_6_V) * 2 || databaseS.size() != size_t(BufferSizes::SRP_6_S) * 2)
        _SetVSFields(pStr);
    else
    {
        s.SetHexStr(databaseS.c_str());
        v.SetHexStr(databaseV.c_str());
    }

    b.SetRand(128 * 8);
    B = ((v * k) + g.ModExp(b, N)) % N;
    BigNumber unk;
    unk.SetRand(128 * 8);

    BitStream passwordData;
    uint8 state = 0;
    passwordData.WriteBytes(&state, 1);
    passwordData.WriteBytes(I.AsByteArray(32).get(), 32);
    passwordData.WriteBytes(s.AsByteArray(32).get(), 32);
    passwordData.WriteBytes(B.AsByteArray(128).get(), 128);
    passwordData.WriteBytes(unk.AsByteArray(128).get(), 128);

    password->DataSize = passwordData.GetSize();
    password->Data = new uint8[password->DataSize];
    memcpy(password->Data, passwordData.GetBuffer(), password->DataSize);

    _modulesWaitingForData.push(MODULE_PASSWORD);

    Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest();
    proofRequest->Modules.push_back(password);
    // if has authenticator, send Token module
    proofRequest->Modules.push_back(thumbprint);
    AsyncWrite(proofRequest);
}
Beispiel #26
0
void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest const& logonRequest)
{
    if (_queryCallback)
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_LOGON_TOO_FAST);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log too quick after previous attempt!", GetClientInfo().c_str());
        return;
    }

    if (logonRequest.Program != "WoW")
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with game other than WoW (using %s)!", GetClientInfo().c_str(), logonRequest.Program.c_str());
        return;
    }

    if (!sComponentMgr->HasPlatform(logonRequest.Platform))
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_INVALID_OS);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in from an unsupported platform (using %s)!", GetClientInfo().c_str(), logonRequest.Platform.c_str());
        return;
    }

    if (!sComponentMgr->HasPlatform(logonRequest.Locale))
    {
        Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
        logonResponse->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE);
        AsyncWrite(logonResponse);
        TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with unsupported locale (using %s)!", GetClientInfo().c_str(), logonRequest.Locale.c_str());
        return;
    }

    for (Component const& component : logonRequest.Components)
    {
        if (!sComponentMgr->HasComponent(&component))
        {
            Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse();
            if (!sComponentMgr->HasProgram(component.Program))
            {
                logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM);
                TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component program %s!", GetClientInfo().c_str(), component.Program.c_str());
            }
            else if (!sComponentMgr->HasPlatform(component.Platform))
            {
                logonResponse->SetAuthResult(AUTH_INVALID_OS);
                TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component platform %s!", GetClientInfo().c_str(), component.Platform.c_str());
            }
            else
            {
                if (component.Program != "WoW" || AuthHelper::IsBuildSupportingBattlenet(component.Build))
                    logonResponse->SetAuthResult(AUTH_REGION_BAD_VERSION);
                else
                    logonResponse->SetAuthResult(AUTH_USE_GRUNT_LOGON);

                TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component version %u!", GetClientInfo().c_str(), component.Build);
            }

            AsyncWrite(logonResponse);
            return;
        }

        if (component.Platform == "base")
            _build = component.Build;
    }

    std::string login = logonRequest.Login;
    _locale = logonRequest.Locale;
    _os = logonRequest.Platform;

    Utf8ToUpperOnlyLatin(login);
    PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO);
    stmt->setString(0, login);

    _queryCallback = std::bind(&Battlenet::Session::HandleLogonRequestCallback, this, std::placeholders::_1);
    _queryFuture = LoginDatabase.AsyncQuery(stmt);
}
Beispiel #27
0
BOOL WriteAsync(PAIO_DEV dev, LPVOID buffer, int bsize, AIO_CALLBACK cb, LPVOID ctx) {
	SetAioOper(dev, cb, ctx);

	return AsyncWrite(dev->dev, buffer, bsize, &dev->ioStatus);
}
//! asynchronously write buffer and callback when delivered. COPIES the data
//! into a Buffer!
void DispatcherThread::AsyncWriteCopy(Connection& c, const void* buffer, size_t size,
                                      AsyncWriteCallback done_cb) {
    return AsyncWrite(c, Buffer(buffer, size), done_cb);
}
    cf_void OnReadComplete(cf::T_SESSION session,
                           std::shared_ptr < cl::ReadBuffer > readBuffer)
    {
        CF_PRINT_FUNC;
#if 1
        fprintf (stderr, "OnReadComplete,fd=%d,addr=%s,total()=%d,buf=%s \n",
                 session->Fd(),session->Addr().c_str(),readBuffer->GetTotal(),
                 (cf_char *)(readBuffer->GetBuffer()));
#endif
        TYPE_TID_CLIENTFD::const_iterator it =g_tid_fd.begin();
        bool found =false;
        for(;it!=g_tid_fd.end();it++)
        {
            printf( "for,tid=%u,fd=%d g_tid_fd.size()=%u\n",(cf_uint32)(it->first),it->second, (cf_uint32)(g_tid_fd.size()) );
            if(it->second==session->Fd())
            {
                found =true;
                break;
            }
        }
        if(found)
        {
            printf( "is db query. \n" );
            QueueElement qeOut =g_outQueue[_tid].Get();
            int clientfd =qeOut.fd;
            std::string output_data =qeOut.pack;
            
            AsyncWrite(clientfd, output_data.c_str(), output_data.size());           
            return;
        }
        printf( "recv query request \n" );
        
        cf_uint32 totalLen =readBuffer->GetTotal();
        if(_recvHeader[session->Fd()])
        {
            if(_headLen!=totalLen)
            {
                fprintf (stderr, "OnReadComplete,fd=%d,_headLen{%u}!=totalLen{%u} \n",
                        session->Fd(),_headLen,totalLen);
            }
            else
            {
                cf_uint32 * p =(cf_uint32 *)(readBuffer->GetBuffer());
                cf_uint32 size =ntohl(*p);
                _recvHeader[session->Fd()] =false;
                if(size>0)
                    AsyncRead(session->Fd(), size);
                else
                    _THROW(cf::ValueError, "size==0 !");
            }
        }
        else
        {
            _recvHeader[session->Fd()] =true;
            //AsyncWrite(session->Fd(), readBuffer->GetBuffer(), totalLen);
            std::string packet((const char*)(readBuffer->GetBuffer()), size_t(totalLen));
            QueueElement qe;
            qe.fd =session->Fd();
            qe.pack =packet;
            g_inQueue[g_tid_pipe[_tid]].Put(qe);
            AsyncRead(session->Fd(), _headLen);
        }
    }