2021-12-05 17:54:36 +00:00
# include "AuthPackets.h"
# include "PacketUtils.h"
2023-09-21 01:06:28 +00:00
# include "BitStreamUtils.h"
2021-12-05 17:54:36 +00:00
# include "dNetCommon.h"
# include "dServer.h"
2023-10-21 23:31:55 +00:00
# include "Logger.h"
2021-12-05 17:54:36 +00:00
# include "Database.h"
# include "ZoneInstanceManager.h"
# include "MD5.h"
# include "SHA512.h"
2023-07-23 21:59:43 +00:00
# include "GeneralUtils.h"
2021-12-05 17:54:36 +00:00
# include <bcrypt/BCrypt.hpp>
# include <BitStream.h>
# include <future>
# include "Game.h"
# include "dConfig.h"
2023-02-19 12:29:14 +00:00
# include "eServerDisconnectIdentifiers.h"
2023-05-02 22:39:21 +00:00
# include "eLoginResponse.h"
2023-05-03 21:38:32 +00:00
# include "eConnectionType.h"
# include "eServerMessageType.h"
# include "eMasterMessageType.h"
2023-11-18 00:47:18 +00:00
# include "eGameMasterLevel.h"
2021-12-05 17:54:36 +00:00
2023-11-22 02:05:15 +00:00
namespace {
std : : vector < uint32_t > claimCodes ;
}
void AuthPackets : : LoadClaimCodes ( ) {
if ( ! claimCodes . empty ( ) ) return ;
auto rcstring = Game : : config - > GetValue ( " rewardcodes " ) ;
auto codestrings = GeneralUtils : : SplitString ( rcstring , ' , ' ) ;
for ( auto const & codestring : codestrings ) {
uint32_t code = - 1 ;
if ( GeneralUtils : : TryParse ( codestring , code ) & & code ! = - 1 ) {
claimCodes . push_back ( code ) ;
}
}
}
2021-12-05 17:54:36 +00:00
void AuthPackets : : HandleHandshake ( dServer * server , Packet * packet ) {
RakNet : : BitStream inStream ( packet - > data , packet - > length , false ) ;
uint64_t header = inStream . Read ( header ) ;
uint32_t clientVersion = 0 ;
inStream . Read ( clientVersion ) ;
2022-07-25 02:26:51 +00:00
2023-10-21 23:31:55 +00:00
LOG ( " Received client version: %i " , clientVersion ) ;
2022-11-07 09:27:48 +00:00
SendHandshake ( server , packet - > systemAddress , server - > GetIP ( ) , server - > GetPort ( ) , server - > GetServerType ( ) ) ;
2021-12-05 17:54:36 +00:00
}
2022-11-07 09:27:48 +00:00
void AuthPackets : : SendHandshake ( dServer * server , const SystemAddress & sysAddr , const std : : string & nextServerIP , uint16_t nextServerPort , const ServerType serverType ) {
2021-12-05 17:54:36 +00:00
RakNet : : BitStream bitStream ;
2023-09-21 01:06:28 +00:00
BitStreamUtils : : WriteHeader ( bitStream , eConnectionType : : SERVER , eServerMessageType : : VERSION_CONFIRM ) ;
2023-08-04 02:38:33 +00:00
uint32_t netVersion ;
2024-01-02 03:50:00 +00:00
const std : : string & expectedVersion = Game : : config - > GetValue ( " client_net_version " ) ;
LOG ( " Expected Version: '%s' " , expectedVersion . c_str ( ) ) ;
if ( ! GeneralUtils : : TryParse ( expectedVersion , netVersion ) ) {
2023-10-21 23:31:55 +00:00
LOG ( " Failed to parse client_net_version. Cannot authenticate to %s:%i " , nextServerIP . c_str ( ) , nextServerPort ) ;
2023-08-04 02:38:33 +00:00
return ;
}
bitStream . Write < uint32_t > ( netVersion ) ;
2023-12-28 04:18:20 +00:00
bitStream . Write < uint32_t > ( 0x93 ) ;
2022-07-25 02:26:51 +00:00
2022-11-07 09:27:48 +00:00
if ( serverType = = ServerType : : Auth ) bitStream . Write ( uint32_t ( 1 ) ) ; //Conn: auth
2023-12-28 04:18:20 +00:00
else bitStream . Write < uint32_t > ( 4 ) ; //Conn: world
2022-07-25 02:26:51 +00:00
2023-12-28 04:18:20 +00:00
bitStream . Write < uint32_t > ( 0 ) ; //Server process ID
2021-12-05 17:54:36 +00:00
bitStream . Write ( nextServerPort ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
server - > Send ( & bitStream , sysAddr , false ) ;
}
void AuthPackets : : HandleLoginRequest ( dServer * server , Packet * packet ) {
std : : string username = PacketUtils : : ReadString ( 8 , packet , true ) ;
std : : string password = PacketUtils : : ReadString ( 0x4A , packet , true ) ;
const char * szUsername = username . c_str ( ) ;
// Fetch account details
2023-11-18 00:47:18 +00:00
auto accountInfo = Database : : Get ( ) - > GetAccountInfo ( username ) ;
2022-07-25 02:26:51 +00:00
2023-11-18 00:47:18 +00:00
if ( ! accountInfo ) {
LOG ( " No user by name %s found! " , username . c_str ( ) ) ;
2023-05-02 22:39:21 +00:00
AuthPackets : : SendLoginResponse ( server , packet - > systemAddress , eLoginResponse : : INVALID_USER , " " , " " , 2001 , username ) ;
2021-12-05 17:54:36 +00:00
return ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
//If we aren't running in live mode, then only GMs are allowed to enter:
const auto & closedToNonDevs = Game : : config - > GetValue ( " closed_to_non_devs " ) ;
2023-11-18 00:47:18 +00:00
if ( closedToNonDevs . size ( ) > 0 & & bool ( std : : stoi ( closedToNonDevs ) ) & & accountInfo - > maxGmLevel = = eGameMasterLevel : : CIVILIAN ) {
2023-05-02 22:39:21 +00:00
AuthPackets : : SendLoginResponse ( server , packet - > systemAddress , eLoginResponse : : PERMISSIONS_NOT_HIGH_ENOUGH , " The server is currently only open to developers. " , " " , 2001 , username ) ;
2021-12-05 17:54:36 +00:00
return ;
}
2023-11-18 00:47:18 +00:00
if ( Game : : config - > GetValue ( " dont_use_keys " ) ! = " 1 " & & accountInfo - > maxGmLevel = = eGameMasterLevel : : CIVILIAN ) {
LOG ( " " ) ;
2021-12-05 17:54:36 +00:00
//Check to see if we have a play key:
2023-11-18 00:47:18 +00:00
if ( accountInfo - > playKeyId = = 0 ) {
2023-05-02 22:39:21 +00:00
AuthPackets : : SendLoginResponse ( server , packet - > systemAddress , eLoginResponse : : PERMISSIONS_NOT_HIGH_ENOUGH , " Your account doesn't have a play key associated with it! " , " " , 2001 , username ) ;
2023-10-21 23:31:55 +00:00
LOG ( " User %s tried to log in, but they don't have a play key. " , username . c_str ( ) ) ;
2021-12-05 17:54:36 +00:00
return ;
}
//Check if the play key is _valid_:
2023-11-18 00:47:18 +00:00
auto playKeyStatus = Database : : Get ( ) - > IsPlaykeyActive ( accountInfo - > playKeyId ) ;
2022-07-25 02:26:51 +00:00
2023-11-18 00:47:18 +00:00
if ( ! playKeyStatus ) {
AuthPackets : : SendLoginResponse ( server , packet - > systemAddress , eLoginResponse : : PERMISSIONS_NOT_HIGH_ENOUGH , " Your account doesn't have a valid play key associated with it! " , " " , 2001 , username ) ;
2021-12-05 17:54:36 +00:00
return ;
}
2023-11-18 00:47:18 +00:00
if ( ! playKeyStatus . value ( ) ) {
2023-05-02 22:39:21 +00:00
AuthPackets : : SendLoginResponse ( server , packet - > systemAddress , eLoginResponse : : PERMISSIONS_NOT_HIGH_ENOUGH , " Your play key has been disabled. " , " " , 2001 , username ) ;
2023-10-21 23:31:55 +00:00
LOG ( " User %s tried to log in, but their play key was disabled " , username . c_str ( ) ) ;
2021-12-05 17:54:36 +00:00
return ;
}
}
2022-07-25 02:26:51 +00:00
2023-11-18 00:47:18 +00:00
if ( accountInfo - > banned ) {
2023-05-02 22:39:21 +00:00
AuthPackets : : SendLoginResponse ( server , packet - > systemAddress , eLoginResponse : : BANNED , " " , " " , 2001 , username ) ; return ;
2021-12-05 17:54:36 +00:00
}
2023-11-18 00:47:18 +00:00
if ( accountInfo - > locked ) {
2023-05-02 22:39:21 +00:00
AuthPackets : : SendLoginResponse ( server , packet - > systemAddress , eLoginResponse : : ACCOUNT_LOCKED , " " , " " , 2001 , username ) ; return ;
2021-12-05 17:54:36 +00:00
}
2023-11-18 00:47:18 +00:00
bool loginSuccess = : : bcrypt_checkpw ( password . c_str ( ) , accountInfo - > bcryptPassword . c_str ( ) ) = = 0 ;
2021-12-05 17:54:36 +00:00
if ( ! loginSuccess ) {
2023-05-02 22:39:21 +00:00
AuthPackets : : SendLoginResponse ( server , packet - > systemAddress , eLoginResponse : : WRONG_PASS , " " , " " , 2001 , username ) ;
2023-10-21 23:31:55 +00:00
LOG ( " Wrong password used " ) ;
2022-07-28 13:39:57 +00:00
} else {
2021-12-05 17:54:36 +00:00
SystemAddress system = packet - > systemAddress ; //Copy the sysAddr before the Packet gets destroyed from main
if ( ! server - > GetIsConnectedToMaster ( ) ) {
2023-05-02 22:39:21 +00:00
AuthPackets : : SendLoginResponse ( server , system , eLoginResponse : : GENERAL_FAILED , " " , " " , 0 , username ) ;
2021-12-05 17:54:36 +00:00
return ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
ZoneInstanceManager : : Instance ( ) - > RequestZoneTransfer ( server , 0 , 0 , false , [ system , server , username ] ( bool mythranShift , uint32_t zoneID , uint32_t zoneInstance , uint32_t zoneClone , std : : string zoneIP , uint16_t zonePort ) {
2023-05-02 22:39:21 +00:00
AuthPackets : : SendLoginResponse ( server , system , eLoginResponse : : SUCCESS , " " , zoneIP , zonePort , username ) ;
2022-07-28 13:39:57 +00:00
} ) ;
2021-12-05 17:54:36 +00:00
}
2023-11-22 02:05:15 +00:00
for ( auto const code : claimCodes ) {
Database : : Get ( ) - > InsertRewardCode ( accountInfo - > id , code ) ;
}
2021-12-05 17:54:36 +00:00
}
void AuthPackets : : SendLoginResponse ( dServer * server , const SystemAddress & sysAddr , eLoginResponse responseCode , const std : : string & errorMsg , const std : : string & wServerIP , uint16_t wServerPort , std : : string username ) {
2022-07-28 13:39:57 +00:00
RakNet : : BitStream packet ;
2023-09-21 01:06:28 +00:00
BitStreamUtils : : WriteHeader ( packet , eConnectionType : : CLIENT , eClientMessageType : : LOGIN_RESPONSE ) ;
2022-07-25 02:26:51 +00:00
2023-12-28 04:18:20 +00:00
packet . Write < uint8_t > ( GeneralUtils : : CastUnderlyingType ( responseCode ) ) ;
2022-07-25 02:26:51 +00:00
2023-09-21 01:06:28 +00:00
// Event Gating
2023-11-18 09:33:23 +00:00
packet . Write ( LUString ( Game : : config - > GetValue ( " event_1 " ) ) ) ;
packet . Write ( LUString ( Game : : config - > GetValue ( " event_2 " ) ) ) ;
packet . Write ( LUString ( Game : : config - > GetValue ( " event_3 " ) ) ) ;
packet . Write ( LUString ( Game : : config - > GetValue ( " event_4 " ) ) ) ;
packet . Write ( LUString ( Game : : config - > GetValue ( " event_5 " ) ) ) ;
packet . Write ( LUString ( Game : : config - > GetValue ( " event_6 " ) ) ) ;
packet . Write ( LUString ( Game : : config - > GetValue ( " event_7 " ) ) ) ;
packet . Write ( LUString ( Game : : config - > GetValue ( " event_8 " ) ) ) ;
uint16_t version_major = 1 ;
uint16_t version_current = 10 ;
uint16_t version_minor = 64 ;
GeneralUtils : : TryParse < uint16_t > ( Game : : config - > GetValue ( " version_major " ) , version_major ) ;
GeneralUtils : : TryParse < uint16_t > ( Game : : config - > GetValue ( " version_current " ) , version_current ) ;
GeneralUtils : : TryParse < uint16_t > ( Game : : config - > GetValue ( " version_minor " ) , version_minor ) ;
packet . Write ( version_major ) ;
packet . Write ( version_current ) ;
packet . Write ( version_minor ) ;
2022-07-25 02:26:51 +00:00
2022-07-28 13:39:57 +00:00
// Writes the user key
2023-07-23 21:59:43 +00:00
uint32_t sessionKey = GeneralUtils : : GenerateRandomNumber < uint32_t > ( ) ;
2021-12-05 17:54:36 +00:00
std : : string userHash = std : : to_string ( sessionKey ) ;
2022-07-28 13:39:57 +00:00
userHash = md5 ( userHash ) ;
2023-09-21 01:06:28 +00:00
packet . Write ( LUWString ( userHash ) ) ;
2022-07-25 02:26:51 +00:00
2022-07-28 13:39:57 +00:00
// Write the Character and Chat IPs
2023-09-21 01:06:28 +00:00
packet . Write ( LUString ( wServerIP ) ) ;
packet . Write ( LUString ( " " ) ) ;
2022-07-25 02:26:51 +00:00
2022-07-28 13:39:57 +00:00
// Write the Character and Chat Ports
2023-12-28 04:18:20 +00:00
packet . Write < uint16_t > ( wServerPort ) ;
packet . Write < uint16_t > ( 0 ) ;
2022-07-25 02:26:51 +00:00
2023-09-21 01:06:28 +00:00
// CDN Key
packet . Write ( LUString ( " " ) ) ;
2022-07-25 02:26:51 +00:00
2023-09-21 01:06:28 +00:00
// CDN Ticket
packet . Write ( LUString ( " 00000000-0000-0000-0000-000000000000 " , 37 ) ) ;
2022-07-25 02:26:51 +00:00
2023-12-28 04:18:20 +00:00
packet . Write < uint32_t > ( 0 ) ; // Language
2022-07-25 02:26:51 +00:00
2022-07-28 13:39:57 +00:00
// Write the localization
2023-09-21 01:06:28 +00:00
packet . Write ( LUString ( " US " , 3 ) ) ;
2022-07-25 02:26:51 +00:00
2023-12-28 04:18:20 +00:00
packet . Write < uint8_t > ( false ) ; // Just upgraded from F2P
packet . Write < uint8_t > ( false ) ; // User is F2P
packet . Write < uint64_t > ( 0 ) ; // Time Remaining in F2P
2022-07-25 02:26:51 +00:00
2022-07-28 13:39:57 +00:00
// Write custom error message
2023-12-28 04:18:20 +00:00
packet . Write < uint16_t > ( errorMsg . length ( ) ) ;
2023-09-21 01:06:28 +00:00
packet . Write ( LUWString ( errorMsg , static_cast < uint32_t > ( errorMsg . length ( ) ) ) ) ;
2022-07-25 02:26:51 +00:00
2022-07-28 13:39:57 +00:00
// Here write auth logs
2023-12-28 04:18:20 +00:00
packet . Write < uint32_t > ( 20 ) ;
2022-07-28 13:39:57 +00:00
for ( uint32_t i = 0 ; i < 20 ; + + i ) {
2023-12-28 04:18:20 +00:00
packet . Write < uint32_t > ( 8 ) ;
packet . Write < uint32_t > ( 44 ) ;
packet . Write < uint32_t > ( 14000 ) ;
packet . Write < uint32_t > ( 0 ) ;
2022-07-28 13:39:57 +00:00
}
2022-07-25 02:26:51 +00:00
2022-07-28 13:39:57 +00:00
server - > Send ( & packet , sysAddr , false ) ;
2021-12-05 17:54:36 +00:00
//Inform the master server that we've created a session for this user:
2023-12-23 07:53:21 +00:00
if ( responseCode = = eLoginResponse : : SUCCESS ) {
2021-12-05 17:54:36 +00:00
CBITSTREAM ;
2023-09-21 01:06:28 +00:00
BitStreamUtils : : WriteHeader ( bitStream , eConnectionType : : MASTER , eMasterMessageType : : SET_SESSION_KEY ) ;
2021-12-05 17:54:36 +00:00
bitStream . Write ( sessionKey ) ;
2023-09-21 01:06:28 +00:00
bitStream . Write ( LUString ( username , 66 ) ) ;
2021-12-05 17:54:36 +00:00
server - > SendToMaster ( & bitStream ) ;
2023-10-21 23:31:55 +00:00
LOG ( " Set sessionKey: %i for user %s " , sessionKey , username . c_str ( ) ) ;
2021-12-05 17:54:36 +00:00
}
}