From: Michael Marley Date: Tue, 3 Apr 2018 18:21:11 +0000 (-0400) Subject: Add strict-oidentd mode X-Git-Tag: travis-deploy-test~125 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=f932e5c8a0ec3ff689686a71c32ee61a428c4340 Add strict-oidentd mode This mode is disabled by default. When specified, this restricts authoratative ident responses to be the authuser account name. This is a cut-down version of, https://github.com/quassel/quassel/pull/164 which was originally authored by @esainane. @AlD requested that the database schema change be removed, but the request fell dormant and was eventually closed. This version removes the schema change as requested, always using the user's core username as the ident when enabled. Co-authored-by: Sai Nane Co-authored-by: Michael Marley --- diff --git a/src/common/main.cpp b/src/common/main.cpp index 12f69ef0..a2cb5745 100644 --- a/src/common/main.cpp +++ b/src/common/main.cpp @@ -169,6 +169,7 @@ int main(int argc, char **argv) cliParser->addOption("change-userpass", 0, "Starts an interactive session to change the password of the user identified by ", "username"); cliParser->addSwitch("oidentd", 0, "Enable oidentd integration"); cliParser->addOption("oidentd-conffile", 0, "Set path to oidentd configuration file", "file"); + cliParser->addSwitch("oidentd-strict", 0, "Use users' quasselcore username as ident reply. Ignores each user's configured ident setting. Only meaningful with --oidentd."); #ifdef HAVE_SSL cliParser->addSwitch("require-ssl", 0, "Require SSL for remote (non-loopback) client connections"); cliParser->addOption("ssl-cert", 0, "Specify the path to the SSL Certificate", "path", "configdir/quasselCert.pem"); diff --git a/src/core/SQL/PostgreSQL/select_authusername.sql b/src/core/SQL/PostgreSQL/select_authusername.sql new file mode 100644 index 00000000..00aaf77d --- /dev/null +++ b/src/core/SQL/PostgreSQL/select_authusername.sql @@ -0,0 +1,3 @@ +SELECT username +FROM quasseluser +WHERE userid = :userid diff --git a/src/core/SQL/SQLite/select_authusername.sql b/src/core/SQL/SQLite/select_authusername.sql new file mode 100644 index 00000000..00aaf77d --- /dev/null +++ b/src/core/SQL/SQLite/select_authusername.sql @@ -0,0 +1,3 @@ +SELECT username +FROM quasseluser +WHERE userid = :userid diff --git a/src/core/core.cpp b/src/core/core.cpp index 69175081..73fde97c 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -237,7 +237,7 @@ void Core::init() if (!startListening()) exit(1); // TODO make this less brutal if (Quassel::isOptionSet("oidentd")) - _oidentdConfigGenerator = new OidentdConfigGenerator(this); + _oidentdConfigGenerator = new OidentdConfigGenerator(Quassel::isOptionSet("oidentd-strict"), this); } diff --git a/src/core/core.h b/src/core/core.h index fd082780..a29d6724 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -493,6 +493,14 @@ public: return instance()->_storage->setBufferLastSeenMsg(user, bufferId, msgId); } + //! Get the auth username associated with a userId + /** \param user The user to retrieve the username for + * \return The username for the user + */ + static inline const QString getAuthusername(UserId user) { + return instance()->_storage->getAuthusername(user); + } + //! Get a Hash of all last seen message ids /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index 7ff87d4a..b2637397 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -508,6 +508,10 @@ void CoreSession::createIdentity(const Identity &identity, const QVariantMap &ad createIdentity(coreIdentity); } +const QString CoreSession::strictSysident() { + const QString authusername = Core::getAuthusername(_user); + return authusername; +} void CoreSession::createIdentity(const CoreIdentity &identity) { diff --git a/src/core/coresession.h b/src/core/coresession.h index 9828478f..fb5995bb 100644 --- a/src/core/coresession.h +++ b/src/core/coresession.h @@ -69,6 +69,7 @@ public: inline UserId user() const { return _user; } CoreNetwork *network(NetworkId) const; CoreIdentity *identity(IdentityId) const; + const QString strictSysident(); inline CoreNetworkConfig *networkConfig() const { return _networkConfig; } NetworkConnection *networkConnection(NetworkId) const; diff --git a/src/core/oidentdconfiggenerator.cpp b/src/core/oidentdconfiggenerator.cpp index 02225387..ba54f00c 100644 --- a/src/core/oidentdconfiggenerator.cpp +++ b/src/core/oidentdconfiggenerator.cpp @@ -19,10 +19,14 @@ ***************************************************************************/ #include "oidentdconfiggenerator.h" +#include "corenetwork.h" -OidentdConfigGenerator::OidentdConfigGenerator(QObject *parent) : +#include + +OidentdConfigGenerator::OidentdConfigGenerator(bool strict, QObject *parent) : QObject(parent), - _initialized(false) + _initialized(false), + _strict(strict) { if (!_initialized) init(); @@ -65,11 +69,18 @@ bool OidentdConfigGenerator::init() return _initialized; } +const QString OidentdConfigGenerator::sysidentForIdentity(const CoreIdentity *identity) { + if (!_strict) { + return identity->ident(); + } + const CoreNetwork *network = qobject_cast(sender()); + return network->coreSession()->strictSysident(); +} bool OidentdConfigGenerator::addSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort) { Q_UNUSED(localAddress) Q_UNUSED(peerAddress) Q_UNUSED(peerPort) - QString ident = identity->ident(); + const QString ident = sysidentForIdentity(identity); _quasselConfig.append(_quasselStanzaTemplate.arg(localPort).arg(ident).arg(_configTag).toLatin1()); diff --git a/src/core/oidentdconfiggenerator.h b/src/core/oidentdconfiggenerator.h index 3302c87b..f4128d67 100644 --- a/src/core/oidentdconfiggenerator.h +++ b/src/core/oidentdconfiggenerator.h @@ -22,6 +22,7 @@ #define OIDENTDCONFIGGENERATOR_H #include +#include #include #include #include @@ -58,7 +59,11 @@ class OidentdConfigGenerator : public QObject { Q_OBJECT public: - explicit OidentdConfigGenerator(QObject *parent = 0); + /** + * @param strict If false, any identity a user chooses is reported to servers as authoritative. + * If true, the user's quassel username is always reported. + */ + explicit OidentdConfigGenerator(bool strict = false, QObject *parent = 0); ~OidentdConfigGenerator(); public slots: @@ -66,12 +71,14 @@ public slots: bool removeSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); private: + const QString sysidentForIdentity(const CoreIdentity *identity); bool init(); bool writeConfig(); bool parseConfig(bool readQuasselStanzas = false); bool lineByUs(const QByteArray &line); bool _initialized; + bool _strict; QDateTime _lastSync; QFile *_configFile; QByteArray _parsedConfig; diff --git a/src/core/postgresqlstorage.cpp b/src/core/postgresqlstorage.cpp index d9b518f3..48ee466d 100644 --- a/src/core/postgresqlstorage.cpp +++ b/src/core/postgresqlstorage.cpp @@ -1702,6 +1702,19 @@ QList PostgreSqlStorage::requestAllMsgs(UserId user, MsgId first, MsgId return messagelist; } +const QString PostgreSqlStorage::getAuthusername(UserId user) { + QString authusername; + QSqlQuery query(logDb()); + query.prepare(queryString("select_authusername")); + query.bindValue(":userid", user.toInt()); + safeExec(query); + watchQuery(query); + + if (query.first()) { + authusername = query.value(0).toString(); + } + return authusername; +} // void PostgreSqlStorage::safeExec(QSqlQuery &query) { // qDebug() << "PostgreSqlStorage::safeExec"; diff --git a/src/core/postgresqlstorage.h b/src/core/postgresqlstorage.h index 785a3037..ad09ff99 100644 --- a/src/core/postgresqlstorage.h +++ b/src/core/postgresqlstorage.h @@ -105,6 +105,9 @@ public slots: QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1) override; QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1) override; + /* Sysident handling */ + virtual const QString getAuthusername(UserId user); + protected: bool initDbSession(QSqlDatabase &db) override; void setConnectionProperties(const QVariantMap &properties) override; diff --git a/src/core/sql.qrc b/src/core/sql.qrc index 84ceb78a..597df0f7 100644 --- a/src/core/sql.qrc +++ b/src/core/sql.qrc @@ -32,6 +32,7 @@ ./SQL/PostgreSQL/migrate_write_usersetting.sql ./SQL/PostgreSQL/select_authenticator.sql ./SQL/PostgreSQL/select_authuser.sql + ./SQL/PostgreSQL/select_authusername.sql ./SQL/PostgreSQL/select_bufferByName.sql ./SQL/PostgreSQL/select_bufferExists.sql ./SQL/PostgreSQL/select_buffer_bufferactivities.sql @@ -141,6 +142,7 @@ ./SQL/SQLite/migrate_read_usersetting.sql ./SQL/SQLite/select_authenticator.sql ./SQL/SQLite/select_authuser.sql + ./SQL/SQLite/select_authusername.sql ./SQL/SQLite/select_bufferByName.sql ./SQL/SQLite/select_bufferExists.sql ./SQL/SQLite/select_buffer_bufferactivities.sql diff --git a/src/core/sqlitestorage.cpp b/src/core/sqlitestorage.cpp index 0c0f0dca..0962fac1 100644 --- a/src/core/sqlitestorage.cpp +++ b/src/core/sqlitestorage.cpp @@ -1820,6 +1820,23 @@ QList SqliteStorage::requestAllMsgs(UserId user, MsgId first, MsgId las return messagelist; } +const QString SqliteStorage::getAuthusername(UserId user) { + QString authusername; + QSqlQuery query(logDb()); + query.prepare(queryString("select_authusername")); + query.bindValue(":userid", user.toInt()); + + lockForRead(); + safeExec(query); + watchQuery(query); + unlock(); + + if (query.first()) { + authusername = query.value(0).toString(); + } + + return authusername; +} QString SqliteStorage::backlogFile() { diff --git a/src/core/sqlitestorage.h b/src/core/sqlitestorage.h index 7ae09067..15d54373 100644 --- a/src/core/sqlitestorage.h +++ b/src/core/sqlitestorage.h @@ -106,6 +106,9 @@ public slots: QList requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1) override; QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1) override; + /* Sysident handling */ + virtual const QString getAuthusername(UserId user); + protected: void setConnectionProperties(const QVariantMap & /* properties */) override {} QString driverName() override { return "QSQLITE"; } diff --git a/src/core/storage.h b/src/core/storage.h index 28f60494..c77e9ebf 100644 --- a/src/core/storage.h +++ b/src/core/storage.h @@ -442,6 +442,12 @@ public slots: */ virtual QList requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1) = 0; + //! Get the auth username associated with a userId + /** \param user The user to retrieve the username for + * \return The username for the user + */ + virtual const QString getAuthusername(UserId user) = 0; + signals: //! Sent when a new BufferInfo is created, or an existing one changed somehow. void bufferInfoUpdated(UserId user, const BufferInfo &);