void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) { std::shared_ptr<AuthSession> authSession = std::make_shared<AuthSession>(); // Read the content of the packet recvPacket >> authSession->Build; recvPacket >> authSession->LoginServerID; recvPacket >> authSession->Account; recvPacket >> authSession->LoginServerType; recvPacket >> authSession->LocalChallenge; recvPacket >> authSession->RegionID; recvPacket >> authSession->BattlegroupID; recvPacket >> authSession->RealmID; // realmId from auth_database.realmlist table recvPacket >> authSession->DosResponse; recvPacket.read(authSession->Digest, 20); authSession->AddonInfo.append(recvPacket.contents() + recvPacket.rpos(), recvPacket.size() - recvPacket.rpos()); // Get the account information from the auth database PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME); stmt->setInt32(0, int32(realmID)); stmt->setString(1, authSession->Account); { std::lock_guard<std::mutex> guard(_queryLock); _queryCallback = io_service().wrap(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1)); _queryFuture = LoginDatabase.AsyncQuery(stmt); } }
void LogonCommServerSocket::HandleAuthChallenge(WorldPacket & recvData) { unsigned char key[20]; uint32 result = 1; recvData.read(key, 20); // check if we have the correct password if(memcmp(key, LogonServer::getSingleton().sql_hash, 20)) result = 0; Log.Notice("LogonCommServer","Authentication request from %s, result %s.", GetIP(), result ? "OK" : "FAIL"); printf("Key: "); for(int i = 0; i < 20; ++i) printf("%.2X", key[i]); printf("\n"); recvCrypto.Setup(key, 20); sendCrypto.Setup(key, 20); /* packets are encrypted from now on */ use_crypto = true; /* send the response packet */ WorldPacket data(RSMSG_AUTH_RESPONSE, 4); data << result; SendPacket(&data); /* set our general var */ authenticated = result; }
void PostPluginMessage(WorldPacket & data) { // we need to move this into a struct PluginMessage * msg = new PluginMessage; msg->DataLen = data.size(); msg->Data = new uint8[data.size()]; data.read((uint8*)msg->Data, data.size()); //msg->Data = new uint8[data.size()]; //memcpy((uint8*)msg->Data, data.contents(), data.size()); msg->Opcode = data.GetOpcode(); // tell scriptmgr to distribute it to all plugins // (it will clean up memory) sScriptMgr.PostMessageToPlugins(msg); }
void WSSocket::HandleAuthRequest(WorldPacket & pck) { uint8 key[20]; uint32 build; string ver; pck.read(key, 20); pck >> build; pck >> ver; Log.Notice("WSSocket", "Auth reply, server is %s build %u", ver.c_str(), build); // accept it WorldPacket data(ISMSG_AUTH_RESULT, 4); data << uint32(1); SendPacket(&data); _authenticated = true; }
void CHandlerPlayersession::Process(WorldPacket &packet) { //to do implementation // IME_LOG("playersession get packet size %u", packet.size()); char test[200]; std::string str; packet.read((uint8_t *)test, 200); IME_LOG("get data string %s", test); WorldPacket info; info << "I get the data packet"; SendPacket(&info); WorldPacket pkg; pkg << std::string("front send data to back hello backserver"); SendPacketToRelay(&pkg, 0); SendPacketToRelay(&pkg, 1); IME_DEBUG("send pkg to every backends"); }
void LogonCommServerSocket::HandleTestConsoleLogin(WorldPacket & recvData) { WorldPacket data(RSMSG_CONSOLE_LOGIN_RESULT, 8); uint32 request; string accountname; uint8 key[20]; recvData >> request; recvData >> accountname; recvData.read(key, 20); DEBUG_LOG("LogonCommServerSocket","Testing console login: %s\n", accountname.c_str()); data << request; Account * pAccount = sAccountMgr.GetAccount(accountname); if(pAccount == NULL) { data << uint32(0); SendPacket(&data); return; } if(pAccount->GMFlags == NULL || strchr(pAccount->GMFlags, 'z') == NULL) { data << uint32(0); SendPacket(&data); return; } if(memcmp(pAccount->SrpHash, key, 20) != 0) { data << uint32(0); SendPacket(&data); return; } data << uint32(1); SendPacket(&data); }
bool WorldSocket::HandleAuthSession(WorldPacket &recvPacket) { // NOTE: ATM the socket is singlethread, have this in mind ... uint8 digest[20]; uint32 clientSeed, id, security; uint32 ClientBuild; LocaleConstant locale; std::string account; Sha1Hash sha1; BigNumber v, s, g, N, K; WorldPacket packet, SendAddonPacked; // Read the content of the packet recvPacket >> ClientBuild; recvPacket.read_skip<uint32>(); recvPacket >> account; recvPacket >> clientSeed; recvPacket.read(digest, 20); DEBUG_LOG("WorldSocket::HandleAuthSession: client build %u, account %s, clientseed %X", ClientBuild, account.c_str(), clientSeed); // Check the version of client trying to connect if (!IsAcceptableClientBuild(ClientBuild)) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_VERSION_MISMATCH); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (version mismatch)."); return false; } // Get the account information from the realmd database std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below LoginDatabase.escape_string(safe_account); // No SQL injection, username escaped. QueryResult* result = LoginDatabase.PQuery("SELECT " "id, " //0 "gmlevel, " //1 "sessionkey, " //2 "last_ip, " //3 "locked, " //4 "v, " //5 "s, " //6 "mutetime, " //7 "locale " //8 "FROM account " "WHERE username = '******'", safe_account.c_str()); // Stop if the account is not found if (!result) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_UNKNOWN_ACCOUNT); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); return false; } Field* fields = result->Fetch(); N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); g.SetDword(7); v.SetHexStr(fields[5].GetString()); s.SetHexStr(fields[6].GetString()); m_s = s; const char* sStr = s.AsHexStr(); // Must be freed by OPENSSL_free() const char* vStr = v.AsHexStr(); // Must be freed by OPENSSL_free() DEBUG_LOG("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s", sStr, vStr); OPENSSL_free((void*) sStr); OPENSSL_free((void*) vStr); ///- Re-check ip locking (same check as in realmd). if (fields[4].GetUInt8() == 1) // if ip is locked { if (strcmp(fields[3].GetString(), GetRemoteAddress().c_str())) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_FAILED); SendPacket(packet); delete result; BASIC_LOG("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); return false; } } id = fields[0].GetUInt32(); security = fields[1].GetUInt16(); if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB security = SEC_ADMINISTRATOR; K.SetHexStr(fields[2].GetString()); time_t mutetime = time_t (fields[7].GetUInt64()); uint8 tempLoc = LocaleConstant(fields[8].GetUInt8()); if (tempLoc >= static_cast<uint8>(MAX_LOCALE)) locale = LOCALE_enUS; else locale = LocaleConstant(tempLoc); delete result; // Re-check account ban (same check as in realmd) QueryResult* banresult = LoginDatabase.PQuery("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 AND (unbandate > UNIX_TIMESTAMP() OR unbandate = bandate)" "UNION " "SELECT 1 FROM ip_banned WHERE (unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'", id, GetRemoteAddress().c_str()); if (banresult) // if account banned { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_BANNED); SendPacket(packet); delete banresult; sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); return false; } // Check locked state for server AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType) { WorldPacket Packet(SMSG_AUTH_RESPONSE, 1); Packet << uint8(AUTH_UNAVAILABLE); SendPacket(packet); BASIC_LOG("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough"); return false; } // Check that Key and account name are the same on client and server Sha1Hash sha; uint32 t = 0; uint32 seed = m_seed; sha.UpdateData(account); sha.UpdateData((uint8*) & t, 4); sha.UpdateData((uint8*) & clientSeed, 4); sha.UpdateData((uint8*) & seed, 4); sha.UpdateBigNumbers(&K, nullptr); sha.Finalize(); if (memcmp(sha.GetDigest(), digest, 20)) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_FAILED); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); return false; } const std::string &address = GetRemoteAddress(); DEBUG_LOG("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", account.c_str(), address.c_str()); // Update the last_ip in the database // No SQL injection, username escaped. static SqlStatementID updAccount; SqlStatement stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET last_ip = ? WHERE username = ?"); stmt.PExecute(address.c_str(), account.c_str()); if (!(m_session = new WorldSession(id, this, AccountTypes(security), mutetime, locale))) return false; m_crypt.Init(&K); m_session->LoadTutorialsData(); sWorld.AddSession(m_session); // Create and send the Addon packet if (sAddOnHandler.BuildAddonPacket(recvPacket, SendAddonPacked)) SendPacket(SendAddonPacked); return true; }
void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) { uint8 digest[SHA_DIGEST_LENGTH]; uint32 clientSeed; uint8 security; uint32 id; LocaleConstant locale; std::string account; bool isPremium = false; SHA1Hash sha; uint32 clientBuild; uint32 serverId, loginServerType, region, battlegroup, realmIndex; uint64 unk4; WorldPacket packet, SendAddonPacked; BigNumber k; bool wardenActive = sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED); // Read the content of the packet recvPacket >> clientBuild; recvPacket >> serverId; // Used for GRUNT only recvPacket >> account; recvPacket >> loginServerType; // 0 GRUNT, 1 Battle.net recvPacket >> clientSeed; recvPacket >> region >> battlegroup; // Used for Battle.net only recvPacket >> realmIndex; // realmId from auth_database.realmlist table recvPacket >> unk4; recvPacket.read(digest, 20); TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: client %u, serverId %u, account %s, loginServerType %u, clientseed %u, realmIndex %u", clientBuild, serverId, account.c_str(), loginServerType, clientSeed, realmIndex); // Get the account information from the auth database // 0 1 2 3 4 5 6 7 8 // SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ? PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME); stmt->setString(0, account); PreparedQueryResult result = LoginDatabase.Query(stmt); // Stop if the account is not found if (!result) { // We can not log here, as we do not know the account. Thus, no accountId. SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); DelayedCloseSocket(); return; } Field* fields = result->Fetch(); uint8 expansion = fields[4].GetUInt8(); uint32 world_expansion = sWorld->getIntConfig(CONFIG_EXPANSION); if (expansion > world_expansion) expansion = world_expansion; // For hook purposes, we get Remoteaddress at this point. std::string address = GetRemoteIpAddress().to_string(); // As we don't know if attempted login process by ip works, we update last_attempt_ip right away stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_ATTEMPT_IP); stmt->setString(0, address); stmt->setString(1, account); LoginDatabase.Execute(stmt); // This also allows to check for possible "hack" attempts on account // id has to be fetched at this point, so that first actual account response that fails can be logged id = fields[0].GetUInt32(); k.SetHexStr(fields[1].GetCString()); // even if auth credentials are bad, try using the session key we have - client cannot read auth response error without it _authCrypt.Init(&k); // First reject the connection if packet contains invalid data or realm state doesn't allow logging in if (sWorld->IsClosed()) { SendAuthResponseError(AUTH_REJECT); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: World closed, denying client (%s).", GetRemoteIpAddress().to_string().c_str()); DelayedCloseSocket(); return; } if (realmIndex != realmID) { SendAuthResponseError(REALM_LIST_REALM_NOT_FOUND); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (bad realm)."); DelayedCloseSocket(); return; } std::string os = fields[8].GetString(); // Must be done before WorldSession is created if (wardenActive && os != "Win" && os != "OSX") { SendAuthResponseError(AUTH_REJECT); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), os.c_str()); DelayedCloseSocket(); return; } // Check that Key and account name are the same on client and server uint32 t = 0; sha.UpdateData(account); sha.UpdateData((uint8*)&t, 4); sha.UpdateData((uint8*)&clientSeed, 4); sha.UpdateData((uint8*)&_authSeed, 4); sha.UpdateBigNumbers(&k, NULL); sha.Finalize(); if (memcmp(sha.GetDigest(), digest, SHA_DIGEST_LENGTH) != 0) { SendAuthResponseError(AUTH_FAILED); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, account.c_str(), address.c_str()); DelayedCloseSocket(); return; } ///- Re-check ip locking (same check as in auth). if (fields[3].GetUInt8() == 1) // if ip is locked { if (strcmp(fields[2].GetCString(), address.c_str()) != 0) { SendAuthResponseError(AUTH_FAILED); TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs. Original IP: %s, new IP: %s).", fields[2].GetCString(), address.c_str()); // We could log on hook only instead of an additional db log, however action logger is config based. Better keep DB logging as well sScriptMgr->OnFailedAccountLogin(id); DelayedCloseSocket(); return; } } int64 mutetime = fields[5].GetInt64(); //! Negative mutetime indicates amount of seconds to be muted effective on next login - which is now. if (mutetime < 0) { mutetime = time(NULL) + llabs(mutetime); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_MUTE_TIME_LOGIN); stmt->setInt64(0, mutetime); stmt->setUInt32(1, id); LoginDatabase.Execute(stmt); } locale = LocaleConstant(fields[6].GetUInt8()); if (locale >= TOTAL_LOCALES) locale = LOCALE_enUS; uint32 recruiter = fields[7].GetUInt32(); // Checks gmlevel per Realm stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID); stmt->setUInt32(0, id); stmt->setInt32(1, int32(realmID)); result = LoginDatabase.Query(stmt); if (!result) security = 0; else { fields = result->Fetch(); security = fields[0].GetUInt8(); } // Re-check account ban (same check as in auth) stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BANS); stmt->setUInt32(0, id); stmt->setString(1, address); PreparedQueryResult banresult = LoginDatabase.Query(stmt); if (banresult) // if account banned { SendAuthResponseError(AUTH_BANNED); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); sScriptMgr->OnFailedAccountLogin(id); DelayedCloseSocket(); return; } // Check premium stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PREMIUM); stmt->setUInt32(0, id); PreparedQueryResult premresult = LoginDatabase.Query(stmt); if (premresult) { isPremium = true; } // Check locked state for server AccountTypes allowedAccountType = sWorld->GetPlayerSecurityLimit(); TC_LOG_DEBUG("network", "Allowed Level: %u Player Level %u", allowedAccountType, AccountTypes(security)); if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType) { SendAuthResponseError(AUTH_UNAVAILABLE); TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: User tries to login but his security level is not enough"); sScriptMgr->OnFailedAccountLogin(id); DelayedCloseSocket(); return; } TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", account.c_str(), address.c_str()); // Check if this user is by any chance a recruiter stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_RECRUITER); stmt->setUInt32(0, id); result = LoginDatabase.Query(stmt); bool isRecruiter = false; if (result) isRecruiter = true; // Update the last_ip in the database as it was successful for login stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_IP); stmt->setString(0, address); stmt->setString(1, account); LoginDatabase.Execute(stmt); // At this point, we can safely hook a successful login sScriptMgr->OnAccountLogin(id); _authed = true; _worldSession = new WorldSession(id, shared_from_this(), AccountTypes(security), isPremium, expansion, mutetime, locale, recruiter, isRecruiter); _worldSession->LoadGlobalAccountData(); _worldSession->LoadTutorialsData(); _worldSession->ReadAddonsInfo(recvPacket); _worldSession->LoadPermissions(); // Initialize Warden system only if it is enabled by config if (wardenActive) _worldSession->InitWarden(&k, os); sWorld->AddSession(_worldSession); }
int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) { // NOTE: ATM the socket is singlethread, have this in mind ... uint8 digest[20]; uint32 clientSeed; uint32 unk2; uint32 BuiltNumberClient; uint32 id, security; //uint8 expansion = 0; LocaleConstant locale; std::string account; Sha1Hash sha1; BigNumber v, s, g, N; WorldPacket packet, SendAddonPacked; BigNumber K; // Read the content of the packet recvPacket >> BuiltNumberClient; recvPacket >> unk2; recvPacket >> account; recvPacket >> clientSeed; recvPacket.read (digest, 20); DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u", BuiltNumberClient, unk2, account.c_str (), clientSeed); // Check the version of client trying to connect if (!IsAcceptableClientBuild(BuiltNumberClient)) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_VERSION_MISMATCH); SendPacket (packet); sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (version mismatch)."); return -1; } // Get the account information from the realmd database std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below LoginDatabase.escape_string (safe_account); // No SQL injection, username escaped. QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT " "id, " //0 "gmlevel, " //1 "sessionkey, " //2 "last_ip, " //3 "locked, " //4 "v, " //5 "s, " //6 "expansion, " //7 "mutetime, " //8 "locale " //9 "FROM account " "WHERE username = '******'", safe_account.c_str ()); // Stop if the account is not found if (!result) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_UNKNOWN_ACCOUNT); SendPacket (packet); sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); return -1; } Field* fields = result->Fetch (); uint8 expansion = fields[7].GetUInt8(); uint32 world_expansion = sWorld.getConfig(CONFIG_EXPANSION); if (expansion > world_expansion) expansion = world_expansion; //expansion = ((sWorld.getConfig(CONFIG_EXPANSION) > fields[7].GetUInt8()) ? fields[7].GetUInt8() : sWorld.getConfig(CONFIG_EXPANSION)); N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); g.SetDword (7); v.SetHexStr(fields[5].GetString()); s.SetHexStr (fields[6].GetString ()); const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free() const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free() DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s", sStr, vStr); OPENSSL_free ((void*) sStr); OPENSSL_free ((void*) vStr); // Re-check ip locking (same check as in realmd). if (fields[4].GetUInt8 () == 1) // if ip is locked { if (strcmp (fields[3].GetString (), GetRemoteAddress ().c_str ())) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_FAILED); SendPacket (packet); sLog.outBasic ("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); return -1; } } id = fields[0].GetUInt32 (); security = fields[1].GetUInt16 (); K.SetHexStr (fields[2].GetString ()); time_t mutetime = time_t (fields[8].GetUInt64 ()); locale = LocaleConstant (fields[9].GetUInt8 ()); if (locale >= MAX_LOCALE) locale = LOCALE_enUS; // Re-check account ban (same check as in realmd) QueryResult_AutoPtr banresult = LoginDatabase.PQuery ("SELECT " "bandate, " "unbandate " "FROM account_banned " "WHERE id = '%u' " "AND active = 1", id); if (banresult) // if account banned { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_BANNED); SendPacket (packet); sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); return -1; } // Check locked state for server sWorld.UpdateAllowedSecurity(); AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit (); sLog.outDebug("Allowed Level: %u Player Level %u", allowedAccountType, AccountTypes(security)); if (allowedAccountType > SEC_PLAYER && security < allowedAccountType) { WorldPacket Packet (SMSG_AUTH_RESPONSE, 1); Packet << uint8 (AUTH_UNAVAILABLE); SendPacket (packet); sLog.outDetail ("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough"); return -1; } // Check that Key and account name are the same on client and server Sha1Hash sha; uint32 t = 0; uint32 seed = m_Seed; sha.UpdateData (account); sha.UpdateData ((uint8 *) & t, 4); sha.UpdateData ((uint8 *) & clientSeed, 4); sha.UpdateData ((uint8 *) & seed, 4); sha.UpdateBigNumbers (&K, NULL); sha.Finalize (); if (memcmp (sha.GetDigest (), digest, 20)) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_FAILED); SendPacket (packet); sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); return -1; } std::string address = GetRemoteAddress(); DEBUG_LOG ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", account.c_str(), address.c_str()); // Update the last_ip in the database // No SQL injection, username escaped. LoginDatabase.escape_string (address); LoginDatabase.PExecute ("UPDATE account " "SET last_ip = '%s' " "WHERE username = '******'", address.c_str(), safe_account.c_str()); // NOTE ATM the socket is single-threaded, have this in mind ... ACE_NEW_RETURN (m_Session, WorldSession (id, this, security, expansion, mutetime, locale), -1); m_Crypt.SetKey(&K); m_Crypt.Init(); // Sleep this Network thread for uint32 sleepTime = sWorld.getConfig(CONFIG_SESSION_ADD_DELAY); ACE_OS::sleep(ACE_Time_Value (0, sleepTime)); sWorld.AddSession (m_Session); // Create and send the Addon packet if (sAddOnHandler.BuildAddonPacket (&recvPacket, &SendAddonPacked)) SendPacket(SendAddonPacked); return 0; }
void WorldSocket::InformationRetreiveCallback(WorldPacket & recvData, uint32 requestid) { if(requestid != mRequestID) return; uint32 error; recvData >> error; if(error != 0 || pAuthenticationPacket == NULL) { // something happened wrong @ the logon server OutPacket(SMSG_AUTH_RESPONSE, 1, "\x0D"); return; } // Extract account information from the packet. string AccountName; const string * ForcedPermissions; uint32 AccountID; string GMFlags; uint8 AccountFlags; string lang = "enUS"; uint32 i; recvData >> AccountID >> AccountName >> GMFlags >> AccountFlags; ForcedPermissions = sLogonCommHandler.GetForcedPermissions(AccountName); if( ForcedPermissions != NULL ) GMFlags.assign(ForcedPermissions->c_str()); sLog.outDebug( " >> got information packet from logon: `%s` ID %u (request %u)", AccountName.c_str(), AccountID, mRequestID); // sLog.outColor(TNORMAL, "\n"); mRequestID = 0; // Pull the session key. uint8 K[40]; recvData.read(K, 40); BigNumber BNK; BNK.SetBinary(K, 40); uint8 *key = new uint8[20]; WowCrypt::GenerateKey(key, K); // Initialize crypto. _crypt.SetKey(key, 20); _crypt.Init(); delete [] key; //checking if player is already connected //disconnect corrent player and login this one(blizzlike) if(recvData.rpos() != recvData.wpos()) recvData.read((uint8*)lang.data(), 4); WorldSession *session = sWorld.FindSession( AccountID ); if( session) { // AUTH_FAILED = 0x0D session->Disconnect(); // clear the logout timer so he times out straight away session->SetLogoutTimer(1); // we must send authentication failed here. // the stupid newb can relog his client. // otherwise accounts dupe up and disasters happen. OutPacket(SMSG_AUTH_RESPONSE, 1, "\x15"); return; } Sha1Hash sha; uint8 digest[20]; pAuthenticationPacket->read(digest, 20); uint32 t = 0; if( m_fullAccountName == NULL ) // should never happen ! sha.UpdateData(AccountName); else { sha.UpdateData(*m_fullAccountName); // this is unused now. we may as well free up the memory. delete m_fullAccountName; m_fullAccountName = NULL; } sha.UpdateData((uint8 *)&t, 4); sha.UpdateData((uint8 *)&mClientSeed, 4); sha.UpdateData((uint8 *)&mSeed, 4); sha.UpdateBigNumbers(&BNK, NULL); sha.Finalize(); if (memcmp(sha.GetDigest(), digest, 20)) { // AUTH_UNKNOWN_ACCOUNT = 21 OutPacket(SMSG_AUTH_RESPONSE, 1, "\x15"); return; } // Allocate session WorldSession * pSession = new WorldSession(AccountID, AccountName, this); mSession = pSession; ASSERT(mSession); pSession->deleteMutex.Acquire(); // Set session properties pSession->SetClientBuild(mClientBuild); pSession->LoadSecurity(GMFlags); pSession->SetAccountFlags(AccountFlags); pSession->m_lastPing = (uint32)UNIXTIME; pSession->language = sLocalizationMgr.GetLanguageId(lang); if(recvData.rpos() != recvData.wpos()) recvData >> pSession->m_muted; for(uint32 i = 0; i < 8; ++i) pSession->SetAccountData(i, NULL, true, 0); // queue the account loading /*AsyncQuery * aq = new AsyncQuery( new SQLClassCallbackP1<World, uint32>(World::getSingletonPtr(), &World::LoadAccountDataProc, AccountID) ); aq->AddQuery("SELECT * FROM account_data WHERE acct = %u", AccountID); CharacterDatabase.QueueAsyncQuery(aq);*/ if(sWorld.m_useAccountData) { QueryResult * pResult = CharacterDatabase.Query("SELECT * FROM account_data WHERE acct = %u", AccountID); if( pResult == NULL ) CharacterDatabase.Execute("INSERT INTO account_data VALUES(%u, '', '', '', '', '', '', '', '', '')", AccountID); else { size_t len; const char * data; char * d; for(i = 0; i < 8; ++i) { data = pResult->Fetch()[1+i].GetString(); len = data ? strlen(data) : 0; if(len > 1) { d = new char[len+1]; memcpy(d, data, len+1); pSession->SetAccountData(i, d, true, (uint32)len); } } delete pResult; } } Log.Debug("Auth", "%s from %s:%u [%ums]", AccountName.c_str(), GetRemoteIP().c_str(), GetRemotePort(), _latency); #ifdef SESSION_CAP if( sWorld.GetSessionCount() >= SESSION_CAP ) { OutPacket(SMSG_AUTH_RESPONSE, 1, "\x0D"); Disconnect(); return; } #endif // Check for queue. if( (sWorld.GetSessionCount() < sWorld.GetPlayerLimit()) || pSession->HasGMPermissions() ) { Authenticate(); } else { // Queued, sucker. uint32 Position = sWorld.AddQueuedSocket(this); mQueued = true; Log.Debug("Queue", "%s added to queue in position %u", AccountName.c_str(), Position); // Send packet so we know what we're doing UpdateQueuePosition(Position); } pSession->deleteMutex.Release(); }
/// Handle the client authentication packet void WorldSocket::_HandleAuthSession(WorldPacket& recvPacket) { uint8 digest[20]; uint32 clientSeed; uint32 unk2; uint32 BuiltNumberClient; uint32 id, security; std::string account; Sha1Hash I; Sha1Hash sha1; BigNumber v, s, g, N, x; std::string password; WorldPacket packet, SendAddonPacked; BigNumber K; ///- Read the content of the packet try { recvPacket >> BuiltNumberClient; // for now no use recvPacket >> unk2; recvPacket >> account; recvPacket >> clientSeed; recvPacket.read(digest, 20); } catch(ByteBuffer::error &) { sLog.outError("WorldSocket::_HandleAuthSession Get Incomplete packet"); return; } sLog.outDebug("Auth: client %u, unk2 %u, account %s, clientseed %u", BuiltNumberClient, unk2, account.c_str(), clientSeed); ///- Get the account information from the realmd database std::string safe_account=account; // Duplicate, else will screw the SHA hash verification below loginDatabase.escape_string(safe_account); //No SQL injection, username escaped. QueryResult *result = loginDatabase.PQuery("SELECT `id`,`gmlevel`,`sessionkey`,`last_ip`,`locked`, `password`, `v`, `s`, `banned` FROM `account` WHERE `username` = '%s'", safe_account.c_str()); ///- Stop if the account is not found if ( !result ) { packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); packet << uint8( AUTH_UNKNOWN_ACCOUNT ); SendPacket( &packet ); sLog.outDetail( "SOCKET: Sent Auth Response (unknown account)." ); return; } N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); g.SetDword(7); password = (*result)[5].GetString(); std::transform(password.begin(), password.end(), password.begin(), std::towupper); s.SetHexStr((*result)[7].GetString()); std::string sI = account + ":" + password; I.UpdateData(sI); I.Finalize(); sha1.UpdateData(s.AsByteArray(), s.GetNumBytes()); sha1.UpdateData(I.GetDigest(), 20); sha1.Finalize(); x.SetBinary(sha1.GetDigest(), sha1.GetLength()); v = g.ModExp(x, N); sLog.outDebug("SOCKET: (s,v) check s: %s v_old: %s v_new: %s", s.AsHexStr(), (*result)[6].GetString(), v.AsHexStr() ); loginDatabase.PQuery("UPDATE `account` SET `v` = '0', `s` = '0' WHERE `username` = '%s'", safe_account.c_str()); if ( strcmp(v.AsHexStr(),(*result)[6].GetString() ) ) { packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); packet << uint8( AUTH_UNKNOWN_ACCOUNT ); SendPacket( &packet ); sLog.outDetail( "SOCKET: User not logged."); delete result; return; } ///- Re-check ip locking (same check as in realmd). if((*result)[4].GetUInt8() == 1) // if ip is locked { if ( strcmp((*result)[3].GetString(),GetRemoteAddress().c_str()) ) { packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); packet << uint8( REALM_AUTH_ACCOUNT_FREEZED ); SendPacket( &packet ); sLog.outDetail( "SOCKET: Sent Auth Response (Account IP differs)." ); delete result; return; } } ///- Re-check account ban (same check as in realmd). if((*result)[8].GetUInt8() == 1) // if account banned { packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); packet << uint8( AUTH_BANNED ); SendPacket( &packet ); sLog.outDetail( "SOCKET: Sent Auth Response (Account banned)." ); delete result; return; } id = (*result)[0].GetUInt32(); security = (*result)[1].GetUInt16(); K.SetHexStr((*result)[2].GetString()); delete result; ///- Check that we do not exceed the maximum number of online players in the realm uint32 num = sWorld.GetSessionCount(); if (sWorld.GetPlayerLimit() > 0 && num >= sWorld.GetPlayerLimit() && security == 0) { /// \todo Handle the waiting queue when the server is full SendAuthWaitQue(1); sLog.outDetail( "SOCKET: Sent Auth Response (server queue)." ); return; } ///- kick already loaded player with same account (if any) and remove session ///- if player is in loading and want to load again, return if(!sWorld.RemoveSession(id)) { return; } ///- Check that Key and account name are the same on client and server Sha1Hash sha; uint32 t = 0; uint32 seed = _seed; sha.UpdateData(account); sha.UpdateData((uint8 *)&t, 4); sha.UpdateData((uint8 *)&clientSeed, 4); sha.UpdateData((uint8 *)&seed, 4); sha.UpdateBigNumbers(&K, NULL); sha.Finalize(); if (memcmp(sha.GetDigest(), digest, 20)) { packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); packet << uint8( AUTH_FAILED ); SendPacket( &packet ); sLog.outDetail( "SOCKET: Sent Auth Response (authentification failed)." ); return; } ///- Initialize the encryption with the Key _crypt.SetKey(K.AsByteArray(), 40); _crypt.Init(); ///- Send 'Auth is ok' packet.Initialize( SMSG_AUTH_RESPONSE, 1+4+1+4 ); packet << uint8( AUTH_OK ); packet << (uint32)0; // unknown random value... packet << (uint8)2; packet << (uint32)0; SendPacket(&packet); ///- Create a new WorldSession for the player and add it to the World _session = new WorldSession(id, this,security); sWorld.AddSession(_session); sLog.outDebug( "SOCKET: Client '%s' authenticated successfully.", account.c_str() ); sLog.outDebug( "Account: '%s' Logged in from IP %s.", account.c_str(), GetRemoteAddress().c_str()); ///- Update the last_ip in the database //No SQL injection, username escaped. loginDatabase.PQuery("UPDATE `account` SET `last_ip` = '%s' WHERE `username` = '%s'",GetRemoteAddress().c_str(), safe_account.c_str()); // do small delay (10ms) at accepting successful authed connection to prevent droping packets by client // don't must harm anyone (let login ~100 accounts in 1 sec ;) ) #ifdef WIN32 Sleep(10); #endif ///- Create and send the Addon packet if(sAddOnHandler.BuildAddonPacket(&recvPacket, &SendAddonPacked, recvPacket.rpos())) SendPacket(&SendAddonPacked); return; }
int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) { // NOTE: ATM the socket is singlethread, have this in mind ... uint8 digest[20]; uint32 clientSeed, id, security; uint32 unk2; uint32 BuiltNumberClient; uint8 expansion = 0; uint8 xp_rate = 0; LocaleConstant locale; std::string account; Sha1Hash sha1; BigNumber v, s, g, N, K; WorldPacket packet, SendAddonPacked; // Read the content of the packet recvPacket >> BuiltNumberClient; recvPacket >> unk2; recvPacket >> account; recvPacket >> clientSeed; recvPacket.read(digest, 20); DEBUG_LOG("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u", BuiltNumberClient, unk2, account.c_str(), clientSeed); // Check the version of client trying to connect if (!IsAcceptableClientBuild(BuiltNumberClient)) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_VERSION_MISMATCH); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (version mismatch)."); return -1; } // Get the account information from the realmd database std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below LoginDatabase.escape_string(safe_account); // No SQL injection, username escaped. QueryResult* result = LoginDatabase.PQuery("SELECT " "id, " //0 "gmlevel, " //1 "sessionkey, " //2 "last_ip, " //3 "locked, " //4 "v, " //5 "s, " //6 "expansion, " //7 "mutetime, " //8 "locale, " //9 "os " //10 "FROM account " "WHERE username = '******'", safe_account.c_str()); // Stop if the account is not found if (!result) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_UNKNOWN_ACCOUNT); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); return -1; } Field* fields = result->Fetch(); expansion = ((sWorld.getConfig(CONFIG_UINT32_EXPANSION) > fields[7].GetUInt8()) ? fields[7].GetUInt8() : sWorld.getConfig(CONFIG_UINT32_EXPANSION)); N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); g.SetDword(7); v.SetHexStr(fields[5].GetString()); s.SetHexStr(fields[6].GetString()); const char* sStr = s.AsHexStr(); // Must be freed by OPENSSL_free() const char* vStr = v.AsHexStr(); // Must be freed by OPENSSL_free() DEBUG_LOG("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s", sStr, vStr); OPENSSL_free((void*) sStr); OPENSSL_free((void*) vStr); ///- Re-check ip locking (same check as in realmd). if (fields[4].GetUInt8() == 1) // if ip is locked { if (strcmp(fields[3].GetString(), GetRemoteAddress().c_str())) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_FAILED); SendPacket(packet); delete result; BASIC_LOG("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); return -1; } } id = fields[0].GetUInt32(); security = fields[1].GetUInt16(); if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB security = SEC_ADMINISTRATOR; K.SetHexStr(fields[2].GetString()); time_t mutetime = time_t (fields[8].GetUInt64()); locale = LocaleConstant(fields[9].GetUInt8()); if (locale >= MAX_LOCALE) locale = LOCALE_enUS; std::string os = fields[10].GetString(); delete result; // Re-check account ban (same check as in realmd) QueryResult* banresult = LoginDatabase.PQuery("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 AND (unbandate > UNIX_TIMESTAMP() OR unbandate = bandate)" "UNION " "SELECT 1 FROM ip_banned WHERE (unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'", id, GetRemoteAddress().c_str()); if (banresult) // if account banned { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_BANNED); SendPacket(packet); delete banresult; sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); return -1; } // Check for custom xp rate QueryResult* customXpResult = CharacterDatabase.PQuery ("SELECT xp_rate FROM account_xp_rates WHERE id = '%u'", id); if (customXpResult) { Field* xpFields = customXpResult->Fetch(); xp_rate = xpFields[0].GetUInt8(); } // Check locked state for server AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType) { WorldPacket Packet(SMSG_AUTH_RESPONSE, 1); Packet << uint8(AUTH_UNAVAILABLE); SendPacket(packet); BASIC_LOG("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough"); return -1; } // Check that Key and account name are the same on client and server Sha1Hash sha; uint32 t = 0; uint32 seed = m_Seed; sha.UpdateData(account); sha.UpdateData((uint8*) & t, 4); sha.UpdateData((uint8*) & clientSeed, 4); sha.UpdateData((uint8*) & seed, 4); sha.UpdateBigNumbers(&K, NULL); sha.Finalize(); if (memcmp(sha.GetDigest(), digest, 20)) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_FAILED); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); return -1; } std::string address = GetRemoteAddress(); DEBUG_LOG("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", account.c_str(), address.c_str()); // Update the last_ip in the database // No SQL injection, username escaped. static SqlStatementID updAccount; SqlStatement stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET last_ip = ? WHERE username = ?"); stmt.PExecute(address.c_str(), account.c_str()); // NOTE ATM the socket is single-threaded, have this in mind ... ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes(security), expansion, xp_rate, mutetime, locale), -1); m_Crypt.Init(&K); m_Session->LoadTutorialsData(); m_Session->InitWarden(&K, os); // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec ACE_OS::sleep(ACE_Time_Value(0, 10000)); sWorld.AddSession(m_Session); // Create and send the Addon packet if (sAddOnHandler.BuildAddonPacket(&recvPacket, &SendAddonPacked)) SendPacket(SendAddonPacked); return 0; }
void WorldSocket::InformationRetreiveCallback(WorldPacket & recvData, uint32 requestid) { if(requestid != mRequestID) return; uint32 error; recvData >> error; if(error != 0) { // something happened wrong @ the logon server OutPacket(SMSG_AUTH_RESPONSE, 1, "\x0D"); printf("Information callback returns failure.\n"); return; } // Extract account information from the packet. string AccountName; uint32 AccountID; string GMFlags; uint8 AccountFlags; recvData >> AccountID >> AccountName >> GMFlags >> AccountFlags; printf( " >> got information packet from logon: `%s` ID %u (request %u)", AccountName.c_str(), AccountID, mRequestID); // sLog.outColor(TNORMAL, "\n"); mRequestID = 0; //Pull the session key. recvData.read(K, 40); _crypt.Init(K); BigNumber BNK; BNK.SetBinary(K, 40); //checking if player is already connected //disconnect current player and login this one(blizzlike) string lang = "enUS"; if(recvData.rpos() != recvData.wpos()) recvData.read((uint8*)lang.data(), 4); Session * session = sClientMgr.CreateSession(AccountID); if(session == NULL) { /* we are already logged in. send auth failed. (if anyone has a better error lemme know :P) */ OutPacket(SMSG_AUTH_RESPONSE, 1, "\x0D"); printf("Duplicate client error.\n"); return; } m_session = session; session->m_socket = this; Sha1Hash sha; uint8 digest[20]; pAuthenticationPacket->read(digest, 20); uint32 t = 0; if( m_fullAccountName == NULL ) // should never happen ! sha.UpdateData(AccountName); else { sha.UpdateData(*m_fullAccountName); // this is unused now. we may as well free up the memory. delete m_fullAccountName; m_fullAccountName = NULL; } sha.UpdateData((uint8 *)&t, 4); sha.UpdateData((uint8 *)&mClientSeed, 4); sha.UpdateData((uint8 *)&mSeed, 4); sha.UpdateBigNumbers(&BNK, NULL); sha.Finalize(); if (memcmp(sha.GetDigest(), digest, 20)) { // AUTH_UNKNOWN_ACCOUNT = 21 OutPacket(SMSG_AUTH_RESPONSE, 1, "\x15"); return; } //_crypt.Init(digest); // Allocate session m_session->m_accountFlags = AccountFlags; m_session->m_GMPermissions = GMFlags; m_session->m_accountId = AccountID; m_session->m_latency = _latency; m_session->m_accountName = AccountName; m_session->m_ClientBuild = mClientBuild; Log.Notice("Auth", "%s from %s:%u [%ums]", AccountName.c_str(), GetRemoteIP().c_str(), GetRemotePort(), _latency); Authenticate(); }
void WorldSocket::InformationRetreiveCallback(WorldPacket & recvData, uint32 requestid) { if(requestid != mRequestID) return; uint32 error; recvData >> error; if(error != 0 || pAuthenticationPacket == NULL) { // something happened wrong @ the logon server OutPacket(SMSG_AUTH_RESPONSE, 1, "\x0D"); return; } // Extract account information from the packet. string AccountName; const string * ForcedPermissions; uint32 AccountID; string GMFlags; uint8 AccountFlags; string lang = "enUS"; uint32 i; recvData >> AccountID >> AccountName >> GMFlags >> AccountFlags; ForcedPermissions = sLogonCommHandler.GetForcedPermissions(AccountName); if( ForcedPermissions != NULL ) GMFlags.assign(ForcedPermissions->c_str()); DEBUG_LOG( "WorldSocket","Received information packet from logon: `%s` ID %u (request %u)", AccountName.c_str(), AccountID, mRequestID); mRequestID = 0; // Pull the session key. BigNumber BNK; recvData.read(K, 40); _crypt.Init(K); BNK.SetBinary(K, 40); //checking if player is already connected //disconnect current player and login this one(blizzlike) if(recvData.rpos() != recvData.wpos()) recvData.read((uint8*)lang.data(), 4); WorldSession *session = NULL; session = sWorld.FindSession( AccountID ); if( session != NULL ) { if(session->_player != NULL && session->_player->GetMapMgr() == NULL) { DEBUG_LOG("WorldSocket","_player found without m_mapmgr during logon, trying to remove him [player %s, map %d, instance %d].", session->_player->GetName(), session->_player->GetMapId(), session->_player->GetInstanceID() ); if(objmgr.GetPlayer(session->_player->GetLowGUID())) objmgr.RemovePlayer(session->_player); session->LogoutPlayer(false); } // AUTH_FAILED = 0x0D session->Disconnect(); // clear the logout timer so he times out straight away session->SetLogoutTimer(1); // we must send authentication failed here. // the stupid newb can relog his client. // otherwise accounts dupe up and disasters happen. OutPacket(SMSG_AUTH_RESPONSE, 1, "\x15"); return; } Sha1Hash sha; uint8 digest[20]; pAuthenticationPacket->read(digest, 20); uint32 t = 0; if( m_fullAccountName == NULL ) // should never happen ! sha.UpdateData(AccountName); else { sha.UpdateData(*m_fullAccountName); // this is unused now. we may as well free up the memory. delete m_fullAccountName; m_fullAccountName = NULL; } sha.UpdateData((uint8 *)&t, 4); sha.UpdateData((uint8 *)&mClientSeed, 4); sha.UpdateData((uint8 *)&mSeed, 4); sha.UpdateBigNumbers(&BNK, NULL); sha.Finalize(); if (memcmp(sha.GetDigest(), digest, 20)) { // AUTH_UNKNOWN_ACCOUNT = 21 OutPacket(SMSG_AUTH_RESPONSE, 1, "\x15"); return; } // Allocate session WorldSession * pSession = new WorldSession(AccountID, AccountName, this); mSession = pSession; ASSERT(mSession); pSession->deleteMutex.Acquire(); // Set session properties pSession->permissioncount = 0; // just to make sure it's 0 pSession->SetClientBuild(mClientBuild); pSession->LoadSecurity(GMFlags); pSession->SetAccountFlags(AccountFlags); pSession->m_lastPing = (uint32)UNIXTIME; if(recvData.rpos() != recvData.wpos()) recvData >> pSession->m_muted; for(uint32 i = 0; i < 8; i++) pSession->SetAccountData(i, NULL, true, 0); if(sWorld.m_useAccountData) { QueryResult * pResult = CharacterDatabase.Query("SELECT * FROM account_data WHERE acct = %u", AccountID); if( pResult == NULL ) CharacterDatabase.Execute("INSERT INTO account_data VALUES(%u, '', '', '', '', '', '', '', '', '')", AccountID); else { char * d; size_t len; const char * data; for(i = 0; i < 8; i++) { data = pResult->Fetch()[1+i].GetString(); len = data ? strlen(data) : 0; if(len > 1) { d = new char[len+1]; memcpy(d, data, len+1); pSession->SetAccountData(i, d, true, (uint32)len); } } delete pResult; } } DEBUG_LOG("Auth", "%s from %s:%u [%ums]", AccountName.c_str(), GetRemoteIP().c_str(), GetRemotePort(), _latency); #ifdef SESSION_CAP if( sWorld.GetSessionCount() >= SESSION_CAP ) { OutPacket(SMSG_AUTH_RESPONSE, 1, "\x0D"); Disconnect(); return; } #endif // Check for queue. if( (sWorld.GetSessionCount() < sWorld.GetPlayerLimit()) || pSession->HasGMPermissions() ) Authenticate(); else { // Queued, sucker. uint32 Position = sWorld.AddQueuedSocket(this); mQueued = true; DEBUG_LOG("Queue", "%s added to queue in position %u", AccountName.c_str(), Position); // Send packet so we know what we're doing UpdateQueuePosition(Position); } pSession->deleteMutex.Release(); }
int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) { // NOTE: ATM the socket is singlethread, have this in mind ... uint8 digest[20]; uint32 clientSeed; uint32 serverId; uint32 BuiltNumberClient; uint32 id, security; LocaleConstant locale; std::string account, os; BigNumber v, s, g, N, K; WorldPacket packet, SendAddonPacked; // Read the content of the packet recvPacket >> BuiltNumberClient; recvPacket >> serverId; recvPacket >> account; recvPacket >> clientSeed; recvPacket.read(digest, 20); DEBUG_LOG("WorldSocket::HandleAuthSession: client %u, serverId %u, account %s, clientseed %u", BuiltNumberClient, serverId, account.c_str(), clientSeed); // Check the version of client trying to connect if (!IsAcceptableClientBuild(BuiltNumberClient)) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_VERSION_MISMATCH); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (version mismatch)."); return -1; } // Get the account information from the realmd database std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below LoginDatabase.escape_string(safe_account); // No SQL injection, username escaped. QueryResult *result = LoginDatabase.PQuery("SELECT a.id, aa.gmLevel, a.sessionkey, a.last_ip, a.locked, a.v, a.s, a.mutetime, a.locale, a.os, a.flags, " "ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate FROM account a LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, %u) " "LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 WHERE a.username = '******' ORDER BY aa.RealmID DESC LIMIT 1", realmID, safe_account.c_str()); // Stop if the account is not found if (!result) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_UNKNOWN_ACCOUNT); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); return -1; } Field* fields = result->Fetch(); N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); g.SetDword(7); v.SetHexStr(fields[5].GetString()); s.SetHexStr(fields[6].GetString()); const char* sStr = s.AsHexStr(); //Must be freed by OPENSSL_free() const char* vStr = v.AsHexStr(); //Must be freed by OPENSSL_free() DEBUG_LOG("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s", sStr, vStr); OPENSSL_free((void*) sStr); OPENSSL_free((void*) vStr); ///- Re-check ip locking (same check as in realmd). if (fields[4].GetUInt8() == 1) // if ip is locked { if (strcmp(fields[3].GetString(), GetRemoteAddress().c_str())) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_FAILED); SendPacket(packet); delete result; BASIC_LOG("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); return -1; } } id = fields[0].GetUInt32(); security = sAccountMgr.GetSecurity(id); //fields[1].GetUInt16 (); if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB security = SEC_ADMINISTRATOR; K.SetHexStr(fields[2].GetString()); time_t mutetime = time_t (fields[7].GetUInt64()); locale = LocaleConstant(fields[8].GetUInt8()); if (locale >= MAX_LOCALE) locale = LOCALE_enUS; os = fields[9].GetString(); uint32 accFlags = fields[10].GetUInt32(); delete result; bool isBanned = fields[11].GetBool(); if (isBanned || sAccountMgr.IsIPBanned(GetRemoteAddress())) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_BANNED); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); return -1; } // Check locked state for server AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType) { WorldPacket Packet(SMSG_AUTH_RESPONSE, 1); Packet << uint8(AUTH_UNAVAILABLE); SendPacket(packet); BASIC_LOG("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough"); return -1; } // Check that Key and account name are the same on client and server Sha1Hash sha; uint32 t = 0; uint32 seed = m_Seed; sha.UpdateData(account); sha.UpdateData((uint8 *) & t, 4); sha.UpdateData((uint8 *) & clientSeed, 4); sha.UpdateData((uint8 *) & seed, 4); sha.UpdateBigNumbers(&K, NULL); sha.Finalize(); if (memcmp(sha.GetDigest(), digest, 20)) { packet.Initialize(SMSG_AUTH_RESPONSE, 1); packet << uint8(AUTH_FAILED); SendPacket(packet); sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); return -1; } std::string address = GetRemoteAddress(); DEBUG_LOG("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", account.c_str(), address.c_str()); // Update the last_ip in the database // No SQL injection, username escaped. static SqlStatementID updAccount; SqlStatement stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET last_ip = ? WHERE username = ?"); stmt.PExecute(address.c_str(), account.c_str()); // NOTE ATM the socket is single-threaded, have this in mind ... ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes(security), mutetime, locale), -1); m_Crypt.SetKey(K.AsByteArray()); m_Crypt.Init(); m_Session->SetUsername(account); m_Session->SetGameBuild(BuiltNumberClient); m_Session->SetAccountFlags(accFlags); ClientOSType clientOs; if (os == "niW") clientOs = CLIENT_OS_WIN; else if (os == "XSO") clientOs = CLIENT_OS_MAC; else { sLog.outError("WorldSocket::HandleAuthSession: Unrecognized OS '%s' for account '%s' from %s", os.c_str(), account.c_str(), address.c_str()); return -1; } m_Session->SetOS(clientOs); m_Session->LoadTutorialsData(); m_Session->InitWarden(&K); // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec ACE_OS::sleep(ACE_Time_Value(0, 10000)); sWorld.AddSession(m_Session); // Create and send the Addon packet if (sAddOnHandler.BuildAddonPacket(&recvPacket, &SendAddonPacked)) SendPacket(SendAddonPacked); return 0; }
void WorldSocket::InformationRetreiveCallback(WorldPacket & recvData, uint32 requestid) { if(requestid != mRequestID) return; uint32 error; recvData >> error; if(error != 0) { // something happened wrong @ the logon server OutPacket(SMSG_AUTH_RESPONSE, 1, "\x0D"); return; } // Extract account information from the packet. string AccountName; uint32 AccountID; string GMFlags; uint32 AccountFlags; recvData >> AccountID >> AccountName >> GMFlags >> AccountFlags; sLog.outDebug( " >> got information packet from logon: `%s` ID %u (request %u)", AccountName.c_str(), AccountID, mRequestID); // sLog.outColor(TNORMAL, "\n"); mRequestID = 0; // Pull the session key. uint8 K[40]; recvData.read(K, 40); BigNumber BNK; BNK.SetBinary(K, 40); // Initialize crypto. _crypt.SetKey(K, 40); _crypt.Init(); Session * session = sClientMgr.CreateSession(AccountID); if(session == NULL) { /* we are already logged in. send auth failed. (if anyone has a better error lemme know :P) */ OutPacket(SMSG_AUTH_RESPONSE, 1, "\x0D"); return; } m_session = session; session->m_socket = this; Sha1Hash sha; uint8 digest[20]; pAuthenticationPacket->read(digest, 20); uint32 t = 0; sha.UpdateData(AccountName); sha.UpdateData((uint8 *)&t, 4); sha.UpdateData((uint8 *)&mClientSeed, 4); sha.UpdateData((uint8 *)&mSeed, 4); sha.UpdateBigNumbers(&BNK, NULL); sha.Finalize(); if (memcmp(sha.GetDigest(), digest, 20)) { // AUTH_UNKNOWN_ACCOUNT = 21 OutPacket(SMSG_AUTH_RESPONSE, 1, "\x15"); return; } // Allocate session m_session->m_accountFlags = AccountFlags; m_session->m_GMPermissions = GMFlags; m_session->m_accountId = AccountID; m_session->m_latency = _latency; m_session->m_accountName = AccountName; Log.Notice("Auth", "%s from %s:%u [%ums]", AccountName.c_str(), GetRemoteIP().c_str(), GetRemotePort(), _latency); Authenticate(); }
int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) { // NOTE: ATM the socket is singlethread, have this in mind ... uint8 digest[20]; uint32 clientSeed; uint32 unk2; uint32 BuiltNumberClient; uint32 id, security; uint8 expansion = 0; LocaleConstant locale; std::string account; Sha1Hash sha1; BigNumber v, s, g, N, x, I; WorldPacket packet, SendAddonPacked; BigNumber K; if (recvPacket.size () < (4 + 4 + 1 + 4 + 20)) { sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size"); return -1; } // Read the content of the packet recvPacket >> BuiltNumberClient; // for now no use recvPacket >> unk2; recvPacket >> account; if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20)) { sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size second check"); return -1; } recvPacket >> clientSeed; recvPacket.read (digest, 20); DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u", BuiltNumberClient, unk2, account.c_str (), clientSeed); // Get the account information from the realmd database std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below loginDatabase.escape_string (safe_account); // No SQL injection, username escaped. QueryResult *result = loginDatabase.PQuery ("SELECT " "id, " //0 "gmlevel, " //1 "sessionkey, " //2 "last_ip, " //3 "locked, " //4 "sha_pass_hash, " //5 "v, " //6 "s, " //7 "expansion, " //8 "mutetime, " //9 "locale " //10 "FROM account " "WHERE username = '******'", safe_account.c_str ()); // Stop if the account is not found if (!result) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_UNKNOWN_ACCOUNT); SendPacket (packet); sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); return -1; } Field* fields = result->Fetch (); expansion = fields[8].GetUInt8 () && sWorld.getConfig (CONFIG_EXPANSION) > 0; N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); g.SetDword (7); I.SetHexStr (fields[5].GetString ()); //In case of leading zeros in the I hash, restore them uint8 mDigest[SHA_DIGEST_LENGTH]; memset (mDigest, 0, SHA_DIGEST_LENGTH); if (I.GetNumBytes () <= SHA_DIGEST_LENGTH) memcpy (mDigest, I.AsByteArray (), I.GetNumBytes ()); std::reverse (mDigest, mDigest + SHA_DIGEST_LENGTH); s.SetHexStr (fields[7].GetString ()); sha1.UpdateData (s.AsByteArray (), s.GetNumBytes ()); sha1.UpdateData (mDigest, SHA_DIGEST_LENGTH); sha1.Finalize (); x.SetBinary (sha1.GetDigest (), sha1.GetLength ()); v = g.ModExp (x, N); const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free() const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free() const char* vold = fields[6].GetString (); DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v_old: %s v_new: %s", sStr, vold, vStr); loginDatabase.PExecute ("UPDATE account " "SET " "v = '0', " "s = '0' " "WHERE username = '******'", safe_account.c_str ()); if (!vold || strcmp (vStr, vold)) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_UNKNOWN_ACCOUNT); SendPacket (packet); delete result; OPENSSL_free ((void*) sStr); OPENSSL_free ((void*) vStr); sLog.outBasic ("WorldSocket::HandleAuthSession: User not logged."); return -1; } OPENSSL_free ((void*) sStr); OPENSSL_free ((void*) vStr); ///- Re-check ip locking (same check as in realmd). if (fields[4].GetUInt8 () == 1) // if ip is locked { if (strcmp (fields[3].GetString (), GetRemoteAddress ().c_str ())) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_FAILED); SendPacket (packet); delete result; sLog.outBasic ("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); return -1; } } id = fields[0].GetUInt32 (); security = fields[1].GetUInt16 (); K.SetHexStr (fields[2].GetString ()); time_t mutetime = time_t (fields[9].GetUInt64 ()); locale = LocaleConstant (fields[10].GetUInt8 ()); if (locale >= MAX_LOCALE) locale = LOCALE_enUS; delete result; // Re-check account ban (same check as in realmd) QueryResult *banresult = loginDatabase.PQuery ("SELECT " "bandate, " "unbandate " "FROM account_banned " "WHERE id = '%u' " "AND active = 1", id); if (banresult) // if account banned { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_BANNED); SendPacket (packet); delete banresult; sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); return -1; } // Check locked state for server AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit (); if (allowedAccountType > SEC_PLAYER && security < allowedAccountType) { WorldPacket Packet (SMSG_AUTH_RESPONSE, 1); Packet << uint8 (AUTH_UNAVAILABLE); SendPacket (packet); sLog.outBasic ("WorldSocket::HandleAuthSession: User tryes to login but his security level is not enough"); return -1; } // Check that Key and account name are the same on client and server Sha1Hash sha; uint32 t = 0; uint32 seed = m_Seed; sha.UpdateData (account); sha.UpdateData ((uint8 *) & t, 4); sha.UpdateData ((uint8 *) & clientSeed, 4); sha.UpdateData ((uint8 *) & seed, 4); sha.UpdateBigNumbers (&K, NULL); sha.Finalize (); if (memcmp (sha.GetDigest (), digest, 20)) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); packet << uint8 (AUTH_FAILED); SendPacket (packet); sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); return -1; } std::string address = GetRemoteAddress (); DEBUG_LOG ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", account.c_str (), address.c_str ()); // Update the last_ip in the database // No SQL injection, username escaped. loginDatabase.escape_string (address); loginDatabase.PExecute ("UPDATE account " "SET last_ip = '%s' " "WHERE username = '******'", address.c_str (), safe_account.c_str ()); // NOTE ATM the socket is singlethreaded, have this in mind ... ACE_NEW_RETURN (m_Session, WorldSession (id, this, security, expansion, mutetime, locale), -1); m_Crypt.SetKey (&K); m_Crypt.Init (); // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec ACE_OS::sleep (ACE_Time_Value (0, 10000)); sWorld.AddSession (m_Session); // Create and send the Addon packet if (sAddOnHandler.BuildAddonPacket (&recvPacket, &SendAddonPacked)) SendPacket (SendAddonPacked); return 0; }