[Dovecot] Authentication cache, failure to login after changed password
Hi,
I have an issue with the authentication cache.
When a user changes his password, the cache doesn't seem to get flushed. Meaning the user is unable to log in to his IMAP account after changing his password.
Flow:
- Log into IMAP account using pass1
- Approved
- Stored in auth cache
- Approved
- Change password to pass2 in MySQL
- Log into IMAP account using pass2
- Access is denied
- Restart dovecot
- Log into IMAP account using pass2
- Approved
I'd really like to continue to use the auth cache, is there any solution to the above? perhaps a way to debug the cache and auth process? I wasn't able to activate auth_debug without restarting Dovecot and solving the problem.
Using version 1.1.1, MySQL userdb, with "nopassword=Y".
Maybe it's due to nopassword?
Thanks
Tom
On Tue, August 19, 2008 15:44, Tom Sommer wrote:
Using version 1.1.1, MySQL userdb, with "nopassword=Y".
Maybe it's due to nopassword?
Should add, this is my password_query:
password_query = SELECT username as user, NULL as password, "Y" as nopassword FROM users WHERE ...
Does the auth cache think the user's password is always NULL then? rendering it ineffective? nopassword requires a NULL password, so I can't really turn it off.
-- Tom
On Tue, 2008-08-19 at 15:49 +0200, Tom Sommer wrote:
On Tue, August 19, 2008 15:44, Tom Sommer wrote:
Using version 1.1.1, MySQL userdb, with "nopassword=Y".
Maybe it's due to nopassword?
Should add, this is my password_query:
password_query = SELECT username as user, NULL as password, "Y" as nopassword FROM users WHERE ...
So how do you check the password validity?
Timo Sirainen wrote:
On Tue, 2008-08-19 at 15:49 +0200, Tom Sommer wrote:
On Tue, August 19, 2008 15:44, Tom Sommer wrote:
Using version 1.1.1, MySQL userdb, with "nopassword=Y".
Maybe it's due to nopassword? Should add, this is my password_query:
password_query = SELECT username as user, NULL as password, "Y" as nopassword FROM users WHERE ...
So how do you check the password validity?
Simple
SELECT username as user, NULL as password, "Y" as nopassword FROM users WHERE username = '%u' AND password = '[password]'
The reason why I need to do this, is because my password is unpractically encrypted
// Tom
On Thu, 2008-08-21 at 09:11 +0200, Tom Sommer wrote:
Timo Sirainen wrote:
On Tue, 2008-08-19 at 15:49 +0200, Tom Sommer wrote:
On Tue, August 19, 2008 15:44, Tom Sommer wrote:
Using version 1.1.1, MySQL userdb, with "nopassword=Y".
Maybe it's due to nopassword? Should add, this is my password_query:
password_query = SELECT username as user, NULL as password, "Y" as nopassword FROM users WHERE ...
So how do you check the password validity?
Simple
SELECT username as user, NULL as password, "Y" as nopassword FROM users WHERE username = '%u' AND password = '[password]'
By [password] I suppose you mean %w?
The way it's supposed to work then is that Dovecot places %u and %w to the cache key. So only if both of them match, the cache is used. This also means that if the password is changed and old password is cached, the user is able to log in using either old or the new password (both of them will be cached to separate entries). And I just tested that it works like that. So if you're getting auth failures, there's something wrong.
Timo Sirainen wrote:
On Thu, 2008-08-21 at 09:11 +0200, Tom Sommer wrote:
Timo Sirainen wrote:
On Tue, 2008-08-19 at 15:49 +0200, Tom Sommer wrote:
On Tue, August 19, 2008 15:44, Tom Sommer wrote:
Using version 1.1.1, MySQL userdb, with "nopassword=Y".
Maybe it's due to nopassword?
Should add, this is my password_query:
password_query = SELECT username as user, NULL as password, "Y" as nopassword FROM users WHERE ...
So how do you check the password validity?
Simple
SELECT username as user, NULL as password, "Y" as nopassword FROM users WHERE username = '%u' AND password = '[password]'
By [password] I suppose you mean %w?
The way it's supposed to work then is that Dovecot places %u and %w to the cache key. So only if both of them match, the cache is used. This also means that if the password is changed and old password is cached, the user is able to log in using either old or the new password (both of them will be cached to separate entries). And I just tested that it works like that. So if you're getting auth failures, there's something wrong.
Sorry to bump this, but I can still reproduce it - I have enabled auth_debug now to attempt to provide some more details.
It seems to happen after some time have passed, so maybe it has something to do with auth_cache_size being reached, some incremented ID growing too large and wrapping? or.. well, I don't know, and I don't know enough C++ to be smart on the code :) As I wrote previously, a simple restart of Dovecot fixes the problem for a while.
It also seem to only happen if both the new and the old password is entirely numeric and 8 ciphers.
Will get back with more details when I have a case where auth_debug was enabled.
Any help is appreciated, thanks.
Tom Sommer
On Mon, 2009-01-05 at 14:33 +0100, Tom Sommer wrote:
Sorry to bump this, but I can still reproduce it - I have enabled auth_debug now to attempt to provide some more details.
Actually enable auth_debug_passwords=yes. It then also logs what's seen in the cache entries.
Timo Sirainen wrote:
On Mon, 2009-01-05 at 14:33 +0100, Tom Sommer wrote:
Sorry to bump this, but I can still reproduce it - I have enabled auth_debug now to attempt to provide some more details.
Actually enable auth_debug_passwords=yes. It then also logs what's seen in the cache entries.
dovecot: Jan 20 09:01:18 Info: auth(default):
cache(user@example.com,127.0.0.1): miss
dovecot: Jan 20 09:01:18 Info: auth-worker(default):
sql(user@example.com,127.0.0.1): query: SELECT username as user,
plainpassword as password, nopassword FROM cyrususers WHERE username =
'user@example.com' AND password = PASSWORD('SECRET') AND active = 1
dovecot: Jan 20 09:01:18 Info: auth-worker(default):
sql(user@example.com,127.0.0.1): unknown user
dovecot: Jan 20 09:01:20 Info: auth(default): client out: FAIL 1
user=user@example.com
dovecot: Jan 20 09:01:20 Info: imap-login: Disconnected (auth failed, 1
attempts): user=<user@example.com>, method=PLAIN, rip=127.0.0.1,
lip=127.0.0.2
dovecot: Jan 20 09:01:32 Info: auth(default):
cache(user@example.com,127.0.0.1): hit:
dovecot: Jan 20 09:01:32 Info: auth(default):
cache(user@example.com,127.0.0.1): User unknown
dovecot: Jan 20 09:01:34 Info: auth(default): client out: FAIL 1
user=user@example.com
It appears the user missed the cache, a SQL lookup is performed (which returns 1 record, I tested the query directly) - however for some reason the lookup is set as Unknown User, a state which it then keeps. Obviously I can adjust this with auth_cache_negative_ttl, but I presumed the default value was always 0
Setting auth_cache_negative_ttl = 0 now and awaiting results
-- Tom Sommer
On Tue, 2009-01-20 at 09:53 +0100, Tom Sommer wrote:
sql(user@example.com,127.0.0.1): query: SELECT username as user, plainpassword as password, nopassword FROM cyrususers WHERE username = 'user@example.com' AND password = PASSWORD('SECRET') AND active = 1 dovecot: Jan 20 09:01:18 Info: auth-worker(default): sql(user@example.com,127.0.0.1): unknown user .. It appears the user missed the cache, a SQL lookup is performed (which returns 1 record, I tested the query directly) - however for some reason the lookup is set as Unknown User, a state which it then keeps.
It's most likely set to unknown user because the password=PASSWORD() check fails and no rows are returned. If you're already returning plainpassword for Dovecot, why do you do the password check also in the SQL query? That doesn't allow Dovecot to differentiate between unknown user and invalid password.
Obviously I can adjust this with auth_cache_negative_ttl, but I presumed the default value was always 0
Nope, 3600.
Timo Sirainen wrote:
On Tue, 2009-01-20 at 09:53 +0100, Tom Sommer wrote:
sql(user@example.com,127.0.0.1): query: SELECT username as user, plainpassword as password, nopassword FROM cyrususers WHERE username = 'user@example.com' AND password = PASSWORD('SECRET') AND active = 1 dovecot: Jan 20 09:01:18 Info: auth-worker(default): sql(user@example.com,127.0.0.1): unknown user
..
It appears the user missed the cache, a SQL lookup is performed (which returns 1 record, I tested the query directly) - however for some reason the lookup is set as Unknown User, a state which it then keeps.
It's most likely set to unknown user because the password=PASSWORD() check fails and no rows are returned. If you're already returning plainpassword for Dovecot, why do you do the password check also in the SQL query? That doesn't allow Dovecot to differentiate between unknown user and invalid password.
No I ran the query manually afterwards and it returned 1 row. The reason I'm using plainpassword, PASSWORD() and nopassword, etc. is because not all users have a plainpassword - yet - as time progress more and more users will return plainpassword and nopassword=NULL
That's how you fix design flaws without forcing all users to change passwords :)
auth_cache_negative_ttl seems like a good source for user flaws (login attempt before account is created = you cant log in for 3600 seconds even after the account is valid), gonna go with 0 on all servers.
Thanks
Tom Sommer
Tom Sommer wrote:
Timo Sirainen wrote:
On Tue, 2009-01-20 at 09:53 +0100, Tom Sommer wrote:
sql(user@example.com,127.0.0.1): query: SELECT username as user, plainpassword as password, nopassword FROM cyrususers WHERE username = 'user@example.com' AND password = PASSWORD('SECRET') AND active = 1 dovecot: Jan 20 09:01:18 Info: auth-worker(default): sql(user@example.com,127.0.0.1): unknown user
..
It appears the user missed the cache, a SQL lookup is performed (which returns 1 record, I tested the query directly) - however for some reason the lookup is set as Unknown User, a state which it then keeps.
It's most likely set to unknown user because the password=PASSWORD() check fails and no rows are returned. If you're already returning plainpassword for Dovecot, why do you do the password check also in the SQL query? That doesn't allow Dovecot to differentiate between unknown user and invalid password.
No I ran the query manually afterwards and it returned 1 row. The reason I'm using plainpassword, PASSWORD() and nopassword, etc. is because not all users have a plainpassword - yet - as time progress more and more users will return plainpassword and nopassword=NULL
That's how you fix design flaws without forcing all users to change passwords :)
auth_cache_negative_ttl seems like a good source for user flaws (login attempt before account is created = you cant log in for 3600 seconds even after the account is valid), gonna go with 0 on all servers. I'm sorry, but I still have problems with this. I got cache_size 1024, cache_ttl 3600, cache_negative_ttl 0, but if a user changes password in my SQL, sometimes it requires a restart of dovecot for him to be able to log in. Dovecot 1.1.14.
Using plain passwords, no "nopassword" feature, and MySQL for passdb.
Basically my log is: --- Dovecot starts
- auth failed, 1 attempts
- auth failed, 1 attempts
- auth failed, 1 attempts
- auth failed, 1 attempts
- auth failed, 1 attempts
- auth failed, 1 attempts
- auth failed, 1 attempts --- I RESTART DOVECOT ---
- Login successful (same password, same everything)
The cache seems to be faulty somehow, I wish there was a way to dump the contents of the cache to debug this, because somehow I cannot forcefully reproduce it. Notice in this case the user never before logged in successfully, so I dont understand why he would even be in the cache, unless there is something wrong with cache_negative_ttl.
Thanks // Tom
On Fri, 2009-05-15 at 09:29 +0200, Tom Sommer wrote:
I'm sorry, but I still have problems with this. I got cache_size 1024, cache_ttl 3600, cache_negative_ttl 0, but if a user changes password in my SQL, sometimes it requires a restart of dovecot for him to be able to log in.
You can always send SIGHUP to dovecot-auth instead of restart to flush auth cache.
The cache seems to be faulty somehow, I wish there was a way to dump the contents of the cache to debug this, because somehow I cannot forcefully reproduce it.
Here's a way:
- Try to log in unsuccessfully.
- Change the password.
- Try to log in with the changed password -> doesn't work, because the old one is still cached.
Notice in this case the user never before logged in successfully, so I dont understand why he would even be in the cache, unless there is something wrong with cache_negative_ttl.
You're misunderstanding what it does. See its description:
# TTL for negative hits (user not found). 0 disables caching them completely. #auth_cache_negative_ttl = 3600
I suppose there could be a new setting to use auth cache only for successful lookups..
Timo Sirainen wrote:
The cache seems to be faulty somehow, I wish there was a way to dump the contents of the cache to debug this, because somehow I cannot forcefully reproduce it.
Here's a way:
- Try to log in unsuccessfully.
- Change the password.
- Try to log in with the changed password -> doesn't work, because the old one is still cached.
If the auth is unsuccessful (cache missmatch), the cache should then go for a lookup in the passdb, correct?
Notice in this case the user never before logged in successfully, so I dont understand why he would even be in the cache, unless there is something wrong with cache_negative_ttl.
You're misunderstanding what it does. See its description:
# TTL for negative hits (user not found). 0 disables caching them completely. #auth_cache_negative_ttl = 3600
I suppose there could be a new setting to use auth cache only for successful lookups..
I don't understand why it would cache negative lookups if I set negative_ttl to 0, even if the setting isn't suppose to work that way currently, it should. Enabling the cache is effectively preventing newly created users from logging in, which is hardly the point.
-- Tom
On Sun, 2009-05-17 at 21:09 +0200, Tom Sommer wrote:
Timo Sirainen wrote:
The cache seems to be faulty somehow, I wish there was a way to dump the contents of the cache to debug this, because somehow I cannot forcefully reproduce it.
Here's a way:
- Try to log in unsuccessfully.
- Change the password.
- Try to log in with the changed password -> doesn't work, because the old one is still cached.
If the auth is unsuccessful (cache missmatch), the cache should then go for a lookup in the passdb, correct?
Only when the previous authentication was successful.
# TTL for negative hits (user not found). 0 disables caching them completely. #auth_cache_negative_ttl = 3600
I suppose there could be a new setting to use auth cache only for successful lookups..
I don't understand why it would cache negative lookups if I set negative_ttl to 0, even if the setting isn't suppose to work that way currently, it should.
Hmm. Maybe.
Timo Sirainen wrote:
On Sun, 2009-05-17 at 21:09 +0200, Tom Sommer wrote:
Timo Sirainen wrote:
The cache seems to be faulty somehow, I wish there was a way to dump the contents of the cache to debug this, because somehow I cannot forcefully reproduce it.
Here's a way:
- Try to log in unsuccessfully.
- Change the password.
- Try to log in with the changed password -> doesn't work, because the old one is still cached.
If the auth is unsuccessful (cache missmatch), the cache should then go for a lookup in the passdb, correct?
Only when the previous authentication was successful.
# TTL for negative hits (user not found). 0 disables caching them completely. #auth_cache_negative_ttl = 3600
I suppose there could be a new setting to use auth cache only for successful lookups..
I don't understand why it would cache negative lookups if I set negative_ttl to 0, even if the setting isn't suppose to work that way currently, it should.
Hmm. Maybe.
This is still a rather big support issue for us. We have customers who are essentially blocked from their accounts because of the above auth cache "functionality". Is this something you are willing to look at? It's getting old to have to restart Dovecot when it happens :)
Thanks a lot
On Jun 16, 2009, at 4:01 AM, Tom Sommer wrote:
# TTL for negative hits (user not found). 0 disables caching them
completely. #auth_cache_negative_ttl = 3600I suppose there could be a new setting to use auth cache only for successful lookups..
I don't understand why it would cache negative lookups if I set negative_ttl to 0, even if the setting isn't suppose to work that
way currently, it should.Hmm. Maybe.
This is still a rather big support issue for us. We have customers who are essentially blocked from their accounts because of the above auth cache "functionality". Is this something you are willing to look at?
Already done in 1.2.rc5. http://hg.dovecot.org/dovecot-1.2/rev/8a23ab43132a
It's getting old to have to restart Dovecot when it happens :)
SIGHUP to dovecot-auth is enough.
Timo Sirainen wrote:
On Jun 16, 2009, at 4:01 AM, Tom Sommer wrote:
# TTL for negative hits (user not found). 0 disables caching them completely. #auth_cache_negative_ttl = 3600
I suppose there could be a new setting to use auth cache only for successful lookups..
I don't understand why it would cache negative lookups if I set negative_ttl to 0, even if the setting isn't suppose to work that way currently, it should.
Hmm. Maybe.
This is still a rather big support issue for us. We have customers who are essentially blocked from their accounts because of the above auth cache "functionality". Is this something you are willing to look at? Already done in 1.2.rc5. http://hg.dovecot.org/dovecot-1.2/rev/8a23ab43132a Brilliant, thank you so much.
participants (2)
-
Timo Sirainen
-
Tom Sommer