Heavy wip on login changes to get it to actually work like we want

This commit is contained in:
KimLS 2017-12-10 23:35:25 -08:00
parent 6b70faf141
commit 5bbeec626c
28 changed files with 338 additions and 138 deletions

View File

@ -86,7 +86,7 @@ Database::~Database()
Return the account id or zero if no account matches.
Zero will also be returned if there is a database error.
*/
uint32 Database::CheckLogin(const char* name, const char* password, int16* oStatus) {
uint32 Database::CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus) {
if(strlen(name) >= 50 || strlen(password) >= 50)
return(0);
@ -97,9 +97,10 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat
DoEscapeString(tmpUN, name, strlen(name));
DoEscapeString(tmpPW, password, strlen(password));
std::string query = StringFormat("SELECT id, status FROM account WHERE name='%s' AND password is not null "
std::string query = StringFormat("SELECT id, status FROM account WHERE name='%s' AND ls_id='%s' AND password is not null "
"and length(password) > 0 and (password='%s' or password=MD5('%s'))",
tmpUN, tmpPW, tmpPW);
tmpUN, EscapeString(loginserver).c_str(), tmpPW, tmpPW);
auto results = QueryDatabase(query);
if (!results.Success())
@ -788,11 +789,12 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) {
return atoi(row[0]);
}
uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* lsid) {
uint32 Database::GetAccountIDByName(const char* accname, const char *loginserver, int16* status, uint32* lsid) {
if (!isAlphaNumeric(accname))
return 0;
std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' LIMIT 1", accname);
std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' AND `ls_id`='%s' LIMIT 1",
EscapeString(accname).c_str(), EscapeString(loginserver).c_str());
auto results = QueryDatabase(query);
if (!results.Success()) {

View File

@ -127,7 +127,7 @@ public:
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0);
uint32 GetAccountIDByName(const char* accname, const char *loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const char *name);
uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
uint32 GetGuildIDByCharID(uint32 char_id);
@ -182,7 +182,7 @@ public:
int16 CheckStatus(uint32 account_id);
uint32 CheckLogin(const char* name, const char* password, int16* oStatus = 0);
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
uint32 GetAccountIDFromLSID(const std::string& iLoginServer, uint32 iLSID, char* oAccountName = 0, int16* oStatus = 0);
uint8 GetAgreementFlag(uint32 acctid);

View File

@ -70,10 +70,6 @@ void EQEmuConfig::do_world(TiXmlElement *ele)
if (text) {
LoginLegacy = atoi(text) > 0 ? true : false;
}
text = ParseTextBlock(sub_ele, "name", true);
if (text) {
LoginName = text;
}
text = ParseTextBlock(sub_ele, "account", true);
if (text) {
LoginAccount = text;
@ -101,10 +97,6 @@ void EQEmuConfig::do_world(TiXmlElement *ele)
if (text) {
loginconfig->LoginLegacy = atoi(text) > 0 ? true : false;
}
text = ParseTextBlock(sub_ele, "name", true);
if (text) {
loginconfig->LoginName = text;
}
text = ParseTextBlock(sub_ele, "account", true);
if (text) {
loginconfig->LoginAccount = text;
@ -402,9 +394,6 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
if (var_name == "LoginLegacy") {
return (itoa(LoginLegacy ? 1 : 0));
}
if (var_name == "LoginName") {
return LoginName;
}
if (var_name == "Locked") {
return (Locked ? "true" : "false");
}
@ -537,7 +526,6 @@ void EQEmuConfig::Dump() const
std::cout << "LoginPassword = " << LoginPassword << std::endl;
std::cout << "LoginPort = " << LoginPort << std::endl;
std::cout << "LoginLegacy = " << LoginLegacy << std::endl;
std::cout << "LoginName = " << LoginName << std::endl;
std::cout << "Locked = " << Locked << std::endl;
std::cout << "WorldTCPPort = " << WorldTCPPort << std::endl;
std::cout << "WorldIP = " << WorldIP << std::endl;

View File

@ -27,7 +27,6 @@ struct LoginConfig {
std::string LoginPassword;
uint16 LoginPort;
bool LoginLegacy;
std::string LoginName;
};
class EQEmuConfig : public XMLParser
@ -45,7 +44,6 @@ class EQEmuConfig : public XMLParser
std::string LoginPassword;
uint16 LoginPort;
bool LoginLegacy;
std::string LoginName;
uint32 LoginCount;
LinkedList<LoginConfig*> loginlist;
bool Locked;
@ -136,7 +134,6 @@ class EQEmuConfig : public XMLParser
LoginHost = "login.eqemulator.net";
LoginPort = 5998;
LoginLegacy = false;
LoginName = "eqemu";
// World
Locked = false;
WorldTCPPort = 9000;

View File

@ -142,14 +142,15 @@
#define ServerOP_ClientVersionSummary 0x0215
#define ServerOP_LSInfo 0x1000
#define ServerOP_LSStatus 0x1001
#define ServerOP_LSClientAuth 0x1002
#define ServerOP_LSClientAuthLeg 0x1002
#define ServerOP_LSFatalError 0x1003
#define ServerOP_SystemwideMessage 0x1005
#define ServerOP_ListWorlds 0x1006
#define ServerOP_PeerConnect 0x1007
#define ServerOP_NewLSInfo 0x1008
#define ServerOP_LSRemoteAddr 0x1009
#define ServerOP_LSAccountUpdate 0x100A
#define ServerOP_LSAccountUpdate 0x100A
#define ServerOP_LSClientAuth 0x100B
#define ServerOP_EncapPacket 0x2007 // Packet within a packet
#define ServerOP_WorldListUpdate 0x2008
@ -169,8 +170,10 @@
#define ServerOP_LSPlayerJoinWorld 0x3007
#define ServerOP_LSPlayerZoneChange 0x3008
#define ServerOP_UsertoWorldReq 0xAB00
#define ServerOP_UsertoWorldResp 0xAB01
#define ServerOP_UsertoWorldReqLeg 0xAB00
#define ServerOP_UsertoWorldRespLeg 0xAB01
#define ServerOP_UsertoWorldReq 0xAB02
#define ServerOP_UsertoWorldResp 0xAB03
#define ServerOP_LauncherConnectInfo 0x3000
#define ServerOP_LauncherZoneRequest 0x3001
@ -512,6 +515,23 @@ struct ServerLSPlayerZoneChange_Struct {
};
struct ClientAuth_Struct {
uint32 lsaccount_id; // ID# in login server's db
char lsname[64];
char name[30]; // username in login server's db
char key[30]; // the Key the client will present
uint8 lsadmin; // login server admin level
int16 worldadmin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
uint32 ip;
uint8 local; // 1 if the client is from the local network
template <class Archive>
void serialize(Archive &ar)
{
ar(lsaccount_id, lsname, name, key, lsadmin, worldadmin, ip, local);
}
};
struct ClientAuthLegacy_Struct {
uint32 lsaccount_id; // ID# in login server's db
char name[30]; // username in login server's db
char key[30]; // the Key the client will present
@ -651,12 +671,29 @@ struct ServerSyncWorldList_Struct {
bool placeholder;
};
struct UsertoWorldRequestLegacy_Struct {
uint32 lsaccountid;
uint32 worldid;
uint32 FromID;
uint32 ToID;
char IPAddr[64];
};
struct UsertoWorldRequest_Struct {
uint32 lsaccountid;
uint32 worldid;
uint32 FromID;
uint32 ToID;
char IPAddr[64];
char login[64];
};
struct UsertoWorldResponseLegacy_Struct {
uint32 lsaccountid;
uint32 worldid;
int8 response; // -3) World Full, -2) Banned, -1) Suspended, 0) Denied, 1) Allowed
uint32 FromID;
uint32 ToID;
};
struct UsertoWorldResponse_Struct {
@ -665,6 +702,7 @@ struct UsertoWorldResponse_Struct {
int8 response; // -3) World Full, -2) Banned, -1) Suspended, 0) Denied, 1) Allowed
uint32 FromID;
uint32 ToID;
char login[64];
};
// generic struct to be used for alot of simple zone->world questions

View File

@ -5,7 +5,6 @@ SET(eqlogin_sources
client_manager.cpp
config.cpp
database_mysql.cpp
database_postgresql.cpp
encryption.cpp
main.cpp
server_manager.cpp
@ -18,7 +17,6 @@ SET(eqlogin_headers
config.h
database.h
database_mysql.h
database_postgresql.h
encryption.h
login_server.h
login_structures.h

View File

@ -219,37 +219,38 @@ void Client::Handle_Login(const char* data, unsigned int size)
bool result = false;
if (outbuffer[0] == 0 && outbuffer[1] == 0) {
if (server.options.IsTokenLoginAllowed()) {
cred = (&outbuffer[2 + user.length()]);
result = server.db->GetLoginTokenDataFromToken(cred, connection->GetRemoteAddr(), db_account_id, user);
}
//if (server.options.IsTokenLoginAllowed()) {
// cred = (&outbuffer[2 + user.length()]);
// result = server.db->GetLoginTokenDataFromToken(cred, connection->GetRemoteAddr(), db_account_id, user);
//}
}
else {
if (server.options.IsPasswordLoginAllowed()) {
cred = (&outbuffer[1 + user.length()]);
if (server.db->GetLoginDataFromAccountName(user, db_account_password_hash, db_account_id) == false) {
/* If we have auto_create_accounts enabled in the login.ini, we will process the creation of an account on our own*/
if (
server.options.CanAutoCreateAccounts() &&
server.db->CreateLoginData(user, eqcrypt_hash(user, cred, mode), db_account_id) == true
) {
LogF(Logs::General, Logs::Error, "User {0} does not exist in the database, so we created it...", user);
result = true;
}
else {
LogF(Logs::General, Logs::Error, "Error logging in, user {0} does not exist in the database.", user);
result = false;
}
}
else {
if (eqcrypt_verify_hash(user, cred, db_account_password_hash, mode)) {
result = true;
}
else {
result = false;
}
}
}
//if (server.options.IsPasswordLoginAllowed()) {
// result = false;
// //cred = (&outbuffer[1 + user.length()]);
// //if (server.db->GetLoginDataFromAccountName(user, db_account_password_hash, db_account_id) == false) {
// // /* If we have auto_create_accounts enabled in the login.ini, we will process the creation of an account on our own*/
// // if (
// // server.options.CanAutoCreateAccounts() &&
// // server.db->CreateLoginData(user, eqcrypt_hash(user, cred, mode), db_account_id) == true
// // ) {
// // LogF(Logs::General, Logs::Error, "User {0} does not exist in the database, so we created it...", user);
// // result = true;
// // }
// // else {
// // LogF(Logs::General, Logs::Error, "Error logging in, user {0} does not exist in the database.", user);
// // result = false;
// // }
// //}
// //else {
// // if (eqcrypt_verify_hash(user, cred, db_account_password_hash, mode)) {
// // result = true;
// // }
// // else {
// // result = false;
// // }
// //}
//}
}
/* Login Accepted */

View File

@ -129,6 +129,7 @@ private:
std::string account_name;
unsigned int account_id;
std::string loginserver_name;
unsigned int play_server_id;
unsigned int play_sequence_id;
std::string key;

View File

@ -21,7 +21,6 @@
#include <string>
#define EQEMU_MYSQL_ENABLED
//#define EQEMU_POSTGRESQL_ENABLED
/**
* Base database class, intended to be extended.
@ -42,9 +41,9 @@ public:
* Needed for client login procedure.
* Returns true if the record was found, false otherwise.
*/
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id) { return false; }
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id, std::string &loginserver) { return false; }
virtual bool GetLoginTokenDataFromToken(const std::string &token, const std::string &ip, unsigned int &db_account_id, std::string &user) { return false; }
virtual bool GetLoginTokenDataFromToken(const std::string &token, const std::string &ip, unsigned int &db_account_id, std::string &db_loginserver, std::string &user) { return false; }
virtual bool CreateLoginData(const std::string &name, const std::string &password, unsigned int &id) { return false; }

View File

@ -59,7 +59,7 @@ DatabaseMySQL::~DatabaseMySQL()
}
}
bool DatabaseMySQL::GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id)
bool DatabaseMySQL::GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id, std::string &loginserver)
{
if (!database)
{
@ -96,7 +96,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(std::string name, std::string &p
return false;
}
bool DatabaseMySQL::GetLoginTokenDataFromToken(const std::string &token, const std::string &ip, unsigned int &db_account_id, std::string &user)
bool DatabaseMySQL::GetLoginTokenDataFromToken(const std::string &token, const std::string &ip, unsigned int &db_account_id, std::string &db_loginserver, std::string &user)
{
if (!database)
{
@ -120,6 +120,7 @@ bool DatabaseMySQL::GetLoginTokenDataFromToken(const std::string &token, const s
bool found_username = false;
bool found_login_id = false;
bool found_login_server_name = false;
if (res)
{
while ((row = mysql_fetch_row(res)) != nullptr)
@ -135,12 +136,18 @@ bool DatabaseMySQL::GetLoginTokenDataFromToken(const std::string &token, const s
found_login_id = true;
continue;
}
if (strcmp(row[2], "login_server_name") == 0) {
db_loginserver = row[3];
found_login_server_name = true;
continue;
}
}
mysql_free_result(res);
}
return found_username && found_login_id;
return found_username && found_login_id && found_login_server_name;
}
bool DatabaseMySQL::CreateLoginData(const std::string &name, const std::string &password, unsigned int &id)

View File

@ -57,9 +57,9 @@ public:
* Needed for client login procedure.
* Returns true if the record was found, false otherwise.
*/
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id);
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id, std::string &loginserver);
virtual bool GetLoginTokenDataFromToken(const std::string &token, const std::string &ip, unsigned int &db_account_id, std::string &user);
virtual bool GetLoginTokenDataFromToken(const std::string &token, const std::string &ip, unsigned int &db_account_id, std::string &db_loginserver, std::string &user);
virtual bool CreateLoginData(const std::string &name, const std::string &password, unsigned int &id);

View File

@ -53,7 +53,7 @@ DatabasePostgreSQL::~DatabasePostgreSQL()
}
}
bool DatabasePostgreSQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id)
bool DatabasePostgreSQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id, std::string &loginserver)
{
if(!db)
{

View File

@ -57,7 +57,7 @@ public:
* Needed for client login procedure.
* Returns true if the record was found, false otherwise.
*/
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id);
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id, std::string &loginserver);
/**
* Retrieves the world registration from the long and short names provided.

View File

@ -21,7 +21,6 @@
#include "config.h"
#include "database.h"
#include "database_mysql.h"
#include "database_postgresql.h"
#include "encryption.h"
#include "options.h"
#include "server_manager.h"

View File

@ -116,17 +116,6 @@ int main()
server.config->GetVariable("database", "db"));
#endif
}
else if (server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0) {
#ifdef EQEMU_POSTGRESQL_ENABLED
Log(Logs::General, Logs::Login_Server, "PostgreSQL Database Init.");
server.db = (Database*)new DatabasePostgreSQL(
server.config->GetVariable("database", "user"),
server.config->GetVariable("database", "password"),
server.config->GetVariable("database", "host"),
server.config->GetVariable("database", "port"),
server.config->GetVariable("database", "db"));
#endif
}
/* Make sure our database got created okay, otherwise cleanup and exit. */
if (!server.db) {

View File

@ -213,11 +213,11 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
while (iter != world_servers.end()) {
if ((*iter)->GetRuntimeID() == server_id) {
EQ::Net::DynamicPacket outapp;
outapp.Resize(sizeof(UsertoWorldRequest_Struct));
UsertoWorldRequest_Struct *utwr = (UsertoWorldRequest_Struct*)outapp.Data();
outapp.Resize(sizeof(UsertoWorldRequestLegacy_Struct));
UsertoWorldRequestLegacy_Struct *utwr = (UsertoWorldRequestLegacy_Struct*)outapp.Data();
utwr->worldid = server_id;
utwr->lsaccountid = client_account_id;
(*iter)->GetConnection()->Send(ServerOP_UsertoWorldReq, outapp);
(*iter)->GetConnection()->Send(ServerOP_UsertoWorldReqLeg, outapp);
found = true;
if (server.options.IsDumpInPacketsOn()) {

View File

@ -39,6 +39,7 @@ WorldServer::WorldServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> c)
c->OnMessage(ServerOP_NewLSInfo, std::bind(&WorldServer::ProcessNewLSInfo, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_LSStatus, std::bind(&WorldServer::ProcessLSStatus, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_UsertoWorldRespLeg, std::bind(&WorldServer::ProcessUsertoWorldRespLeg, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_UsertoWorldResp, std::bind(&WorldServer::ProcessUsertoWorldResp, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_LSAccountUpdate, std::bind(&WorldServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2));
}
@ -116,6 +117,93 @@ void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &p)
Handle_LSStatus(ls_status);
}
void WorldServer::ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Packet &p)
{
if (server.options.IsWorldTraceOn())
{
Log(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length());
}
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(opcode, p);
}
if (p.Length() < sizeof(UsertoWorldResponseLegacy_Struct))
{
Log(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
"but was too small. Discarded to avoid buffer overrun.");
return;
}
//I don't use world trace for this and here is why:
//Because this is a part of the client login procedure it makes tracking client errors
//While keeping world server spam with multiple servers connected almost impossible.
if (server.options.IsTraceOn())
{
Log(Logs::General, Logs::Netcode, "User-To-World Response received.");
}
UsertoWorldResponseLegacy_Struct *utwr = (UsertoWorldResponseLegacy_Struct*)p.Data();
Log(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid);
Client *c = server.client_manager->GetClient(utwr->lsaccountid);
if (c)
{
Log(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct));
PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer;
per->Sequence = c->GetPlaySequence();
per->ServerNumber = c->GetPlayServerID();
Log(Logs::General, Logs::Debug, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
Log(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
if (utwr->response > 0)
{
per->Allowed = 1;
SendClientAuth(c->GetConnection()->GetRemoteAddr(), c->GetAccountName(), c->GetKey(), c->GetAccountID());
}
switch (utwr->response)
{
case 1:
per->Message = 101;
break;
case 0:
per->Message = 326;
break;
case -1:
per->Message = 337;
break;
case -2:
per->Message = 338;
break;
case -3:
per->Message = 303;
break;
}
if (server.options.IsTraceOn())
{
Log(Logs::General, Logs::Netcode, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
per->Allowed, per->Sequence, per->ServerNumber, per->Message);
Log(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
}
if (server.options.IsDumpOutPacketsOn())
{
DumpPacket(outapp);
}
c->SendPlayResponse(outapp);
delete outapp;
}
else
{
Log(Logs::General, Logs::Error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
}
}
void WorldServer::ProcessUsertoWorldResp(uint16_t opcode, const EQ::Net::Packet &p)
{
if (server.options.IsWorldTraceOn())
@ -501,7 +589,7 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s)
void WorldServer::SendClientAuth(std::string ip, std::string account, std::string key, unsigned int account_id)
{
EQ::Net::DynamicPacket outapp;
ClientAuth_Struct client_auth;
ClientAuthLegacy_Struct client_auth;
client_auth.lsaccount_id = account_id;
strncpy(client_auth.name, account.c_str(), 30);
strncpy(client_auth.key, key.c_str(), 30);
@ -523,10 +611,10 @@ void WorldServer::SendClientAuth(std::string ip, std::string account, std::strin
}
outapp.PutSerialize(0, client_auth);
connection->Send(ServerOP_LSClientAuth, outapp);
connection->Send(ServerOP_LSClientAuthLeg, outapp);
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(ServerOP_LSClientAuth, outapp);
DumpPacket(ServerOP_LSClientAuthLeg, outapp);
}
}

View File

@ -133,6 +133,7 @@ private:
*/
void ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &p);
void ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &p);
void ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Packet &p);
void ProcessUsertoWorldResp(uint16_t opcode, const EQ::Net::Packet &p);
void ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &p);

