Core/RA: Calculate password hash internally instead of sending plaintext password to mysql.
Convert tabs to spaces. --HG-- branch : trunk
This commit is contained in:
@@ -35,59 +35,59 @@
|
|||||||
|
|
||||||
RARunnable::RARunnable() : m_Reactor(NULL)
|
RARunnable::RARunnable() : m_Reactor(NULL)
|
||||||
{
|
{
|
||||||
ACE_Reactor_Impl* imp = 0;
|
ACE_Reactor_Impl* imp = 0;
|
||||||
|
|
||||||
#if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL)
|
#if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL)
|
||||||
|
|
||||||
imp = new ACE_Dev_Poll_Reactor();
|
imp = new ACE_Dev_Poll_Reactor();
|
||||||
|
|
||||||
imp->max_notify_iterations (128);
|
imp->max_notify_iterations (128);
|
||||||
imp->restart (1);
|
imp->restart (1);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
imp = new ACE_TP_Reactor();
|
imp = new ACE_TP_Reactor();
|
||||||
imp->max_notify_iterations (128);
|
imp->max_notify_iterations (128);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_Reactor = new ACE_Reactor (imp, 1);
|
m_Reactor = new ACE_Reactor (imp, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
RARunnable::~RARunnable()
|
RARunnable::~RARunnable()
|
||||||
{
|
{
|
||||||
delete m_Reactor;
|
delete m_Reactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RARunnable::run()
|
void RARunnable::run()
|
||||||
{
|
{
|
||||||
if (!sConfig.GetBoolDefault("Ra.Enable", false))
|
if (!sConfig.GetBoolDefault("Ra.Enable", false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ACE_Acceptor<RASocket, ACE_SOCK_ACCEPTOR> acceptor;
|
ACE_Acceptor<RASocket, ACE_SOCK_ACCEPTOR> acceptor;
|
||||||
|
|
||||||
uint16 raport = sConfig.GetIntDefault("Ra.Port", 3443);
|
uint16 raport = sConfig.GetIntDefault("Ra.Port", 3443);
|
||||||
std::string stringip = sConfig.GetStringDefault("Ra.IP", "0.0.0.0");
|
std::string stringip = sConfig.GetStringDefault("Ra.IP", "0.0.0.0");
|
||||||
|
|
||||||
ACE_INET_Addr listen_addr(raport, stringip.c_str());
|
ACE_INET_Addr listen_addr(raport, stringip.c_str());
|
||||||
|
|
||||||
if (acceptor.open(listen_addr, m_Reactor) == -1)
|
if (acceptor.open(listen_addr, m_Reactor) == -1)
|
||||||
{
|
{
|
||||||
sLog.outError("Trinity RA can not bind to port %d on %s", raport, stringip.c_str());
|
sLog.outError("Trinity RA can not bind to port %d on %s", raport, stringip.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sLog.outString("Starting Trinity RA on port %d on %s", raport, stringip.c_str());
|
sLog.outString("Starting Trinity RA on port %d on %s", raport, stringip.c_str());
|
||||||
|
|
||||||
while (!World::IsStopped())
|
while (!World::IsStopped())
|
||||||
{
|
{
|
||||||
// don't be too smart to move this outside the loop
|
// don't be too smart to move this outside the loop
|
||||||
// the run_reactor_event_loop will modify interval
|
// the run_reactor_event_loop will modify interval
|
||||||
ACE_Time_Value interval(0, 100000);
|
ACE_Time_Value interval(0, 100000);
|
||||||
|
|
||||||
if (m_Reactor->run_reactor_event_loop(interval) == -1)
|
if (m_Reactor->run_reactor_event_loop(interval) == -1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sLog.outStaticDebug("Trinity RA thread exiting");
|
sLog.outStaticDebug("Trinity RA thread exiting");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public:
|
|||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ACE_Reactor* m_Reactor;
|
ACE_Reactor* m_Reactor;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -28,10 +28,11 @@
|
|||||||
#include "RASocket.h"
|
#include "RASocket.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
#include "SHA1.h"
|
||||||
|
|
||||||
RASocket::RASocket()
|
RASocket::RASocket()
|
||||||
{
|
{
|
||||||
iMinLevel = sConfig.GetIntDefault("RA.MinLevel", 3);
|
iMinLevel = sConfig.GetIntDefault("RA.MinLevel", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
RASocket::~RASocket()
|
RASocket::~RASocket()
|
||||||
@@ -40,289 +41,291 @@ RASocket::~RASocket()
|
|||||||
|
|
||||||
int RASocket::open(void *)
|
int RASocket::open(void *)
|
||||||
{
|
{
|
||||||
ACE_INET_Addr remote_addr;
|
ACE_INET_Addr remote_addr;
|
||||||
|
|
||||||
if (peer().get_remote_addr(remote_addr) == -1)
|
if (peer().get_remote_addr(remote_addr) == -1)
|
||||||
{
|
{
|
||||||
sLog.outError("RASocket::open: peer().get_remote_addr error is %s", ACE_OS::strerror(errno));
|
sLog.outError("RASocket::open: peer().get_remote_addr error is %s", ACE_OS::strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sLog.outRemote("Incoming connection from %s", remote_addr.get_host_addr());
|
sLog.outRemote("Incoming connection from %s", remote_addr.get_host_addr());
|
||||||
|
|
||||||
return activate();
|
return activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
int RASocket::handle_close(ACE_HANDLE, ACE_Reactor_Mask)
|
int RASocket::handle_close(ACE_HANDLE, ACE_Reactor_Mask)
|
||||||
{
|
{
|
||||||
sLog.outRemote("Closing connection");
|
sLog.outRemote("Closing connection");
|
||||||
peer().close_reader();
|
peer().close_reader();
|
||||||
wait();
|
wait();
|
||||||
destroy();
|
destroy();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RASocket::send(const std::string& line)
|
int RASocket::send(const std::string& line)
|
||||||
{
|
{
|
||||||
return peer().send(line.c_str(), line.length()) == line.length() ? 0 : -1;
|
return peer().send(line.c_str(), line.length()) == line.length() ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RASocket::recv_line(ACE_Message_Block& buffer)
|
int RASocket::recv_line(ACE_Message_Block& buffer)
|
||||||
{
|
{
|
||||||
char byte;
|
char byte;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
ssize_t n = peer().recv(&byte, sizeof(byte));
|
ssize_t n = peer().recv(&byte, sizeof(byte));
|
||||||
|
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
// EOF, connection was closed
|
// EOF, connection was closed
|
||||||
errno = ECONNRESET;
|
errno = ECONNRESET;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ACE_ASSERT(n == sizeof(byte));
|
ACE_ASSERT(n == sizeof(byte));
|
||||||
|
|
||||||
if (byte == '\n')
|
if (byte == '\n')
|
||||||
break;
|
break;
|
||||||
else if (byte == '\r') /* Ignore CR */
|
else if (byte == '\r') /* Ignore CR */
|
||||||
continue;
|
continue;
|
||||||
else if (buffer.copy(&byte, sizeof(byte)) == -1)
|
else if (buffer.copy(&byte, sizeof(byte)) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char null_term = '\0';
|
const char null_term = '\0';
|
||||||
if (buffer.copy(&null_term, sizeof(null_term)) == -1)
|
if (buffer.copy(&null_term, sizeof(null_term)) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RASocket::recv_line(std::string& out_line)
|
int RASocket::recv_line(std::string& out_line)
|
||||||
{
|
{
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
|
||||||
ACE_Data_Block db(sizeof (buf),
|
ACE_Data_Block db(sizeof (buf),
|
||||||
ACE_Message_Block::MB_DATA,
|
ACE_Message_Block::MB_DATA,
|
||||||
buf,
|
buf,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
ACE_Message_Block::DONT_DELETE,
|
ACE_Message_Block::DONT_DELETE,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
ACE_Message_Block message_block(&db,
|
ACE_Message_Block message_block(&db,
|
||||||
ACE_Message_Block::DONT_DELETE,
|
ACE_Message_Block::DONT_DELETE,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (recv_line(message_block) == -1)
|
if (recv_line(message_block) == -1)
|
||||||
{
|
{
|
||||||
sLog.outRemote("Recv error %s", ACE_OS::strerror(errno));
|
sLog.outRemote("Recv error %s", ACE_OS::strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_line = message_block.rd_ptr();
|
out_line = message_block.rd_ptr();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RASocket::process_command(const std::string& command)
|
int RASocket::process_command(const std::string& command)
|
||||||
{
|
{
|
||||||
if (command.length() == 0)
|
if (command.length() == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sLog.outRemote("Got command: %s", command.c_str());
|
sLog.outRemote("Got command: %s", command.c_str());
|
||||||
|
|
||||||
// handle quit, exit and logout commands to terminate connection
|
// handle quit, exit and logout commands to terminate connection
|
||||||
if (command == "quit" || command == "exit" || command == "logout") {
|
if (command == "quit" || command == "exit" || command == "logout") {
|
||||||
(void) send("Bye\r\n");
|
(void) send("Bye\r\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CliCommandHolder* cmd = new CliCommandHolder(this, command.c_str(), &RASocket::zprint, &RASocket::commandFinished);
|
CliCommandHolder* cmd = new CliCommandHolder(this, command.c_str(), &RASocket::zprint, &RASocket::commandFinished);
|
||||||
sWorld.QueueCliCommand(cmd);
|
sWorld.QueueCliCommand(cmd);
|
||||||
|
|
||||||
// wait for result
|
// wait for result
|
||||||
ACE_Message_Block* mb;
|
ACE_Message_Block* mb;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (getq(mb) == -1)
|
if (getq(mb) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (mb->msg_type() == ACE_Message_Block::MB_BREAK)
|
if (mb->msg_type() == ACE_Message_Block::MB_BREAK)
|
||||||
{
|
{
|
||||||
mb->release();
|
mb->release();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peer().send(mb->rd_ptr(), mb->length()) != mb->length())
|
if (peer().send(mb->rd_ptr(), mb->length()) != mb->length())
|
||||||
{
|
{
|
||||||
mb->release();
|
mb->release();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mb->release();
|
mb->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RASocket::check_access_level(const std::string& user)
|
int RASocket::check_access_level(const std::string& user)
|
||||||
{
|
{
|
||||||
std::string safe_user = user;
|
std::string safe_user = user;
|
||||||
|
|
||||||
AccountMgr::normalizeString(safe_user);
|
AccountMgr::normalizeString(safe_user);
|
||||||
LoginDatabase.escape_string(safe_user);
|
LoginDatabase.escape_string(safe_user);
|
||||||
|
|
||||||
QueryResult result = LoginDatabase.PQuery("SELECT a.id, aa.gmlevel, aa.RealmID FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = '%s'", safe_user.c_str());
|
QueryResult result = LoginDatabase.PQuery("SELECT a.id, aa.gmlevel, aa.RealmID FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = '%s'", safe_user.c_str());
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
sLog.outRemote("User %s does not exist in database", user.c_str());
|
sLog.outRemote("User %s does not exist in database", user.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Field *fields = result->Fetch();
|
Field *fields = result->Fetch();
|
||||||
|
|
||||||
if (fields[1].GetUInt32() < iMinLevel)
|
if (fields[1].GetUInt32() < iMinLevel)
|
||||||
{
|
{
|
||||||
sLog.outRemote("User %s has no privilege to login", user.c_str());
|
sLog.outRemote("User %s has no privilege to login", user.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (fields[2].GetInt32() != -1)
|
else if (fields[2].GetInt32() != -1)
|
||||||
{
|
{
|
||||||
sLog.outRemote("User %s has to be assigned on all realms (with RealmID = '-1')", user.c_str());
|
sLog.outRemote("User %s has to be assigned on all realms (with RealmID = '-1')", user.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RASocket::check_password(const std::string& user, const std::string& pass)
|
int RASocket::check_password(const std::string& user, const std::string& pass)
|
||||||
{
|
{
|
||||||
std::string safe_user = user;
|
std::string safe_user = user;
|
||||||
AccountMgr::normalizeString(safe_user);
|
AccountMgr::normalizeString(safe_user);
|
||||||
LoginDatabase.escape_string(safe_user);
|
LoginDatabase.escape_string(safe_user);
|
||||||
|
|
||||||
std::string safe_pass = pass;
|
std::string safe_pass = pass;
|
||||||
AccountMgr::normalizeString(safe_pass);
|
AccountMgr::normalizeString(safe_pass);
|
||||||
LoginDatabase.escape_string(safe_pass);
|
LoginDatabase.escape_string(safe_pass);
|
||||||
|
|
||||||
QueryResult check = LoginDatabase.PQuery(
|
std::string hash = sAccountMgr.CalculateShaPassHash(safe_user, safe_pass);
|
||||||
"SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT('%s',':','%s'))",
|
|
||||||
safe_user.c_str(), safe_user.c_str(), safe_pass.c_str());
|
|
||||||
|
|
||||||
if (!check)
|
QueryResult check = LoginDatabase.PQuery(
|
||||||
{
|
"SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash = '%s'",
|
||||||
sLog.outRemote("Wrong password for user: %s", user.c_str());
|
safe_user.c_str(), hash.c_str());
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
if (!check)
|
||||||
|
{
|
||||||
|
sLog.outRemote("Wrong password for user: %s", user.c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RASocket::authenticate()
|
int RASocket::authenticate()
|
||||||
{
|
{
|
||||||
if (send(std::string("Username: ")) == -1)
|
if (send(std::string("Username: ")) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
std::string user;
|
std::string user;
|
||||||
if (recv_line(user) == -1)
|
if (recv_line(user) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (send(std::string("Password: ")) == -1)
|
if (send(std::string("Password: ")) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
std::string pass;
|
std::string pass;
|
||||||
if (recv_line(pass) == -1)
|
if (recv_line(pass) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
sLog.outRemote("Login attempt for user: %s", user.c_str());
|
sLog.outRemote("Login attempt for user: %s", user.c_str());
|
||||||
|
|
||||||
if (check_access_level(user) == -1)
|
if (check_access_level(user) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (check_password(user, pass) == -1)
|
if (check_password(user, pass) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
sLog.outRemote("User login: %s", user.c_str());
|
sLog.outRemote("User login: %s", user.c_str());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RASocket::svc(void)
|
int RASocket::svc(void)
|
||||||
{
|
{
|
||||||
if (send("Authentication required\r\n") == -1)
|
if (send("Authentication required\r\n") == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (authenticate() == -1)
|
if (authenticate() == -1)
|
||||||
{
|
{
|
||||||
(void) send("Authentication failed\r\n");
|
(void) send("Authentication failed\r\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send motd
|
// send motd
|
||||||
if (send(std::string(sWorld.GetMotd()) + "\r\n") == -1)
|
if (send(std::string(sWorld.GetMotd()) + "\r\n") == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
// show prompt
|
// show prompt
|
||||||
const char* tc_prompt = "TC> ";
|
const char* tc_prompt = "TC> ";
|
||||||
if (peer().send(tc_prompt, strlen(tc_prompt)) != strlen(tc_prompt))
|
if (peer().send(tc_prompt, strlen(tc_prompt)) != strlen(tc_prompt))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
if (recv_line(line) == -1)
|
if (recv_line(line) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (process_command(line) == -1)
|
if (process_command(line) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RASocket::zprint(void* callbackArg, const char * szText)
|
void RASocket::zprint(void* callbackArg, const char * szText)
|
||||||
{
|
{
|
||||||
if (!szText || !callbackArg)
|
if (!szText || !callbackArg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RASocket* socket = static_cast<RASocket*>(callbackArg);
|
RASocket* socket = static_cast<RASocket*>(callbackArg);
|
||||||
size_t sz = strlen(szText);
|
size_t sz = strlen(szText);
|
||||||
|
|
||||||
ACE_Message_Block* mb = new ACE_Message_Block(sz);
|
ACE_Message_Block* mb = new ACE_Message_Block(sz);
|
||||||
mb->copy(szText, sz);
|
mb->copy(szText, sz);
|
||||||
|
|
||||||
if (socket->putq(mb, const_cast<ACE_Time_Value*>(&ACE_Time_Value::zero)) == -1)
|
if (socket->putq(mb, const_cast<ACE_Time_Value*>(&ACE_Time_Value::zero)) == -1)
|
||||||
{
|
{
|
||||||
sLog.outRemote("Failed to enqueue message, queue is full or closed. Error is %s", ACE_OS::strerror(errno));
|
sLog.outRemote("Failed to enqueue message, queue is full or closed. Error is %s", ACE_OS::strerror(errno));
|
||||||
mb->release();
|
mb->release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RASocket::commandFinished(void* callbackArg, bool /*success*/)
|
void RASocket::commandFinished(void* callbackArg, bool /*success*/)
|
||||||
{
|
{
|
||||||
if (!callbackArg)
|
if (!callbackArg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RASocket* socket = static_cast<RASocket*>(callbackArg);
|
RASocket* socket = static_cast<RASocket*>(callbackArg);
|
||||||
|
|
||||||
ACE_Message_Block* mb = new ACE_Message_Block();
|
ACE_Message_Block* mb = new ACE_Message_Block();
|
||||||
|
|
||||||
mb->msg_type(ACE_Message_Block::MB_BREAK);
|
mb->msg_type(ACE_Message_Block::MB_BREAK);
|
||||||
|
|
||||||
// the message is 0 size control message to tell that command output is finished
|
// the message is 0 size control message to tell that command output is finished
|
||||||
// hence we don't put timeout, because it shouldn't increase queue size and shouldn't block
|
// hence we don't put timeout, because it shouldn't increase queue size and shouldn't block
|
||||||
if (socket->putq(mb) == -1)
|
if (socket->putq(mb) == -1)
|
||||||
{
|
{
|
||||||
// getting here is bad, command can't be marked as complete
|
// getting here is bad, command can't be marked as complete
|
||||||
sLog.outRemote("Failed to enqueue command end message. Error is %s", ACE_OS::strerror(errno));
|
sLog.outRemote("Failed to enqueue command end message. Error is %s", ACE_OS::strerror(errno));
|
||||||
mb->release();
|
mb->release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user