Add ability to ban by client id

This commit is contained in:
woogerboy21 2015-08-12 21:55:40 -04:00
parent 26e63a9a3a
commit b102a05a36
17 changed files with 114 additions and 24 deletions

View file

@ -229,7 +229,7 @@ QChar Servatrice_DatabaseInterface::getGenderChar(ServerInfo_User_Gender const &
}
}
AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &banSecondsLeft)
AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, const QString &clientId, QString &reasonStr, int &banSecondsLeft)
{
switch (server->getAuthenticationMethod()) {
case Servatrice::AuthenticationNone: return UnknownUser;
@ -247,7 +247,7 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
if (!usernameIsValid(user, reasonStr))
return UsernameInvalid;
if (checkUserIsBanned(handler->getAddress(), user, reasonStr, banSecondsLeft))
if (checkUserIsBanned(handler->getAddress(), user, clientId, reasonStr, banSecondsLeft))
return UserIsBanned;
QSqlQuery *passwordQuery = prepareQuery("select password_sha512, active from {prefix}_users where name = :name");
@ -280,7 +280,7 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
return UnknownUser;
}
bool Servatrice_DatabaseInterface::checkUserIsBanned(const QString &ipAddress, const QString &userName, QString &banReason, int &banSecondsRemaining)
bool Servatrice_DatabaseInterface::checkUserIsBanned(const QString &ipAddress, const QString &userName, const QString &clientId, QString &banReason, int &banSecondsRemaining)
{
if (server->getAuthenticationMethod() != Servatrice::AuthenticationSql)
return false;
@ -291,11 +291,48 @@ bool Servatrice_DatabaseInterface::checkUserIsBanned(const QString &ipAddress, c
}
return
checkUserIsIpBanned(ipAddress, banReason, banSecondsRemaining)
|| checkUserIsNameBanned(userName, banReason, banSecondsRemaining);
checkUserIsIpBanned(ipAddress, banReason, banSecondsRemaining) || checkUserIsNameBanned(userName, banReason, banSecondsRemaining) || checkUserIsIdBanned(clientId, banReason, banSecondsRemaining);
}
bool Servatrice_DatabaseInterface::checkUserIsIdBanned(const QString &clientId, QString &banReason, int &banSecondsRemaining)
{
if (clientId.isEmpty())
return false;
QSqlQuery *idBanQuery = prepareQuery(
"select"
" timestampdiff(second, now(), date_add(b.time_from, interval b.minutes minute)),"
" b.minutes <=> 0,"
" b.visible_reason"
" from {prefix}_bans b"
" where"
" b.time_from = (select max(c.time_from)"
" from {prefix}_bans c"
" where c.clientid = :id)"
" and b.clientid = :id2");
idBanQuery->bindValue(":id", clientId);
idBanQuery->bindValue(":id2", clientId);
if (!execSqlQuery(idBanQuery)) {
qDebug() << "Id ban check failed: SQL error." << idBanQuery->lastError();
return false;
}
if (idBanQuery->next()) {
const int secondsLeft = idBanQuery->value(0).toInt();
const bool permanentBan = idBanQuery->value(1).toInt();
if ((secondsLeft > 0) || permanentBan) {
banReason = idBanQuery->value(2).toString();
banSecondsRemaining = permanentBan ? 0 : secondsLeft;
qDebug() << "User is banned by client id" << clientId;
return true;
}
}
return false;
}
bool Servatrice_DatabaseInterface::checkUserIsNameBanned(const QString &userName, QString &banReason, int &banSecondsRemaining)
{
QSqlQuery *nameBanQuery = prepareQuery("select timestampdiff(second, now(), date_add(b.time_from, interval b.minutes minute)), b.minutes <=> 0, b.visible_reason from {prefix}_bans b where b.time_from = (select max(c.time_from) from {prefix}_bans c where c.user_name = :name2) and b.user_name = :name1");
@ -477,6 +514,10 @@ ServerInfo_User Servatrice_DatabaseInterface::evalUserQueryResult(const QSqlQuer
const QString email = query->value(8).toString();
if (!email.isEmpty())
result.set_email(email.toStdString());
const QString clientid = query->value(9).toString();
if (!clientid.isEmpty())
result.set_clientid(clientid.toStdString());
}
return result;
}
@ -491,7 +532,7 @@ ServerInfo_User Servatrice_DatabaseInterface::getUserData(const QString &name, b
if (!checkSql())
return result;
QSqlQuery *query = prepareQuery("select id, name, admin, country, gender, realname, avatar_bmp, registrationDate, email from {prefix}_users where name = :name and active = 1");
QSqlQuery *query = prepareQuery("select id, name, admin, country, gender, realname, avatar_bmp, registrationDate, email, clientid from {prefix}_users where name = :name and active = 1");
query->bindValue(":name", name);
if (!execSqlQuery(query))
return result;

View file

@ -9,7 +9,7 @@
#include "server.h"
#include "server_database_interface.h"
#define DATABASE_SCHEMA_VERSION 4
#define DATABASE_SCHEMA_VERSION 5
class Servatrice;
@ -22,13 +22,14 @@ private:
Servatrice *server;
ServerInfo_User evalUserQueryResult(const QSqlQuery *query, bool complete, bool withId = false);
/** Must be called after checkSql and server is known to be in auth mode. */
bool checkUserIsIdBanned(const QString &clientId, QString &banReason, int &banSecondsRemaining);
/** Must be called after checkSql and server is known to be in auth mode. */
bool checkUserIsIpBanned(const QString &ipAddress, QString &banReason, int &banSecondsRemaining);
/** Must be called after checkSql and server is known to be in auth mode. */
bool checkUserIsNameBanned(QString const &userName, QString &banReason, int &banSecondsRemaining);
protected:
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user,
const QString &password, QString &reasonStr, int &secondsLeft);
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, const QString &clientId, QString &reasonStr, int &secondsLeft);
public slots:
void initDatabase(const QSqlDatabase &_sqlDatabase);
@ -66,7 +67,7 @@ public:
void unlockSessionTables();
bool userSessionExists(const QString &userName);
bool usernameIsValid(const QString &user, QString & error);
bool checkUserIsBanned(const QString &ipAddress, const QString &userName, QString &banReason, int &banSecondsRemaining);
bool checkUserIsBanned(const QString &ipAddress, const QString &userName, const QString &clientId, QString &banReason, int &banSecondsRemaining);
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);