View File

@ -31,18 +31,21 @@ extern LoginServerList loginserverlist;
extern ClientList client_list;
extern volatile bool RunLoops;
ClientListEntry::ClientListEntry(const char* iLoginServer, uint32 in_id, uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin, uint32 ip, uint8 local)
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iLSID, const char *iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin, uint32 ip, uint8 local)
: id(in_id)
{
ClearVars(true);
pIP = ip;
pLSID = iLSID;
if(iLSID > 0)
paccountid = database.GetAccountIDFromLSID(iLoginServer, iLSID, paccountname, &padmin);
if (iLSID > 0) {
paccountid = database.GetAccountIDFromLSID(iLoginServerName, iLSID, paccountname, &padmin);
}
strn0cpy(plsname, iLoginName, sizeof(plsname));
strn0cpy(plskey, iLoginKey, sizeof(plskey));
strn0cpy(pLoginServer, iLoginServer, sizeof(pLoginServer));
strn0cpy(pLoginServer, iLoginServerName, sizeof(pLoginServer));
pworldadmin = iWorldAdmin;
plocal=(local==1);
@ -258,7 +261,7 @@ bool ClientListEntry::CheckStale() {
}
bool ClientListEntry::CheckAuth(uint32 iLSID, const char* iKey) {
if (strncmp(plskey, iKey, 10) == 0) {
if (pLSID == iLSID && strncmp(plskey, iKey, 10) == 0) {
if (paccountid == 0 && LSID() > 0) {
int16 tmpStatus = WorldConfig::get()->DefaultStatus;
paccountid = database.CreateAccount(plsname, 0, tmpStatus, pLoginServer, LSID());

View File

@ -21,7 +21,7 @@ struct ServerClientList_Struct;
class ClientListEntry {
public:
ClientListEntry(const char* iLoginServer, uint32 id, uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
ClientListEntry(uint32 id, uint32 iLSID, const char *iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
ClientListEntry(uint32 id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline);
~ClientListEntry();
bool CheckStale();

View File

@ -349,8 +349,8 @@ void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnect
}
void ClientList::CLEAdd(const char* iLoginServer, uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin, uint32 ip, uint8 local) {
auto tmp = new ClientListEntry(iLoginServer, GetNextCLEID(), iLSID, iLoginName, iLoginKey, iWorldAdmin, ip, local);
void ClientList::CLEAdd(uint32 iLSID, const char *iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin, uint32 ip, uint8 local) {
auto tmp = new ClientListEntry(GetNextCLEID(), iLSID, iLoginServerName, iLoginName, iLoginKey, iWorldAdmin, ip, local);
clientlist.Append(tmp);
}

View File

@ -61,7 +61,7 @@ public:
void EnforceSessionLimit(uint32 iLSAccountID);
void CLCheckStale();
void CLEKeepAlive(uint32 numupdates, uint32* wid);
void CLEAdd(const char* iLoginServer, uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
void CLEAdd(uint32 iLSID, const char* iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
void UpdateClientGuild(uint32 char_id, uint32 guild_id);
int GetClientCount();

View File

@ -15,18 +15,30 @@ extern ZSList zoneserver_list;
extern LoginServerList loginserverlist;
struct EQ::Net::ConsoleLoginStatus CheckLogin(const std::string& username, const std::string& password) {
//TODO REIMPLEMENT
struct EQ::Net::ConsoleLoginStatus ret;
//ret.account_id = database.CheckLogin(username.c_str(), password.c_str());
//if (ret.account_id == 0) {
// return ret;
//}
//
//char account_name[64];
//database.GetAccountName(ret.account_id, account_name);
//
//ret.account_name = account_name;
//ret.status = database.CheckStatus(ret.account_id);
std::string prefix = "eqemu";
std::string raw_user = "";
auto split = SplitString(username, ':');
if (split.size() == 2) {
prefix = split[0];
raw_user = split[1];
}
else {
raw_user = split[0];
}
ret.account_id = database.CheckLogin(raw_user.c_str(), password.c_str(), prefix.c_str());
if (ret.account_id == 0) {
return ret;
}
char account_name[64];
database.GetAccountName(ret.account_id, account_name);
ret.account_name = account_name;
ret.status = database.CheckStatus(ret.account_id);
return ret;
}
@ -380,23 +392,33 @@ void ConsoleFlag(EQ::Net::ConsoleServerConnection* connection, const std::string
}
void ConsoleSetPass(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
//TODO: REIMPLEMENT
//if (args.size() != 2) {
// connection->SendLine("Format: setpass accountname password");
//}
//else {
// int16 tmpstatus = 0;
// uint32 tmpid = database.GetAccountIDByName(args[0].c_str(), &tmpstatus);
// if (!tmpid)
// connection->SendLine("Error: Account not found");
// else if (tmpstatus > connection->Admin())
// connection->SendLine("Cannot change password: Account's status is higher than yours");
// else if (database.SetLocalPassword(tmpid, args[1].c_str()))
// connection->SendLine("Password changed.");
// else
// connection->SendLine("Error changing password.");
//}
if (args.size() != 2) {
connection->SendLine("Format: setpass accountname password");
}
else {
std::string prefix = "eqemu";
std::string raw_user = "";
auto split = SplitString(args[0], ':');
if (split.size() == 2) {
prefix = split[0];
raw_user = split[1];
}
else {
raw_user = split[0];
}
int16 tmpstatus = 0;
uint32 tmpid = database.GetAccountIDByName(raw_user.c_str(), prefix.c_str(), &tmpstatus);
if (!tmpid)
connection->SendLine("Error: Account not found");
else if (tmpstatus > connection->Admin())
connection->SendLine("Cannot change password: Account's status is higher than yours");
else if (database.SetLocalPassword(tmpid, args[1].c_str()))
connection->SendLine("Password changed.");
else
connection->SendLine("Error changing password.");
}
}
void ConsoleVersion(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {

View File

@ -41,7 +41,7 @@ extern uint32 numzones;
extern uint32 numplayers;
extern volatile bool RunLoops;
LoginServer::LoginServer(const char *Name, const char* iAddress, uint16 iPort, const char* Account, const char* Password, bool legacy)
LoginServer::LoginServer(const char* iAddress, uint16 iPort, const char* Account, const char* Password, bool legacy)
{
strn0cpy(LoginServerAddress, iAddress, 256);
LoginServerPort = iPort;
@ -49,27 +49,26 @@ LoginServer::LoginServer(const char *Name, const char* iAddress, uint16 iPort, c
LoginPassword = Password;
CanAccountUpdate = false;
IsLegacy = legacy;
LoginName = Name;
Connect();
}
LoginServer::~LoginServer() {
}
void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) {
void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p) {
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
UsertoWorldRequest_Struct* utwr = (UsertoWorldRequest_Struct*)p.Data();
uint32 id = database.GetAccountIDFromLSID(LoginName, utwr->lsaccountid);
UsertoWorldRequestLegacy_Struct* utwr = (UsertoWorldRequestLegacy_Struct*)p.Data();
uint32 id = database.GetAccountIDFromLSID("eqemu", utwr->lsaccountid);
int16 status = database.CheckStatus(id);
auto outpack = new ServerPacket;
outpack->opcode = ServerOP_UsertoWorldResp;
outpack->size = sizeof(UsertoWorldResponse_Struct);
outpack->opcode = ServerOP_UsertoWorldRespLeg;
outpack->size = sizeof(UsertoWorldResponseLegacy_Struct);
outpack->pBuffer = new uchar[outpack->size];
memset(outpack->pBuffer, 0, outpack->size);
UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*)outpack->pBuffer;
UsertoWorldResponseLegacy_Struct* utwrs = (UsertoWorldResponseLegacy_Struct*)outpack->pBuffer;
utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID;
@ -98,6 +97,69 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) {
delete outpack;
}
void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) {
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
UsertoWorldRequest_Struct* utwr = (UsertoWorldRequest_Struct*)p.Data();
uint32 id = database.GetAccountIDFromLSID(utwr->login, utwr->lsaccountid);
int16 status = database.CheckStatus(id);
auto outpack = new ServerPacket;
outpack->opcode = ServerOP_UsertoWorldResp;
outpack->size = sizeof(UsertoWorldResponse_Struct);
outpack->pBuffer = new uchar[outpack->size];
memset(outpack->pBuffer, 0, outpack->size);
UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*)outpack->pBuffer;
utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID;
strn0cpy(utwrs->login, utwr->login, 64);
if (Config->Locked == true)
{
if ((status == 0 || status < 100) && (status != -2 || status != -1))
utwrs->response = 0;
if (status >= 100)
utwrs->response = 1;
}
else {
utwrs->response = 1;
}
int32 x = Config->MaxClients;
if ((int32)numplayers >= x && x != -1 && x != 255 && status < 80)
utwrs->response = -3;
if (status == -1)
utwrs->response = -1;
if (status == -2)
utwrs->response = -2;
utwrs->worldid = utwr->worldid;
SendPacket(outpack);
delete outpack;
}
void LoginServer::ProcessLSClientAuthLeg(uint16_t opcode, EQ::Net::Packet &p) {
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
try {
auto slsca = p.GetSerialize<ClientAuthLegacy_Struct>(0);
if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be
// online at the same time.
client_list.EnforceSessionLimit(slsca.lsaccount_id);
}
client_list.CLEAdd(slsca.lsaccount_id, "eqemu", slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local);
}
catch (std::exception &ex) {
LogF(Logs::General, Logs::Error, "Error parsing LSClientAuth packet from world.\n{0}", ex.what());
}
}
void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) {
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
@ -111,7 +173,7 @@ void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) {
client_list.EnforceSessionLimit(slsca.lsaccount_id);
}
client_list.CLEAdd(LoginName.c_str(), slsca.lsaccount_id, slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local);
client_list.CLEAdd(slsca.lsaccount_id, slsca.lsname, slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local);
}
catch (std::exception &ex) {
LogF(Logs::General, Logs::Error, "Error parsing LSClientAuth packet from world.\n{0}", ex.what());
@ -184,7 +246,9 @@ bool LoginServer::Connect() {
}
});
legacy_client->OnMessage(ServerOP_UsertoWorldReqLeg, std::bind(&LoginServer::ProcessUsertoWorldReqLeg, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_UsertoWorldReq, std::bind(&LoginServer::ProcessUsertoWorldReq, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_LSClientAuthLeg, std::bind(&LoginServer::ProcessLSClientAuthLeg, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_LSClientAuth, std::bind(&LoginServer::ProcessLSClientAuth, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_LSFatalError, std::bind(&LoginServer::ProcessLSFatalError, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_SystemwideMessage, std::bind(&LoginServer::ProcessSystemwideMessage, this, std::placeholders::_1, std::placeholders::_2));
@ -210,7 +274,9 @@ bool LoginServer::Connect() {
}
});
client->OnMessage(ServerOP_UsertoWorldReqLeg, std::bind(&LoginServer::ProcessUsertoWorldReqLeg, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_UsertoWorldReq, std::bind(&LoginServer::ProcessUsertoWorldReq, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSClientAuthLeg, std::bind(&LoginServer::ProcessLSClientAuthLeg, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSClientAuth, std::bind(&LoginServer::ProcessLSClientAuth, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSFatalError, std::bind(&LoginServer::ProcessLSFatalError, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_SystemwideMessage, std::bind(&LoginServer::ProcessSystemwideMessage, this, std::placeholders::_1, std::placeholders::_2));

View File

@ -31,7 +31,7 @@
class LoginServer{
public:
LoginServer(const char *, const char*, uint16, const char*, const char*, bool legacy);
LoginServer(const char*, uint16, const char*, const char*, bool legacy);
~LoginServer();
bool Connect();
@ -45,8 +45,10 @@ public:
bool CanUpdate() { return CanAccountUpdate; }
private:
void ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p);
void ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSClientAuthLeg(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p);
void ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p);
@ -62,6 +64,5 @@ private:
std::string LoginPassword;
bool CanAccountUpdate;
bool IsLegacy;
std::string LoginName;
};
#endif

View File

@ -49,9 +49,9 @@ LoginServerList::LoginServerList() {
LoginServerList::~LoginServerList() {
}
void LoginServerList::Add(const char* Name, const char* iAddress, uint16 iPort, const char* Account, const char* Password, bool Legacy)
void LoginServerList::Add(const char* iAddress, uint16 iPort, const char* Account, const char* Password, bool Legacy)
{
auto loginserver = new LoginServer(Name, iAddress, iPort, Account, Password, Legacy);
auto loginserver = new LoginServer(iAddress, iPort, Account, Password, Legacy);
m_list.push_back(std::unique_ptr<LoginServer>(loginserver));
}

View File

@ -15,7 +15,7 @@ public:
LoginServerList();
~LoginServerList();
void Add(const char*, const char*, uint16, const char*, const char*, bool);
void Add(const char*, uint16, const char*, const char*, bool);
bool SendInfo();
bool SendStatus();

View File

@ -157,7 +157,7 @@ int main(int argc, char** argv) {
// add login server config to list
if (Config->LoginCount == 0) {
if (Config->LoginHost.length()) {
loginserverlist.Add(Config->LoginName.c_str(), Config->LoginHost.c_str(), Config->LoginPort, Config->LoginAccount.c_str(), Config->LoginPassword.c_str(), Config->LoginLegacy);
loginserverlist.Add(Config->LoginHost.c_str(), Config->LoginPort, Config->LoginAccount.c_str(), Config->LoginPassword.c_str(), Config->LoginLegacy);
Log(Logs::General, Logs::World_Server, "Added loginserver %s:%i", Config->LoginHost.c_str(), Config->LoginPort);
}
}
@ -166,7 +166,7 @@ int main(int argc, char** argv) {
LinkedListIterator<LoginConfig*> iterator(loginlist);
iterator.Reset();
while (iterator.MoreElements()) {
loginserverlist.Add(iterator.GetData()->LoginName.c_str(), iterator.GetData()->LoginHost.c_str(), iterator.GetData()->LoginPort, iterator.GetData()->LoginAccount.c_str(), iterator.GetData()->LoginPassword.c_str(),
loginserverlist.Add(iterator.GetData()->LoginHost.c_str(), iterator.GetData()->LoginPort, iterator.GetData()->LoginAccount.c_str(), iterator.GetData()->LoginPassword.c_str(),
iterator.GetData()->LoginLegacy);
Log(Logs::General, Logs::World_Server, "Added loginserver %s:%i", iterator.GetData()->LoginHost.c_str(), iterator.GetData()->LoginPort);
iterator.Advance();