mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +00:00
Reimplement some functions
This commit is contained in:
parent
7a778c549f
commit
0ec53eff52
@ -224,7 +224,7 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta
|
||||
return results.LastInsertedID();
|
||||
}
|
||||
|
||||
bool Database::DeleteAccount(const char *loginserver, const char* name) {
|
||||
bool Database::DeleteAccount(const char* name, const char *loginserver) {
|
||||
std::string query = StringFormat("DELETE FROM account WHERE name='%s' AND ls_id='%s'", name, loginserver);
|
||||
Log(Logs::General, Logs::World_Server, "Account Attempting to be deleted:'%s:%s'", loginserver, name);
|
||||
|
||||
|
||||
@ -174,7 +174,7 @@ public:
|
||||
|
||||
/* Account Related */
|
||||
|
||||
bool DeleteAccount(const char *loginserver, const char* name);
|
||||
bool DeleteAccount(const char *name, const char* loginserver);
|
||||
bool GetLiveChar(uint32 account_id, char* cname);
|
||||
bool SetAccountStatus(const char* name, int16 status);
|
||||
bool SetLocalPassword(uint32 accid, const char* password);
|
||||
|
||||
@ -196,6 +196,19 @@ void find_replace(std::string& string_subject, const std::string& search_string,
|
||||
}
|
||||
}
|
||||
|
||||
void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver)
|
||||
{
|
||||
auto split = SplitString(s, '.');
|
||||
if (split.size() == 2) {
|
||||
loginserver = split[0];
|
||||
account = split[1];
|
||||
}
|
||||
else if(split.size() == 1) {
|
||||
loginserver = "eqemu";
|
||||
account = split[0];
|
||||
}
|
||||
}
|
||||
|
||||
//Const char based
|
||||
|
||||
// normal strncpy doesnt put a null term on copied strings, this one does
|
||||
|
||||
@ -34,6 +34,7 @@ void ToLowerString(std::string &s);
|
||||
void ToUpperString(std::string &s);
|
||||
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim);
|
||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
|
||||
void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver);
|
||||
|
||||
//const char based
|
||||
|
||||
|
||||
@ -180,8 +180,6 @@ void Client::Handle_SessionReady(const char* data, unsigned int size)
|
||||
|
||||
void Client::Handle_Login(const char* data, unsigned int size)
|
||||
{
|
||||
auto mode = server.options.GetEncryptionMode();
|
||||
|
||||
if (status != cs_waiting_for_login) {
|
||||
Log(Logs::General, Logs::Error, "Login received after already having logged in.");
|
||||
return;
|
||||
@ -241,6 +239,8 @@ void Client::Handle_Login(const char* data, unsigned int size)
|
||||
db_loginserver = components[0];
|
||||
user = components[1];
|
||||
}
|
||||
|
||||
ParseAccountString(user, user, db_loginserver);
|
||||
|
||||
if (server.db->GetLoginDataFromAccountInfo(user, db_loginserver, db_account_password_hash, db_account_id) == false) {
|
||||
status = cs_creating_account;
|
||||
@ -248,41 +248,7 @@ void Client::Handle_Login(const char* data, unsigned int size)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (eqcrypt_verify_hash(user, cred, db_account_password_hash, mode)) {
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (server.options.IsUpdatingInsecurePasswords()) {
|
||||
auto len = db_account_password_hash.length();
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
switch (len) {
|
||||
case 32:
|
||||
start = 1;
|
||||
end = 4;
|
||||
break;
|
||||
case 40:
|
||||
start = 5;
|
||||
end = 8;
|
||||
break;
|
||||
case 128:
|
||||
start = 9;
|
||||
end = 12;
|
||||
break;
|
||||
}
|
||||
|
||||
if (start != 0) {
|
||||
for (int i = start; i <= end; ++i) {
|
||||
if (eqcrypt_verify_hash(user, cred, db_account_password_hash, i)) {
|
||||
result = true;
|
||||
server.db->UpdateLoginHash(user, db_loginserver, eqcrypt_hash(user, cred, mode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = VerifyLoginHash(user, db_loginserver, cred, db_account_password_hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -432,6 +398,50 @@ void Client::DoFailedLogin()
|
||||
status = cs_failed_to_login;
|
||||
}
|
||||
|
||||
bool Client::VerifyLoginHash(const std::string &user, const std::string &loginserver, const std::string &cred, const std::string &hash)
|
||||
{
|
||||
auto mode = server.options.GetEncryptionMode();
|
||||
if (eqcrypt_verify_hash(user, cred, hash, mode)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (server.options.IsUpdatingInsecurePasswords()) {
|
||||
if (mode < EncryptionModeArgon2) {
|
||||
mode = EncryptionModeArgon2;
|
||||
}
|
||||
|
||||
if (hash.length() == 32) { //md5 is insecure
|
||||
for (int i = EncryptionModeMD5; i <= EncryptionModeMD5Triple; ++i) {
|
||||
if (i != mode && eqcrypt_verify_hash(user, cred, hash, i)) {
|
||||
server.db->UpdateLoginHash(user, loginserver, eqcrypt_hash(user, cred, mode));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hash.length() == 40) { //sha1 is insecure
|
||||
for (int i = EncryptionModeSHA; i <= EncryptionModeSHATriple; ++i) {
|
||||
if (i != mode && eqcrypt_verify_hash(user, cred, hash, i)) {
|
||||
server.db->UpdateLoginHash(user, loginserver, eqcrypt_hash(user, cred, mode));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hash.length() == 128) { //sha2-512 is insecure
|
||||
for (int i = EncryptionModeSHA512; i <= EncryptionModeSHA512Triple; ++i) {
|
||||
if (i != mode && eqcrypt_verify_hash(user, cred, hash, i)) {
|
||||
server.db->UpdateLoginHash(user, loginserver, eqcrypt_hash(user, cred, mode));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//argon2 is still secure
|
||||
//scrypt is still secure
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::DoSuccessfulLogin(const std::string &user, int db_account_id, const std::string &db_loginserver)
|
||||
{
|
||||
stored_user.clear();
|
||||
|
||||
@ -141,6 +141,11 @@ public:
|
||||
*/
|
||||
void DoFailedLogin();
|
||||
|
||||
/**
|
||||
* Verifies a login hash, will also attempt to update a login hash if needed.
|
||||
*/
|
||||
bool VerifyLoginHash(const std::string &user, const std::string &loginserver, const std::string &cred, const std::string &hash);
|
||||
|
||||
/**
|
||||
* Does a successful login
|
||||
*/
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
#include <sodium.h>
|
||||
#endif
|
||||
|
||||
#include "encryption.h"
|
||||
|
||||
const char* eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char* buffer_out, bool enc) {
|
||||
DES_key_schedule k;
|
||||
DES_cblock v;
|
||||
@ -100,34 +102,34 @@ std::string eqcrypt_scrypt(const std::string &msg)
|
||||
std::string eqcrypt_hash(const std::string &username, const std::string &password, int mode) {
|
||||
switch (mode)
|
||||
{
|
||||
case 1:
|
||||
case EncryptionModeMD5:
|
||||
return eqcrypt_md5(password);
|
||||
case 2:
|
||||
case EncryptionModeMD5PassUser:
|
||||
return eqcrypt_md5(password + ":" + username);
|
||||
case 3:
|
||||
case EncryptionModeMD5UserPass:
|
||||
return eqcrypt_md5(username + ":" + password);
|
||||
case 4:
|
||||
case EncryptionModeMD5Triple:
|
||||
return eqcrypt_md5(eqcrypt_md5(username) + eqcrypt_md5(password));
|
||||
case 5:
|
||||
case EncryptionModeSHA:
|
||||
return eqcrypt_sha1(password);
|
||||
case 6:
|
||||
case EncryptionModeSHAPassUser:
|
||||
return eqcrypt_sha1(password + ":" + username);
|
||||
case 7:
|
||||
case EncryptionModeSHAUserPass:
|
||||
return eqcrypt_sha1(username + ":" + password);
|
||||
case 8:
|
||||
case EncryptionModeSHATriple:
|
||||
return eqcrypt_sha1(eqcrypt_sha1(username) + eqcrypt_sha1(password));
|
||||
case 9:
|
||||
case EncryptionModeSHA512:
|
||||
return eqcrypt_sha512(password);
|
||||
case 10:
|
||||
case EncryptionModeSHA512PassUser:
|
||||
return eqcrypt_sha512(password + ":" + username);
|
||||
case 11:
|
||||
case EncryptionModeSHA512UserPass:
|
||||
return eqcrypt_sha512(username + ":" + password);
|
||||
case 12:
|
||||
case EncryptionModeSHA512Triple:
|
||||
return eqcrypt_sha512(eqcrypt_sha512(username) + eqcrypt_sha512(password));
|
||||
#ifdef ENABLE_SECURITY
|
||||
case 13:
|
||||
case EncryptionModeArgon2:
|
||||
return eqcrypt_argon2(password);
|
||||
case 14:
|
||||
case EncryptionModeSCrypt:
|
||||
return eqcrypt_scrypt(password);
|
||||
#endif
|
||||
//todo bcrypt? pbkdf2?
|
||||
|
||||
@ -2,6 +2,24 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
enum EncryptionMode
|
||||
{
|
||||
EncryptionModeMD5 = 1,
|
||||
EncryptionModeMD5PassUser = 2,
|
||||
EncryptionModeMD5UserPass = 3,
|
||||
EncryptionModeMD5Triple = 4,
|
||||
EncryptionModeSHA = 5,
|
||||
EncryptionModeSHAPassUser = 6,
|
||||
EncryptionModeSHAUserPass = 7,
|
||||
EncryptionModeSHATriple = 8,
|
||||
EncryptionModeSHA512 = 9,
|
||||
EncryptionModeSHA512PassUser = 10,
|
||||
EncryptionModeSHA512UserPass = 11,
|
||||
EncryptionModeSHA512Triple = 12,
|
||||
EncryptionModeArgon2 = 13,
|
||||
EncryptionModeSCrypt = 14
|
||||
};
|
||||
|
||||
const char* eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char* buffer_out, bool enc);
|
||||
std::string eqcrypt_hash(const std::string &username, const std::string &password, int mode);
|
||||
bool eqcrypt_verify_hash(const std::string &username, const std::string &password, const std::string &pwhash, int mode);
|
||||
|
||||
@ -19,14 +19,7 @@ struct EQ::Net::ConsoleLoginStatus CheckLogin(const std::string& username, const
|
||||
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];
|
||||
}
|
||||
ParseAccountString(username, raw_user, prefix);
|
||||
|
||||
ret.account_id = database.CheckLogin(raw_user.c_str(), password.c_str(), prefix.c_str());
|
||||
|
||||
@ -399,14 +392,7 @@ void ConsoleSetPass(EQ::Net::ConsoleServerConnection* connection, const std::str
|
||||
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];
|
||||
}
|
||||
ParseAccountString(args[0], raw_user, prefix);
|
||||
|
||||
int16 tmpstatus = 0;
|
||||
uint32 tmpid = database.GetAccountIDByName(raw_user.c_str(), prefix.c_str(), &tmpstatus);
|
||||
|
||||
@ -213,24 +213,28 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(argv[1], "adduser") == 0) {
|
||||
//TODO: REIMPLEMENT
|
||||
//if (argc == 5) {
|
||||
// if (Seperator::IsNumber(argv[4])) {
|
||||
// if (atoi(argv[4]) >= 0 && atoi(argv[4]) <= 255) {
|
||||
// if (database.CreateAccount(argv[2], argv[3], atoi(argv[4])) == 0) {
|
||||
// std::cerr << "database.CreateAccount failed." << std::endl;
|
||||
// return 1;
|
||||
// }
|
||||
// else {
|
||||
// std::cout << "Account created: Username='" << argv[2] << "', Password='" << argv[3] << "', status=" << argv[4] << std::endl;
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//std::cout << "Usage: world adduser username password flag" << std::endl;
|
||||
//std::cout << "flag = 0, 1 or 2" << std::endl;
|
||||
//return 0;
|
||||
if (argc == 5) {
|
||||
if (Seperator::IsNumber(argv[4])) {
|
||||
if (atoi(argv[4]) >= 0 && atoi(argv[4]) <= 255) {
|
||||
std::string user;
|
||||
std::string loginserver;
|
||||
|
||||
ParseAccountString(argv[2], user, loginserver);
|
||||
|
||||
if (database.CreateAccount(argv[2], argv[3], atoi(argv[4]), loginserver.c_str(), 0) == 0) {
|
||||
std::cerr << "database.CreateAccount failed." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
std::cout << "Account created: Username='" << argv[2] << "', Password='" << argv[3] << "', status=" << argv[4] << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "Usage: world adduser username password flag" << std::endl;
|
||||
std::cout << "flag = 0, 1 or 2" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
else if (strcasecmp(argv[1], "flag") == 0) {
|
||||
if (argc == 4) {
|
||||
|
||||
128
zone/command.cpp
128
zone/command.cpp
@ -1957,33 +1957,40 @@ void command_shutdown(Client *c, const Seperator *sep)
|
||||
|
||||
void command_delacct(Client *c, const Seperator *sep)
|
||||
{
|
||||
//TODO: REIMPLEMENT
|
||||
// if(sep->arg[1][0] == 0)
|
||||
// c->Message(0, "Format: #delacct accountname");
|
||||
// else
|
||||
// if (database.DeleteAccount(sep->arg[1]))
|
||||
// c->Message(0, "The account was deleted.");
|
||||
// else
|
||||
// c->Message(0, "Unable to delete account.");
|
||||
if (sep->arg[1][0] == 0)
|
||||
c->Message(0, "Format: #delacct accountname");
|
||||
else {
|
||||
std::string user;
|
||||
std::string loginserver;
|
||||
ParseAccountString(sep->arg[1], user, loginserver);
|
||||
|
||||
if (database.DeleteAccount(user.c_str(), loginserver.c_str()))
|
||||
c->Message(0, "The account was deleted.");
|
||||
else
|
||||
c->Message(0, "Unable to delete account.");
|
||||
}
|
||||
}
|
||||
|
||||
void command_setpass(Client *c, const Seperator *sep)
|
||||
{
|
||||
//TODO: REIMPLEMENT
|
||||
//if(sep->argnum != 2)
|
||||
// c->Message(0, "Format: #setpass accountname password");
|
||||
//else {
|
||||
// int16 tmpstatus = 0;
|
||||
// uint32 tmpid = database.GetAccountIDByName(sep->arg[1], &tmpstatus);
|
||||
// if (!tmpid)
|
||||
// c->Message(0, "Error: Account not found");
|
||||
// else if (tmpstatus > c->Admin())
|
||||
// c->Message(0, "Cannot change password: Account's status is higher than yours");
|
||||
// else if (database.SetLocalPassword(tmpid, sep->arg[2]))
|
||||
// c->Message(0, "Password changed.");
|
||||
// else
|
||||
// c->Message(0, "Error changing password.");
|
||||
//}
|
||||
if(sep->argnum != 2)
|
||||
c->Message(0, "Format: #setpass accountname password");
|
||||
else {
|
||||
std::string user;
|
||||
std::string loginserver;
|
||||
ParseAccountString(sep->arg[1], user, loginserver);
|
||||
|
||||
int16 tmpstatus = 0;
|
||||
uint32 tmpid = database.GetAccountIDByName(user.c_str(), loginserver.c_str(), &tmpstatus);
|
||||
if (!tmpid)
|
||||
c->Message(0, "Error: Account not found");
|
||||
else if (tmpstatus > c->Admin())
|
||||
c->Message(0, "Cannot change password: Account's status is higher than yours");
|
||||
else if (database.SetLocalPassword(tmpid, sep->arg[2]))
|
||||
c->Message(0, "Password changed.");
|
||||
else
|
||||
c->Message(0, "Error changing password.");
|
||||
}
|
||||
}
|
||||
|
||||
void command_setlsinfo(Client *c, const Seperator *sep)
|
||||
@ -4416,42 +4423,45 @@ void command_uptime(Client *c, const Seperator *sep)
|
||||
|
||||
void command_flag(Client *c, const Seperator *sep)
|
||||
{
|
||||
//TODO: REIMPLEMENT
|
||||
// if(sep->arg[2][0] == 0) {
|
||||
// if (!c->GetTarget() || (c->GetTarget() && c->GetTarget() == c)) {
|
||||
// c->UpdateAdmin();
|
||||
// c->Message(0, "Refreshed your admin flag from DB.");
|
||||
// } else if (c->GetTarget() && c->GetTarget() != c && c->GetTarget()->IsClient()) {
|
||||
// c->GetTarget()->CastToClient()->UpdateAdmin();
|
||||
// c->Message(0, "%s's admin flag has been refreshed.", c->GetTarget()->GetName());
|
||||
// c->GetTarget()->Message(0, "%s refreshed your admin flag.", c->GetName());
|
||||
// }
|
||||
// }
|
||||
// else if (!sep->IsNumber(1) || atoi(sep->arg[1]) < -2 || atoi(sep->arg[1]) > 255 || strlen(sep->arg[2]) == 0)
|
||||
// c->Message(0, "Usage: #flag [status] [acctname]");
|
||||
//
|
||||
// else if (c->Admin() < commandChangeFlags) {
|
||||
////this check makes banning players by less than this level
|
||||
////impossible, but i'll leave it in anyways
|
||||
// c->Message(0, "You may only refresh your own flag, doing so now.");
|
||||
// c->UpdateAdmin();
|
||||
// }
|
||||
// else {
|
||||
// if (atoi(sep->arg[1]) > c->Admin())
|
||||
// c->Message(0, "You cannot set people's status to higher than your own");
|
||||
// else if (atoi(sep->arg[1]) < 0 && c->Admin() < commandBanPlayers)
|
||||
// c->Message(0, "You have too low of status to suspend/ban");
|
||||
// else if (!database.SetAccountStatus(sep->argplus[2], atoi(sep->arg[1])))
|
||||
// c->Message(0, "Unable to set GM Flag.");
|
||||
// else {
|
||||
// c->Message(0, "Set GM Flag on account.");
|
||||
// auto pack = new ServerPacket(ServerOP_FlagUpdate, 6);
|
||||
// *((uint32*) pack->pBuffer) = database.GetAccountIDByName(sep->argplus[2]);
|
||||
// *((int16*) &pack->pBuffer[4]) = atoi(sep->arg[1]);
|
||||
// worldserver.SendPacket(pack);
|
||||
// delete pack;
|
||||
// }
|
||||
// }
|
||||
if(sep->arg[2][0] == 0) {
|
||||
if (!c->GetTarget() || (c->GetTarget() && c->GetTarget() == c)) {
|
||||
c->UpdateAdmin();
|
||||
c->Message(0, "Refreshed your admin flag from DB.");
|
||||
} else if (c->GetTarget() && c->GetTarget() != c && c->GetTarget()->IsClient()) {
|
||||
c->GetTarget()->CastToClient()->UpdateAdmin();
|
||||
c->Message(0, "%s's admin flag has been refreshed.", c->GetTarget()->GetName());
|
||||
c->GetTarget()->Message(0, "%s refreshed your admin flag.", c->GetName());
|
||||
}
|
||||
}
|
||||
else if (!sep->IsNumber(1) || atoi(sep->arg[1]) < -2 || atoi(sep->arg[1]) > 255 || strlen(sep->arg[2]) == 0)
|
||||
c->Message(0, "Usage: #flag [status] [acctname]");
|
||||
|
||||
else if (c->Admin() < commandChangeFlags) {
|
||||
//this check makes banning players by less than this level
|
||||
//impossible, but i'll leave it in anyways
|
||||
c->Message(0, "You may only refresh your own flag, doing so now.");
|
||||
c->UpdateAdmin();
|
||||
}
|
||||
else {
|
||||
if (atoi(sep->arg[1]) > c->Admin())
|
||||
c->Message(0, "You cannot set people's status to higher than your own");
|
||||
else if (atoi(sep->arg[1]) < 0 && c->Admin() < commandBanPlayers)
|
||||
c->Message(0, "You have too low of status to suspend/ban");
|
||||
else if (!database.SetAccountStatus(sep->argplus[2], atoi(sep->arg[1])))
|
||||
c->Message(0, "Unable to set GM Flag.");
|
||||
else {
|
||||
c->Message(0, "Set GM Flag on account.");
|
||||
|
||||
std::string user;
|
||||
std::string loginserver;
|
||||
ParseAccountString(sep->argplus[2], user, loginserver);
|
||||
|
||||
ServerPacket pack(ServerOP_FlagUpdate, 6);
|
||||
*((uint32*) pack.pBuffer) = database.GetAccountIDByName(user.c_str(), loginserver.c_str());
|
||||
*((int16*) &pack.pBuffer[4]) = atoi(sep->arg[1]);
|
||||
worldserver.SendPacket(&pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void command_time(Client *c, const Seperator *sep)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user