View file

@ -756,20 +756,40 @@ Response::ResponseCode ServerSocketInterface::cmdBanFromServer(const Command_Ban
if (trustedSources.contains(address,Qt::CaseInsensitive))
address = "";
QSqlQuery *query = sqlInterface->prepareQuery("insert into {prefix}_bans (user_name, ip_address, id_admin, time_from, minutes, reason, visible_reason) values(:user_name, :ip_address, :id_admin, NOW(), :minutes, :reason, :visible_reason)");
QSqlQuery *query = sqlInterface->prepareQuery("insert into {prefix}_bans (user_name, ip_address, id_admin, time_from, minutes, reason, visible_reason, clientid) values(:user_name, :ip_address, :id_admin, NOW(), :minutes, :reason, :visible_reason, :client_id)");
query->bindValue(":user_name", userName);
query->bindValue(":ip_address", address);
query->bindValue(":id_admin", userInfo->id());
query->bindValue(":minutes", minutes);
query->bindValue(":reason", QString::fromStdString(cmd.reason()));
query->bindValue(":visible_reason", QString::fromStdString(cmd.visible_reason()));
query->bindValue(":client_id", QString::fromStdString(cmd.clientid()));
sqlInterface->execSqlQuery(query);
servatrice->clientsLock.lockForRead();
QList<ServerSocketInterface *> userList = servatrice->getUsersWithAddressAsList(QHostAddress(address));
ServerSocketInterface *user = static_cast<ServerSocketInterface *>(server->getUsers().value(userName));
if (user && !userList.contains(user))
if (!userName.isEmpty()) {
ServerSocketInterface *user = static_cast<ServerSocketInterface *>(server->getUsers().value(userName));
userList.append(user);
}
if (userName.isEmpty() && address.isEmpty()) {
QSqlQuery *query = sqlInterface->prepareQuery("select name from {prefix}_users where clientid = :client_id");
query->bindValue(":client_id", QString::fromStdString(cmd.clientid()));
sqlInterface->execSqlQuery(query);
if (!sqlInterface->execSqlQuery(query)){
qDebug("ClientID username ban lookup failed: SQL Error");
} else {
while (query->next()) {
userName = query->value(0).toString();
ServerSocketInterface *user = static_cast<ServerSocketInterface *>(server->getUsers().value(userName));
if (user && !userList.contains(user))
userList.append(user);
}
}
}
if (!userList.isEmpty()) {
Event_ConnectionClosed event;
event.set_reason(Event_ConnectionClosed::BANNED);
@ -792,6 +812,7 @@ Response::ResponseCode ServerSocketInterface::cmdBanFromServer(const Command_Ban
Response::ResponseCode ServerSocketInterface::cmdRegisterAccount(const Command_Register &cmd, ResponseContainer &rc)
{
QString userName = QString::fromStdString(cmd.user_name());
QString clientId = QString::fromStdString(cmd.clientid());
qDebug() << "Got register command: " << userName;
bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool();
@ -822,7 +843,7 @@ Response::ResponseCode ServerSocketInterface::cmdRegisterAccount(const Command_R
QString banReason;
int banSecondsRemaining;
if (sqlInterface->checkUserIsBanned(this->getAddress(), userName, banReason, banSecondsRemaining))
if (sqlInterface->checkUserIsBanned(this->getAddress(), userName, clientId, banReason, banSecondsRemaining))
{
Response_Register *re = new Response_Register;
re->set_denied_reason_str(banReason.toStdString());