Beispiel #1
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 #2
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 #3
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 #4
0
bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket** response)
{
    if (dataStream->Read<uint8>(8) != 1)
    {
        Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse();
        resumeResponse->SetAuthResult(AUTH_CORRUPTED_MODULE);
        ReplaceResponse(response, resumeResponse);
        return false;
    }

    static uint8 const ResumeClient = 0;
    static uint8 const ResumeServer = 1;

    std::unique_ptr<uint8[]> clientChallenge = dataStream->ReadBytes(16);
    std::unique_ptr<uint8[]> clientProof = dataStream->ReadBytes(32);
    std::unique_ptr<uint8[]> serverChallenge = _reconnectProof.AsByteArray(16);
    std::unique_ptr<uint8[]> sessionKey = K.AsByteArray(64);

    HmacSha256 clientPart(64, sessionKey.get());
    clientPart.UpdateData(&ResumeClient, 1);
    clientPart.UpdateData(clientChallenge.get(), 16);
    clientPart.UpdateData(serverChallenge.get(), 16);
    clientPart.Finalize();

    HmacSha256 serverPart(64, sessionKey.get());
    serverPart.UpdateData(&ResumeServer, 1);
    serverPart.UpdateData(serverChallenge.get(), 16);
    serverPart.UpdateData(clientChallenge.get(), 16);
    serverPart.Finalize();

    uint8 newSessionKey[64];
    memcpy(&newSessionKey[0], clientPart.GetDigest(), clientPart.GetLength());
    memcpy(&newSessionKey[32], serverPart.GetDigest(), serverPart.GetLength());

    K.SetBinary(newSessionKey, 64);

    HmacSha256 proof(64, newSessionKey);
    proof.UpdateData(&ResumeClient, 1);
    proof.UpdateData(clientChallenge.get(), 16);
    proof.UpdateData(serverChallenge.get(), 16);
    proof.Finalize();

    if (memcmp(proof.GetDigest(), clientProof.get(), serverPart.GetLength()))
    {
        PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_FAILED_LOGINS);
        stmt->setString(0, _accountInfo->Login);
        LoginDatabase.Execute(stmt);

        TC_LOG_DEBUG("session", "[Battlenet::Resume] %s attempted to reconnect with invalid password!", GetClientInfo().c_str());
        Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse();
        resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT);
        ReplaceResponse(response, resumeResponse);
        return false;
    }

    PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY);
    stmt->setString(0, K.AsHexStr());
    stmt->setBool(1, true);
    stmt->setUInt32(2, _accountInfo->Id);
    LoginDatabase.Execute(stmt);

    HmacSha256 serverProof(64, newSessionKey);
    serverProof.UpdateData(&ResumeServer, 1);
    serverProof.UpdateData(serverChallenge.get(), 16);
    serverProof.UpdateData(clientChallenge.get(), 16);
    serverProof.Finalize();

    ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume");

    BitStream resumeData;
    uint8 state = 2;
    resumeData.WriteBytes(&state, 1);
    resumeData.WriteBytes(serverProof.GetDigest(), serverProof.GetLength());

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

    Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse();
    resumeResponse->Modules.push_back(resume);
    ReplaceResponse(response, resumeResponse);
    _authed = true;
    sSessionMgr.AddSession(this);
    return true;
}