diff --git a/loginserver/client.cpp b/loginserver/client.cpp index 66a62efe7..9a6a81593 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -175,83 +175,91 @@ void Client::Handle_SessionReady(const char* data, unsigned int size) void Client::Handle_Login(const char* data, unsigned int size) { - if(status != cs_waiting_for_login) - { + if(status != cs_waiting_for_login) { Log.Out(Logs::General, Logs::Error, "Login received after already having logged in."); return; } - if((size - 12) % 8 != 0) - { + if((size - 12) % 8 != 0) { Log.Out(Logs::General, Logs::Error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size); return; } status = cs_logged_in; - string e_user; - string e_hash; - char *e_buffer = nullptr; - unsigned int d_account_id = 0; - string d_pass_hash; + string entered_username; + string entered_password_hash_result; + + char *login_packet_buffer = nullptr; + + unsigned int db_account_id = 0; + string db_account_password_hash; #ifdef WIN32 - e_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode()); + login_packet_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode()); - int buffer_len = strlen(e_buffer); - e_hash.assign(e_buffer, buffer_len); - e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1)); + int login_packet_buffer_length = strlen(login_packet_buffer); + entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length); + entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1)); - if(server.options.IsTraceOn()) - { - Log.Out(Logs::General, Logs::Debug, "User: %s", e_user.c_str()); - Log.Out(Logs::General, Logs::Debug, "Hash: %s", e_hash.c_str()); + if(server.options.IsTraceOn()) { + Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str()); + Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str()); } - server.eq_crypto->DeleteHeap(e_buffer); + server.eq_crypto->DeleteHeap(login_packet_buffer); #else - e_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode()); + login_packet_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode()); - int buffer_len = strlen(e_buffer); - e_hash.assign(e_buffer, buffer_len); - e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1)); + int login_packet_buffer_length = strlen(login_packet_buffer); + entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length); + entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1)); - if(server.options.IsTraceOn()) - { - Log.Out(Logs::General, Logs::Debug, "User: %s", e_user.c_str()); - Log.Out(Logs::General, Logs::Debug, "Hash: %s", e_hash.c_str()); + if(server.options.IsTraceOn()) { + Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str()); + Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str()); } - _HeapDeleteCharBuffer(e_buffer); + _HeapDeleteCharBuffer(login_packet_buffer); #endif bool result; - if(server.db->GetLoginDataFromAccountName(e_user, d_pass_hash, d_account_id) == false) - { - Log.Out(Logs::General, Logs::Error, "Error logging in, user %s does not exist in the database.", e_user.c_str()); - result = false; - } - else - { - if(d_pass_hash.compare(e_hash) == 0) - { + if(server.db->GetLoginDataFromAccountName(entered_username, 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.config->GetVariable("options", "auto_create_accounts").compare("TRUE") == 0 && + server.db->CreateLoginData(entered_username, entered_password_hash_result, db_account_id) == true + ){ + Log.Out(Logs::General, Logs::Error, "User %s does not exist in the database, so we created it...", entered_username.c_str()); result = true; } - else - { + else{ + Log.Out(Logs::General, Logs::Error, "Error logging in, user %s does not exist in the database.", entered_username.c_str()); + result = false; + } + } + else { + if(db_account_password_hash.compare(entered_password_hash_result) == 0) { + result = true; + } + else { result = false; } } - if(result) - { - server.client_manager->RemoveExistingClient(d_account_id); + /* Login Accepted */ + if(result) { + + server.client_manager->RemoveExistingClient(db_account_id); + in_addr in; in.s_addr = connection->GetRemoteIP(); - server.db->UpdateLSAccountData(d_account_id, string(inet_ntoa(in))); + + server.db->UpdateLSAccountData(db_account_id, string(inet_ntoa(in))); GenerateKey(); - account_id = d_account_id; - account_name = e_user; + + account_id = db_account_id; + account_name = entered_username; EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80); const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data; @@ -267,7 +275,7 @@ void Client::Handle_Login(const char* data, unsigned int size) login_failed_attempts->failed_attempts = 0; login_failed_attempts->message = 0x01; - login_failed_attempts->lsid = d_account_id; + login_failed_attempts->lsid = db_account_id; login_failed_attempts->unknown3[3] = 0x03; login_failed_attempts->unknown4[3] = 0x02; login_failed_attempts->unknown5[0] = 0xe7; @@ -304,8 +312,7 @@ void Client::Handle_Login(const char* data, unsigned int size) connection->QueuePacket(outapp); delete outapp; } - else - { + else { EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, sizeof(LoginLoginFailed_Struct)); const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data; LoginLoginFailed_Struct* llas = (LoginLoginFailed_Struct *)outapp->pBuffer; diff --git a/loginserver/database.h b/loginserver/database.h index 7244f2e79..b7e9f9d24 100644 --- a/loginserver/database.h +++ b/loginserver/database.h @@ -44,6 +44,8 @@ public: */ virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id) { return false; } + virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id) { return false; } + /** * Retrieves the world registration from the long and short names provided. * Needed for world login procedure. diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index 9d1d8b57b..b9536de7e 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -96,6 +96,33 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u return false; } + +bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int &id) +{ + if (!database) { + return false; + } + + MYSQL_RES *result; + MYSQL_ROW row; + stringstream query(stringstream::in | stringstream::out); + + query << "INSERT INTO " << server.options.GetAccountTable() << " (AccountName, AccountPassword, AccountEmail, LastLoginDate, LastIPAddress) "; + query << " VALUES('" << name << "', '" << password << "', 'local_creation', NOW(), '127.0.0.1'); "; + + if (mysql_query(database, query.str().c_str()) != 0) { + Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str()); + return false; + } + else{ + id = mysql_insert_id(database); + return true; + } + + Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str()); + return false; +} + bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id, unsigned int &trusted, string &list_desc, string &account, string &password) { diff --git a/loginserver/database_mysql.h b/loginserver/database_mysql.h index 165d787c7..5cadff34a 100644 --- a/loginserver/database_mysql.h +++ b/loginserver/database_mysql.h @@ -59,6 +59,8 @@ public: */ virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id); + virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id); + /** * Retrieves the world registration from the long and short names provided. * Needed for world login procedure. diff --git a/loginserver/login_structures.h b/loginserver/login_structures.h index f9d3cc054..6e3f290e9 100644 --- a/loginserver/login_structures.h +++ b/loginserver/login_structures.h @@ -47,7 +47,7 @@ struct LoginAccepted_Struct { char encrypt[80]; }; -struct LoginFailedReply_Struct +struct LoginFailedAttempts_Struct { char message; //0x01 char unknown2[7]; //0x00