Add authenticator column to quasseluser table
authorBen Rosser <rosser.bjr@gmail.com>
Wed, 30 Dec 2015 06:23:26 +0000 (01:23 -0500)
committerBen Rosser <rosser.bjr@gmail.com>
Sat, 27 May 2017 18:00:11 +0000 (14:00 -0400)
... as additional cross-check when logging in a user.

This will default to storage-based auth.

14 files changed:
src/core/SQL/PostgreSQL/select_authenticator.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/setup_000_quasseluser.sql
src/core/SQL/PostgreSQL/version/22/upgrade_000_alter_quasseluser_add_authenticator.sql [new file with mode: 0644]
src/core/SQL/SQLite/select_authenticator.sql [new file with mode: 0644]
src/core/SQL/SQLite/setup_000_quasseluser.sql
src/core/SQL/SQLite/version/23/upgrade_000_alter_quasseluser_add_authenticator.sql [new file with mode: 0644]
src/core/core.h
src/core/ldapauthenticator.cpp
src/core/postgresqlstorage.cpp
src/core/postgresqlstorage.h
src/core/sql.qrc
src/core/sqlitestorage.cpp
src/core/sqlitestorage.h
src/core/storage.h

diff --git a/src/core/SQL/PostgreSQL/select_authenticator.sql b/src/core/SQL/PostgreSQL/select_authenticator.sql
new file mode 100644 (file)
index 0000000..637a3d9
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT authenticator
+FROM quasseluser
+WHERE userid = :userid
index 9c99376..0f4c782 100644 (file)
@@ -2,5 +2,6 @@ CREATE TABLE quasseluser (
        userid serial NOT NULL PRIMARY KEY,
        username varchar(64) UNIQUE NOT NULL,
        password TEXT NOT NULL,
        userid serial NOT NULL PRIMARY KEY,
        username varchar(64) UNIQUE NOT NULL,
        password TEXT NOT NULL,
-       hashversion integer NOT NULL DEFAULT 0
+       hashversion integer NOT NULL DEFAULT 0,
+       authenticator varchar(64) UNIQUE NOT NULL
 )
 )
diff --git a/src/core/SQL/PostgreSQL/version/22/upgrade_000_alter_quasseluser_add_authenticator.sql b/src/core/SQL/PostgreSQL/version/22/upgrade_000_alter_quasseluser_add_authenticator.sql
new file mode 100644 (file)
index 0000000..50a5203
--- /dev/null
@@ -0,0 +1,2 @@
+ALTER TABLE quasseluser
+ADD COLUMN authenticator varchar(64) NOT NULL DEFAULT "Database";
diff --git a/src/core/SQL/SQLite/select_authenticator.sql b/src/core/SQL/SQLite/select_authenticator.sql
new file mode 100644 (file)
index 0000000..637a3d9
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT authenticator
+FROM quasseluser
+WHERE userid = :userid
index 1833f96..0a325e2 100644 (file)
@@ -2,5 +2,6 @@ CREATE TABLE quasseluser (
        userid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
        username TEXT UNIQUE NOT NULL,
        password TEXT NOT NULL,
        userid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
        username TEXT UNIQUE NOT NULL,
        password TEXT NOT NULL,
-       hashversion INTEGER NOT NULL DEFAULT 0
+       hashversion INTEGER NOT NULL DEFAULT 0,
+       authenticator varchar(64) NOT NULL DEFAULT "Database"
 )
 )
diff --git a/src/core/SQL/SQLite/version/23/upgrade_000_alter_quasseluser_add_authenticator.sql b/src/core/SQL/SQLite/version/23/upgrade_000_alter_quasseluser_add_authenticator.sql
new file mode 100644 (file)
index 0000000..50a5203
--- /dev/null
@@ -0,0 +1,2 @@
+ALTER TABLE quasseluser
+ADD COLUMN authenticator varchar(64) NOT NULL DEFAULT "Database";
index 644e9b9..835e787 100644 (file)
@@ -89,10 +89,21 @@ public:
     /**
      * \param userName The user's login name
      * \param password The user's uncrypted password
     /**
      * \param userName The user's login name
      * \param password The user's uncrypted password
+     * \param authenticator The name of the auth provider service used to log the user in, defaults to "Database".
      * \return The user's ID if valid; 0 otherwise
      */
      * \return The user's ID if valid; 0 otherwise
      */
-    static inline UserId addUser(const QString &userName, const QString &password) {
-        return instance()->_storage->addUser(userName, password);
+    static inline UserId addUser(const QString &userName, const QString &password, const QString &authenticator = "Database") {
+        return instance()->_storage->addUser(userName, password, authenticator);
+    }
+    
+    //! Does a comparison test against the authenticator in the database and the authenticator currently in use for a UserID.
+    /**
+     * \param userid The user's ID (note: not login name).
+     * \param authenticator The name of the auth provider service used to log the user in, defaults to "Database".
+     * \return True if the userid was configured with the passed authenticator, false otherwise.
+     */
+    static inline bool checkAuthProvider(const UserId userid, const QString &authenticator) {
+        return instance()->_storage->getUserAuthenticator(userid) == authenticator;
     }
 
     //! Change a user's password
     }
 
     //! Change a user's password
index 378fc4b..90b7e89 100644 (file)
@@ -118,11 +118,17 @@ UserId LdapAuthenticator::validateUser(const QString &username, const QString &p
 
     // If auth succeeds, but the user has not logged into quassel previously, make
     // a new user for them and return that ID.
 
     // If auth succeeds, but the user has not logged into quassel previously, make
     // a new user for them and return that ID.
-    // Users created via LDAP have empty usernames.
+    // Users created via LDAP have empty passwords, but authenticator column = LDAP.
+    // On the other hand, if auth succeeds and the user already exists, do a final
+    // cross-check to confirm we're using the right auth provider.
     UserId quasselID = Core::validateUser(username, QString());
     if (!quasselID.isValid())
     {
     UserId quasselID = Core::validateUser(username, QString());
     if (!quasselID.isValid())
     {
-        return Core::addUser(username, QString());
+        return Core::addUser(username, QString(), displayName());
+    }
+    else if (!(Core::checkAuthProvider(quasselID, displayName())))
+    {
+        return 0;
     }
     return quasselID;
 }
     }
     return quasselID;
 }
index cbbd473..6a7f788 100644 (file)
@@ -210,13 +210,14 @@ bool PostgreSqlStorage::setupSchemaVersion(int version)
 }
 
 
 }
 
 
-UserId PostgreSqlStorage::addUser(const QString &user, const QString &password)
+UserId PostgreSqlStorage::addUser(const QString &user, const QString &password, const QString &authenticator)
 {
     QSqlQuery query(logDb());
     query.prepare(queryString("insert_quasseluser"));
     query.bindValue(":username", user);
     query.bindValue(":password", hashPassword(password));
     query.bindValue(":hashversion", Storage::HashVersion::Latest);
 {
     QSqlQuery query(logDb());
     query.prepare(queryString("insert_quasseluser"));
     query.bindValue(":username", user);
     query.bindValue(":password", hashPassword(password));
     query.bindValue(":hashversion", Storage::HashVersion::Latest);
+    query.bindValue(":authenticator", authenticator);
     safeExec(query);
     if (!watchQuery(query))
         return 0;
     safeExec(query);
     if (!watchQuery(query))
         return 0;
@@ -286,6 +287,21 @@ UserId PostgreSqlStorage::getUserId(const QString &user)
     }
 }
 
     }
 }
 
+QString PostgreSqlStorage::getUserAuthenticator(const UserId userid)
+{
+    QSqlQuery query(logDb());
+    query.prepare(queryString("select_authenticator"));
+    query.bindValue(":userid", userid.toInt());
+    safeExec(query);
+    watchQuery(query);
+
+    if (query.first()) {
+        return query.value(0).toString();
+    }
+    else {
+        return QString("");
+    }
+}
 
 UserId PostgreSqlStorage::internalUser()
 {
 
 UserId PostgreSqlStorage::internalUser()
 {
index c96687e..530e7aa 100644 (file)
@@ -48,11 +48,12 @@ public slots:
 
     /* User handling */
 
 
     /* User handling */
 
-    virtual UserId addUser(const QString &user, const QString &password);
+    virtual UserId addUser(const QString &user, const QString &password, const QString &authenticator = "Database");
     virtual bool updateUser(UserId user, const QString &password);
     virtual void renameUser(UserId user, const QString &newName);
     virtual UserId validateUser(const QString &user, const QString &password);
     virtual UserId getUserId(const QString &username);
     virtual bool updateUser(UserId user, const QString &password);
     virtual void renameUser(UserId user, const QString &newName);
     virtual UserId validateUser(const QString &user, const QString &password);
     virtual UserId getUserId(const QString &username);
+    virtual QString getUserAuthenticator(const UserId userid);
     virtual UserId internalUser();
     virtual void delUser(UserId user);
     virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data);
     virtual UserId internalUser();
     virtual void delUser(UserId user);
     virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data);
index d302b4d..f945690 100644 (file)
@@ -30,6 +30,7 @@
     <file>./SQL/PostgreSQL/migrate_write_quasseluser.sql</file>
     <file>./SQL/PostgreSQL/migrate_write_sender.sql</file>
     <file>./SQL/PostgreSQL/migrate_write_usersetting.sql</file>
     <file>./SQL/PostgreSQL/migrate_write_quasseluser.sql</file>
     <file>./SQL/PostgreSQL/migrate_write_sender.sql</file>
     <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_bufferByName.sql</file>
     <file>./SQL/PostgreSQL/select_bufferExists.sql</file>
     <file>./SQL/PostgreSQL/select_authuser.sql</file>
     <file>./SQL/PostgreSQL/select_bufferByName.sql</file>
     <file>./SQL/PostgreSQL/select_bufferExists.sql</file>
     <file>./SQL/PostgreSQL/version/20/upgrade_004_add_lastseenmsgid_constraint.sql</file>
     <file>./SQL/PostgreSQL/version/21/upgrade_000_add_function_backlog_lastmsgid_update.sql</file>
     <file>./SQL/PostgreSQL/version/21/upgrade_001_add_trigger_backlog_lastmsgid_update.sql</file>
     <file>./SQL/PostgreSQL/version/20/upgrade_004_add_lastseenmsgid_constraint.sql</file>
     <file>./SQL/PostgreSQL/version/21/upgrade_000_add_function_backlog_lastmsgid_update.sql</file>
     <file>./SQL/PostgreSQL/version/21/upgrade_001_add_trigger_backlog_lastmsgid_update.sql</file>
+    <file>./SQL/PostgreSQL/version/22/upgrade_000_alter_quasseluser_add_authenticator.sql</file>
     <file>./SQL/SQLite/delete_backlog_by_uid.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_buffer.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_network.sql</file>
     <file>./SQL/SQLite/delete_backlog_by_uid.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_buffer.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_network.sql</file>
     <file>./SQL/SQLite/migrate_read_quasseluser.sql</file>
     <file>./SQL/SQLite/migrate_read_sender.sql</file>
     <file>./SQL/SQLite/migrate_read_usersetting.sql</file>
     <file>./SQL/SQLite/migrate_read_quasseluser.sql</file>
     <file>./SQL/SQLite/migrate_read_sender.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_bufferByName.sql</file>
     <file>./SQL/SQLite/select_bufferExists.sql</file>
     <file>./SQL/SQLite/select_authuser.sql</file>
     <file>./SQL/SQLite/select_bufferByName.sql</file>
     <file>./SQL/SQLite/select_bufferExists.sql</file>
     <file>./SQL/SQLite/version/21/upgrade_006_alter_table_buffer_new_rename_to_buffer.sql</file>
     <file>./SQL/SQLite/version/22/upgrade_000_add_trigger_backlog_lastmsgid_update_direct_insert.sql</file>
     <file>./SQL/SQLite/version/22/upgrade_001_add_trigger_backlog_lastmsgid_update_direct_update.sql</file>
     <file>./SQL/SQLite/version/21/upgrade_006_alter_table_buffer_new_rename_to_buffer.sql</file>
     <file>./SQL/SQLite/version/22/upgrade_000_add_trigger_backlog_lastmsgid_update_direct_insert.sql</file>
     <file>./SQL/SQLite/version/22/upgrade_001_add_trigger_backlog_lastmsgid_update_direct_update.sql</file>
+    <file>./SQL/SQLite/version/23/upgrade_000_alter_quasseluser_add_authenticator.sql</file>
 </qresource>
 </RCC>
 </qresource>
 </RCC>
index 10c5f1b..3457c1e 100644 (file)
@@ -116,7 +116,7 @@ bool SqliteStorage::setupSchemaVersion(int version)
 }
 
 
 }
 
 
-UserId SqliteStorage::addUser(const QString &user, const QString &password)
+UserId SqliteStorage::addUser(const QString &user, const QString &password, const QString &authenticator)
 {
     QSqlDatabase db = logDb();
     UserId uid;
 {
     QSqlDatabase db = logDb();
     UserId uid;
@@ -131,6 +131,7 @@ UserId SqliteStorage::addUser(const QString &user, const QString &password)
         query.bindValue(":username", user);
         query.bindValue(":password", hashPassword(password));
         query.bindValue(":hashversion", Storage::HashVersion::Latest);
         query.bindValue(":username", user);
         query.bindValue(":password", hashPassword(password));
         query.bindValue(":hashversion", Storage::HashVersion::Latest);
+        query.bindValue(":authenticator", authenticator);
         lockForWrite();
         safeExec(query);
         if (query.lastError().isValid() && query.lastError().number() == 19) { // user already exists - sadly 19 seems to be the general constraint violation error...
         lockForWrite();
         safeExec(query);
         if (query.lastError().isValid() && query.lastError().number() == 19) { // user already exists - sadly 19 seems to be the general constraint violation error...
@@ -240,6 +241,26 @@ UserId SqliteStorage::getUserId(const QString &username)
     return userId;
 }
 
     return userId;
 }
 
+QString SqliteStorage::getUserAuthenticator(const UserId userid)
+{
+    QString authenticator = QString("");
+
+    {
+        QSqlQuery query(logDb());
+        query.prepare(queryString("select_authenticator"));
+        query.bindValue(":userid", userid.toInt());
+
+        lockForRead();
+        safeExec(query);
+
+        if (query.first()) {
+            authenticator = query.value(0).toString();
+        }
+    }
+    unlock();
+
+    return authenticator;
+}
 
 UserId SqliteStorage::internalUser()
 {
 
 UserId SqliteStorage::internalUser()
 {
index 9a12fbe..8287f38 100644 (file)
@@ -49,11 +49,12 @@ public slots:
     // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc
 
     /* User handling */
     // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc
 
     /* User handling */
-    virtual UserId addUser(const QString &user, const QString &password);
+    virtual UserId addUser(const QString &user, const QString &password, const QString &authenticator = "Database");
     virtual bool updateUser(UserId user, const QString &password);
     virtual void renameUser(UserId user, const QString &newName);
     virtual UserId validateUser(const QString &user, const QString &password);
     virtual UserId getUserId(const QString &username);
     virtual bool updateUser(UserId user, const QString &password);
     virtual void renameUser(UserId user, const QString &newName);
     virtual UserId validateUser(const QString &user, const QString &password);
     virtual UserId getUserId(const QString &username);
+    virtual QString getUserAuthenticator(const UserId userid);
     virtual UserId internalUser();
     virtual void delUser(UserId user);
     virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data);
     virtual UserId internalUser();
     virtual void delUser(UserId user);
     virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data);
index 71492d5..29a8df8 100644 (file)
@@ -103,7 +103,7 @@ public slots:
      *  \param password The cleartext password for the new user
      *  \return The new user's UserId
      */
      *  \param password The cleartext password for the new user
      *  \return The new user's UserId
      */
-    virtual UserId addUser(const QString &user, const QString &password) = 0;
+    virtual UserId addUser(const QString &user, const QString &password, const QString &authenticator = "Database") = 0;
 
     //! Update a core user's password.
     /** \param user     The user's id
 
     //! Update a core user's password.
     /** \param user     The user's id
@@ -131,6 +131,13 @@ public slots:
      */
     virtual UserId getUserId(const QString &username) = 0;
 
      */
     virtual UserId getUserId(const QString &username) = 0;
 
+    //! Get the authentication provider for a given user.
+    /** \param username  The username to validate
+     *  \return The name of the auth provider if the UserId exists, "" otherwise.
+     */
+    virtual QString getUserAuthenticator(const UserId userid) = 0;
+
+
     //! Determine the UserId of the internal user
     /** \return A valid UserId if the password matches the username; 0 else
      */
     //! Determine the UserId of the internal user
     /** \return A valid UserId if the password matches the username; 0 else
      */