mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Servers: nuke authserver
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
option(SERVERS "Build worldserver and authserver" 1)
|
||||
option(SERVERS "Build worldserver and bnetserver" 1)
|
||||
|
||||
set(SCRIPTS_AVAILABLE_OPTIONS none static dynamic minimal-static minimal-dynamic)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ message("")
|
||||
if( SERVERS )
|
||||
message("* Build world/auth : Yes (default)")
|
||||
else()
|
||||
message("* Build world/authserver : No")
|
||||
message("* Build world/bnetserver : No")
|
||||
endif()
|
||||
|
||||
if(SCRIPTS AND (NOT SCRIPTS STREQUAL "none"))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
==== PHP merger (index.php + merge.php) ====
|
||||
|
||||
This is a PHP script for merging a new .dist file with your existing .conf file (worldserver.conf.dist and authserver.conf.dist)
|
||||
This is a PHP script for merging a new .dist file with your existing .conf file (worldserver.conf.dist and bnetserver.conf.dist)
|
||||
It should also work with mangos dist/conf files as well.
|
||||
|
||||
It uses sessions so it is multi user safe, it adds any options that are removed to the bottom of the file,
|
||||
|
||||
@@ -49,7 +49,7 @@ than where to install using flags built into our cmake files. Just open
|
||||
up CMakeLists.txt in the main folder and take a look at some of the
|
||||
flags like
|
||||
|
||||
SERVERS Build worldserver and authserver
|
||||
SERVERS Build worldserver and bnetserver
|
||||
SCRIPTS Build core with scripts included
|
||||
TOOLS Build map/vmap extraction/assembler tools
|
||||
USE_SCRIPTPCH Use precompiled headers when compiling scripts
|
||||
|
||||
@@ -30,7 +30,6 @@ endif(WIN32)
|
||||
add_subdirectory(database)
|
||||
add_subdirectory(shared)
|
||||
add_subdirectory(ipc)
|
||||
add_subdirectory(authserver)
|
||||
add_subdirectory(bnetserver)
|
||||
add_subdirectory(game)
|
||||
add_subdirectory(scripts)
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://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 nullptr;
|
||||
}
|
||||
|
||||
bool IsBuildSupportingBattlenet(int build)
|
||||
{
|
||||
return build >= 15595;
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _AUTHCODES_H
|
||||
#define _AUTHCODES_H
|
||||
|
||||
enum AuthResult
|
||||
{
|
||||
WOW_SUCCESS = 0x00,
|
||||
WOW_FAIL_BANNED = 0x03,
|
||||
WOW_FAIL_UNKNOWN_ACCOUNT = 0x04,
|
||||
WOW_FAIL_INCORRECT_PASSWORD = 0x05,
|
||||
WOW_FAIL_ALREADY_ONLINE = 0x06,
|
||||
WOW_FAIL_NO_TIME = 0x07,
|
||||
WOW_FAIL_DB_BUSY = 0x08,
|
||||
WOW_FAIL_VERSION_INVALID = 0x09,
|
||||
WOW_FAIL_VERSION_UPDATE = 0x0A,
|
||||
WOW_FAIL_INVALID_SERVER = 0x0B,
|
||||
WOW_FAIL_SUSPENDED = 0x0C,
|
||||
WOW_FAIL_FAIL_NOACCESS = 0x0D,
|
||||
WOW_SUCCESS_SURVEY = 0x0E,
|
||||
WOW_FAIL_PARENTCONTROL = 0x0F,
|
||||
WOW_FAIL_LOCKED_ENFORCED = 0x10,
|
||||
WOW_FAIL_TRIAL_ENDED = 0x11,
|
||||
WOW_FAIL_USE_BATTLENET = 0x12,
|
||||
WOW_FAIL_ANTI_INDULGENCE = 0x13,
|
||||
WOW_FAIL_EXPIRED = 0x14,
|
||||
WOW_FAIL_NO_GAME_ACCOUNT = 0x15,
|
||||
WOW_FAIL_CHARGEBACK = 0x16,
|
||||
WOW_FAIL_INTERNET_GAME_ROOM_WITHOUT_BNET = 0x17,
|
||||
WOW_FAIL_GAME_ACCOUNT_LOCKED = 0x18,
|
||||
WOW_FAIL_UNLOCKABLE_LOCK = 0x19,
|
||||
WOW_FAIL_CONVERSION_REQUIRED = 0x20,
|
||||
WOW_FAIL_DISCONNECTED = 0xFF
|
||||
};
|
||||
|
||||
enum LoginResult
|
||||
{
|
||||
LOGIN_OK = 0x00,
|
||||
LOGIN_FAILED = 0x01,
|
||||
LOGIN_FAILED2 = 0x02,
|
||||
LOGIN_BANNED = 0x03,
|
||||
LOGIN_UNKNOWN_ACCOUNT = 0x04,
|
||||
LOGIN_UNKNOWN_ACCOUNT3 = 0x05,
|
||||
LOGIN_ALREADYONLINE = 0x06,
|
||||
LOGIN_NOTIME = 0x07,
|
||||
LOGIN_DBBUSY = 0x08,
|
||||
LOGIN_BADVERSION = 0x09,
|
||||
LOGIN_DOWNLOAD_FILE = 0x0A,
|
||||
LOGIN_FAILED3 = 0x0B,
|
||||
LOGIN_SUSPENDED = 0x0C,
|
||||
LOGIN_FAILED4 = 0x0D,
|
||||
LOGIN_CONNECTED = 0x0E,
|
||||
LOGIN_PARENTALCONTROL = 0x0F,
|
||||
LOGIN_LOCKED_ENFORCED = 0x10
|
||||
};
|
||||
|
||||
enum GameAccountFlags
|
||||
{
|
||||
GAMEACCOUNT_FLAG_GM = 0x00000001,
|
||||
GAMEACCOUNT_FLAG_NOKICK = 0x00000002,
|
||||
GAMEACCOUNT_FLAG_COLLECTOR = 0x00000004,
|
||||
GAMEACCOUNT_FLAG_WOW_TRIAL = 0x00000008,
|
||||
GAMEACCOUNT_FLAG_CANCELLED = 0x00000010,
|
||||
GAMEACCOUNT_FLAG_IGR = 0x00000020,
|
||||
GAMEACCOUNT_FLAG_WHOLESALER = 0x00000040,
|
||||
GAMEACCOUNT_FLAG_PRIVILEGED = 0x00000080,
|
||||
GAMEACCOUNT_FLAG_EU_FORBID_ELV = 0x00000100,
|
||||
GAMEACCOUNT_FLAG_EU_FORBID_BILLING = 0x00000200,
|
||||
GAMEACCOUNT_FLAG_WOW_RESTRICTED = 0x00000400,
|
||||
GAMEACCOUNT_FLAG_REFERRAL = 0x00000800,
|
||||
GAMEACCOUNT_FLAG_BLIZZARD = 0x00001000,
|
||||
GAMEACCOUNT_FLAG_RECURRING_BILLING = 0x00002000,
|
||||
GAMEACCOUNT_FLAG_NOELECTUP = 0x00004000,
|
||||
GAMEACCOUNT_FLAG_KR_CERTIFICATE = 0x00008000,
|
||||
GAMEACCOUNT_FLAG_EXPANSION_COLLECTOR = 0x00010000,
|
||||
GAMEACCOUNT_FLAG_DISABLE_VOICE = 0x00020000,
|
||||
GAMEACCOUNT_FLAG_DISABLE_VOICE_SPEAK = 0x00040000,
|
||||
GAMEACCOUNT_FLAG_REFERRAL_RESURRECT = 0x00080000,
|
||||
GAMEACCOUNT_FLAG_EU_FORBID_CC = 0x00100000,
|
||||
GAMEACCOUNT_FLAG_OPENBETA_DELL = 0x00200000,
|
||||
GAMEACCOUNT_FLAG_PROPASS = 0x00400000,
|
||||
GAMEACCOUNT_FLAG_PROPASS_LOCK = 0x00800000,
|
||||
GAMEACCOUNT_FLAG_PENDING_UPGRADE = 0x01000000,
|
||||
GAMEACCOUNT_FLAG_RETAIL_FROM_TRIAL = 0x02000000,
|
||||
GAMEACCOUNT_FLAG_EXPANSION2_COLLECTOR = 0x04000000,
|
||||
GAMEACCOUNT_FLAG_OVERMIND_LINKED = 0x08000000,
|
||||
GAMEACCOUNT_FLAG_DEMOS = 0x10000000,
|
||||
GAMEACCOUNT_FLAG_DEATH_KNIGHT_OK = 0x20000000,
|
||||
};
|
||||
|
||||
enum ExpansionFlags
|
||||
{
|
||||
POST_BC_EXP_FLAG = 0x2,
|
||||
PRE_BC_EXP_FLAG = 0x1,
|
||||
NO_VALID_EXP_FLAG = 0x0
|
||||
};
|
||||
|
||||
struct RealmBuildInfo
|
||||
{
|
||||
int Build;
|
||||
int MajorVersion;
|
||||
int MinorVersion;
|
||||
int BugfixVersion;
|
||||
int HotfixVersion;
|
||||
};
|
||||
|
||||
namespace AuthHelper
|
||||
{
|
||||
RealmBuildInfo const* GetBuildInfo(int build);
|
||||
bool IsAcceptedClientBuild(int build);
|
||||
bool IsPostBCAcceptedClientBuild(int build);
|
||||
bool IsPreBCAcceptedClientBuild(int build);
|
||||
bool IsBuildSupportingBattlenet(int build);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://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 "TOTP.h"
|
||||
#include <cstring>
|
||||
|
||||
int base32_decode(char const* encoded, char* result, int bufSize)
|
||||
{
|
||||
// Base32 implementation
|
||||
// Copyright 2010 Google Inc.
|
||||
// Author: Markus Gutschke
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
int buffer = 0;
|
||||
int bitsLeft = 0;
|
||||
int count = 0;
|
||||
for (const char *ptr = encoded; count < bufSize && *ptr; ++ptr)
|
||||
{
|
||||
char ch = *ptr;
|
||||
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-')
|
||||
continue;
|
||||
buffer <<= 5;
|
||||
|
||||
// Deal with commonly mistyped characters
|
||||
if (ch == '0')
|
||||
ch = 'O';
|
||||
else if (ch == '1')
|
||||
ch = 'L';
|
||||
else if (ch == '8')
|
||||
ch = 'B';
|
||||
|
||||
// Look up one base32 digit
|
||||
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
|
||||
ch = (ch & 0x1F) - 1;
|
||||
else if (ch >= '2' && ch <= '7')
|
||||
ch -= '2' - 26;
|
||||
else
|
||||
return -1;
|
||||
|
||||
buffer |= ch;
|
||||
bitsLeft += 5;
|
||||
if (bitsLeft >= 8)
|
||||
{
|
||||
result[count++] = buffer >> (bitsLeft - 8);
|
||||
bitsLeft -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (count < bufSize)
|
||||
result[count] = '\000';
|
||||
return count;
|
||||
}
|
||||
|
||||
#define HMAC_RES_SIZE 20
|
||||
|
||||
namespace TOTP
|
||||
{
|
||||
unsigned int GenerateToken(char const* b32key)
|
||||
{
|
||||
size_t keySize = strlen(b32key);
|
||||
int bufsize = (keySize + 7)/8*5;
|
||||
char* encoded = new char[bufsize];
|
||||
memset(encoded, 0, bufsize);
|
||||
unsigned int hmacResSize = HMAC_RES_SIZE;
|
||||
unsigned char hmacRes[HMAC_RES_SIZE];
|
||||
unsigned long timestamp = time(nullptr)/30;
|
||||
unsigned char challenge[8];
|
||||
|
||||
for (int i = 8; i--;timestamp >>= 8)
|
||||
challenge[i] = timestamp;
|
||||
|
||||
base32_decode(b32key, encoded, bufsize);
|
||||
HMAC(EVP_sha1(), encoded, bufsize, challenge, 8, hmacRes, &hmacResSize);
|
||||
unsigned int offset = hmacRes[19] & 0xF;
|
||||
unsigned int truncHash = (hmacRes[offset] << 24) | (hmacRes[offset+1] << 16 )| (hmacRes[offset+2] << 8) | (hmacRes[offset+3]);
|
||||
truncHash &= 0x7FFFFFFF;
|
||||
|
||||
delete[] encoded;
|
||||
|
||||
return truncHash % 1000000;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://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/>.
|
||||
*/
|
||||
|
||||
#ifndef _TOTP_H
|
||||
#define _TOTP_H
|
||||
|
||||
#include "openssl/hmac.h"
|
||||
#include "openssl/evp.h"
|
||||
|
||||
namespace TOTP
|
||||
{
|
||||
unsigned int GenerateToken(char const* b32key);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,90 +0,0 @@
|
||||
# Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
#
|
||||
# This file is free software; as a special exception the author gives
|
||||
# unlimited permission to copy and/or distribute it, with or without
|
||||
# modifications, as long as this notice is preserved.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
########### authserver ###############
|
||||
|
||||
CollectSourceFiles(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PRIVATE_SOURCES
|
||||
# Exclude
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders)
|
||||
|
||||
if( WIN32 )
|
||||
list(APPEND PRIVATE_SOURCES ${sources_windows})
|
||||
if ( MSVC )
|
||||
list(APPEND PRIVATE_SOURCES authserver.rc)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (USE_COREPCH)
|
||||
set(PRIVATE_PCH_HEADER PrecompiledHeaders/authPCH.h)
|
||||
endif()
|
||||
|
||||
GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_executable(authserver
|
||||
${PRIVATE_SOURCES}
|
||||
)
|
||||
|
||||
if( NOT WIN32 )
|
||||
set_target_properties(authserver PROPERTIES
|
||||
COMPILE_DEFINITIONS _TRINITY_REALM_CONFIG="${CONF_DIR}/authserver.conf"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(authserver
|
||||
PRIVATE
|
||||
trinity-core-interface
|
||||
PUBLIC
|
||||
shared)
|
||||
|
||||
CollectIncludeDirectories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PUBLIC_INCLUDES
|
||||
# Exclude
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders)
|
||||
|
||||
target_include_directories(authserver
|
||||
PUBLIC
|
||||
${PUBLIC_INCLUDES}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set_target_properties(authserver
|
||||
PROPERTIES
|
||||
FOLDER
|
||||
"server")
|
||||
|
||||
if( WIN32 )
|
||||
if ( "${CMAKE_MAKE_PROGRAM}" MATCHES "MSBuild" )
|
||||
add_custom_command(TARGET authserver
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/authserver.conf.dist ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/
|
||||
)
|
||||
elseif ( MINGW )
|
||||
add_custom_command(TARGET authserver
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/authserver.conf.dist ${CMAKE_BINARY_DIR}/bin/
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if( UNIX )
|
||||
install(TARGETS authserver DESTINATION bin)
|
||||
install(FILES authserver.conf.dist DESTINATION ${CONF_DIR})
|
||||
elseif( WIN32 )
|
||||
install(TARGETS authserver DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
install(FILES authserver.conf.dist DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
endif()
|
||||
|
||||
# Generate precompiled header
|
||||
if (USE_COREPCH)
|
||||
add_cxx_pch(authserver ${PRIVATE_PCH_HEADER})
|
||||
endif()
|
||||
@@ -1,344 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file main.cpp
|
||||
* @brief Authentication Server main program
|
||||
*
|
||||
* This file contains the main program for the
|
||||
* authentication server
|
||||
*/
|
||||
|
||||
#include "AppenderDB.h"
|
||||
#include "AuthSocketMgr.h"
|
||||
#include "Banner.h"
|
||||
#include "Config.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseLoader.h"
|
||||
#include "DeadlineTimer.h"
|
||||
#include "GitRevision.h"
|
||||
#include "GruntRealmList.h"
|
||||
#include "IoContext.h"
|
||||
#include "IPLocation.h"
|
||||
#include "MySQLThreading.h"
|
||||
#include "ProcessPriority.h"
|
||||
#include "Util.h"
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#include <iostream>
|
||||
#include <csignal>
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
using namespace boost::program_options;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
#ifndef _TRINITY_REALM_CONFIG
|
||||
# define _TRINITY_REALM_CONFIG "authserver.conf"
|
||||
#endif
|
||||
|
||||
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
|
||||
#include "ServiceWin32.h"
|
||||
char serviceName[] = "authserver";
|
||||
char serviceLongName[] = "TrinityCore auth service";
|
||||
char serviceDescription[] = "TrinityCore World of Warcraft emulator auth service";
|
||||
/*
|
||||
* -1 - not in service mode
|
||||
* 0 - stopped
|
||||
* 1 - running
|
||||
* 2 - paused
|
||||
*/
|
||||
int m_ServiceStatus = -1;
|
||||
|
||||
void ServiceStatusWatcher(std::weak_ptr<Trinity::Asio::DeadlineTimer> serviceStatusWatchTimerRef, std::weak_ptr<Trinity::Asio::IoContext> ioContextRef, boost::system::error_code const& error);
|
||||
#endif
|
||||
|
||||
bool StartDB();
|
||||
void StopDB();
|
||||
void SignalHandler(std::weak_ptr<Trinity::Asio::IoContext> ioContextRef, boost::system::error_code const& error, int signalNumber);
|
||||
void KeepDatabaseAliveHandler(std::weak_ptr<Trinity::Asio::DeadlineTimer> dbPingTimerRef, int32 dbPingInterval, boost::system::error_code const& error);
|
||||
void BanExpiryHandler(std::weak_ptr<Trinity::Asio::DeadlineTimer> banExpiryCheckTimerRef, int32 banExpiryCheckInterval, boost::system::error_code const& error);
|
||||
variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
signal(SIGABRT, &Trinity::AbortHandler);
|
||||
|
||||
auto configFile = fs::absolute(_TRINITY_REALM_CONFIG);
|
||||
std::string configService;
|
||||
auto vm = GetConsoleArguments(argc, argv, configFile, configService);
|
||||
// exit if help or version is enabled
|
||||
if (vm.count("help") || vm.count("version"))
|
||||
return 0;
|
||||
|
||||
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
|
||||
if (configService.compare("install") == 0)
|
||||
return WinServiceInstall() == true ? 0 : 1;
|
||||
else if (configService.compare("uninstall") == 0)
|
||||
return WinServiceUninstall() == true ? 0 : 1;
|
||||
else if (configService.compare("run") == 0)
|
||||
return WinServiceRun() ? 0 : 1;
|
||||
#endif
|
||||
|
||||
std::string configError;
|
||||
if (!sConfigMgr->LoadInitial(configFile.generic_string(),
|
||||
std::vector<std::string>(argv, argv + argc),
|
||||
configError))
|
||||
{
|
||||
printf("Error in config file: %s\n", configError.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
sLog->RegisterAppender<AppenderDB>();
|
||||
sLog->Initialize(nullptr);
|
||||
|
||||
Trinity::Banner::Show("authserver",
|
||||
[](char const* text)
|
||||
{
|
||||
TC_LOG_INFO("server.authserver", "%s", text);
|
||||
},
|
||||
[]()
|
||||
{
|
||||
TC_LOG_INFO("server.authserver", "Using configuration file %s.", sConfigMgr->GetFilename().c_str());
|
||||
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);
|
||||
}
|
||||
);
|
||||
|
||||
// authserver PID file creation
|
||||
std::string pidFile = sConfigMgr->GetStringDefault("PidFile", "");
|
||||
if (!pidFile.empty())
|
||||
{
|
||||
if (uint32 pid = CreatePIDFile(pidFile))
|
||||
TC_LOG_INFO("server.authserver", "Daemon PID: %u\n", pid);
|
||||
else
|
||||
{
|
||||
TC_LOG_ERROR("server.authserver", "Cannot create PID file %s.\n", pidFile.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the database connection
|
||||
if (!StartDB())
|
||||
return 1;
|
||||
|
||||
// Load IP Location Database
|
||||
sIPLocation->Load();
|
||||
|
||||
std::shared_ptr<void> dbHandle(nullptr, [](void*) { StopDB(); });
|
||||
|
||||
std::shared_ptr<Trinity::Asio::IoContext> ioContext = std::make_shared<Trinity::Asio::IoContext>();
|
||||
|
||||
// Get the list of realms for the server
|
||||
sGruntRealmList->Initialize(*ioContext, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20));
|
||||
|
||||
std::shared_ptr<void> sRealmListHandle(nullptr, [](void*) { sGruntRealmList->Close(); });
|
||||
|
||||
if (sGruntRealmList->GetRealms().empty())
|
||||
{
|
||||
TC_LOG_ERROR("server.authserver", "No valid realms specified.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Start the listening port (acceptor) for auth connections
|
||||
int32 port = sConfigMgr->GetIntDefault("RealmServerPort", 3724);
|
||||
if (port < 0 || port > 0xFFFF)
|
||||
{
|
||||
TC_LOG_ERROR("server.authserver", "Specified port out of allowed range (1-65535)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0");
|
||||
|
||||
if (!sAuthSocketMgr.StartNetwork(*ioContext, bindIp, port))
|
||||
{
|
||||
TC_LOG_ERROR("server.authserver", "Failed to initialize network");
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::shared_ptr<void> sAuthSocketMgrHandle(nullptr, [](void*) { sAuthSocketMgr.StopNetwork(); });
|
||||
|
||||
// Set signal handlers
|
||||
boost::asio::signal_set signals(*ioContext, SIGINT, SIGTERM);
|
||||
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
|
||||
signals.add(SIGBREAK);
|
||||
#endif
|
||||
signals.async_wait(std::bind(&SignalHandler, std::weak_ptr<Trinity::Asio::IoContext>(ioContext), std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
// Set process priority according to configuration settings
|
||||
SetProcessPriority("server.authserver", sConfigMgr->GetIntDefault(CONFIG_PROCESSOR_AFFINITY, 0), sConfigMgr->GetBoolDefault(CONFIG_HIGH_PRIORITY, false));
|
||||
|
||||
// Enabled a timed callback for handling the database keep alive ping
|
||||
int32 dbPingInterval = sConfigMgr->GetIntDefault("MaxPingTime", 30);
|
||||
std::shared_ptr<Trinity::Asio::DeadlineTimer> dbPingTimer = std::make_shared<Trinity::Asio::DeadlineTimer>(*ioContext);
|
||||
dbPingTimer->expires_from_now(boost::posix_time::minutes(dbPingInterval));
|
||||
dbPingTimer->async_wait(std::bind(&KeepDatabaseAliveHandler, std::weak_ptr<Trinity::Asio::DeadlineTimer>(dbPingTimer), dbPingInterval, std::placeholders::_1));
|
||||
|
||||
int32 banExpiryCheckInterval = sConfigMgr->GetIntDefault("BanExpiryCheckInterval", 60);
|
||||
std::shared_ptr<Trinity::Asio::DeadlineTimer> banExpiryCheckTimer = std::make_shared<Trinity::Asio::DeadlineTimer>(*ioContext);
|
||||
banExpiryCheckTimer->expires_from_now(boost::posix_time::seconds(banExpiryCheckInterval));
|
||||
banExpiryCheckTimer->async_wait(std::bind(&BanExpiryHandler, std::weak_ptr<Trinity::Asio::DeadlineTimer>(banExpiryCheckTimer), banExpiryCheckInterval, std::placeholders::_1));
|
||||
|
||||
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
|
||||
std::shared_ptr<Trinity::Asio::DeadlineTimer> serviceStatusWatchTimer;
|
||||
if (m_ServiceStatus != -1)
|
||||
{
|
||||
serviceStatusWatchTimer = std::make_shared<Trinity::Asio::DeadlineTimer>(*ioContext);
|
||||
serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1));
|
||||
serviceStatusWatchTimer->async_wait(std::bind(&ServiceStatusWatcher,
|
||||
std::weak_ptr<Trinity::Asio::DeadlineTimer>(serviceStatusWatchTimer),
|
||||
std::weak_ptr<Trinity::Asio::IoContext>(ioContext),
|
||||
std::placeholders::_1));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Start the io service worker loop
|
||||
ioContext->run();
|
||||
|
||||
banExpiryCheckTimer->cancel();
|
||||
dbPingTimer->cancel();
|
||||
|
||||
TC_LOG_INFO("server.authserver", "Halting process...");
|
||||
|
||||
signals.cancel();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Initialize connection to the database
|
||||
bool StartDB()
|
||||
{
|
||||
MySQL::Library_Init();
|
||||
|
||||
// Load databases
|
||||
// NOTE: While authserver is singlethreaded you should keep synch_threads == 1.
|
||||
// Increasing it is just silly since only 1 will be used ever.
|
||||
DatabaseLoader loader("server.authserver", DatabaseLoader::DATABASE_NONE);
|
||||
loader
|
||||
.AddDatabase(LoginDatabase, "Login");
|
||||
|
||||
if (!loader.Load())
|
||||
return false;
|
||||
|
||||
TC_LOG_INFO("server.authserver", "Started auth database connection pool.");
|
||||
sLog->SetRealmId(0); // Enables DB appenders when realm is set.
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Close the connection to the database
|
||||
void StopDB()
|
||||
{
|
||||
LoginDatabase.Close();
|
||||
MySQL::Library_End();
|
||||
}
|
||||
|
||||
void SignalHandler(std::weak_ptr<Trinity::Asio::IoContext> ioContextRef, boost::system::error_code const& error, int /*signalNumber*/)
|
||||
{
|
||||
if (!error)
|
||||
if (std::shared_ptr<Trinity::Asio::IoContext> ioContext = ioContextRef.lock())
|
||||
ioContext->stop();
|
||||
}
|
||||
|
||||
void KeepDatabaseAliveHandler(std::weak_ptr<Trinity::Asio::DeadlineTimer> dbPingTimerRef, int32 dbPingInterval, boost::system::error_code const& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
if (std::shared_ptr<Trinity::Asio::DeadlineTimer> dbPingTimer = dbPingTimerRef.lock())
|
||||
{
|
||||
TC_LOG_INFO("server.authserver", "Ping MySQL to keep connection alive");
|
||||
LoginDatabase.KeepAlive();
|
||||
|
||||
dbPingTimer->expires_from_now(boost::posix_time::minutes(dbPingInterval));
|
||||
dbPingTimer->async_wait(std::bind(&KeepDatabaseAliveHandler, dbPingTimerRef, dbPingInterval, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BanExpiryHandler(std::weak_ptr<Trinity::Asio::DeadlineTimer> banExpiryCheckTimerRef, int32 banExpiryCheckInterval, boost::system::error_code const& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
if (std::shared_ptr<Trinity::Asio::DeadlineTimer> banExpiryCheckTimer = banExpiryCheckTimerRef.lock())
|
||||
{
|
||||
LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));
|
||||
LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS));
|
||||
|
||||
banExpiryCheckTimer->expires_from_now(boost::posix_time::seconds(banExpiryCheckInterval));
|
||||
banExpiryCheckTimer->async_wait(std::bind(&BanExpiryHandler, banExpiryCheckTimerRef, banExpiryCheckInterval, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
|
||||
void ServiceStatusWatcher(std::weak_ptr<Trinity::Asio::DeadlineTimer> serviceStatusWatchTimerRef, std::weak_ptr<Trinity::Asio::IoContext> ioContextRef, boost::system::error_code const& error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
if (std::shared_ptr<Trinity::Asio::IoContext> ioContext = ioContextRef.lock())
|
||||
{
|
||||
if (m_ServiceStatus == 0)
|
||||
ioContext->stop();
|
||||
else if (std::shared_ptr<Trinity::Asio::DeadlineTimer> serviceStatusWatchTimer = serviceStatusWatchTimerRef.lock())
|
||||
{
|
||||
serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1));
|
||||
serviceStatusWatchTimer->async_wait(std::bind(&ServiceStatusWatcher, serviceStatusWatchTimerRef, ioContextRef, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService)
|
||||
{
|
||||
options_description all("Allowed options");
|
||||
all.add_options()
|
||||
("help,h", "print usage message")
|
||||
("version,v", "print version build info")
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::absolute(_TRINITY_REALM_CONFIG)),
|
||||
"use <arg> as configuration file")
|
||||
;
|
||||
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
|
||||
options_description win("Windows platform specific options");
|
||||
win.add_options()
|
||||
("service,s", value<std::string>(&configService)->default_value(""), "Windows service options: [install | uninstall]")
|
||||
;
|
||||
|
||||
all.add(win);
|
||||
#else
|
||||
(void)configService;
|
||||
#endif
|
||||
variables_map variablesMap;
|
||||
try
|
||||
{
|
||||
store(command_line_parser(argc, argv).options(all).allow_unregistered().run(), variablesMap);
|
||||
notify(variablesMap);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << "\n";
|
||||
}
|
||||
|
||||
if (variablesMap.count("help"))
|
||||
std::cout << all << "\n";
|
||||
else if (variablesMap.count("version"))
|
||||
std::cout << GitRevision::GetFullVersion() << "\n";
|
||||
|
||||
return variablesMap;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://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 "Common.h"
|
||||
#include "Configuration/Config.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "Log.h"
|
||||
#include "GruntRealmList.h"
|
||||
#include "AuthSession.h"
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* 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 "GruntRealmList.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DeadlineTimer.h"
|
||||
#include "DeadlineTimer.h"
|
||||
#include "IoContext.h"
|
||||
#include "Log.h"
|
||||
#include "Resolver.h"
|
||||
#include "Util.h"
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
GruntRealmList::GruntRealmList() : _updateInterval(0)
|
||||
{
|
||||
}
|
||||
|
||||
GruntRealmList::~GruntRealmList()
|
||||
{
|
||||
}
|
||||
|
||||
GruntRealmList* GruntRealmList::Instance()
|
||||
{
|
||||
static GruntRealmList instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
// Load the realm list from the database
|
||||
void GruntRealmList::Initialize(Trinity::Asio::IoContext& ioContext, uint32 updateInterval)
|
||||
{
|
||||
_updateInterval = updateInterval;
|
||||
_updateTimer = Trinity::make_unique<Trinity::Asio::DeadlineTimer>(ioContext);
|
||||
_resolver = Trinity::make_unique<boost::asio::ip::tcp_resolver>(ioContext);
|
||||
|
||||
// Get the content of the realmlist table in the database
|
||||
UpdateRealms(boost::system::error_code());
|
||||
}
|
||||
|
||||
void GruntRealmList::Close()
|
||||
{
|
||||
_updateTimer->cancel();
|
||||
}
|
||||
|
||||
void GruntRealmList::UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, std::string const& name,
|
||||
boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask,
|
||||
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population)
|
||||
{
|
||||
// Create new if not exist or update existed
|
||||
Realm& realm = _realms[id];
|
||||
|
||||
// grunt server doesn't use these values, but keep them initialized
|
||||
realm.Updated = false;
|
||||
realm.Keep = true;
|
||||
|
||||
realm.Id = id;
|
||||
realm.Build = build;
|
||||
realm.Name = name;
|
||||
realm.Type = icon;
|
||||
realm.Flags = flag;
|
||||
realm.Timezone = timezone;
|
||||
realm.AllowedSecurityLevel = allowedSecurityLevel;
|
||||
realm.PopulationLevel = population;
|
||||
if (!realm.ExternalAddress || *realm.ExternalAddress != address)
|
||||
realm.ExternalAddress = Trinity::make_unique<boost::asio::ip::address>(std::move(address));
|
||||
if (!realm.LocalAddress || *realm.LocalAddress != localAddr)
|
||||
realm.LocalAddress = Trinity::make_unique<boost::asio::ip::address>(std::move(localAddr));
|
||||
if (!realm.LocalSubnetMask || *realm.LocalSubnetMask != localSubmask)
|
||||
realm.LocalSubnetMask = Trinity::make_unique<boost::asio::ip::address>(std::move(localSubmask));
|
||||
realm.Port = port;
|
||||
}
|
||||
|
||||
void GruntRealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
{
|
||||
if (error)
|
||||
return;
|
||||
|
||||
TC_LOG_DEBUG("server.authserver", "Updating Realm List...");
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST);
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
|
||||
std::map<Battlenet::RealmHandle, std::string> existingRealms;
|
||||
for (auto const& p : _realms)
|
||||
existingRealms[p.first] = p.second.Name;
|
||||
|
||||
_realms.clear();
|
||||
|
||||
// Circle through results and add them to the realm map
|
||||
if (result)
|
||||
{
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint32 realmId = fields[0].GetUInt32();
|
||||
std::string name = fields[1].GetString();
|
||||
std::string externalAddressString = fields[2].GetString();
|
||||
std::string localAddressString = fields[3].GetString();
|
||||
std::string localSubmaskString = fields[4].GetString();
|
||||
|
||||
Optional<boost::asio::ip::tcp::endpoint> externalAddress = Trinity::Net::Resolve(*_resolver, boost::asio::ip::tcp::v4(), externalAddressString, "");
|
||||
if (!externalAddress)
|
||||
{
|
||||
TC_LOG_ERROR("realmlist", "Could not resolve address %s", externalAddressString.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
Optional<boost::asio::ip::tcp::endpoint> localAddress = Trinity::Net::Resolve(*_resolver, boost::asio::ip::tcp::v4(), localAddressString, "");
|
||||
if (!localAddress)
|
||||
{
|
||||
TC_LOG_ERROR("realmlist", "Could not resolve address %s", localAddressString.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
Optional<boost::asio::ip::tcp::endpoint> localSubmask = Trinity::Net::Resolve(*_resolver, boost::asio::ip::tcp::v4(), localSubmaskString, "");
|
||||
if (!localSubmask)
|
||||
{
|
||||
TC_LOG_ERROR("realmlist", "Could not resolve address %s", localSubmaskString.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16 port = fields[5].GetUInt16();
|
||||
uint8 icon = fields[6].GetUInt8();
|
||||
if (icon == REALM_TYPE_FFA_PVP)
|
||||
icon = REALM_TYPE_PVP;
|
||||
if (icon >= MAX_CLIENT_REALM_TYPE)
|
||||
icon = REALM_TYPE_NORMAL;
|
||||
RealmFlags flag = RealmFlags(fields[7].GetUInt8());
|
||||
uint8 timezone = fields[8].GetUInt8();
|
||||
uint8 allowedSecurityLevel = fields[9].GetUInt8();
|
||||
float pop = fields[10].GetFloat();
|
||||
uint32 build = fields[11].GetUInt32();
|
||||
uint8 region = fields[12].GetUInt8();
|
||||
uint8 battlegroup = fields[13].GetUInt8();
|
||||
|
||||
Battlenet::RealmHandle id{ region, battlegroup, realmId };
|
||||
|
||||
UpdateRealm(id, build, name, externalAddress->address(), localAddress->address(), localSubmask->address(), port, icon, flag,
|
||||
timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
|
||||
|
||||
if (!existingRealms.count(id))
|
||||
TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port);
|
||||
else
|
||||
TC_LOG_DEBUG("server.authserver", "Updating realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port);
|
||||
|
||||
existingRealms.erase(id);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
TC_LOG_ERROR("server.authserver", "GruntRealmList::UpdateRealms has thrown an exception: %s", ex.what());
|
||||
ABORT();
|
||||
}
|
||||
}
|
||||
while (result->NextRow());
|
||||
}
|
||||
|
||||
for (auto itr = existingRealms.begin(); itr != existingRealms.end(); ++itr)
|
||||
TC_LOG_INFO("server.authserver", "Removed realm \"%s\".", itr->second.c_str());
|
||||
|
||||
if (_updateInterval)
|
||||
{
|
||||
_updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval));
|
||||
_updateTimer->async_wait(std::bind(&GruntRealmList::UpdateRealms, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
|
||||
Realm const* GruntRealmList::GetRealm(Battlenet::RealmHandle const& id) const
|
||||
{
|
||||
auto itr = _realms.find(id);
|
||||
if (itr != _realms.end())
|
||||
return &itr->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef GruntRealmList_h__
|
||||
#define GruntRealmList_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include "Realm.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace system
|
||||
{
|
||||
class error_code;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
namespace Asio
|
||||
{
|
||||
class IoContext;
|
||||
class DeadlineTimer;
|
||||
}
|
||||
}
|
||||
|
||||
/// Storage object for the list of realms on the server
|
||||
class GruntRealmList
|
||||
{
|
||||
public:
|
||||
typedef std::map<Battlenet::RealmHandle, Realm> RealmMap;
|
||||
|
||||
static GruntRealmList* Instance();
|
||||
|
||||
~GruntRealmList();
|
||||
|
||||
void Initialize(Trinity::Asio::IoContext& ioContext, uint32 updateInterval);
|
||||
void Close();
|
||||
|
||||
RealmMap const& GetRealms() const { return _realms; }
|
||||
Realm const* GetRealm(Battlenet::RealmHandle const& id) const;
|
||||
|
||||
private:
|
||||
GruntRealmList();
|
||||
|
||||
void UpdateRealms(boost::system::error_code const& error);
|
||||
void UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, std::string const& name,
|
||||
boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask,
|
||||
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
|
||||
|
||||
RealmMap _realms;
|
||||
uint32 _updateInterval;
|
||||
std::unique_ptr<Trinity::Asio::DeadlineTimer> _updateTimer;
|
||||
std::unique_ptr<boost::asio::ip::tcp_resolver> _resolver;
|
||||
};
|
||||
|
||||
#define sGruntRealmList GruntRealmList::Instance()
|
||||
|
||||
#endif // GruntRealmList_h__
|
||||
@@ -1,924 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* 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 "AuthSession.h"
|
||||
#include "AuthCodes.h"
|
||||
#include "ByteBuffer.h"
|
||||
#include "Config.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Errors.h"
|
||||
#include "IPLocation.h"
|
||||
#include "GruntRealmList.h"
|
||||
#include "Log.h"
|
||||
#include "Realm.h"
|
||||
#include "SHA1.h"
|
||||
#include "TOTP.h"
|
||||
#include "Util.h"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
enum eAuthCmd
|
||||
{
|
||||
AUTH_LOGON_CHALLENGE = 0x00,
|
||||
AUTH_LOGON_PROOF = 0x01,
|
||||
AUTH_RECONNECT_CHALLENGE = 0x02,
|
||||
AUTH_RECONNECT_PROOF = 0x03,
|
||||
REALM_LIST = 0x10,
|
||||
XFER_INITIATE = 0x30,
|
||||
XFER_DATA = 0x31,
|
||||
XFER_ACCEPT = 0x32,
|
||||
XFER_RESUME = 0x33,
|
||||
XFER_CANCEL = 0x34
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct AUTH_LOGON_CHALLENGE_C
|
||||
{
|
||||
uint8 cmd;
|
||||
uint8 error;
|
||||
uint16 size;
|
||||
uint8 gamename[4];
|
||||
uint8 version1;
|
||||
uint8 version2;
|
||||
uint8 version3;
|
||||
uint16 build;
|
||||
uint8 platform[4];
|
||||
uint8 os[4];
|
||||
uint8 country[4];
|
||||
uint32 timezone_bias;
|
||||
uint32 ip;
|
||||
uint8 I_len;
|
||||
uint8 I[1];
|
||||
} sAuthLogonChallenge_C;
|
||||
|
||||
typedef struct AUTH_LOGON_PROOF_C
|
||||
{
|
||||
uint8 cmd;
|
||||
uint8 A[32];
|
||||
uint8 M1[20];
|
||||
uint8 crc_hash[20];
|
||||
uint8 number_of_keys;
|
||||
uint8 securityFlags;
|
||||
} sAuthLogonProof_C;
|
||||
|
||||
typedef struct AUTH_LOGON_PROOF_S
|
||||
{
|
||||
uint8 cmd;
|
||||
uint8 error;
|
||||
uint8 M2[20];
|
||||
uint32 AccountFlags;
|
||||
uint32 SurveyId;
|
||||
uint16 unk3;
|
||||
} sAuthLogonProof_S;
|
||||
|
||||
typedef struct AUTH_LOGON_PROOF_S_OLD
|
||||
{
|
||||
uint8 cmd;
|
||||
uint8 error;
|
||||
uint8 M2[20];
|
||||
uint32 unk2;
|
||||
} sAuthLogonProof_S_Old;
|
||||
|
||||
typedef struct AUTH_RECONNECT_PROOF_C
|
||||
{
|
||||
uint8 cmd;
|
||||
uint8 R1[16];
|
||||
uint8 R2[20];
|
||||
uint8 R3[20];
|
||||
uint8 number_of_keys;
|
||||
} sAuthReconnectProof_C;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
enum class BufferSizes : uint32
|
||||
{
|
||||
SRP_6_V = 0x20,
|
||||
SRP_6_S = 0x20,
|
||||
};
|
||||
|
||||
#define MAX_ACCEPTED_CHALLENGE_SIZE (sizeof(AUTH_LOGON_CHALLENGE_C) + 16)
|
||||
|
||||
#define AUTH_LOGON_CHALLENGE_INITIAL_SIZE 4
|
||||
#define REALM_LIST_PACKET_SIZE 5
|
||||
|
||||
std::unordered_map<uint8, AuthHandler> AuthSession::InitHandlers()
|
||||
{
|
||||
std::unordered_map<uint8, AuthHandler> handlers;
|
||||
|
||||
handlers[AUTH_LOGON_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleLogonChallenge };
|
||||
handlers[AUTH_LOGON_PROOF] = { STATUS_LOGON_PROOF, sizeof(AUTH_LOGON_PROOF_C), &AuthSession::HandleLogonProof };
|
||||
handlers[AUTH_RECONNECT_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleReconnectChallenge };
|
||||
handlers[AUTH_RECONNECT_PROOF] = { STATUS_RECONNECT_PROOF, sizeof(AUTH_RECONNECT_PROOF_C), &AuthSession::HandleReconnectProof };
|
||||
handlers[REALM_LIST] = { STATUS_AUTHED, REALM_LIST_PACKET_SIZE, &AuthSession::HandleRealmList };
|
||||
|
||||
return handlers;
|
||||
}
|
||||
|
||||
std::unordered_map<uint8, AuthHandler> const Handlers = AuthSession::InitHandlers();
|
||||
|
||||
void AccountInfo::LoadResult(Field* fields)
|
||||
{
|
||||
// 0 1 2 3 4 5 6
|
||||
//SELECT a.id, a.username, a.locked, a.lock_country, a.last_ip, a.failed_logins, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate,
|
||||
// 7 8 9 10 11 12
|
||||
// ab.unbandate = ab.bandate, aa.gmlevel, a.token_key, a.sha_pass_hash, a.v, a.s
|
||||
//FROM account a LEFT JOIN account_access aa ON a.id = aa.id LEFT JOIN account_banned ab ON ab.id = a.id AND ab.active = 1 WHERE a.username = ?
|
||||
|
||||
Id = fields[0].GetUInt32();
|
||||
Login = fields[1].GetString();
|
||||
IsLockedToIP = fields[2].GetBool();
|
||||
LockCountry = fields[3].GetString();
|
||||
LastIP = fields[4].GetString();
|
||||
FailedLogins = fields[5].GetUInt32();
|
||||
IsBanned = fields[6].GetUInt64() != 0;
|
||||
IsPermanenetlyBanned = fields[7].GetUInt64() != 0;
|
||||
SecurityLevel = AccountTypes(fields[8].GetUInt8());
|
||||
|
||||
// Use our own uppercasing of the account name instead of using UPPER() in mysql query
|
||||
// This is how the account was created in the first place and changing it now would result in breaking
|
||||
// login for all accounts having accented characters in their name
|
||||
Utf8ToUpperOnlyLatin(Login);
|
||||
}
|
||||
|
||||
AuthSession::AuthSession(tcp::socket&& socket) : Socket(std::move(socket)),
|
||||
_status(STATUS_CHALLENGE), _build(0), _expversion(0)
|
||||
{
|
||||
N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
|
||||
g.SetDword(7);
|
||||
}
|
||||
|
||||
void AuthSession::Start()
|
||||
{
|
||||
std::string ip_address = GetRemoteIpAddress().to_string();
|
||||
TC_LOG_TRACE("session", "Accepted connection from %s", ip_address.c_str());
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO);
|
||||
stmt->setString(0, ip_address);
|
||||
|
||||
_queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::CheckIpCallback, this, std::placeholders::_1)));
|
||||
}
|
||||
|
||||
bool AuthSession::Update()
|
||||
{
|
||||
if (!AuthSocket::Update())
|
||||
return false;
|
||||
|
||||
_queryProcessor.ProcessReadyQueries();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AuthSession::CheckIpCallback(PreparedQueryResult result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
bool banned = false;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
if (fields[0].GetUInt64() != 0)
|
||||
banned = true;
|
||||
|
||||
} while (result->NextRow());
|
||||
|
||||
if (banned)
|
||||
{
|
||||
ByteBuffer pkt;
|
||||
pkt << uint8(AUTH_LOGON_CHALLENGE);
|
||||
pkt << uint8(0x00);
|
||||
pkt << uint8(WOW_FAIL_BANNED);
|
||||
SendPacket(pkt);
|
||||
TC_LOG_DEBUG("session", "[AuthSession::CheckIpCallback] Banned ip '%s:%d' tries to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AsyncRead();
|
||||
}
|
||||
|
||||
void AuthSession::ReadHandler()
|
||||
{
|
||||
MessageBuffer& packet = GetReadBuffer();
|
||||
while (packet.GetActiveSize())
|
||||
{
|
||||
uint8 cmd = packet.GetReadPointer()[0];
|
||||
auto itr = Handlers.find(cmd);
|
||||
if (itr == Handlers.end())
|
||||
{
|
||||
// well we dont handle this, lets just ignore it
|
||||
packet.Reset();
|
||||
break;
|
||||
}
|
||||
|
||||
if (_status != itr->second.status)
|
||||
{
|
||||
CloseSocket();
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 size = uint16(itr->second.packetSize);
|
||||
if (packet.GetActiveSize() < size)
|
||||
break;
|
||||
|
||||
if (cmd == AUTH_LOGON_CHALLENGE || cmd == AUTH_RECONNECT_CHALLENGE)
|
||||
{
|
||||
sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(packet.GetReadPointer());
|
||||
size += challenge->size;
|
||||
if (size > MAX_ACCEPTED_CHALLENGE_SIZE)
|
||||
{
|
||||
CloseSocket();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet.GetActiveSize() < size)
|
||||
break;
|
||||
|
||||
if (!(*this.*itr->second.handler)())
|
||||
{
|
||||
CloseSocket();
|
||||
return;
|
||||
}
|
||||
|
||||
packet.ReadCompleted(size);
|
||||
}
|
||||
|
||||
AsyncRead();
|
||||
}
|
||||
|
||||
void AuthSession::SendPacket(ByteBuffer& packet)
|
||||
{
|
||||
if (!IsOpen())
|
||||
return;
|
||||
|
||||
if (!packet.empty())
|
||||
{
|
||||
MessageBuffer buffer;
|
||||
buffer.Write(packet.contents(), packet.size());
|
||||
QueuePacket(std::move(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
bool AuthSession::HandleLogonChallenge()
|
||||
{
|
||||
_status = STATUS_CLOSED;
|
||||
|
||||
sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetReadBuffer().GetReadPointer());
|
||||
if (challenge->size - (sizeof(sAuthLogonChallenge_C) - AUTH_LOGON_CHALLENGE_INITIAL_SIZE - 1) != challenge->I_len)
|
||||
return false;
|
||||
|
||||
std::string login((char const*)challenge->I, challenge->I_len);
|
||||
TC_LOG_DEBUG("server.authserver", "[AuthChallenge] '%s'", login.c_str());
|
||||
|
||||
_build = challenge->build;
|
||||
_expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
|
||||
std::array<char, 5> os;
|
||||
os.fill('\0');
|
||||
memcpy(os.data(), challenge->os, sizeof(challenge->os));
|
||||
_os = os.data();
|
||||
|
||||
// Restore string order as its byte order is reversed
|
||||
std::reverse(_os.begin(), _os.end());
|
||||
|
||||
_localizationName.resize(4);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
_localizationName[i] = challenge->country[4 - i - 1];
|
||||
|
||||
// Get the account details from the account table
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGONCHALLENGE);
|
||||
stmt->setString(0, login);
|
||||
|
||||
_queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::LogonChallengeCallback, this, std::placeholders::_1)));
|
||||
return true;
|
||||
}
|
||||
|
||||
void AuthSession::LogonChallengeCallback(PreparedQueryResult result)
|
||||
{
|
||||
ByteBuffer pkt;
|
||||
pkt << uint8(AUTH_LOGON_CHALLENGE);
|
||||
pkt << uint8(0x00);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
pkt << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
|
||||
SendPacket(pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
_accountInfo.LoadResult(fields);
|
||||
|
||||
std::string ipAddress = GetRemoteIpAddress().to_string();
|
||||
uint16 port = GetRemotePort();
|
||||
|
||||
// If the IP is 'locked', check that the player comes indeed from the correct IP address
|
||||
if (_accountInfo.IsLockedToIP)
|
||||
{
|
||||
TC_LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountInfo.Login.c_str(), _accountInfo.LastIP.c_str(), ipAddress.c_str());
|
||||
if (_accountInfo.LastIP != ipAddress)
|
||||
{
|
||||
pkt << uint8(WOW_FAIL_LOCKED_ENFORCED);
|
||||
SendPacket(pkt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(ipAddress))
|
||||
_ipCountry = location->CountryCode;
|
||||
|
||||
TC_LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is not locked to ip", _accountInfo.Login.c_str());
|
||||
if (_accountInfo.LockCountry.empty() || _accountInfo.LockCountry == "00")
|
||||
TC_LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is not locked to country", _accountInfo.Login.c_str());
|
||||
else if (!_accountInfo.LockCountry.empty() && !_ipCountry.empty())
|
||||
{
|
||||
TC_LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _accountInfo.Login.c_str(), _accountInfo.LockCountry.c_str(), _ipCountry.c_str());
|
||||
if (_ipCountry != _accountInfo.LockCountry)
|
||||
{
|
||||
pkt << uint8(WOW_FAIL_UNLOCKABLE_LOCK);
|
||||
SendPacket(pkt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the account is banned, reject the logon attempt
|
||||
if (_accountInfo.IsBanned)
|
||||
{
|
||||
if (_accountInfo.IsPermanenetlyBanned)
|
||||
{
|
||||
pkt << uint8(WOW_FAIL_BANNED);
|
||||
SendPacket(pkt);
|
||||
TC_LOG_INFO("server.authserver.banned", "'%s:%d' [AuthChallenge] Banned account %s tried to login!", ipAddress.c_str(), port, _accountInfo.Login.c_str());
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt << uint8(WOW_FAIL_SUSPENDED);
|
||||
SendPacket(pkt);
|
||||
TC_LOG_INFO("server.authserver.banned", "'%s:%d' [AuthChallenge] Temporarily banned account %s tried to login!", ipAddress.c_str(), port, _accountInfo.Login.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the password from the account table, upper it, and make the SRP6 calculation
|
||||
std::string rI = fields[10].GetString();
|
||||
|
||||
// Don't calculate (v, s) if there are already some in the database
|
||||
std::string databaseV = fields[11].GetString();
|
||||
std::string databaseS = fields[12].GetString();
|
||||
|
||||
TC_LOG_DEBUG("network", "database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str());
|
||||
|
||||
// multiply with 2 since bytes are stored as hexstring
|
||||
if (databaseV.size() != size_t(BufferSizes::SRP_6_V) * 2 || databaseS.size() != size_t(BufferSizes::SRP_6_S) * 2)
|
||||
SetVSFields(rI);
|
||||
else
|
||||
{
|
||||
s.SetHexStr(databaseS.c_str());
|
||||
v.SetHexStr(databaseV.c_str());
|
||||
}
|
||||
|
||||
b.SetRand(19 * 8);
|
||||
BigNumber gmod = g.ModExp(b, N);
|
||||
B = ((v * 3) + gmod) % N;
|
||||
|
||||
ASSERT(gmod.GetNumBytes() <= 32);
|
||||
|
||||
BigNumber unk3;
|
||||
unk3.SetRand(16 * 8);
|
||||
|
||||
// Fill the response packet with the result
|
||||
if (fields[13].GetUInt32() && AuthHelper::IsBuildSupportingBattlenet(_build))
|
||||
pkt << uint8(WOW_FAIL_USE_BATTLENET);
|
||||
else if (AuthHelper::IsAcceptedClientBuild(_build))
|
||||
{
|
||||
pkt << uint8(WOW_SUCCESS);
|
||||
_status = STATUS_LOGON_PROOF;
|
||||
}
|
||||
else
|
||||
pkt << uint8(WOW_FAIL_VERSION_INVALID);
|
||||
|
||||
// B may be calculated < 32B so we force minimal length to 32B
|
||||
pkt.append(B.AsByteArray(32).get(), 32); // 32 bytes
|
||||
pkt << uint8(1);
|
||||
pkt.append(g.AsByteArray(1).get(), 1);
|
||||
pkt << uint8(32);
|
||||
pkt.append(N.AsByteArray(32).get(), 32);
|
||||
pkt.append(s.AsByteArray(int32(BufferSizes::SRP_6_S)).get(), size_t(BufferSizes::SRP_6_S)); // 32 bytes
|
||||
pkt.append(unk3.AsByteArray(16).get(), 16);
|
||||
uint8 securityFlags = 0;
|
||||
|
||||
// Check if token is used
|
||||
_tokenKey = fields[9].GetString();
|
||||
if (!_tokenKey.empty())
|
||||
securityFlags = 4;
|
||||
|
||||
pkt << uint8(securityFlags); // security flags (0x0...0x04)
|
||||
|
||||
if (securityFlags & 0x01) // PIN input
|
||||
{
|
||||
pkt << uint32(0);
|
||||
pkt << uint64(0) << uint64(0); // 16 bytes hash?
|
||||
}
|
||||
|
||||
if (securityFlags & 0x02) // Matrix input
|
||||
{
|
||||
pkt << uint8(0);
|
||||
pkt << uint8(0);
|
||||
pkt << uint8(0);
|
||||
pkt << uint8(0);
|
||||
pkt << uint64(0);
|
||||
}
|
||||
|
||||
if (securityFlags & 0x04) // Security token input
|
||||
pkt << uint8(1);
|
||||
|
||||
TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] account %s is using '%s' locale (%u)",
|
||||
ipAddress.c_str(), port, _accountInfo.Login.c_str(), _localizationName.c_str(), GetLocaleByName(_localizationName));
|
||||
|
||||
SendPacket(pkt);
|
||||
}
|
||||
|
||||
// Logon Proof command handler
|
||||
bool AuthSession::HandleLogonProof()
|
||||
{
|
||||
TC_LOG_DEBUG("server.authserver", "Entering _HandleLogonProof");
|
||||
_status = STATUS_CLOSED;
|
||||
|
||||
// Read the packet
|
||||
sAuthLogonProof_C *logonProof = reinterpret_cast<sAuthLogonProof_C*>(GetReadBuffer().GetReadPointer());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Continue the SRP6 calculation based on data received from the client
|
||||
BigNumber A;
|
||||
|
||||
A.SetBinary(logonProof->A, 32);
|
||||
|
||||
// SRP safeguard: abort if A == 0
|
||||
if ((A % N).IsZero())
|
||||
return false;
|
||||
|
||||
SHA1Hash sha;
|
||||
sha.UpdateBigNumbers(&A, &B, nullptr);
|
||||
sha.Finalize();
|
||||
BigNumber u;
|
||||
u.SetBinary(sha.GetDigest(), 20);
|
||||
BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N);
|
||||
|
||||
uint8 t[32];
|
||||
uint8 t1[16];
|
||||
uint8 vK[40];
|
||||
memcpy(t, S.AsByteArray(32).get(), 32);
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
t1[i] = t[i * 2];
|
||||
|
||||
sha.Initialize();
|
||||
sha.UpdateData(t1, 16);
|
||||
sha.Finalize();
|
||||
|
||||
for (int i = 0; i < 20; ++i)
|
||||
vK[i * 2] = sha.GetDigest()[i];
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
t1[i] = t[i * 2 + 1];
|
||||
|
||||
sha.Initialize();
|
||||
sha.UpdateData(t1, 16);
|
||||
sha.Finalize();
|
||||
|
||||
for (int i = 0; i < 20; ++i)
|
||||
vK[i * 2 + 1] = sha.GetDigest()[i];
|
||||
|
||||
K.SetBinary(vK, 40);
|
||||
|
||||
uint8 hash[20];
|
||||
|
||||
sha.Initialize();
|
||||
sha.UpdateBigNumbers(&N, nullptr);
|
||||
sha.Finalize();
|
||||
memcpy(hash, sha.GetDigest(), 20);
|
||||
sha.Initialize();
|
||||
sha.UpdateBigNumbers(&g, nullptr);
|
||||
sha.Finalize();
|
||||
|
||||
for (int i = 0; i < 20; ++i)
|
||||
hash[i] ^= sha.GetDigest()[i];
|
||||
|
||||
BigNumber t3;
|
||||
t3.SetBinary(hash, 20);
|
||||
|
||||
sha.Initialize();
|
||||
sha.UpdateData(_accountInfo.Login);
|
||||
sha.Finalize();
|
||||
uint8 t4[SHA_DIGEST_LENGTH];
|
||||
memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH);
|
||||
|
||||
sha.Initialize();
|
||||
sha.UpdateBigNumbers(&t3, nullptr);
|
||||
sha.UpdateData(t4, SHA_DIGEST_LENGTH);
|
||||
sha.UpdateBigNumbers(&s, &A, &B, &K, nullptr);
|
||||
sha.Finalize();
|
||||
BigNumber M;
|
||||
M.SetBinary(sha.GetDigest(), sha.GetLength());
|
||||
|
||||
// Check if SRP6 results match (password is correct), else send an error
|
||||
if (!memcmp(M.AsByteArray(sha.GetLength()).get(), logonProof->M1, 20))
|
||||
{
|
||||
// Check auth token
|
||||
if ((logonProof->securityFlags & 0x04) || !_tokenKey.empty())
|
||||
{
|
||||
uint8 size = *(GetReadBuffer().GetReadPointer() + sizeof(sAuthLogonProof_C));
|
||||
std::string token(reinterpret_cast<char*>(GetReadBuffer().GetReadPointer() + sizeof(sAuthLogonProof_C) + sizeof(size)), size);
|
||||
GetReadBuffer().ReadCompleted(sizeof(size) + size);
|
||||
uint32 validToken = TOTP::GenerateToken(_tokenKey.c_str());
|
||||
_tokenKey.clear();
|
||||
uint32 incomingToken = atoi(token.c_str());
|
||||
if (validToken != incomingToken)
|
||||
{
|
||||
ByteBuffer packet;
|
||||
packet << uint8(AUTH_LOGON_PROOF);
|
||||
packet << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
|
||||
packet << uint8(3);
|
||||
packet << uint8(0);
|
||||
SendPacket(packet);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo.Login.c_str());
|
||||
|
||||
// Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
|
||||
// No SQL injection (escaped user name) and IP address as received by socket
|
||||
|
||||
PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
|
||||
stmt->setString(0, K.AsHexStr());
|
||||
stmt->setString(1, GetRemoteIpAddress().to_string());
|
||||
stmt->setUInt32(2, GetLocaleByName(_localizationName));
|
||||
stmt->setString(3, _os);
|
||||
stmt->setString(4, _accountInfo.Login);
|
||||
LoginDatabase.DirectExecute(stmt);
|
||||
|
||||
// Finish SRP6 and send the final result to the client
|
||||
sha.Initialize();
|
||||
sha.UpdateBigNumbers(&A, &M, &K, nullptr);
|
||||
sha.Finalize();
|
||||
|
||||
ByteBuffer packet;
|
||||
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
|
||||
{
|
||||
sAuthLogonProof_S proof;
|
||||
memcpy(proof.M2, sha.GetDigest(), 20);
|
||||
proof.cmd = AUTH_LOGON_PROOF;
|
||||
proof.error = 0;
|
||||
proof.AccountFlags = GAMEACCOUNT_FLAG_PROPASS_LOCK;
|
||||
proof.SurveyId = 0;
|
||||
proof.unk3 = 0;
|
||||
|
||||
packet.resize(sizeof(proof));
|
||||
std::memcpy(packet.contents(), &proof, sizeof(proof));
|
||||
}
|
||||
else
|
||||
{
|
||||
sAuthLogonProof_S_Old proof;
|
||||
memcpy(proof.M2, sha.GetDigest(), 20);
|
||||
proof.cmd = AUTH_LOGON_PROOF;
|
||||
proof.error = 0;
|
||||
proof.unk2 = 0x00;
|
||||
|
||||
packet.resize(sizeof(proof));
|
||||
std::memcpy(packet.contents(), &proof, sizeof(proof));
|
||||
}
|
||||
|
||||
SendPacket(packet);
|
||||
_status = STATUS_AUTHED;
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteBuffer packet;
|
||||
packet << uint8(AUTH_LOGON_PROOF);
|
||||
packet << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
|
||||
packet << uint8(3);
|
||||
packet << uint8(0);
|
||||
SendPacket(packet);
|
||||
|
||||
TC_LOG_INFO("server.authserver.hack", "'%s:%d' [AuthChallenge] account %s tried to login with invalid password!",
|
||||
GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo.Login.c_str());
|
||||
|
||||
uint32 MaxWrongPassCount = sConfigMgr->GetIntDefault("WrongPass.MaxCount", 0);
|
||||
|
||||
// We can not include the failed account login hook. However, this is a workaround to still log this.
|
||||
if (sConfigMgr->GetBoolDefault("WrongPass.Logging", false))
|
||||
{
|
||||
PreparedStatement* logstmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_FALP_IP_LOGGING);
|
||||
logstmt->setUInt32(0, _accountInfo.Id);
|
||||
logstmt->setString(1, GetRemoteIpAddress().to_string());
|
||||
logstmt->setString(2, "Logged on failed AccountLogin due wrong password");
|
||||
|
||||
LoginDatabase.Execute(logstmt);
|
||||
}
|
||||
|
||||
if (MaxWrongPassCount > 0)
|
||||
{
|
||||
//Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_FAILEDLOGINS);
|
||||
stmt->setString(0, _accountInfo.Login);
|
||||
LoginDatabase.Execute(stmt);
|
||||
|
||||
if (++_accountInfo.FailedLogins >= MaxWrongPassCount)
|
||||
{
|
||||
uint32 WrongPassBanTime = sConfigMgr->GetIntDefault("WrongPass.BanTime", 600);
|
||||
bool WrongPassBanType = sConfigMgr->GetBoolDefault("WrongPass.BanType", false);
|
||||
|
||||
if (WrongPassBanType)
|
||||
{
|
||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED);
|
||||
stmt->setUInt32(0, _accountInfo.Id);
|
||||
stmt->setUInt32(1, WrongPassBanTime);
|
||||
LoginDatabase.Execute(stmt);
|
||||
|
||||
TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
|
||||
GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo.Login.c_str(), WrongPassBanTime, _accountInfo.FailedLogins);
|
||||
}
|
||||
else
|
||||
{
|
||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_AUTO_BANNED);
|
||||
stmt->setString(0, GetRemoteIpAddress().to_string());
|
||||
stmt->setUInt32(1, WrongPassBanTime);
|
||||
LoginDatabase.Execute(stmt);
|
||||
|
||||
TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] IP got banned for '%u' seconds because account %s failed to authenticate '%u' times",
|
||||
GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), WrongPassBanTime, _accountInfo.Login.c_str(), _accountInfo.FailedLogins);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AuthSession::HandleReconnectChallenge()
|
||||
{
|
||||
_status = STATUS_CLOSED;
|
||||
|
||||
sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetReadBuffer().GetReadPointer());
|
||||
if (challenge->size - (sizeof(sAuthLogonChallenge_C) - AUTH_LOGON_CHALLENGE_INITIAL_SIZE - 1) != challenge->I_len)
|
||||
return false;
|
||||
|
||||
std::string login((char const*)challenge->I, challenge->I_len);
|
||||
TC_LOG_DEBUG("server.authserver", "[ReconnectChallenge] '%s'", login.c_str());
|
||||
|
||||
_build = challenge->build;
|
||||
_expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
|
||||
std::array<char, 5> os;
|
||||
os.fill('\0');
|
||||
memcpy(os.data(), challenge->os, sizeof(challenge->os));
|
||||
_os = os.data();
|
||||
|
||||
// Restore string order as its byte order is reversed
|
||||
std::reverse(_os.begin(), _os.end());
|
||||
|
||||
_localizationName.resize(4);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
_localizationName[i] = challenge->country[4 - i - 1];
|
||||
|
||||
// Get the account details from the account table
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RECONNECTCHALLENGE);
|
||||
stmt->setString(0, login);
|
||||
|
||||
_queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::ReconnectChallengeCallback, this, std::placeholders::_1)));
|
||||
return true;
|
||||
}
|
||||
|
||||
void AuthSession::ReconnectChallengeCallback(PreparedQueryResult result)
|
||||
{
|
||||
ByteBuffer pkt;
|
||||
pkt << uint8(AUTH_RECONNECT_CHALLENGE);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
pkt << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
|
||||
SendPacket(pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
_accountInfo.LoadResult(fields);
|
||||
K.SetHexStr(fields[9].GetCString());
|
||||
_reconnectProof.SetRand(16 * 8);
|
||||
_status = STATUS_RECONNECT_PROOF;
|
||||
|
||||
pkt << uint8(WOW_SUCCESS);
|
||||
pkt.append(_reconnectProof.AsByteArray(16).get(), 16); // 16 bytes random
|
||||
pkt << uint64(0x00) << uint64(0x00); // 16 bytes zeros
|
||||
|
||||
SendPacket(pkt);
|
||||
}
|
||||
|
||||
bool AuthSession::HandleReconnectProof()
|
||||
{
|
||||
TC_LOG_DEBUG("server.authserver", "Entering _HandleReconnectProof");
|
||||
_status = STATUS_CLOSED;
|
||||
|
||||
sAuthReconnectProof_C *reconnectProof = reinterpret_cast<sAuthReconnectProof_C*>(GetReadBuffer().GetReadPointer());
|
||||
|
||||
if (_accountInfo.Login.empty() || !_reconnectProof.GetNumBytes() || !K.GetNumBytes())
|
||||
return false;
|
||||
|
||||
BigNumber t1;
|
||||
t1.SetBinary(reconnectProof->R1, 16);
|
||||
|
||||
SHA1Hash sha;
|
||||
sha.Initialize();
|
||||
sha.UpdateData(_accountInfo.Login);
|
||||
sha.UpdateBigNumbers(&t1, &_reconnectProof, &K, nullptr);
|
||||
sha.Finalize();
|
||||
|
||||
if (!memcmp(sha.GetDigest(), reconnectProof->R2, SHA_DIGEST_LENGTH))
|
||||
{
|
||||
// Sending response
|
||||
ByteBuffer pkt;
|
||||
pkt << uint8(AUTH_RECONNECT_PROOF);
|
||||
pkt << uint8(0x00);
|
||||
pkt << uint16(0x00); // 2 bytes zeros
|
||||
SendPacket(pkt);
|
||||
_status = STATUS_AUTHED;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
TC_LOG_ERROR("server.authserver.hack", "'%s:%d' [ERROR] user %s tried to login, but session is invalid.", GetRemoteIpAddress().to_string().c_str(),
|
||||
GetRemotePort(), _accountInfo.Login.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool AuthSession::HandleRealmList()
|
||||
{
|
||||
TC_LOG_DEBUG("server.authserver", "Entering _HandleRealmList");
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALM_CHARACTER_COUNTS);
|
||||
stmt->setUInt32(0, _accountInfo.Id);
|
||||
|
||||
_queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::RealmListCallback, this, std::placeholders::_1)));
|
||||
_status = STATUS_WAITING_FOR_REALM_LIST;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AuthSession::RealmListCallback(PreparedQueryResult result)
|
||||
{
|
||||
std::map<uint32, uint8> characterCounts;
|
||||
if (result)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
characterCounts[fields[0].GetUInt32()] = fields[1].GetUInt8();
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
// Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm)
|
||||
ByteBuffer pkt;
|
||||
|
||||
size_t RealmListSize = 0;
|
||||
for (auto const& i : sGruntRealmList->GetRealms())
|
||||
{
|
||||
Realm const& realm = i.second;
|
||||
// don't work with realms which not compatible with the client
|
||||
bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.Build == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.Build));
|
||||
|
||||
// No SQL injection. id of realm is controlled by the database.
|
||||
uint32 flag = realm.Flags;
|
||||
RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.Build);
|
||||
if (!okBuild)
|
||||
{
|
||||
if (!buildInfo)
|
||||
continue;
|
||||
|
||||
flag |= REALM_FLAG_OFFLINE | REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for
|
||||
}
|
||||
|
||||
if (!buildInfo)
|
||||
flag &= ~REALM_FLAG_SPECIFYBUILD;
|
||||
|
||||
std::string name = realm.Name;
|
||||
if (_expversion & PRE_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << name << " (" << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << ')';
|
||||
name = ss.str();
|
||||
}
|
||||
|
||||
uint8 lock = (realm.AllowedSecurityLevel > _accountInfo.SecurityLevel) ? 1 : 0;
|
||||
|
||||
pkt << uint8(realm.Type); // realm type
|
||||
if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients
|
||||
pkt << uint8(lock); // if 1, then realm locked
|
||||
pkt << uint8(flag); // RealmFlags
|
||||
pkt << name;
|
||||
pkt << boost::lexical_cast<std::string>(realm.GetAddressForClient(GetRemoteIpAddress()));
|
||||
pkt << float(realm.PopulationLevel);
|
||||
pkt << uint8(characterCounts[realm.Id.Realm]);
|
||||
pkt << uint8(realm.Timezone); // realm category
|
||||
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
|
||||
pkt << uint8(realm.Id.Realm);
|
||||
else
|
||||
pkt << uint8(0x0); // 1.12.1 and 1.12.2 clients
|
||||
|
||||
if (_expversion & POST_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD)
|
||||
{
|
||||
pkt << uint8(buildInfo->MajorVersion);
|
||||
pkt << uint8(buildInfo->MinorVersion);
|
||||
pkt << uint8(buildInfo->BugfixVersion);
|
||||
pkt << uint16(buildInfo->Build);
|
||||
}
|
||||
|
||||
++RealmListSize;
|
||||
}
|
||||
|
||||
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
|
||||
{
|
||||
pkt << uint8(0x10);
|
||||
pkt << uint8(0x00);
|
||||
}
|
||||
else // 1.12.1 and 1.12.2 clients
|
||||
{
|
||||
pkt << uint8(0x00);
|
||||
pkt << uint8(0x02);
|
||||
}
|
||||
|
||||
// make a ByteBuffer which stores the RealmList's size
|
||||
ByteBuffer RealmListSizeBuffer;
|
||||
RealmListSizeBuffer << uint32(0);
|
||||
if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients
|
||||
RealmListSizeBuffer << uint16(RealmListSize);
|
||||
else
|
||||
RealmListSizeBuffer << uint32(RealmListSize);
|
||||
|
||||
ByteBuffer hdr;
|
||||
hdr << uint8(REALM_LIST);
|
||||
hdr << uint16(pkt.size() + RealmListSizeBuffer.size());
|
||||
hdr.append(RealmListSizeBuffer); // append RealmList's size buffer
|
||||
hdr.append(pkt); // append realms in the realmlist
|
||||
SendPacket(hdr);
|
||||
|
||||
_status = STATUS_AUTHED;
|
||||
}
|
||||
|
||||
// Make the SRP6 calculation from hash in dB
|
||||
void AuthSession::SetVSFields(const std::string& rI)
|
||||
{
|
||||
s.SetRand(int32(BufferSizes::SRP_6_S) * 8);
|
||||
|
||||
BigNumber I;
|
||||
I.SetHexStr(rI.c_str());
|
||||
|
||||
// In case of leading zeros in the rI hash, restore them
|
||||
uint8 mDigest[SHA_DIGEST_LENGTH];
|
||||
memcpy(mDigest, I.AsByteArray(SHA_DIGEST_LENGTH).get(), SHA_DIGEST_LENGTH);
|
||||
|
||||
std::reverse(mDigest, mDigest + SHA_DIGEST_LENGTH);
|
||||
|
||||
SHA1Hash sha;
|
||||
sha.UpdateData(s.AsByteArray(uint32(BufferSizes::SRP_6_S)).get(), (uint32(BufferSizes::SRP_6_S)));
|
||||
sha.UpdateData(mDigest, SHA_DIGEST_LENGTH);
|
||||
sha.Finalize();
|
||||
BigNumber x;
|
||||
x.SetBinary(sha.GetDigest(), sha.GetLength());
|
||||
v = g.ModExp(x, N);
|
||||
|
||||
// No SQL injection (username escaped)
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_VS);
|
||||
stmt->setString(0, v.AsHexStr());
|
||||
stmt->setString(1, s.AsHexStr());
|
||||
stmt->setString(2, _accountInfo.Login);
|
||||
LoginDatabase.Execute(stmt);
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __AUTHSESSION_H__
|
||||
#define __AUTHSESSION_H__
|
||||
|
||||
#include "Common.h"
|
||||
#include "BigNumber.h"
|
||||
#include "DatabaseEnvFwd.h"
|
||||
#include "QueryCallbackProcessor.h"
|
||||
#include "Socket.h"
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <memory>
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
class ByteBuffer;
|
||||
class Field;
|
||||
struct AuthHandler;
|
||||
|
||||
enum AuthStatus
|
||||
{
|
||||
STATUS_CHALLENGE = 0,
|
||||
STATUS_LOGON_PROOF,
|
||||
STATUS_RECONNECT_PROOF,
|
||||
STATUS_AUTHED,
|
||||
STATUS_WAITING_FOR_REALM_LIST,
|
||||
STATUS_CLOSED
|
||||
};
|
||||
|
||||
struct AccountInfo
|
||||
{
|
||||
void LoadResult(Field* fields);
|
||||
|
||||
uint32 Id = 0;
|
||||
std::string Login;
|
||||
bool IsLockedToIP = false;
|
||||
std::string LockCountry;
|
||||
std::string LastIP;
|
||||
uint32 FailedLogins = 0;
|
||||
bool IsBanned = false;
|
||||
bool IsPermanenetlyBanned = false;
|
||||
AccountTypes SecurityLevel = SEC_PLAYER;
|
||||
std::string TokenKey;
|
||||
};
|
||||
|
||||
class AuthSession : public Socket<AuthSession>
|
||||
{
|
||||
typedef Socket<AuthSession> AuthSocket;
|
||||
|
||||
public:
|
||||
static std::unordered_map<uint8, AuthHandler> InitHandlers();
|
||||
|
||||
AuthSession(tcp::socket&& socket);
|
||||
|
||||
void Start() override;
|
||||
bool Update() override;
|
||||
|
||||
void SendPacket(ByteBuffer& packet);
|
||||
|
||||
protected:
|
||||
void ReadHandler() override;
|
||||
|
||||
private:
|
||||
bool HandleLogonChallenge();
|
||||
bool HandleLogonProof();
|
||||
bool HandleReconnectChallenge();
|
||||
bool HandleReconnectProof();
|
||||
bool HandleRealmList();
|
||||
|
||||
void CheckIpCallback(PreparedQueryResult result);
|
||||
void LogonChallengeCallback(PreparedQueryResult result);
|
||||
void ReconnectChallengeCallback(PreparedQueryResult result);
|
||||
void RealmListCallback(PreparedQueryResult result);
|
||||
|
||||
void SetVSFields(const std::string& rI);
|
||||
|
||||
BigNumber N, s, g, v;
|
||||
BigNumber b, B;
|
||||
BigNumber K;
|
||||
BigNumber _reconnectProof;
|
||||
|
||||
AuthStatus _status;
|
||||
AccountInfo _accountInfo;
|
||||
std::string _tokenKey;
|
||||
std::string _localizationName;
|
||||
std::string _os;
|
||||
std::string _ipCountry;
|
||||
uint16 _build;
|
||||
uint8 _expversion;
|
||||
|
||||
QueryCallbackProcessor _queryProcessor;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct AuthHandler
|
||||
{
|
||||
AuthStatus status;
|
||||
size_t packetSize;
|
||||
bool (AuthSession::*handler)();
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://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/>.
|
||||
*/
|
||||
|
||||
#ifndef AuthSocketMgr_h__
|
||||
#define AuthSocketMgr_h__
|
||||
|
||||
#include "SocketMgr.h"
|
||||
#include "AuthSession.h"
|
||||
|
||||
class AuthSocketMgr : public SocketMgr<AuthSession>
|
||||
{
|
||||
typedef SocketMgr<AuthSession> BaseSocketMgr;
|
||||
|
||||
public:
|
||||
static AuthSocketMgr& Instance()
|
||||
{
|
||||
static AuthSocketMgr instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool StartNetwork(Trinity::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, int threadCount = 1) override
|
||||
{
|
||||
if (!BaseSocketMgr::StartNetwork(ioContext, bindIp, port, threadCount))
|
||||
return false;
|
||||
|
||||
_acceptor->AsyncAcceptWithCallback<&AuthSocketMgr::OnSocketAccept>();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
NetworkThread<AuthSession>* CreateThreads() const override
|
||||
{
|
||||
return new NetworkThread<AuthSession>[1];
|
||||
}
|
||||
|
||||
static void OnSocketAccept(tcp::socket&& sock, uint32 threadIndex)
|
||||
{
|
||||
Instance().OnSocketOpen(std::forward<tcp::socket>(sock), threadIndex);
|
||||
}
|
||||
};
|
||||
|
||||
#define sAuthSocketMgr AuthSocketMgr::Instance()
|
||||
|
||||
#endif // AuthSocketMgr_h__
|
||||
@@ -1,359 +0,0 @@
|
||||
###############################################
|
||||
# Trinity Core Auth Server configuration file #
|
||||
###############################################
|
||||
[authserver]
|
||||
|
||||
###################################################################################################
|
||||
# SECTION INDEX
|
||||
#
|
||||
# EXAMPLE CONFIG
|
||||
# AUTH SERVER SETTINGS
|
||||
# MYSQL SETTINGS
|
||||
# UPDATE SETTINGS
|
||||
# LOGGING SYSTEM 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.
|
||||
###################################################################################################
|
||||
|
||||
###################################################################################################
|
||||
# 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 = ""
|
||||
|
||||
#
|
||||
# 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
|
||||
|
||||
#
|
||||
# WrongPass.Logging
|
||||
# Description: Additionally log attempted wrong password logging
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
WrongPass.Logging = 0
|
||||
|
||||
#
|
||||
# BanExpiryCheckInterval
|
||||
# Description: Time (in seconds) between checks for expired bans
|
||||
# Default: 60
|
||||
|
||||
BanExpiryCheckInterval = 60
|
||||
|
||||
#
|
||||
# SourceDirectory
|
||||
# Description: The path to your TrinityCore source directory.
|
||||
# If the path is left empty, the built-in CMAKE_SOURCE_DIR is used.
|
||||
# Example: "../TrinityCore"
|
||||
# Default: ""
|
||||
|
||||
SourceDirectory = ""
|
||||
|
||||
#
|
||||
# MySQLExecutable
|
||||
# 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: ""
|
||||
|
||||
MySQLExecutable = ""
|
||||
|
||||
#
|
||||
# IPLocationFile
|
||||
# Description: The path to your IP2Location database CSV file.
|
||||
# Example: "C:/Trinity/IP2LOCATION-LITE-DB1.CSV"
|
||||
# "/home/trinity/IP2LOCATION-LITE-DB1.CSV"
|
||||
# Default: "" - (Disabled)
|
||||
|
||||
IPLocationFile = ""
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
###################################################################################################
|
||||
# MYSQL SETTINGS
|
||||
#
|
||||
# LoginDatabaseInfo
|
||||
# Description: Database connection settings for the realm server.
|
||||
# Example: "hostname;port;username;password;database"
|
||||
# ".;somenumber;username;password;database" - (Use named pipes on Windows
|
||||
# "enable-named-pipe" to [mysqld]
|
||||
# section my.ini)
|
||||
# ".;/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;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
|
||||
# MySQL server and their own thread on the MySQL server.
|
||||
# Default: 1
|
||||
|
||||
LoginDatabase.WorkerThreads = 1
|
||||
|
||||
#
|
||||
# LoginDatabase.SynchThreads
|
||||
# Description: The amount of MySQL connections spawned to handle.
|
||||
# Default: 1 - (LoginDatabase.WorkerThreads)
|
||||
|
||||
LoginDatabase.SynchThreads = 1
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
###################################################################################################
|
||||
# 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.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)
|
||||
# 2 - (Debug)
|
||||
# 3 - (Info)
|
||||
# 4 - (Warn)
|
||||
# 5 - (Error)
|
||||
# 6 - (Fatal)
|
||||
#
|
||||
# Flags:
|
||||
# 0 - None
|
||||
# 1 - Prefix Timestamp to the text
|
||||
# 2 - Prefix Log Level to the text
|
||||
# 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
|
||||
# 1 - RED
|
||||
# 2 - GREEN
|
||||
# 3 - BROWN
|
||||
# 4 - BLUE
|
||||
# 5 - MAGENTA
|
||||
# 6 - CYAN
|
||||
# 7 - GREY
|
||||
# 8 - YELLOW
|
||||
# 9 - LRED
|
||||
# 10 - LGREEN
|
||||
# 11 - LBLUE
|
||||
# 12 - LMAGENTA
|
||||
# 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
|
||||
|
||||
# Logger config values: Given a logger "name"
|
||||
# Logger.name
|
||||
# Description: Defines 'What to log'
|
||||
# Format: LogLevel,AppenderList
|
||||
#
|
||||
# LogLevel
|
||||
# 0 - (Disabled)
|
||||
# 1 - (Trace)
|
||||
# 2 - (Debug)
|
||||
# 3 - (Info)
|
||||
# 4 - (Warn)
|
||||
# 5 - (Error)
|
||||
# 6 - (Fatal)
|
||||
#
|
||||
# AppenderList: List of appenders linked to logger
|
||||
# (Using spaces as separator).
|
||||
#
|
||||
|
||||
Logger.root=3,Console Auth
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 133 KiB |
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* 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 "resource.h"
|
||||
#include "revision_data.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "windows.h" //"afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_APPICON ICON "authserver.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Neutre (Par défaut système) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUSD)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
PRODUCTVERSION VER_PRODUCTVERSION
|
||||
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
|
||||
#ifndef _DEBUG
|
||||
FILEFLAGS 0
|
||||
#else
|
||||
#define VER_PRERELEASE VS_FF_PRERELEASE
|
||||
#define VER_PRIVATEBUILD VS_FF_PRIVATEBUILD
|
||||
#define VER_DEBUG 0
|
||||
FILEFLAGS (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG)
|
||||
#endif
|
||||
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "080004b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", VER_COMPANYNAME_STR
|
||||
VALUE "FileDescription", "TrinityCore Authentication Server Daemon"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "InternalName", "authserver"
|
||||
VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
|
||||
VALUE "OriginalFilename", "authserver.exe"
|
||||
VALUE "ProductName", "TrinityCore Authentication Server"
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
END
|
||||
END
|
||||
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x800, 1200
|
||||
END
|
||||
END
|
||||
#endif
|
||||
@@ -1,15 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by TrinityCore.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
###############################################
|
||||
# Trinity Core Auth Server configuration file #
|
||||
###############################################
|
||||
[authserver]
|
||||
[bnetserver]
|
||||
|
||||
###################################################################################################
|
||||
# SECTION INDEX
|
||||
@@ -71,7 +71,7 @@ BindIP = "0.0.0.0"
|
||||
#
|
||||
# PidFile
|
||||
# Description: Auth server PID file.
|
||||
# Example: "./authserver.pid" - (Enabled)
|
||||
# Example: "./bnetserver.pid" - (Enabled)
|
||||
# Default: "" - (Disabled)
|
||||
|
||||
PidFile = ""
|
||||
|
||||
@@ -140,7 +140,7 @@ public:
|
||||
else
|
||||
{
|
||||
handler->PSendSysMessage("IP2Location] No information");
|
||||
TC_LOG_DEBUG("server.authserver", "IP2Location] No information");
|
||||
TC_LOG_DEBUG("server.bnetserver", "IP2Location] No information");
|
||||
}
|
||||
}
|
||||
else if (param == "off")
|
||||
|
||||
@@ -3910,7 +3910,7 @@ Logger.sql.updates=3,Console Server
|
||||
#Logger.rbac=3,Console Server
|
||||
#Logger.scripts=3,Console Server
|
||||
#Logger.scripts.ai=3,Console Server
|
||||
#Logger.server.authserver=3,Console Server
|
||||
#Logger.server.bnetserver=3,Console Server
|
||||
#Logger.spells=3,Console Server
|
||||
#Logger.spells.periodic=3,Console Server
|
||||
#Logger.sql.dev=3,Console Server
|
||||
|
||||
Reference in New Issue
Block a user