Author: ai0867
Date: Sat Nov  5 22:16:19 2011
New Revision: 51870

URL: http://svn.gna.org/viewcvs/wesnoth?rev=51870&view=rev
Log:
Ban IPs that cause too many failed login attempts. Fixes bug #17535

Modified:
    trunk/src/multiplayer_error_codes.hpp
    trunk/src/server/server.cpp
    trunk/src/server/server.hpp

Modified: trunk/src/multiplayer_error_codes.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/multiplayer_error_codes.hpp?rev=51870&r1=51869&r2=51870&view=diff
==============================================================================
--- trunk/src/multiplayer_error_codes.hpp (original)
+++ trunk/src/multiplayer_error_codes.hpp Sat Nov  5 22:16:19 2011
@@ -33,6 +33,7 @@
 #define MP_PASSWORD_REQUEST_FOR_LOGGED_IN_NAME         "201"
 #define MP_NO_SEED_ERROR                               "202"
 #define MP_INCORRECT_PASSWORD_ERROR                    "203"
+#define MP_TOO_MANY_ATTEMPTS_ERROR                     "204"
 
 #endif // MULTIPLAYER_ERROR_CODES_HPP_INCLUDES
 

Modified: trunk/src/server/server.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/server/server.cpp?rev=51870&r1=51869&r2=51870&view=diff
==============================================================================
--- trunk/src/server/server.cpp (original)
+++ trunk/src/server/server.cpp Sat Nov  5 22:16:19 2011
@@ -324,6 +324,7 @@
        server_(port),
        ban_manager_(),
        ip_log_(),
+       failed_logins_(),
        user_handler_(NULL),
        seeds_(),
        players_(),
@@ -1115,10 +1116,45 @@
                        }
                        // This name is registered and an incorrect password 
provided
                        else if(!(user_handler_->login(username, password, 
seeds_[sock]))) {
+                               // Log the failure
+                               const std::deque<login_log>::size_type max_size 
= 500;
+
+                               const int max_failed_attempts = 10;
+                               const time_t ban_time = 3600;
+                               const time_t now = time(NULL);
+
+                               login_log login_ip = 
login_log(network::ip_address(sock), now, 0);
+                               std::deque<login_log>::iterator i = 
std::find(failed_logins_.begin(), failed_logins_.end(), login_ip);
+                               if(i == failed_logins_.end()) {
+                                       failed_logins_.push_back(login_ip);
+                                       i = --failed_logins_.end();
+
+                                       // Remove oldest entry if maximum size 
is exceeded
+                                       if(failed_logins_.size() > max_size)
+                                               failed_logins_.pop_front();
+
+                               }
+
+                               // Clear and move to the beginning
+                               if (i->first_attempt + ban_time < now) {
+                                       failed_logins_.erase(i);
+                                       failed_logins_.push_back(login_ip);
+                                       i = --failed_logins_.end();
+                               }
+
+                               i->attempts++;
+
+                               if (i->attempts > max_failed_attempts) {
+                                       LOG_SERVER << 
ban_manager_.ban(login_ip.ip, now + ban_time, "Maximum login attempts 
exceeded", "automatic", "", username);
+                                       send_error(sock, "You have made too 
many failed login attempts.", MP_TOO_MANY_ATTEMPTS_ERROR);
+                                       network::queue_disconnect(sock);
+                               } else {
+                                       send_password_request(sock, "The 
password you provided for the nick '" + username +
+                                               "' was incorrect.", username, 
MP_INCORRECT_PASSWORD_ERROR);
+                               }
+
                                // Reset the random seed
                                seeds_.erase(sock);
-                               send_password_request(sock, "The password you 
provided for the nickname '" + username +
-                                               "' was incorrect.", username, 
MP_INCORRECT_PASSWORD_ERROR);
 
                                LOG_SERVER << network::ip_address(sock) << "\t"
                                                << "Login attempt with 
incorrect password for nickname '" << username << "'.\n";

Modified: trunk/src/server/server.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/server/server.hpp?rev=51870&r1=51869&r2=51870&view=diff
==============================================================================
--- trunk/src/server/server.hpp (original)
+++ trunk/src/server/server.hpp Sat Nov  5 22:16:19 2011
@@ -56,6 +56,22 @@
        };
 
        std::deque<connection_log> ip_log_;
+
+       struct login_log {
+               login_log(std::string _ip, int _attempts, time_t 
_first_attempt) :
+               ip(_ip), attempts(_attempts), first_attempt(_first_attempt) {}
+               std::string ip;
+               int attempts;
+               time_t first_attempt;
+
+               bool operator==(const login_log& l) const
+               {
+                       // only the IP matters
+                       return l.ip == ip;
+               }
+       };
+
+       std::deque<login_log> failed_logins_;
 
        boost::scoped_ptr<user_handler> user_handler_;
        std::map<network::connection,std::string> seeds_;


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to