Reject more invalid usernames from clients.
Specifically this should cover people connecting with a username of "\u200C"
This commit is contained in:
parent
ba5669652c
commit
af09d0d294
8 changed files with 33 additions and 7 deletions
|
@ -76,6 +76,7 @@ void MainWindow::processConnectionClosedEvent(const Event_ConnectionClosed &even
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Event_ConnectionClosed::SERVER_SHUTDOWN: reasonStr = tr("Scheduled server shutdown."); break;
|
case Event_ConnectionClosed::SERVER_SHUTDOWN: reasonStr = tr("Scheduled server shutdown."); break;
|
||||||
|
case Event_ConnectionClosed::USERNAMEINVALID: reasonStr = tr("Invalid username."); break;
|
||||||
default: reasonStr = QString::fromStdString(event.reason_str());
|
default: reasonStr = QString::fromStdString(event.reason_str());
|
||||||
}
|
}
|
||||||
QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr));
|
QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr));
|
||||||
|
@ -257,6 +258,9 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32
|
||||||
QMessageBox::critical(this, tr("Error"), bannedStr);
|
QMessageBox::critical(this, tr("Error"), bannedStr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Response::RespUserIsBanned:
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Invalid username."));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
QMessageBox::critical(this, tr("Error"), tr("Unknown login error: %1").arg(static_cast<int>(r)));
|
QMessageBox::critical(this, tr("Error"), tr("Unknown login error: %1").arg(static_cast<int>(r)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ message Event_ConnectionClosed {
|
||||||
SERVER_SHUTDOWN = 2;
|
SERVER_SHUTDOWN = 2;
|
||||||
TOO_MANY_CONNECTIONS = 3;
|
TOO_MANY_CONNECTIONS = 3;
|
||||||
BANNED = 4;
|
BANNED = 4;
|
||||||
|
USERNAMEINVALID = 5;
|
||||||
}
|
}
|
||||||
optional CloseReason reason = 1;
|
optional CloseReason reason = 1;
|
||||||
optional string reason_str = 2;
|
optional string reason_str = 2;
|
||||||
|
|
|
@ -22,6 +22,7 @@ message Response {
|
||||||
RespChatFlood = 18;
|
RespChatFlood = 18;
|
||||||
RespUserIsBanned = 19;
|
RespUserIsBanned = 19;
|
||||||
RespAccessDenied = 20;
|
RespAccessDenied = 20;
|
||||||
|
RespUsernameInvalid = 21;
|
||||||
}
|
}
|
||||||
enum ResponseType {
|
enum ResponseType {
|
||||||
JOIN_ROOM = 1000;
|
JOIN_ROOM = 1000;
|
||||||
|
|
|
@ -114,7 +114,7 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
|
||||||
QWriteLocker locker(&clientsLock);
|
QWriteLocker locker(&clientsLock);
|
||||||
|
|
||||||
AuthenticationResult authState = databaseInterface->checkUserPassword(session, name, password, reasonStr, secondsLeft);
|
AuthenticationResult authState = databaseInterface->checkUserPassword(session, name, password, reasonStr, secondsLeft);
|
||||||
if ((authState == NotLoggedIn) || (authState == UserIsBanned))
|
if ((authState == NotLoggedIn) || (authState == UserIsBanned || authState == UsernameInvalid))
|
||||||
return authState;
|
return authState;
|
||||||
|
|
||||||
ServerInfo_User data = databaseInterface->getUserData(name, true);
|
ServerInfo_User data = databaseInterface->getUserData(name, true);
|
||||||
|
|
|
@ -27,7 +27,7 @@ class GameEventContainer;
|
||||||
class CommandContainer;
|
class CommandContainer;
|
||||||
class Command_JoinGame;
|
class Command_JoinGame;
|
||||||
|
|
||||||
enum AuthenticationResult { NotLoggedIn = 0, PasswordRight = 1, UnknownUser = 2, WouldOverwriteOldSession = 3, UserIsBanned = 4 };
|
enum AuthenticationResult { NotLoggedIn = 0, PasswordRight = 1, UnknownUser = 2, WouldOverwriteOldSession = 3, UserIsBanned = 4, UsernameInvalid = 5 };
|
||||||
|
|
||||||
class Server : public QObject
|
class Server : public QObject
|
||||||
{
|
{
|
||||||
|
|
|
@ -200,11 +200,11 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
|
||||||
if (!game) {
|
if (!game) {
|
||||||
if (room->getExternalGames().contains(cont.game_id())) {
|
if (room->getExternalGames().contains(cont.game_id())) {
|
||||||
server->sendIsl_GameCommand(cont,
|
server->sendIsl_GameCommand(cont,
|
||||||
room->getExternalGames().value(cont.game_id()).server_id(),
|
room->getExternalGames().value(cont.game_id()).server_id(),
|
||||||
userInfo->session_id(),
|
userInfo->session_id(),
|
||||||
roomIdAndPlayerId.first,
|
roomIdAndPlayerId.first,
|
||||||
roomIdAndPlayerId.second
|
roomIdAndPlayerId.second
|
||||||
);
|
);
|
||||||
return Response::RespNothing;
|
return Response::RespNothing;
|
||||||
}
|
}
|
||||||
return Response::RespNotInRoom;
|
return Response::RespNotInRoom;
|
||||||
|
@ -338,6 +338,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
|
||||||
}
|
}
|
||||||
case NotLoggedIn: return Response::RespWrongPassword;
|
case NotLoggedIn: return Response::RespWrongPassword;
|
||||||
case WouldOverwriteOldSession: return Response::RespWouldOverwriteOldSession;
|
case WouldOverwriteOldSession: return Response::RespWouldOverwriteOldSession;
|
||||||
|
case UsernameInvalid: return Response::RespUsernameInvalid;
|
||||||
default: authState = res;
|
default: authState = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,21 @@ bool Servatrice_DatabaseInterface::execSqlQuery(QSqlQuery &query)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
result.reserve(user.size());
|
||||||
|
foreach (const QChar& c, user) {
|
||||||
|
switch (c.category()) {
|
||||||
|
// TODO: Figure out exactly which categories are OK and not
|
||||||
|
case QChar::Other_Control: break;
|
||||||
|
default: result += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = result.trimmed();
|
||||||
|
return (result.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
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, QString &reasonStr, int &banSecondsLeft)
|
||||||
{
|
{
|
||||||
switch (server->getAuthenticationMethod()) {
|
switch (server->getAuthenticationMethod()) {
|
||||||
|
@ -80,6 +95,9 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
|
||||||
case Servatrice::AuthenticationSql: {
|
case Servatrice::AuthenticationSql: {
|
||||||
if (!checkSql())
|
if (!checkSql())
|
||||||
return UnknownUser;
|
return UnknownUser;
|
||||||
|
|
||||||
|
if (!usernameIsValid(user))
|
||||||
|
return UsernameInvalid;
|
||||||
|
|
||||||
QSqlQuery ipBanQuery(sqlDatabase);
|
QSqlQuery ipBanQuery(sqlDatabase);
|
||||||
ipBanQuery.prepare("select time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))), b.minutes <=> 0, b.visible_reason from " + server->getDbPrefix() + "_bans b where b.time_from = (select max(c.time_from) from " + server->getDbPrefix() + "_bans c where c.ip_address = :address) and b.ip_address = :address2");
|
ipBanQuery.prepare("select time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))), b.minutes <=> 0, b.visible_reason from " + server->getDbPrefix() + "_bans b where b.time_from = (select max(c.time_from) from " + server->getDbPrefix() + "_bans c where c.ip_address = :address) and b.ip_address = :address2");
|
||||||
|
|
|
@ -16,6 +16,7 @@ private:
|
||||||
QSqlDatabase sqlDatabase;
|
QSqlDatabase sqlDatabase;
|
||||||
Servatrice *server;
|
Servatrice *server;
|
||||||
ServerInfo_User evalUserQueryResult(const QSqlQuery &query, bool complete, bool withId = false);
|
ServerInfo_User evalUserQueryResult(const QSqlQuery &query, bool complete, bool withId = false);
|
||||||
|
bool usernameIsValid(const QString &user);
|
||||||
protected:
|
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, QString &reasonStr, int &secondsLeft);
|
||||||
public slots:
|
public slots:
|
||||||
|
|
Loading…
Reference in a new issue