mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-25 23:13:35 +00:00
7f623d358c
* Database: Convert to proper namespace * Database: Use base class and getter * Database: Move files around * Database: Add property Management query Database: Move over user queries Tested at gm 0 that pre-approved names are pre-approved, unapproved need moderator approval deleting characters deletes the selcted one refreshing the character page shows the last character you logged in as tested all my characters show up when i login tested that you can delete all 4 characters and the correct character is selected each time tested renaming, approving names as gm0 Database: Add ugc model getter Hey it works, look I got around the mariadb issue. Database: Add queries Database: consolidate name query Database: Add friends list query Update name of approved names query Documentation Database: Add name check Database: Add BFF Query Database: Move BFF Setter Database: Move new friend query Database: Add remove friend queries Database: Add activity log Database: Add ugc & prop content removal Database: Add model update Database: Add migration queries Database: Add character and xml queries Database: Add user queries Untested, but compiling code Need to test that new character names are properly assigned in the following scenarios gm 0 and pre-approved name gm 0 and unapproved name gm 9 and pre-approved name gm 9 and unapproved name Database: constify function arguments Database: Add pet queries * Database: Move property model queries Untested. Need to test placing a new model moving existing one removing ugc model placing ugc model moving ugc model(?) changing privacy option variously change description and name approve property can properly travel to property * Property: Move stale reference deletion * Database: Move performance update query * Database: Add bug report query * Database: Add cheat detection query * Database: Add mail send query * Untested code need to test mailing from slash command, from all users of SendMail, getting bbb of a property and sending messages to bffs * Update CDComponentsRegistryTable.h Database: Rename and add further comments Datavbase: Add comments Add some comments Build: Fix PCH directories Database: Fix time thanks apple Database: Fix compiler warnings Overload destructor Define specialty for time_t Use string instead of string_view for temp empty string Update CDTable.h Property: Update queries to use mapId Database: Reorganize Reorganize into CDClient folder and GameDatabase folder for clearer meanings and file structure Folders: Rename to GameDatabase MySQL: Remove MySQL Specifier from table Database: Move Tables to Interfaces Database: Reorder functions in header Database: Simplify property queries Database: Remove unused queries Remove extra query definitions as well Database: Consolidate User getters Database: Comment logs Update MySQLDatabase.cpp Database: Use generic code Playkey: Fix bad optional access Database: Move stuff around WorldServer: Update queries Ugc reduced by many scopes use new queries very fast tested that ugc still loads Database: Add auth queries I tested that only the correct password can sign into an account. Tested that disabled playkeys do not allow the user to play the game Database: Add donation query Database: add objectId queries Database: Add master queries Database: Fix mis-named function Database: Add slash command queries Mail: Fix itemId type CharFilter: Use new query ObjectID: Remove duplicate code SlashCommand: Update query with function Database: Add mail queries Ugc: Fix issues with saving models Resolve large scope blocks as well * Database: Add debug try catch rethrow macro * General fixes * fix play key not working * Further fixes --------- Co-authored-by: Aaron Kimbre <aronwk.aaron@gmail.com>
209 lines
7.7 KiB
C++
209 lines
7.7 KiB
C++
#include "AuthPackets.h"
|
|
#include "PacketUtils.h"
|
|
#include "BitStreamUtils.h"
|
|
|
|
#include "dNetCommon.h"
|
|
#include "dServer.h"
|
|
#include "Logger.h"
|
|
#include "Database.h"
|
|
#include "ZoneInstanceManager.h"
|
|
#include "MD5.h"
|
|
#include "SHA512.h"
|
|
#include "GeneralUtils.h"
|
|
|
|
#ifdef _WIN32
|
|
#include <bcrypt/BCrypt.hpp>
|
|
#else
|
|
#include <bcrypt.h>
|
|
#endif
|
|
|
|
#include <BitStream.h>
|
|
#include <future>
|
|
|
|
#include "Game.h"
|
|
#include "dConfig.h"
|
|
#include "eServerDisconnectIdentifiers.h"
|
|
#include "eLoginResponse.h"
|
|
#include "eConnectionType.h"
|
|
#include "eServerMessageType.h"
|
|
#include "eMasterMessageType.h"
|
|
#include "eGameMasterLevel.h"
|
|
|
|
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);
|
|
|
|
LOG("Received client version: %i", clientVersion);
|
|
SendHandshake(server, packet->systemAddress, server->GetIP(), server->GetPort(), server->GetServerType());
|
|
}
|
|
|
|
void AuthPackets::SendHandshake(dServer* server, const SystemAddress& sysAddr, const std::string& nextServerIP, uint16_t nextServerPort, const ServerType serverType) {
|
|
RakNet::BitStream bitStream;
|
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::VERSION_CONFIRM);
|
|
uint32_t netVersion;
|
|
if (!GeneralUtils::TryParse(Game::config->GetValue("client_net_version"), netVersion)) {
|
|
LOG("Failed to parse client_net_version. Cannot authenticate to %s:%i", nextServerIP.c_str(), nextServerPort);
|
|
return;
|
|
}
|
|
bitStream.Write<uint32_t>(netVersion);
|
|
bitStream.Write(uint32_t(0x93));
|
|
|
|
if (serverType == ServerType::Auth) bitStream.Write(uint32_t(1)); //Conn: auth
|
|
else bitStream.Write(uint32_t(4)); //Conn: world
|
|
|
|
bitStream.Write(uint32_t(0)); //Server process ID
|
|
bitStream.Write(nextServerPort);
|
|
|
|
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
|
|
auto accountInfo = Database::Get()->GetAccountInfo(username);
|
|
|
|
if (!accountInfo) {
|
|
LOG("No user by name %s found!", username.c_str());
|
|
AuthPackets::SendLoginResponse(server, packet->systemAddress, eLoginResponse::INVALID_USER, "", "", 2001, username);
|
|
return;
|
|
}
|
|
|
|
//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");
|
|
if (closedToNonDevs.size() > 0 && bool(std::stoi(closedToNonDevs)) && accountInfo->maxGmLevel == eGameMasterLevel::CIVILIAN) {
|
|
AuthPackets::SendLoginResponse(server, packet->systemAddress, eLoginResponse::PERMISSIONS_NOT_HIGH_ENOUGH, "The server is currently only open to developers.", "", 2001, username);
|
|
return;
|
|
}
|
|
|
|
if (Game::config->GetValue("dont_use_keys") != "1" && accountInfo->maxGmLevel == eGameMasterLevel::CIVILIAN) {
|
|
LOG("");
|
|
//Check to see if we have a play key:
|
|
if (accountInfo->playKeyId == 0) {
|
|
AuthPackets::SendLoginResponse(server, packet->systemAddress, eLoginResponse::PERMISSIONS_NOT_HIGH_ENOUGH, "Your account doesn't have a play key associated with it!", "", 2001, username);
|
|
LOG("User %s tried to log in, but they don't have a play key.", username.c_str());
|
|
return;
|
|
}
|
|
|
|
//Check if the play key is _valid_:
|
|
auto playKeyStatus = Database::Get()->IsPlaykeyActive(accountInfo->playKeyId);
|
|
|
|
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);
|
|
return;
|
|
}
|
|
|
|
if (!playKeyStatus.value()) {
|
|
AuthPackets::SendLoginResponse(server, packet->systemAddress, eLoginResponse::PERMISSIONS_NOT_HIGH_ENOUGH, "Your play key has been disabled.", "", 2001, username);
|
|
LOG("User %s tried to log in, but their play key was disabled", username.c_str());
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (accountInfo->banned) {
|
|
AuthPackets::SendLoginResponse(server, packet->systemAddress, eLoginResponse::BANNED, "", "", 2001, username); return;
|
|
}
|
|
|
|
if (accountInfo->locked) {
|
|
AuthPackets::SendLoginResponse(server, packet->systemAddress, eLoginResponse::ACCOUNT_LOCKED, "", "", 2001, username); return;
|
|
}
|
|
|
|
bool loginSuccess = ::bcrypt_checkpw(password.c_str(), accountInfo->bcryptPassword.c_str()) == 0;
|
|
|
|
if (!loginSuccess) {
|
|
AuthPackets::SendLoginResponse(server, packet->systemAddress, eLoginResponse::WRONG_PASS, "", "", 2001, username);
|
|
LOG("Wrong password used");
|
|
} else {
|
|
SystemAddress system = packet->systemAddress; //Copy the sysAddr before the Packet gets destroyed from main
|
|
|
|
if (!server->GetIsConnectedToMaster()) {
|
|
AuthPackets::SendLoginResponse(server, system, eLoginResponse::GENERAL_FAILED, "", "", 0, username);
|
|
return;
|
|
}
|
|
|
|
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) {
|
|
AuthPackets::SendLoginResponse(server, system, eLoginResponse::SUCCESS, "", zoneIP, zonePort, username);
|
|
});
|
|
}
|
|
}
|
|
|
|
void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAddr, eLoginResponse responseCode, const std::string& errorMsg, const std::string& wServerIP, uint16_t wServerPort, std::string username) {
|
|
RakNet::BitStream packet;
|
|
BitStreamUtils::WriteHeader(packet, eConnectionType::CLIENT, eClientMessageType::LOGIN_RESPONSE);
|
|
|
|
packet.Write(static_cast<uint8_t>(responseCode));
|
|
|
|
// Event Gating
|
|
packet.Write(LUString("Talk_Like_A_Pirate"));
|
|
packet.Write(LUString(""));
|
|
packet.Write(LUString(""));
|
|
packet.Write(LUString(""));
|
|
packet.Write(LUString(""));
|
|
packet.Write(LUString(""));
|
|
packet.Write(LUString(""));
|
|
packet.Write(LUString(""));
|
|
|
|
packet.Write(static_cast<uint16_t>(1)); // Version Major
|
|
packet.Write(static_cast<uint16_t>(10)); // Version Current
|
|
packet.Write(static_cast<uint16_t>(64)); // Version Minor
|
|
|
|
// Writes the user key
|
|
uint32_t sessionKey = GeneralUtils::GenerateRandomNumber<uint32_t>();
|
|
std::string userHash = std::to_string(sessionKey);
|
|
userHash = md5(userHash);
|
|
packet.Write(LUWString(userHash));
|
|
|
|
// Write the Character and Chat IPs
|
|
packet.Write(LUString(wServerIP));
|
|
packet.Write(LUString(""));
|
|
|
|
// Write the Character and Chat Ports
|
|
packet.Write(static_cast<uint16_t>(wServerPort));
|
|
packet.Write(static_cast<uint16_t>(0));
|
|
|
|
// CDN Key
|
|
packet.Write(LUString(""));
|
|
|
|
// CDN Ticket
|
|
packet.Write(LUString("00000000-0000-0000-0000-000000000000", 37));
|
|
|
|
packet.Write(static_cast<uint32_t>(0)); // Language
|
|
|
|
// Write the localization
|
|
packet.Write(LUString("US", 3));
|
|
|
|
packet.Write(static_cast<uint8_t>(false)); // Just upgraded from F2P
|
|
packet.Write(static_cast<uint8_t>(false)); // User is F2P
|
|
packet.Write(static_cast<uint64_t>(0)); // Time Remaining in F2P
|
|
|
|
// Write custom error message
|
|
packet.Write(static_cast<uint16_t>(errorMsg.length()));
|
|
packet.Write(LUWString(errorMsg, static_cast<uint32_t>(errorMsg.length())));
|
|
|
|
// Here write auth logs
|
|
packet.Write(static_cast<uint32_t>(20));
|
|
for (uint32_t i = 0; i < 20; ++i) {
|
|
packet.Write(static_cast<uint32_t>(8));
|
|
packet.Write(static_cast<uint32_t>(44));
|
|
packet.Write(static_cast<uint32_t>(14000));
|
|
packet.Write(static_cast<uint32_t>(0));
|
|
}
|
|
|
|
server->Send(&packet, sysAddr, false);
|
|
|
|
//Inform the master server that we've created a session for this user:
|
|
{
|
|
CBITSTREAM;
|
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::SET_SESSION_KEY);
|
|
bitStream.Write(sessionKey);
|
|
bitStream.Write(LUString(username, 66));
|
|
server->SendToMaster(&bitStream);
|
|
|
|
LOG("Set sessionKey: %i for user %s", sessionKey, username.c_str());
|
|
}
|
|
}
|