From a85b0dcbba7c0b91cf66d16c6700f750f888b302 Mon Sep 17 00:00:00 2001 From: woogerboy21 Date: Sat, 7 Jan 2017 11:26:23 -0500 Subject: [PATCH] Add email registration restriction (#2350) * Add ability to limit number of account registrations with same email address This commit adds server side functionality that will allow operators to limit the number of accounts that can be registered to the server with the same email address. * Updated ini wording Updated configuration file wording for better description. --- cockatrice/src/window_main.cpp | 2 +- common/server_database_interface.h | 1 + servatrice/servatrice.ini.example | 4 ++++ servatrice/src/servatrice.cpp | 5 +++++ servatrice/src/servatrice.h | 1 + .../src/servatrice_database_interface.cpp | 19 +++++++++++++++++++ .../src/servatrice_database_interface.h | 2 +- servatrice/src/serversocketinterface.cpp | 5 +++++ 8 files changed, 37 insertions(+), 2 deletions(-) diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 6fad7a0d..f5fd8308 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -444,7 +444,7 @@ void MainWindow::registerError(Response::ResponseCode r, QString reasonStr, quin QMessageBox::critical(this, tr("Registration denied"), tr("It's mandatory to specify a valid email address when registering.")); break; case Response::RespTooManyRequests: - QMessageBox::critical(this, tr("Registration denied"), tr("Too many registration attempts from your IP address.")); + QMessageBox::critical(this, tr("Registration denied"), tr("Too many registration attempts, please try again later or contact the server operator for further details.")); break; case Response::RespPasswordTooShort: QMessageBox::critical(this, tr("Registration denied"), tr("Password too short.")); diff --git a/common/server_database_interface.h b/common/server_database_interface.h index 960a454a..836c843e 100644 --- a/common/server_database_interface.h +++ b/common/server_database_interface.h @@ -45,6 +45,7 @@ public: enum LogMessage_TargetType { MessageTargetRoom, MessageTargetGame, MessageTargetChat, MessageTargetIslRoom }; virtual void logMessage(const int /* senderId */, const QString & /* senderName */, const QString & /* senderIp */, const QString & /* logMessage */, LogMessage_TargetType /* targetType */, const int /* targetId */, const QString & /* targetName */) { }; bool checkUserIsBanned(Server_ProtocolHandler *session, QString &banReason, int &banSecondsRemaining); + virtual int checkNumberOfUserAccounts(const QString & /* email */) { return 0; }; virtual bool changeUserPassword(const QString & /* user */, const QString & /* oldPassword */, const QString & /* newPassword */) { return true; }; virtual QChar getGenderChar(ServerInfo_User_Gender const & /* gender */) { return QChar('u'); }; }; diff --git a/servatrice/servatrice.ini.example b/servatrice/servatrice.ini.example index 0029775a..75bb33a4 100644 --- a/servatrice/servatrice.ini.example +++ b/servatrice/servatrice.ini.example @@ -140,6 +140,10 @@ disallowedregexp="" ; account activated. Default true. ;requireemailactivation=true +; Set this number to the maximum number of accounts any one user can use to create new accounts +; using the same email address. 0 = Unlimited number of accounts (default). +;maxaccountsperemail=0 + [smtp] ; Enable the internal smtp client to send registration emails. If you would like to diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 936132ef..e3c77086 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -242,6 +242,7 @@ bool Servatrice::initServer() if (getRegistrationEnabled()) { qDebug() << "Require email address to register: " << getRequireEmailForRegistrationEnabled(); qDebug() << "Require email activation via token: " << getRequireEmailActivationEnabled(); + if (getMaxAccountsPerEmail()) { qDebug() << "Maximum number of accounts per email: " << getMaxAccountsPerEmail(); } else { qDebug() << "Maximum number of accounts per email: unlimited"; } qDebug() << "Enable Internal SMTP Client: " << getEnableInternalSMTPClient(); if (!getEnableInternalSMTPClient()) { @@ -836,6 +837,10 @@ bool Servatrice::getEnableLogQuery() const { return settingsCache->value("logging/enablelogquery", false).toBool(); } +int Servatrice::getMaxAccountsPerEmail() const { + return settingsCache->value("registration/maxaccountsperemail", 0).toInt(); +} + bool Servatrice::getEnableInternalSMTPClient() const { return settingsCache->value("smtp/enableinternalsmtpclient", true).toBool(); } \ No newline at end of file diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 93207326..4eb2e17e 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -207,6 +207,7 @@ public: int getMaxTcpUserLimit() const; int getMaxWebSocketUserLimit() const; int getUsersWithAddress(const QHostAddress &address) const; + int getMaxAccountsPerEmail() const; QList getUsersWithAddressAsList(const QHostAddress &address) const; void incTxBytes(quint64 num); void incRxBytes(quint64 num); diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index 8065e9a7..cb8d834c 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/src/servatrice_database_interface.cpp @@ -1109,3 +1109,22 @@ QList Servatrice_DatabaseInterface::getMessageLogHistory return results; } + +int Servatrice_DatabaseInterface::checkNumberOfUserAccounts(const QString &email) +{ + if (!checkSql()) + return 0; + + QSqlQuery *query = prepareQuery("SELECT count(email) FROM {prefix}_users WHERE email = :user_email"); + query->bindValue(":user_email", email); + + if (!execSqlQuery(query)) { + qDebug("Failed to identify the number of users accounts for users email address: SQL Error"); + return 0; + } + + if (query->next()) + return query->value(0).toInt(); + + return 0; +} diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index 8d921b46..e770738a 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -69,7 +69,7 @@ public: bool userSessionExists(const QString &userName); bool usernameIsValid(const QString &user, QString & error); bool checkUserIsBanned(const QString &ipAddress, const QString &userName, const QString &clientId, QString &banReason, int &banSecondsRemaining); - + int checkNumberOfUserAccounts(const QString &email); bool registerUser(const QString &userName, const QString &realName, ServerInfo_User_Gender const &gender, const QString &password, const QString &emailAddress, const QString &country, QString &token, bool active = false); bool activateUser(const QString &userName, const QString &token); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index d749108a..dcfecd94 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -906,6 +906,11 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C if(sqlInterface->userExists(userName)) return Response::RespUserAlreadyExists; + if (servatrice->getMaxAccountsPerEmail() && !(sqlInterface->checkNumberOfUserAccounts(emailAddress) < servatrice->getMaxAccountsPerEmail())) + { + return Response::RespTooManyRequests; + } + QString banReason; int banSecondsRemaining; if (sqlInterface->checkUserIsBanned(this->getAddress(), userName, clientId, banReason, banSecondsRemaining))