Core: only try local auth if a user has the "database" auth provider set
authorBen Rosser <rosser.bjr@gmail.com>
Thu, 7 Feb 2019 19:47:50 +0000 (14:47 -0500)
committerManuel Nickschas <sputnick@quassel-irc.org>
Fri, 31 May 2019 14:54:43 +0000 (16:54 +0200)
This commit attempts to resolve issue #1501; currently, quassel will
always attempt to do local authentication, and *then* try LDAP auth. This
makes it difficult to migrate a core from local auth to LDAP auth; users
who have local passwords can always use those passwords to log in, and there
is not a simple way to migrate them to non-local auth.

There is an "authenticator" column in the database for each user, but it
is currently only used to stop passwords from being changed for LDAP users.
This commit modifies the login flow to first check that database field--
if authenticator is not "Database", we don't try local authentication and
proceed directly to non-local authentication.

This is a bit clumsy-- I added a method to the core to look up a user's
authenticator by string. But there's no way to map that to the actual
authenticator object, because we only store one configured authenticator
per core-- so we then just check if that authenticator is "Database" or
not. I think this is something that should be improved in the future,
but as a quick fix to #1501 this is probably good enough.

src/core/core.h
src/core/coreauthhandler.cpp

index 0b455ae..994e473 100644 (file)
@@ -125,6 +125,16 @@ public:
         return instance()->_storage->getUserAuthenticator(userid) == authenticator;
     }
 
         return instance()->_storage->getUserAuthenticator(userid) == authenticator;
     }
 
+    //! Gets the authenticator configured for a user.
+    /**
+     * \param userid The user's name as a QString.
+     * \return String value corresponding to the user's configure dauthenticator.
+     */
+    static inline QString getUserAuthenticator(const QString& userName)
+    {
+        return instance()->_storage->getUserAuthenticator(instance()->_storage->getUserId(userName));
+    }
+
     //! Change a user's password
     /**
      * \param userId     The user's ID
     //! Change a user's password
     /**
      * \param userId     The user's ID
index 1d46e65..d8f81ab 100644 (file)
@@ -228,7 +228,17 @@ void CoreAuthHandler::handle(const Protocol::Login& msg)
 
     // First attempt local auth using the real username and password.
     // If that fails, move onto the auth provider.
 
     // First attempt local auth using the real username and password.
     // If that fails, move onto the auth provider.
-    UserId uid = Core::validateUser(msg.user, msg.password);
+
+    // Check to see if the user has the "Database" authenticator configured.
+    UserId uid = 0;
+    if (Core::getUserAuthenticator(msg.user) == "Database") {
+        uid = Core::validateUser(msg.user, msg.password);
+    }
+
+    // If they did not, *or* if the database login fails, try to use a different authenticator.
+    // TODO: this logic should likely be moved into Core::authenticateUser in the future.
+    // Right now a core can only have one authenticator configured; this might be something
+    // to change in the future.
     if (uid == 0) {
         uid = Core::authenticateUser(msg.user, msg.password);
     }
     if (uid == 0) {
         uid = Core::authenticateUser(msg.user, msg.password);
     }