diff --git a/src/multiplayer_error_codes.hpp b/src/multiplayer_error_codes.hpp index 44e2d5ac716b..1aa41643ab58 100644 --- a/src/multiplayer_error_codes.hpp +++ b/src/multiplayer_error_codes.hpp @@ -26,7 +26,9 @@ #define MP_NAME_RESERVED_ERROR "104" #define MP_NAME_UNREGISTERED_ERROR "105" #define MP_NAME_INACTIVE_WARNING "106" -#define MP_NAME_AUTH_BAN_ERROR "107" +#define MP_NAME_AUTH_BAN_USER_ERROR "107" +#define MP_NAME_AUTH_BAN_IP_ERROR "108" +#define MP_NAME_AUTH_BAN_EMAIL_ERROR "109" #define MP_PASSWORD_REQUEST "200" #define MP_PASSWORD_REQUEST_FOR_LOGGED_IN_NAME "201" diff --git a/src/server/forum_user_handler.cpp b/src/server/forum_user_handler.cpp index 02c07223d43f..446138b25786 100644 --- a/src/server/forum_user_handler.cpp +++ b/src/server/forum_user_handler.cpp @@ -172,7 +172,7 @@ void fuh::set_is_moderator(const std::string& name, const bool& is_moderator) { } } -bool fuh::user_is_banned(const std::string& name, const std::string& addr) +fuh::BAN_TYPE fuh::user_is_banned(const std::string& name, const std::string& addr) { if(!user_exists(name)) { throw error("No user with the name '" + name + "' exists."); @@ -185,26 +185,26 @@ bool fuh::user_is_banned(const std::string& name, const std::string& addr) ERR_UH << "Invalid user id for user '" << name << "'\n"; } else if(prepared_statement("SELECT 1 FROM `" + db_banlist_table_ + "` WHERE ban_userid = ? AND ban_exclude = 0", uid)) { LOG_UH << "User '" << name << "' uid " << uid << " banned by uid\n"; - return true; + return BAN_USER; } if(!addr.empty() && prepared_statement("SELECT 1 FROM `" + db_banlist_table_ + "` WHERE UPPER(ban_ip) = UPPER(?) AND ban_exclude = 0", addr)) { LOG_UH << "User '" << name << "' ip " << addr << " banned by IP address\n"; - return true; + return BAN_IP; } auto email = get_detail_for_user(name, "user_email"); if(!email.empty() && prepared_statement("SELECT 1 FROM `" + db_banlist_table_ + "` WHERE UPPER(ban_email) = UPPER(?) AND ban_exclude = 0", email)) { LOG_UH << "User '" << name << "' email " << email << " banned by email address\n"; - return true; + return BAN_EMAIL; } } catch(sql_error& e) { ERR_UH << "Could not check forum bans on user '" << name << "' :" << e.message << '\n'; } - return false; + return BAN_NONE; } std::string fuh::user_info(const std::string& name) { diff --git a/src/server/forum_user_handler.hpp b/src/server/forum_user_handler.hpp index 16643f9e2d46..5e23e5ef7fc2 100644 --- a/src/server/forum_user_handler.hpp +++ b/src/server/forum_user_handler.hpp @@ -69,7 +69,7 @@ class fuh : public user_handler { bool user_is_moderator(const std::string& name); void set_is_moderator(const std::string& name, const bool& is_moderator); - bool user_is_banned(const std::string& name, const std::string& addr); + BAN_TYPE user_is_banned(const std::string& name, const std::string& addr); // Throws user_handler::error std::string user_info(const std::string& name); diff --git a/src/server/sample_user_handler.cpp b/src/server/sample_user_handler.cpp index f4dcdd16994a..4b14ccb70931 100644 --- a/src/server/sample_user_handler.cpp +++ b/src/server/sample_user_handler.cpp @@ -95,9 +95,9 @@ void suh::set_is_moderator(const std::string& name, const bool& is_moderator) { users_[name].is_moderator = is_moderator; } -bool suh::user_is_banned(const std::string&, const std::string&) { +suh::BAN_TYPE suh::user_is_banned(const std::string&, const std::string&) { // FIXME: stub - return false; + return BAN_NONE; } void suh::set_mail(const std::string& user, const std::string& mail) { diff --git a/src/server/sample_user_handler.hpp b/src/server/sample_user_handler.hpp index 033bae2c58ee..744e23a7f781 100644 --- a/src/server/sample_user_handler.hpp +++ b/src/server/sample_user_handler.hpp @@ -43,7 +43,7 @@ class suh : public user_handler { bool user_is_moderator(const std::string& name); void set_is_moderator(const std::string& name, const bool& is_moderator); - bool user_is_banned(const std::string& name, const std::string&); + BAN_TYPE user_is_banned(const std::string& name, const std::string&); std::string user_info(const std::string& name); diff --git a/src/server/server.cpp b/src/server/server.cpp index b92ef1fbeddd..79e5d9e71d5e 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -650,17 +650,46 @@ bool server::is_login_allowed(socket_ptr socket, const simple_wml::node* const l } const bool is_moderator = user_handler_ && user_handler_->user_is_moderator(username); - const bool is_auth_banned = user_handler_ && user_handler_->user_is_banned(username, client_address(socket)); + const user_handler::BAN_TYPE auth_ban = user_handler_ + ? user_handler_->user_is_banned(username, client_address(socket)) + : user_handler::BAN_NONE; + + if(auth_ban) { + std::string ban_type_desc; + std::string ban_reason; + const char* msg_numeric; + + switch(auth_ban) { + case user_handler::BAN_USER: + ban_type_desc = "account"; + msg_numeric = MP_NAME_AUTH_BAN_USER_ERROR; + ban_reason = "a ban has been issued on your user account."; + break; + case user_handler::BAN_IP: + ban_type_desc = "IP address"; + msg_numeric = MP_NAME_AUTH_BAN_IP_ERROR; + ban_reason = "a ban has been issued on your IP address."; + break; + case user_handler::BAN_EMAIL: + ban_type_desc = "email address"; + msg_numeric = MP_NAME_AUTH_BAN_EMAIL_ERROR; + ban_reason = "a ban has been issued on your email address."; + break; + default: + ban_type_desc = ""; + msg_numeric = ""; + ban_reason = ban_type_desc; + } - if(is_auth_banned) { if(!is_moderator) { LOG_SERVER << client_address(socket) << "\t" << username - << "\tis banned by user_handler\n"; - async_send_error(socket, "The nickname '" + username + "' is banned on this server.", MP_NAME_AUTH_BAN_ERROR); + << "\tis banned by user_handler (" << ban_type_desc << ")\n"; + async_send_error(socket, "You are banned from this server: " + ban_reason, msg_numeric); return false; } else { LOG_SERVER << client_address(socket) << "\t" << username - << "\tis banned by user_handler, ignoring due to moderator flag\n"; + << "\tis banned by user_handler (" << ban_type_desc << "), " + << "ignoring due to moderator flag\n"; } } @@ -694,7 +723,7 @@ bool server::is_login_allowed(socket_ptr socket, const simple_wml::node* const l "If you no longer want to be automatically authenticated use '/query signout'."); } - if(is_auth_banned) { + if(auth_ban) { send_server_message(socket, "You are currently banned by the forum administration."); } diff --git a/src/server/user_handler.hpp b/src/server/user_handler.hpp index c19ab131e4f5..dfa77f54fc7f 100644 --- a/src/server/user_handler.hpp +++ b/src/server/user_handler.hpp @@ -108,6 +108,14 @@ class user_handler { /** Mark this user as a moderator */ virtual void set_is_moderator(const std::string& name, const bool& is_moderator) =0; + enum BAN_TYPE + { + BAN_NONE, + BAN_USER, + BAN_IP, + BAN_EMAIL, + }; + /** * Returns true if this user account or IP address is banned. * @@ -115,7 +123,7 @@ class user_handler { * subclass. Regular IP ban checks are done by @a server_base * instead. */ - virtual bool user_is_banned(const std::string& name, const std::string& addr="") = 0; + virtual BAN_TYPE user_is_banned(const std::string& name, const std::string& addr="") = 0; struct error : public game::error { error(const std::string& message) : game::error(message) {}