Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 8eb6d276a6fd7b391868a186e17d29569efb08fa Mon Sep 17 00:00:00 2001
- From: Shoxxo <Shoxxo@exploit.im>
- Date: Mon, 16 Nov 2015 18:38:09 +0100
- Subject: [PATCH] Sending Patches To The Client Through The WoW App
- ---
- src/common/Logging/Log.cpp | 2 +-
- src/server/authserver/Authentication/AuthCodes.cpp | 150 +-
- src/server/authserver/Authentication/AuthCodes.h | 3 +-
- src/server/authserver/Main.cpp | 8 +
- src/server/authserver/Server/AuthSession.cpp | 397 +-
- src/server/authserver/Server/AuthSession.h | 56 +-
- src/server/authserver/authserver.conf.dist | 166 +-
- .../Database/Implementation/LoginDatabase.cpp | 1 +
- .../Database/Implementation/LoginDatabase.h | 1 +
- src/server/game/World/World.cpp | 2 +-
- rewrite src/server/authserver/Authentication/AuthCodes.cpp (62%)
- diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp
- index 57d399a..51fd0b7 100644
- --- a/src/common/Logging/Log.cpp
- +++ b/src/common/Logging/Log.cpp
- @@ -337,7 +337,7 @@ void Log::LoadFromConfig()
- lowestLogLevel = LOG_LEVEL_FATAL;
- AppenderId = 0;
- - m_logsDir = sConfigMgr->GetStringDefault("LogsDir", "");
- + m_logsDir = sConfigMgr->GetStringDefault("LogsDir", "./log/");
- if (!m_logsDir.empty())
- if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\'))
- m_logsDir.push_back('/');
- diff --git a/src/server/authserver/Authentication/AuthCodes.cpp b/src/server/authserver/Authentication/AuthCodes.cpp
- dissimilarity index 62%
- index 08f091d..999fe63 100644
- --- a/src/server/authserver/Authentication/AuthCodes.cpp
- +++ b/src/server/authserver/Authentication/AuthCodes.cpp
- @@ -1,82 +1,68 @@
- -/*
- - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- - *
- - * This program is free software; you can redistribute it and/or modify it
- - * under the terms of the GNU General Public License as published by the
- - * Free Software Foundation; either version 2 of the License, or (at your
- - * option) any later version.
- - *
- - * This program is distributed in the hope that it will be useful, but WITHOUT
- - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- - * more details.
- - *
- - * You should have received a copy of the GNU General Public License along
- - * with this program. If not, see <http://www.gnu.org/licenses/>.
- - */
- -
- -#include "AuthCodes.h"
- -#include <cstddef>
- -
- -namespace AuthHelper
- -{
- - static RealmBuildInfo const PostBcAcceptedClientBuilds[] =
- - {
- - {15595, 4, 3, 4, ' '},
- - {14545, 4, 2, 2, ' '},
- - {13623, 4, 0, 6, 'a'},
- - {13930, 3, 3, 5, 'a'}, // 3.3.5a China Mainland build
- - {12340, 3, 3, 5, 'a'},
- - {11723, 3, 3, 3, 'a'},
- - {11403, 3, 3, 2, ' '},
- - {11159, 3, 3, 0, 'a'},
- - {10505, 3, 2, 2, 'a'},
- - {9947, 3, 1, 3, ' '},
- - {8606, 2, 4, 3, ' '},
- - {0, 0, 0, 0, ' '} // terminator
- - };
- -
- - static RealmBuildInfo const PreBcAcceptedClientBuilds[] =
- - {
- - {6141, 1, 12, 3, ' '},
- - {6005, 1, 12, 2, ' '},
- - {5875, 1, 12, 1, ' '},
- - {0, 0, 0, 0, ' '} // terminator
- - };
- -
- - bool IsPreBCAcceptedClientBuild(int build)
- - {
- - for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
- - if (PreBcAcceptedClientBuilds[i].Build == build)
- - return true;
- -
- - return false;
- - }
- -
- - bool IsPostBCAcceptedClientBuild(int build)
- - {
- - for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
- - if (PostBcAcceptedClientBuilds[i].Build == build)
- - return true;
- -
- - return false;
- - }
- -
- - bool IsAcceptedClientBuild(int build)
- - {
- - return (IsPostBCAcceptedClientBuild(build) || IsPreBCAcceptedClientBuild(build));
- - }
- -
- - RealmBuildInfo const* GetBuildInfo(int build)
- - {
- - for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
- - if (PostBcAcceptedClientBuilds[i].Build == build)
- - return &PostBcAcceptedClientBuilds[i];
- -
- - for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
- - if (PreBcAcceptedClientBuilds[i].Build == build)
- - return &PreBcAcceptedClientBuilds[i];
- -
- - return NULL;
- - }
- -}
- +/*
- + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- + *
- + * This program is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU General Public License as published by the
- + * Free Software Foundation; either version 2 of the License, or (at your
- + * option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful, but WITHOUT
- + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- + * more details.
- + *
- + * You should have received a copy of the GNU General Public License along
- + * with this program. If not, see <http://www.gnu.org/licenses/>.
- + */
- +
- +#include "AuthCodes.h"
- +#include "Database/DatabaseEnv.h"
- +#include <cstddef>
- +#include <map>
- +
- +typedef std::map<int, RealmBuildInfo*> RealmBuildContainer;
- +
- +namespace AuthHelper
- +{
- + RealmBuildContainer AcceptedClientBuilds;
- + void InitAcceptedClientBuilds()
- + {
- + AcceptedClientBuilds.clear();
- +
- + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_VERSIONS);
- + PreparedQueryResult result = LoginDatabase.Query(stmt);
- +
- + if (!result)
- + TC_LOG_ERROR("server.authserver", "Table `versions` is empty. No one will be able to log in.");
- +
- + do {
- + Field* fields = result->Fetch();
- + RealmBuildInfo* newBuild = new RealmBuildInfo;
- + newBuild->Build = fields[0].GetUInt32();
- + newBuild->MajorVersion = fields[1].GetUInt32();
- + newBuild->MinorVersion = fields[2].GetUInt32();
- + newBuild->BugfixVersion = fields[3].GetUInt32();
- + newBuild->HotfixVersion = fields[4].GetUInt32();
- + AcceptedClientBuilds[newBuild->Build] = newBuild;
- + } while (result->NextRow());
- + }
- +
- + bool IsAcceptedClientBuild(int build)
- + {
- + for (RealmBuildContainer::iterator itr = AcceptedClientBuilds.begin(); itr != AcceptedClientBuilds.end(); itr++)
- + if (itr->second->Build == build)
- + return true;
- +
- + return false;
- + }
- +
- +
- + RealmBuildInfo const* GetBuildInfo(int build)
- + {
- + for (RealmBuildContainer::iterator itr = AcceptedClientBuilds.begin(); itr != AcceptedClientBuilds.end(); itr++)
- + if (itr->second->Build == build)
- + return itr->second;
- +
- + return NULL;
- + }
- +}
- diff --git a/src/server/authserver/Authentication/AuthCodes.h b/src/server/authserver/Authentication/AuthCodes.h
- index 7a5df6d..51290f0 100644
- --- a/src/server/authserver/Authentication/AuthCodes.h
- +++ b/src/server/authserver/Authentication/AuthCodes.h
- @@ -88,10 +88,9 @@ struct RealmBuildInfo
- namespace AuthHelper
- {
- + void InitAcceptedClientBuilds();
- RealmBuildInfo const* GetBuildInfo(int build);
- bool IsAcceptedClientBuild(int build);
- - bool IsPostBCAcceptedClientBuild(int build);
- - bool IsPreBCAcceptedClientBuild(int build);
- }
- #endif
- diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
- index 205053c..1c6ec5b 100644
- --- a/src/server/authserver/Main.cpp
- +++ b/src/server/authserver/Main.cpp
- @@ -25,6 +25,7 @@
- */
- #include "AuthSocketMgr.h"
- +#include "AuthCodes.h"
- #include "Common.h"
- #include "Config.h"
- #include "DatabaseEnv.h"
- @@ -42,6 +43,7 @@
- using boost::asio::ip::tcp;
- using namespace boost::program_options;
- +using namespace AuthHelper;
- #ifndef _TRINITY_REALM_CONFIG
- # define _TRINITY_REALM_CONFIG "authserver.conf"
- @@ -75,6 +77,8 @@ boost::asio::deadline_timer* _dbPingTimer;
- uint32 _dbPingInterval;
- LoginDatabaseWorkerPool LoginDatabase;
- +extern Patcher patcher;
- +
- int main(int argc, char** argv)
- {
- std::string configFile = _TRINITY_REALM_CONFIG;
- @@ -109,6 +113,8 @@ int main(int argc, char** argv)
- TC_LOG_INFO("server.authserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
- TC_LOG_INFO("server.authserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
- + patcher.Initialize();
- +
- // authserver PID file creation
- std::string pidFile = sConfigMgr->GetStringDefault("PidFile", "");
- if (!pidFile.empty())
- @@ -126,6 +132,8 @@ int main(int argc, char** argv)
- if (!StartDB())
- return 1;
- + AuthHelper::InitAcceptedClientBuilds();
- +
- _ioService = new boost::asio::io_service();
- // Get the list of realms for the server
- diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
- index 28819b8..f96708e 100644
- --- a/src/server/authserver/Server/AuthSession.cpp
- +++ b/src/server/authserver/Server/AuthSession.cpp
- @@ -26,6 +26,7 @@
- #include "Configuration/Config.h"
- #include "RealmList.h"
- #include <boost/lexical_cast.hpp>
- +#include <boost/thread.hpp>
- using boost::asio::ip::tcp;
- @@ -107,7 +108,298 @@ typedef struct AUTH_RECONNECT_PROOF_C
- uint8 number_of_keys;
- } sAuthReconnectProof_C;
- +typedef struct XFER_INIT_C
- +{
- + uint8 cmd;
- + uint8 fileNameLen;
- + uint8 fileName[5];
- + uint64 file_size;
- + uint8 md5[MD5_DIGEST_LENGTH];
- +} XferInit_C;
- +
- +typedef struct XFER_RESUME_C
- +{
- + uint8 cmd;
- + uint64 pos;
- +} XferResume_C;
- +
- +typedef struct XFER_RESUME_S
- +{
- + uint8 cmd;
- + uint64 pos;
- +} XferResume_S;
- +
- +#pragma pack(pop)
- +
- +Patcher patcher;
- +
- +PATCH_INFO* Patcher::getPatchInfo(int _build, std::string _locale, bool* fallback)
- +{
- + PATCH_INFO* patch = NULL;
- + int locale = *((int*)(_locale.c_str()));
- +
- + TC_LOG_INFO("network", "Client with version %i and locale %s (%x) looking for patch.", _build, _locale.c_str(), locale);
- +
- + for (Patches::iterator it = _patches.begin(); it != _patches.end(); ++it)
- + if (it->build == _build && it->locale == locale)
- + {
- + patch = &(*it);
- + *fallback = false;
- + }
- +
- + return patch;
- +}
- +
- +bool Patcher::PossiblePatching(int _build, std::string _locale)
- +{
- + bool temp;
- + return getPatchInfo(_build, _locale, &temp) != NULL;
- +}
- +
- +bool Patcher::InitPatching(int _build, std::string _locale, AuthSession* _session)
- +{
- + bool fallback;
- + PATCH_INFO* patch = getPatchInfo(_build, _locale, &fallback);
- +
- + // one of them nonzero, start patching.
- + if (patch)
- + {
- + ByteBuffer pkt;
- + pkt << uint8(AUTH_LOGON_PROOF);
- + pkt << uint8(LOGIN_DOWNLOAD_FILE);
- + _session->SendPacket(pkt);
- +
- + std::stringstream path;
- + path << m_dataDir << _build << "-" << _locale << ".mpq";
- +
- + _session->patch = fopen(path.str().c_str(), "rb");
- + TC_LOG_INFO("network", "Patch: %s", path.str().c_str());
- + XFER_INIT_C xfer;
- + xfer.cmd = XFER_INITIATE;
- + xfer.fileNameLen = 5;
- + xfer.fileName[0] = 'P';
- + xfer.fileName[1] = 'a';
- + xfer.fileName[2] = 'T';
- + xfer.fileName[3] = 'c';
- + xfer.fileName[4] = 'h';
- + xfer.file_size = patch->filesize;
- + memcpy(xfer.md5, patch->md5, MD5_DIGEST_LENGTH);
- + pkt.resize(sizeof(xfer));
- + std::memcpy(pkt.contents(), &xfer, sizeof(xfer));
- + _session->SendPacket(pkt);
- + return true;
- + }
- + else
- + {
- + TC_LOG_INFO("network", "Client with version %i and locale %s did not get a patch.", _build, _locale.c_str());
- + return false;
- + }
- +}
- +
- +// Preload MD5 hashes of existing patch files on server
- +#ifndef _WIN32
- +#include <dirent.h>
- +#include <errno.h>
- +
- +void Patcher::LoadPatchesInfo()
- +{
- + DIR *dirp;
- + struct dirent *dp;
- + dirp = opendir(m_dataDir);
- +
- + if (!dirp)
- + return;
- +
- + while (dirp)
- + {
- + errno = 0;
- + if ((dp = readdir(dirp)) != NULL)
- + {
- + int l = strlen(dp->d_name);
- +
- + if (l < 8)
- + continue;
- +
- + if (!memcmp(&dp->d_name[l - 4], ".mpq", 4))
- + {
- + LoadPatchMD5(m_dataDir.c_str(), dp->d_name);
- + }
- + }
- + else
- + {
- + if (errno != 0)
- + {
- + closedir(dirp);
- + return;
- + }
- + break;
- + }
- + }
- +
- + if (dirp)
- + closedir(dirp);
- +}
- +
- +#else
- +
- +void Patcher::LoadPatchesInfo()
- +{
- + WIN32_FIND_DATA fil;
- + std::string fileName = m_dataDir + "*.mpq";
- + HANDLE hFil = FindFirstFile(fileName.c_str(), &fil);
- + if (hFil == INVALID_HANDLE_VALUE)
- + return; // no patches were found
- +
- + do
- + {
- + LoadPatchMD5(m_dataDir.c_str(), fil.cFileName);
- + } while (FindNextFile(hFil, &fil));
- +}
- +
- +#endif
- +
- +// Calculate and store MD5 hash for a given patch file
- +void Patcher::LoadPatchMD5(const char* szPath, char *szFileName)
- +{
- + int build;
- + union
- + {
- + int i;
- + char c[4];
- + } locale;
- +
- + if (sscanf(szFileName, "%i-%c%c%c%c.mpq", &build, &locale.c[0], &locale.c[1], &locale.c[2], &locale.c[3]) != 5)
- + return;
- +
- + // Try to open the patch file
- + std::string path = szPath;
- + path += szFileName;
- + FILE *patch = fopen(path.c_str(), "rb");
- + if (!patch)
- + {
- + TC_LOG_INFO("network", "Error loading patch %s\n", path.c_str());
- + return;
- + }
- +
- + // Calculate the MD5 hash
- + MD5_CTX ctx;
- + MD5_Init(&ctx);
- + uint8* buf = new uint8[512 * 1024];
- +
- + while (!feof(patch))
- + {
- + size_t read = fread(buf, 1, 512 * 1024, patch);
- + MD5_Update(&ctx, buf, read);
- + }
- +
- + delete[] buf;
- + fseek(patch, 0, SEEK_END);
- + size_t size = ftell(patch);
- + fclose(patch);
- +
- + // Store the result in the internal patch hash map
- + PATCH_INFO pi;
- + pi.build = build;
- + pi.locale = locale.i;
- + pi.filesize = uint64(size);
- + MD5_Final((uint8 *)&pi.md5, &ctx);
- + _patches.push_back(pi);
- + TC_LOG_INFO("network", "Added patch for %i %c%c%c%c.", build, locale.c[0], locale.c[1], locale.c[2], locale.c[3]);
- +}
- +
- +PatcherRunnable::PatcherRunnable(AuthSession* session, uint64 _pos, uint64 _size)
- +{
- + _session = session;
- + pos = _pos;
- + size = _size;
- + stopped = false;
- +}
- +
- +void PatcherRunnable::stop()
- +{
- + stopped = true;
- +}
- +
- +#if defined(__GNUC__)
- +#pragma pack(1)
- +#else
- +#pragma pack(push, 1)
- +#endif
- +struct TransferDataPacket
- +{
- + uint8 cmd;
- + uint16 chunk_size;
- +};
- +#if defined(__GNUC__)
- +#pragma pack()
- +#else
- #pragma pack(pop)
- +#endif
- +
- +// Send content of patch file to the client
- +void PatcherRunnable::run()
- +{
- + TC_LOG_INFO("network", "PatcherRunnable::run(): %ld -> %ld", pos, size);
- +
- + while (pos < size && !stopped)
- + {
- + uint64 left = size - pos;
- + uint16 send = (left > 4096) ? 4096 : left;
- +
- + char* bytes = new char[sizeof(TransferDataPacket) + send];
- + TransferDataPacket* hdr = (TransferDataPacket*)bytes;
- + hdr->cmd = uint8(XFER_DATA);
- + hdr->chunk_size = send;
- + fread(bytes + sizeof(TransferDataPacket), 1, send, _session->patch);
- +
- + ByteBuffer pkt(sizeof(TransferDataPacket) + send);
- + pkt.append(bytes, sizeof(TransferDataPacket) + send);
- +
- + _session->SendPacket(pkt);
- + delete[] bytes;
- +
- + pos += send;
- +
- + _sleep(sConfigMgr->GetIntDefault("PatchPacketDelay", 100));
- + }
- +
- + if (!stopped)
- + {
- + fclose(_session->patch);
- + _session->patch = NULL;
- + _session->_patcher = NULL;
- + }
- +
- + TC_LOG_INFO("network", "patcher done.");
- +}
- +
- +// Launch the patch hashing mechanism on object creation
- +void Patcher::Initialize()
- +{
- + m_dataDir = sConfigMgr->GetStringDefault("DataDir", "./data/") + "/patches/";
- + if (!m_dataDir.empty())
- + if ((m_dataDir.at(m_dataDir.length() - 1) != '/') && (m_dataDir.at(m_dataDir.length() - 1) != '\\'))
- + m_dataDir.push_back('/');
- +
- + TC_LOG_INFO("network", "Searching for available patches.");
- + LoadPatchesInfo();
- +}
- +
- +// Close patch file descriptor before leaving
- +AuthSession::~AuthSession(void)
- +{
- + if (patch)
- + {
- + fclose(patch);
- + patch = NULL;
- + }
- + if (_patcher)
- + {
- + _patcher->stop();
- + delete _patcher;
- + _patcher = NULL;
- + }
- +}
- enum class BufferSizes : uint32
- {
- @@ -205,17 +497,49 @@ bool AuthSession::HandleLogonChallenge()
- _login.assign((const char*)challenge->I, challenge->I_len);
- _build = challenge->build;
- - _expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
- + _expversion = uint8(AuthHelper::IsAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : NO_VALID_EXP_FLAG);
- _os = (const char*)challenge->os;
- if (_os.size() > 4)
- return false;
- +
- + _localizationName.resize(4);
- + for (int i = 0; i < 4; ++i)
- + _localizationName[i] = challenge->country[4 - i - 1];
- // Restore string order as its byte order is reversed
- std::reverse(_os.begin(), _os.end());
- pkt << uint8(AUTH_LOGON_CHALLENGE);
- pkt << uint8(0x00);
- +
- + if (_expversion == NO_VALID_EXP_FLAG)
- + {
- + if (patcher.PossiblePatching(_build, _localizationName))
- + {
- + uint8 response[119] = {
- + 0x00, 0x00, 0x00, 0x72, 0x50, 0xa7, 0xc9, 0x27, 0x4a, 0xfa, 0xb8, 0x77, 0x80, 0x70, 0x22,
- + 0xda, 0xb8, 0x3b, 0x06, 0x50, 0x53, 0x4a, 0x16, 0xe2, 0x65, 0xba, 0xe4, 0x43, 0x6f, 0xe3,
- + 0x29, 0x36, 0x18, 0xe3, 0x45, 0x01, 0x07, 0x20, 0x89, 0x4b, 0x64, 0x5e, 0x89, 0xe1, 0x53,
- + 0x5b, 0xbd, 0xad, 0x5b, 0x8b, 0x29, 0x06, 0x50, 0x53, 0x08, 0x01, 0xb1, 0x8e, 0xbf, 0xbf,
- + 0x5e, 0x8f, 0xab, 0x3c, 0x82, 0x87, 0x2a, 0x3e, 0x9b, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00,
- + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x32, 0xa3,
- + 0x49, 0x76, 0x5c, 0x5b, 0x35, 0x9a, 0x93, 0x3c, 0x6f, 0x3c, 0x63, 0x6d, 0xc0, 0x00
- + };
- + ByteBuffer packet;
- + packet.resize(sizeof(response));
- + std::memcpy(packet.contents(), &response, sizeof(response));
- + SendPacket(packet);
- + return true;
- + }
- + else
- + {
- + pkt << uint8(WOW_FAIL_VERSION_INVALID);
- + SendPacket(pkt);
- + return true;
- + }
- + }
- // Verify that this IP is not in the ip_banned table
- LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));
- @@ -389,10 +713,6 @@ bool AuthSession::HandleLogonChallenge()
- uint8 secLevel = fields[5].GetUInt8();
- _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR;
- - _localizationName.resize(4);
- - for (int i = 0; i < 4; ++i)
- - _localizationName[i] = challenge->country[4 - i - 1];
- -
- TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] account %s is using '%c%c%c%c' locale (%u)",
- ipAddress.c_str(), port, _login.c_str(),
- challenge->country[3], challenge->country[2], challenge->country[1], challenge->country[0],
- @@ -420,9 +740,15 @@ bool AuthSession::HandleLogonProof()
- // If the client has no valid version
- if (_expversion == NO_VALID_EXP_FLAG)
- {
- - // Check if we have the appropriate patch on the disk
- - TC_LOG_DEBUG("network", "Client with invalid version, patching is not implemented");
- - return false;
- + if (patcher.PossiblePatching(_build, _localizationName))
- + {
- + if (patcher.InitPatching(_build, _localizationName, this))
- + return true;
- + else
- + return false;
- + }
- + else
- + return false;
- }
- // Continue the SRP6 calculation based on data received from the client
- @@ -670,7 +996,7 @@ bool AuthSession::HandleReconnectChallenge()
- // Reinitialize build, expansion and the account securitylevel
- _build = challenge->build;
- - _expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
- + _expversion = uint8(AuthHelper::IsAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : NO_VALID_EXP_FLAG);
- _os = (const char*)challenge->os;
- if (_os.size() > 4)
- @@ -798,7 +1124,7 @@ bool AuthSession::HandleRealmList()
- {
- const Realm &realm = i->second;
- // don't work with realms which not compatible with the client
- - bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.gamebuild));
- + bool okBuild = AuthHelper::IsAcceptedClientBuild(realm.gamebuild);
- // No SQL injection. id of realm is controlled by the database.
- uint32 flag = realm.flag;
- @@ -888,25 +1214,62 @@ bool AuthSession::HandleRealmList()
- // Resume patch transfer
- bool AuthSession::HandleXferResume()
- {
- - TC_LOG_DEBUG("server.authserver", "Entering _HandleXferResume");
- - //uint8
- - //uint64
- - return true;
- + TC_LOG_DEBUG("server.authserver", "Entering HandleXferResume");
- + XferResume_C* challenge = reinterpret_cast<XferResume_C*>(GetReadBuffer().GetReadPointer());
- +
- + // Todo: Send back a packet? I think the client don't get we send data.
- + if (patcher.PossiblePatching(_build, _localizationName))
- + {
- + fseek(patch, 0, SEEK_END);
- + size_t size = ftell(patch);
- +
- + fseek(patch, long(challenge->pos), 0);
- +
- + if (_patcher)
- + {
- + _patcher->stop();
- + delete _patcher;
- + }
- + _patcher = new PatcherRunnable(this, challenge->pos, size);
- + boost::thread u(&PatcherRunnable::run, _patcher);
- + u.join();
- + return true;
- + }
- + return false;
- }
- // Cancel patch transfer
- bool AuthSession::HandleXferCancel()
- {
- TC_LOG_DEBUG("server.authserver", "Entering _HandleXferCancel");
- - //uint8
- - return false;
- + CloseSocket();
- + return true;
- }
- // Accept patch transfer
- bool AuthSession::HandleXferAccept()
- {
- TC_LOG_DEBUG("server.authserver", "Entering _HandleXferAccept");
- - //uint8
- +
- + // Check packet length and patch existence
- + if (!patch)
- + {
- + TC_LOG_INFO("network", "Error while accepting patch transfer (wrong packet)");
- + return false;
- + }
- +
- + // Launch a PatcherRunnable thread, starting at the beginning of the patch file
- + fseek(patch, 0, SEEK_END);
- + size_t size = ftell(patch);
- + fseek(patch, 0, 0);
- +
- + if (_patcher)
- + {
- + _patcher->stop();
- + delete _patcher;
- + }
- + _patcher = new PatcherRunnable(this, 0, size);
- + boost::thread u(&PatcherRunnable::run, _patcher);
- return true;
- }
- diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h
- index 1151df7..f8b0fa1 100644
- --- a/src/server/authserver/Server/AuthSession.h
- +++ b/src/server/authserver/Server/AuthSession.h
- @@ -25,22 +25,73 @@
- #include "BigNumber.h"
- #include <memory>
- #include <boost/asio/ip/tcp.hpp>
- +#include <boost/thread.hpp>
- +
- +#include <openssl/md5.h>
- using boost::asio::ip::tcp;
- struct AuthHandler;
- +class AuthSession;
- +
- +// clientpatching
- +
- +typedef struct PATCH_INFO
- +{
- + int build;
- + int locale;
- + uint64 filesize;
- + uint8 md5[MD5_DIGEST_LENGTH];
- +} PATCH_INFO;
- +
- +class Patcher
- +{
- + typedef std::vector<PATCH_INFO> Patches;
- +public:
- + void Initialize();
- +
- + void LoadPatchMD5(const char*, char*);
- + bool GetHash(char * pat, uint8 mymd5[16]);
- +
- + bool InitPatching(int _build, std::string _locale, AuthSession* _session);
- + bool PossiblePatching(int _build, std::string _locale);
- +
- +private:
- + PATCH_INFO* getPatchInfo(int _build, std::string _locale, bool* fallback);
- +
- + void LoadPatchesInfo();
- + Patches _patches;
- + std::string m_dataDir;
- +};
- +
- +// Launch a thread to transfer a patch to the client
- +class PatcherRunnable
- +{
- +public:
- + PatcherRunnable(AuthSession* session, uint64 pos, uint64 size);
- + void run();
- + void stop();
- +
- +private:
- + AuthSession* _session;
- + uint64 pos;
- + uint64 size;
- + bool stopped;
- +};
- +
- class AuthSession : public Socket<AuthSession>
- {
- public:
- static std::unordered_map<uint8, AuthHandler> InitHandlers();
- AuthSession(tcp::socket&& socket) : Socket(std::move(socket)),
- - _isAuthenticated(false), _build(0), _expversion(0), _accountSecurityLevel(SEC_PLAYER)
- + _isAuthenticated(false), _build(0), _expversion(0), _accountSecurityLevel(SEC_PLAYER), _patcher(NULL)
- {
- N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
- g.SetDword(7);
- }
- + ~AuthSession();
- void Start() override
- {
- @@ -49,6 +100,9 @@ public:
- void SendPacket(ByteBuffer& packet);
- + FILE* patch;
- + PatcherRunnable *_patcher;
- +
- protected:
- void ReadHandler() override;
- diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist
- index 1b10fa4..4311608 100644
- --- a/src/server/authserver/authserver.conf.dist
- +++ b/src/server/authserver/authserver.conf.dist
- @@ -9,125 +9,85 @@
- # EXAMPLE CONFIG
- # AUTH SERVER SETTINGS
- # MYSQL SETTINGS
- -# UPDATE SETTINGS
- # LOGGING SYSTEM SETTINGS
- #
- ###################################################################################################
- +# AUTH SERVER SETTINGS
- -###################################################################################################
- -# EXAMPLE CONFIG
- -#
- -# Variable
- -# Description: Brief description what the variable is doing.
- -# Important: Annotation for important things about this variable.
- -# Example: "Example, i.e. if the value is a string"
- -# Default: 10 - (Enabled|Comment|Variable name in case of grouped config options)
- -# 0 - (Disabled|Comment|Variable name in case of grouped config options)
- -#
- -# Note to developers:
- -# - Copy this example to keep the formatting.
- -# - Line breaks should be at column 100.
- -###################################################################################################
- +# DataDir : Data directory setting.
- +DataDir = "./data/"
- -###################################################################################################
- -# AUTH SERVER SETTINGS
- -#
- -# LogsDir
- -# Description: Logs directory setting.
- -# Important: LogsDir needs to be quoted, as the string might contain space characters.
- -# Logs directory must exists, or log file creation will be disabled.
- -# Default: "" - (Log files will be stored in the current path)
- +# LogsDir : Logs directory setting.
- +LogsDir = "./log/"
- -LogsDir = ""
- +# PatchPacketDelay: Time between patch packets.
- +# Default: 100
- +PatchPacketDelay = 100
- -#
- # MaxPingTime
- # Description: Time (in minutes) between database pings.
- # Default: 30
- -
- MaxPingTime = 30
- -#
- # RealmServerPort
- # Description: TCP port to reach the auth server.
- # Default: 3724
- -
- RealmServerPort = 3724
- -#
- -#
- # BindIP
- # Description: Bind auth server to IP/hostname
- # Default: "0.0.0.0" - (Bind to all IPs on the system)
- -
- BindIP = "0.0.0.0"
- -#
- # PidFile
- # Description: Auth server PID file.
- # Example: "./authserver.pid" - (Enabled)
- # Default: "" - (Disabled)
- -
- PidFile = ""
- -#
- # UseProcessors
- # Description: Processors mask for Windows and Linux based multi-processor systems.
- # Example: A computer with 2 CPUs:
- # 1 - 1st CPU only, 2 - 2nd CPU only, 3 - 1st and 2nd CPU, because 1 | 2 is 3
- # Default: 0 - (Selected by OS)
- # 1+ - (Bit mask value of selected processors)
- -
- UseProcessors = 0
- -#
- # ProcessPriority
- # Description: Process priority setting for Windows and Linux based systems.
- # Details: On Linux, a nice value of -15 is used. (requires superuser). On Windows, process is set to HIGH class.
- # Default: 0 - (Normal)
- # 1 - (High)
- -
- ProcessPriority = 0
- -#
- # RealmsStateUpdateDelay
- # Description: Time (in seconds) between realm list updates.
- # Default: 20 - (Enabled)
- # 0 - (Disabled)
- -
- RealmsStateUpdateDelay = 20
- -#
- # WrongPass.MaxCount
- # Description: Number of login attemps with wrong password before the account or IP will be
- # banned.
- # Default: 0 - (Disabled)
- # 1+ - (Enabled)
- -
- WrongPass.MaxCount = 0
- -#
- # WrongPass.BanTime
- # Description: Time (in seconds) for banning account or IP for invalid login attempts.
- # Default: 600 - (10 minutes)
- # 0 - (Permanent ban)
- -
- WrongPass.BanTime = 600
- -#
- # WrongPass.BanType
- # Description: Ban type for invalid login attempts.
- # Default: 0 - (Ban IP)
- # 1 - (Ban Account)
- -
- WrongPass.BanType = 0
- #
- ###################################################################################################
- -
- -###################################################################################################
- # MYSQL SETTINGS
- -#
- # LoginDatabaseInfo
- # Description: Database connection settings for the realm server.
- # Example: "hostname;port;username;password;database"
- @@ -137,126 +97,33 @@ WrongPass.BanType = 0
- # ".;/path/to/unix_socket;username;password;database" - (use Unix sockets on
- # Unix/Linux)
- # Default: "127.0.0.1;3306;trinity;trinity;auth"
- +LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;iwpa"
- -LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth"
- -
- -#
- # LoginDatabase.WorkerThreads
- # Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL
- # statements. Each worker thread is mirrored with its own connection to the
- # Default: 1
- -
- LoginDatabase.WorkerThreads = 1
- -#
- # Wrong.Password.Login.Logging
- # Description: Additionally log attempted wrong password logging
- # Default: 0 - (Disabled)
- # 1 - (Enabled)
- -
- Wrong.Password.Login.Logging = 0
- #
- ###################################################################################################
- -
- -###################################################################################################
- -# UPDATE SETTINGS
- -#
- -# Updates.EnableDatabases
- -# Description: A mask that describes which databases shall be updated.
- -#
- -# Following flags are available
- -# DATABASE_LOGIN = 1, // Auth database
- -#
- -# Default: 0 - (All Disabled)
- -# 1 - (All Enabled)
- -
- -Updates.EnableDatabases = 0
- -
- -#
- -# Updates.SourcePath
- -# Description: The path to your TrinityCore source directory.
- -# If the path is left empty, built-in CMAKE_SOURCE_DIR is used.
- -# Example: "../TrinityCore"
- -# Default: ""
- -
- -Updates.SourcePath = ""
- -
- -#
- -# Updates.MySqlCLIPath
- -# Description: The path to your mysql cli binary.
- -# If the path is left empty, built-in path from cmake is used.
- -# Example: "C:/Program Files/MySQL/MySQL Server 5.6/bin/mysql.exe"
- -# "mysql.exe"
- -# "/usr/bin/mysql"
- -# Default: ""
- -
- -Updates.MySqlCLIPath = ""
- -
- -#
- -# Updates.AutoSetup
- -# Description: Auto populate empty databases.
- -# Default: 1 - (Enabled)
- -# 0 - (Disabled)
- -
- -Updates.AutoSetup = 1
- -
- -#
- -# Updates.Redundancy
- -# Description: Perform data redundancy checks through hashing
- -# to detect changes on sql updates and reapply it.
- -# Default: 1 - (Enabled)
- -# 0 - (Disabled)
- -
- -Updates.Redundancy = 1
- -
- -#
- -# Updates.ArchivedRedundancy
- -# Description: Check hashes of archived updates (slows down startup).
- -# Default: 0 - (Disabled)
- -# 1 - (Enabled)
- -
- -Updates.ArchivedRedundancy = 0
- -
- -#
- -# Updates.AllowRehash
- -# Description: Inserts the current file hash in the database if it is left empty.
- -# Useful if you want to mark a file as applied but you don't know its hash.
- -# Default: 1 - (Enabled)
- -# 0 - (Disabled)
- -
- -Updates.AllowRehash = 1
- -
- -#
- -# Updates.CleanDeadRefMaxCount
- -# Description: Cleans dead/ orphaned references that occur if an update was removed or renamed and edited in one step.
- -# It only starts the clean up if the count of the missing updates is below or equal the Updates.CleanDeadRefMaxCount value.
- -# This way prevents erasing of the update history due to wrong source directory state (maybe wrong branch or bad revision).
- -# Disable this if you want to know if the database is in a possible "dirty state".
- -# Default: 3 - (Enabled)
- -# 0 - (Disabled)
- -# -1 - (Enabled - unlimited)
- -
- -Updates.CleanDeadRefMaxCount = 3
- -
- -#
- -###################################################################################################
- -
- -###################################################################################################
- -#
- # LOGGING SYSTEM SETTINGS
- -#
- +
- # Appender config values: Given a appender "name"
- # Appender.name
- # Description: Defines 'where to log'
- # Format: Type,LogLevel,Flags,optional1,optional2,optional3
- -#
- # Type
- # 0 - (None)
- # 1 - (Console)
- # 2 - (File)
- # 3 - (DB)
- -#
- # LogLevel
- # 0 - (Disabled)
- # 1 - (Trace)
- @@ -265,7 +132,6 @@ Updates.CleanDeadRefMaxCount = 3
- # 4 - (Warn)
- # 5 - (Error)
- # 6 - (Fatal)
- -#
- # Flags:
- # 0 - None
- # 1 - Prefix Timestamp to the text
- @@ -273,7 +139,6 @@ Updates.CleanDeadRefMaxCount = 3
- # 4 - Prefix Log Filter type to the text
- # 8 - Append timestamp to the log file name. Format: YYYY-MM-DD_HH-MM-SS (Only used with Type = 2)
- # 16 - Make a backup of existing file before overwrite (Only used with Mode = w)
- -#
- # Colors (read as optional1 if Type = Console)
- # Format: "fatal error warn info debug trace"
- # 0 - BLACK
- @@ -292,22 +157,17 @@ Updates.CleanDeadRefMaxCount = 3
- # 13 - LCYAN
- # 14 - WHITE
- # Example: "13 11 9 5 3 1"
- -#
- # File: Name of the file (read as optional1 if Type = File)
- # Allows to use one "%s" to create dynamic files
- -#
- # Mode: Mode to open the file (read as optional2 if Type = File)
- # a - (Append)
- # w - (Overwrite)
- -#
- # MaxFileSize: Maximum file size of the log file before creating a new log file
- # (read as optional3 if Type = File)
- # Size is measured in bytes expressed in a 64-bit unsigned integer.
- # Maximum value is 4294967295 (4 gb). Leave blank for no limit.
- # NOTE: Does not work with dynamic filenames.
- # Example: 536870912 (512 mb)
- -#
- -
- Appender.Console=1,2,0
- Appender.Auth=2,2,0,Auth.log,w
- @@ -315,7 +175,6 @@ Appender.Auth=2,2,0,Auth.log,w
- # Logger.name
- # Description: Defines 'What to log'
- # Format: LogLevel,AppenderList
- -#
- # LogLevel
- # 0 - (Disabled)
- # 1 - (Trace)
- @@ -324,12 +183,9 @@ Appender.Auth=2,2,0,Auth.log,w
- # 4 - (Warn)
- # 5 - (Error)
- # 6 - (Fatal)
- -#
- # AppenderList: List of appenders linked to logger
- # (Using spaces as separator).
- -#
- -
- Logger.root=3,Console Auth
- #
- -###################################################################################################
- +###################################################################################################
- \ No newline at end of file
- diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
- index de003c2..95bd3a4 100644
- --- a/src/server/database/Database/Implementation/LoginDatabase.cpp
- +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
- @@ -110,6 +110,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
- // 0: string, 1: string, 2: string // Complete name: "Login_Insert_Failed_Account_Login_due_password_IP_Logging"
- PrepareStatement(LOGIN_INS_FALP_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES ((SELECT id FROM account WHERE username = ?), 0, 1, ?, ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, "SELECT gmlevel, RealmID FROM account_access WHERE id = ? and (RealmID = ? OR RealmID = -1) ORDER BY gmlevel desc", CONNECTION_SYNCH);
- + PrepareStatement(LOGIN_SEL_VERSIONS, "SELECT Build, MajorVersion, MinorVersion, BugfixVersion, HotfixVersion FROM versions", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS, "SELECT permissionId, granted FROM rbac_account_permissions WHERE accountId = ? AND (realmId = ? OR realmId = -1) ORDER BY permissionId, realmId", CONNECTION_BOTH);
- PrepareStatement(LOGIN_INS_RBAC_ACCOUNT_PERMISSION, "INSERT INTO rbac_account_permissions (accountId, permissionId, granted, realmId) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE granted = VALUES(granted)", CONNECTION_ASYNC);
- diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h
- index 3b30105..1a60fc7 100644
- --- a/src/server/database/Database/Implementation/LoginDatabase.h
- +++ b/src/server/database/Database/Implementation/LoginDatabase.h
- @@ -108,6 +108,7 @@ enum LoginDatabaseStatements
- LOGIN_INS_FACL_IP_LOGGING,
- LOGIN_INS_CHAR_IP_LOGGING,
- LOGIN_INS_FALP_IP_LOGGING,
- + LOGIN_SEL_VERSIONS,
- LOGIN_SEL_ACCOUNT_ACCESS_BY_ID,
- LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS,
- diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
- index c41caa8..c10f8b1 100644
- --- a/src/server/game/World/World.cpp
- +++ b/src/server/game/World/World.cpp
- @@ -1139,7 +1139,7 @@ void World::LoadConfigSettings(bool reload)
- }
- ///- Read the "Data" directory from the config file
- - std::string dataPath = sConfigMgr->GetStringDefault("DataDir", "./");
- + std::string dataPath = sConfigMgr->GetStringDefault("DataDir", "./data/");
- if (dataPath.empty() || (dataPath.at(dataPath.length()-1) != '/' && dataPath.at(dataPath.length()-1) != '\\'))
- dataPath.push_back('/');
- --
- 1.9.5.msysgit.0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement