From: Ben Rosser Date: Wed, 30 Dec 2015 06:23:26 +0000 (-0500) Subject: Add authenticator column to quasseluser table X-Git-Tag: travis-deploy-test~283 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=7fb88a023ef8e4658b39d22c2d88c0d8bd6709f8 Add authenticator column to quasseluser table ... as additional cross-check when logging in a user. This will default to storage-based auth. --- diff --git a/src/core/SQL/PostgreSQL/select_authenticator.sql b/src/core/SQL/PostgreSQL/select_authenticator.sql new file mode 100644 index 00000000..637a3d9b --- /dev/null +++ b/src/core/SQL/PostgreSQL/select_authenticator.sql @@ -0,0 +1,3 @@ +SELECT authenticator +FROM quasseluser +WHERE userid = :userid diff --git a/src/core/SQL/PostgreSQL/setup_000_quasseluser.sql b/src/core/SQL/PostgreSQL/setup_000_quasseluser.sql index 9c993769..0f4c782a 100644 --- a/src/core/SQL/PostgreSQL/setup_000_quasseluser.sql +++ b/src/core/SQL/PostgreSQL/setup_000_quasseluser.sql @@ -2,5 +2,6 @@ CREATE TABLE quasseluser ( 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 index 00000000..50a52034 --- /dev/null +++ b/src/core/SQL/PostgreSQL/version/22/upgrade_000_alter_quasseluser_add_authenticator.sql @@ -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 index 00000000..637a3d9b --- /dev/null +++ b/src/core/SQL/SQLite/select_authenticator.sql @@ -0,0 +1,3 @@ +SELECT authenticator +FROM quasseluser +WHERE userid = :userid diff --git a/src/core/SQL/SQLite/setup_000_quasseluser.sql b/src/core/SQL/SQLite/setup_000_quasseluser.sql index 1833f966..0a325e2e 100644 --- a/src/core/SQL/SQLite/setup_000_quasseluser.sql +++ b/src/core/SQL/SQLite/setup_000_quasseluser.sql @@ -2,5 +2,6 @@ CREATE TABLE quasseluser ( 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 index 00000000..50a52034 --- /dev/null +++ b/src/core/SQL/SQLite/version/23/upgrade_000_alter_quasseluser_add_authenticator.sql @@ -0,0 +1,2 @@ +ALTER TABLE quasseluser +ADD COLUMN authenticator varchar(64) NOT NULL DEFAULT "Database"; diff --git a/src/core/core.h b/src/core/core.h index 644e9b97..835e7879 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -89,10 +89,21 @@ public: /** * \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 */ - 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 diff --git a/src/core/ldapauthenticator.cpp b/src/core/ldapauthenticator.cpp index 378fc4bb..90b7e894 100644 --- a/src/core/ldapauthenticator.cpp +++ b/src/core/ldapauthenticator.cpp @@ -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. - // 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()) { - return Core::addUser(username, QString()); + return Core::addUser(username, QString(), displayName()); + } + else if (!(Core::checkAuthProvider(quasselID, displayName()))) + { + return 0; } return quasselID; } diff --git a/src/core/postgresqlstorage.cpp b/src/core/postgresqlstorage.cpp index cbbd4738..6a7f788a 100644 --- a/src/core/postgresqlstorage.cpp +++ b/src/core/postgresqlstorage.cpp @@ -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); + query.bindValue(":authenticator", authenticator); 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() { diff --git a/src/core/postgresqlstorage.h b/src/core/postgresqlstorage.h index c96687e6..530e7aad 100644 --- a/src/core/postgresqlstorage.h +++ b/src/core/postgresqlstorage.h @@ -48,11 +48,12 @@ public slots: /* 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 QString getUserAuthenticator(const UserId userid); virtual UserId internalUser(); virtual void delUser(UserId user); virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data); diff --git a/src/core/sql.qrc b/src/core/sql.qrc index d302b4db..f945690b 100644 --- a/src/core/sql.qrc +++ b/src/core/sql.qrc @@ -30,6 +30,7 @@ ./SQL/PostgreSQL/migrate_write_quasseluser.sql ./SQL/PostgreSQL/migrate_write_sender.sql ./SQL/PostgreSQL/migrate_write_usersetting.sql + ./SQL/PostgreSQL/select_authenticator.sql ./SQL/PostgreSQL/select_authuser.sql ./SQL/PostgreSQL/select_bufferByName.sql ./SQL/PostgreSQL/select_bufferExists.sql @@ -102,6 +103,7 @@ ./SQL/PostgreSQL/version/20/upgrade_004_add_lastseenmsgid_constraint.sql ./SQL/PostgreSQL/version/21/upgrade_000_add_function_backlog_lastmsgid_update.sql ./SQL/PostgreSQL/version/21/upgrade_001_add_trigger_backlog_lastmsgid_update.sql + ./SQL/PostgreSQL/version/22/upgrade_000_alter_quasseluser_add_authenticator.sql ./SQL/SQLite/delete_backlog_by_uid.sql ./SQL/SQLite/delete_backlog_for_buffer.sql ./SQL/SQLite/delete_backlog_for_network.sql @@ -132,6 +134,7 @@ ./SQL/SQLite/migrate_read_quasseluser.sql ./SQL/SQLite/migrate_read_sender.sql ./SQL/SQLite/migrate_read_usersetting.sql + ./SQL/SQLite/select_authenticator.sql ./SQL/SQLite/select_authuser.sql ./SQL/SQLite/select_bufferByName.sql ./SQL/SQLite/select_bufferExists.sql @@ -277,5 +280,6 @@ ./SQL/SQLite/version/21/upgrade_006_alter_table_buffer_new_rename_to_buffer.sql ./SQL/SQLite/version/22/upgrade_000_add_trigger_backlog_lastmsgid_update_direct_insert.sql ./SQL/SQLite/version/22/upgrade_001_add_trigger_backlog_lastmsgid_update_direct_update.sql + ./SQL/SQLite/version/23/upgrade_000_alter_quasseluser_add_authenticator.sql diff --git a/src/core/sqlitestorage.cpp b/src/core/sqlitestorage.cpp index 10c5f1b7..3457c1ef 100644 --- a/src/core/sqlitestorage.cpp +++ b/src/core/sqlitestorage.cpp @@ -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; @@ -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(":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... @@ -240,6 +241,26 @@ UserId SqliteStorage::getUserId(const QString &username) 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() { diff --git a/src/core/sqlitestorage.h b/src/core/sqlitestorage.h index 9a12fbef..8287f384 100644 --- a/src/core/sqlitestorage.h +++ b/src/core/sqlitestorage.h @@ -49,11 +49,12 @@ public slots: // 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 QString getUserAuthenticator(const UserId userid); virtual UserId internalUser(); virtual void delUser(UserId user); virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data); diff --git a/src/core/storage.h b/src/core/storage.h index 71492d5b..29a8df87 100644 --- a/src/core/storage.h +++ b/src/core/storage.h @@ -103,7 +103,7 @@ public slots: * \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 @@ -131,6 +131,13 @@ public slots: */ 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 */