Add strict-oidentd mode
authorMichael Marley <michael@michaelmarley.com>
Tue, 3 Apr 2018 18:21:11 +0000 (14:21 -0400)
committerManuel Nickschas <sputnick@quassel-irc.org>
Mon, 7 May 2018 20:38:41 +0000 (22:38 +0200)
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 <esainane+github@gmail.com>
Co-authored-by: Michael Marley <michael@michaelmarley.com>
15 files changed:
src/common/main.cpp
src/core/SQL/PostgreSQL/select_authusername.sql [new file with mode: 0644]
src/core/SQL/SQLite/select_authusername.sql [new file with mode: 0644]
src/core/core.cpp
src/core/core.h
src/core/coresession.cpp
src/core/coresession.h
src/core/oidentdconfiggenerator.cpp
src/core/oidentdconfiggenerator.h
src/core/postgresqlstorage.cpp
src/core/postgresqlstorage.h
src/core/sql.qrc
src/core/sqlitestorage.cpp
src/core/sqlitestorage.h
src/core/storage.h

index 12f69ef..a2cb574 100644 (file)
@@ -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>", "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 (file)
index 0000000..00aaf77
--- /dev/null
@@ -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 (file)
index 0000000..00aaf77
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT username
+FROM quasseluser
+WHERE userid = :userid
index 6917508..73fde97 100644 (file)
@@ -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);
 }
 
 
index fd08278..a29d672 100644 (file)
@@ -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
index 7ff87d4..b263739 100644 (file)
@@ -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)
 {
index 9828478..fb5995b 100644 (file)
@@ -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;
 
index 0222538..ba54f00 100644 (file)
  ***************************************************************************/
 
 #include "oidentdconfiggenerator.h"
+#include "corenetwork.h"
 
-OidentdConfigGenerator::OidentdConfigGenerator(QObject *parent) :
+#include <QString>
+
+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<CoreNetwork *>(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());
 
index 3302c87..f4128d6 100644 (file)
@@ -22,6 +22,7 @@
 #define OIDENTDCONFIGGENERATOR_H
 
 #include <QObject>
+#include <QString>
 #include <QDir>
 #include <QFile>
 #include <QDateTime>
@@ -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;
index d9b518f..48ee466 100644 (file)
@@ -1702,6 +1702,19 @@ QList<Message> 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";
index 785a303..ad09ff9 100644 (file)
@@ -105,6 +105,9 @@ public slots:
     QList<Message> requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1) override;
     QList<Message> 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;
index 84ceb78..597df0f 100644 (file)
@@ -32,6 +32,7 @@
     <file>./SQL/PostgreSQL/migrate_write_usersetting.sql</file>
     <file>./SQL/PostgreSQL/select_authenticator.sql</file>
     <file>./SQL/PostgreSQL/select_authuser.sql</file>
+    <file>./SQL/PostgreSQL/select_authusername.sql</file>
     <file>./SQL/PostgreSQL/select_bufferByName.sql</file>
     <file>./SQL/PostgreSQL/select_bufferExists.sql</file>
     <file>./SQL/PostgreSQL/select_buffer_bufferactivities.sql</file>
     <file>./SQL/SQLite/migrate_read_usersetting.sql</file>
     <file>./SQL/SQLite/select_authenticator.sql</file>
     <file>./SQL/SQLite/select_authuser.sql</file>
+    <file>./SQL/SQLite/select_authusername.sql</file>
     <file>./SQL/SQLite/select_bufferByName.sql</file>
     <file>./SQL/SQLite/select_bufferExists.sql</file>
     <file>./SQL/SQLite/select_buffer_bufferactivities.sql</file>
index 0c0f0dc..0962fac 100644 (file)
@@ -1820,6 +1820,23 @@ QList<Message> 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()
 {
index 7ae0906..15d5437 100644 (file)
@@ -106,6 +106,9 @@ public slots:
     QList<Message> requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1) override;
     QList<Message> 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"; }
index 28f6049..c77e9eb 100644 (file)
@@ -442,6 +442,12 @@ public slots:
      */
     virtual QList<Message> 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 &);