[Servatrice] Detect MySQL strict mode on startup and exit early (#7251)

* [Servatrice] Detect MySQL strict mode on startup and exit early

* Update servatrice/src/servatrice_database_interface.cpp

Co-authored-by: tooomm <tooomm@users.noreply.github.com>

* [Servatrice] Treat failed strict-mode check as boot error

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: tooomm <tooomm@users.noreply.github.com>
This commit is contained in:
BruebachL 2026-09-18 15:02:45 +02:00 committed by GitHub
parent 1c93309952
commit e11c915a0c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 49 additions and 0 deletions

View file

@ -12,6 +12,7 @@
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QSqlError> #include <QSqlError>
#include <QSqlQuery> #include <QSqlQuery>
#include <QStringList>
#include <libcockatrice/deck_list/deck_list.h> #include <libcockatrice/deck_list/deck_list.h>
#include <libcockatrice/protocol/pb/game_replay.pb.h> #include <libcockatrice/protocol/pb/game_replay.pb.h>
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h> #include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
@ -99,12 +100,59 @@ bool Servatrice_DatabaseInterface::openDatabase()
return false; return false;
} }
if (sqlDatabase.driverName() != "QMYSQL") {
qCCritical(DatabaseInterfaceLog)
<< poolStr
<< "Error opening database: connection is not a MySQL/MariaDB database, Servatrice only "
"supports the QMYSQL driver (actual driver:"
<< sqlDatabase.driverName() << ").";
return false;
}
bool strictModeCheckOk = false;
const bool strictModeEnabled = isStrictModeEnabled(strictModeCheckOk);
if (!strictModeCheckOk) {
qCCritical(DatabaseInterfaceLog) << poolStr
<< "Error opening database: unable to determine whether MySQL/MariaDB strict "
"mode is enabled";
return false;
}
if (strictModeEnabled) {
qCCritical(DatabaseInterfaceLog) << poolStr
<< "Error opening database: MySQL/MariaDB strict mode is enabled, which "
"breaks most Servatrice database operations. Please disable strict mode "
"by removing STRICT_TRANS_TABLES and STRICT_ALL_TABLES from sql_mode, "
"for example by adding 'sql_mode=NO_ENGINE_SUBSTITUTION' under [mysqld] "
"in your my.cnf (or my.ini on Windows) and restarting the database "
"server.";
return false;
}
// reset all prepared statements // reset all prepared statements
qDeleteAll(preparedStatements); qDeleteAll(preparedStatements);
preparedStatements.clear(); preparedStatements.clear();
return true; return true;
} }
bool Servatrice_DatabaseInterface::isStrictModeEnabled(bool &ok) const
{
ok = true;
QSqlQuery query(sqlDatabase);
if (!query.exec("SELECT @@GLOBAL.sql_mode")) {
ok = false;
return false;
}
const QStringList modes = query.next() ? query.value(0).toString().split(',') : QStringList();
for (const QString &mode : modes) {
if (mode.trimmed() == "STRICT_TRANS_TABLES" || mode.trimmed() == "STRICT_ALL_TABLES") {
return true;
}
}
return false;
}
bool Servatrice_DatabaseInterface::checkSql() bool Servatrice_DatabaseInterface::checkSql()
{ {
if (!sqlDatabase.isValid()) { if (!sqlDatabase.isValid()) {

View file

@ -32,6 +32,7 @@ private:
bool checkUserIsIpBanned(const QString &ipAddress, QString &banReason, int &banSecondsRemaining); bool checkUserIsIpBanned(const QString &ipAddress, QString &banReason, int &banSecondsRemaining);
/** Must be called after checkSql and server is known to be in auth mode. */ /** Must be called after checkSql and server is known to be in auth mode. */
bool checkUserIsNameBanned(QString const &userName, QString &banReason, int &banSecondsRemaining); bool checkUserIsNameBanned(QString const &userName, QString &banReason, int &banSecondsRemaining);
bool isStrictModeEnabled(bool &ok) const;
protected: protected:
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler,