... as additional cross-check when logging in a user.
This will default to storage-based auth.
--- /dev/null
+SELECT authenticator
+FROM quasseluser
+WHERE userid = :userid
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
)
--- /dev/null
+ALTER TABLE quasseluser
+ADD COLUMN authenticator varchar(64) NOT NULL DEFAULT "Database";
--- /dev/null
+SELECT authenticator
+FROM quasseluser
+WHERE userid = :userid
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"
)
--- /dev/null
+ALTER TABLE quasseluser
+ADD COLUMN authenticator varchar(64) NOT NULL DEFAULT "Database";
/**
* \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
// 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;
}
}
-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;
}
}
+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()
{
/* 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);
<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/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/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/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>
}
-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;
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...
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()
{
// 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);
* \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
*/
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
*/