Timo Sirainen wrote:
On 30.6.2005, at 10:02, Andrew Hutchings wrote:
-ERR [IN-USE] Internal login failure. Refer to server log for more information. Connection closed by foreign host. robyt:~# Why dovecot don't close the connection at user root? With this system i may know the root password..
Dovecot is hard coded to refuse the root use at the auth stage (when passing the user/pass entered). You are right though, the root user should be rejected for the same reason no matter what the password. The current method could be used to discover the root password.
The fix isn't simple though. Authentication works like:
- login: send user/pass to auth
- auth: validate the password against passdb and reply to login. if auth fails, delay the answer for ~2secs
- login: send file descriptor to master and request a new imap/pop3 process
- master: request user information from auth
- auth: check that master's request is valid and return user information if so
- master: check that user info is valid (eg. UID isn't 0). if it's invalid or something failed, login is sent a failure reply and:
- login: send "internal authentication error" to client and disconnect it
Probably the simplest fix would be to change step 7. to change the error message to same as it's normally and add a ~2second delay. But then the delay must be kept in sync between auth and login, and I don't really like that.
Second possibility would be to check userdb in step 2 already and save the information to the request so at step 5 there's no need to do second userdb lookup. If the UID is 0 (or not in valid range as specified in config file) treat the authentication as if it failed and do the ~2sec delay before replying. This could work I suppose, but it would use a bit more memory.
Third possibility would be to add the ~2sec delay in step 5 before replying to master. This has the downside that while master is waiting for the reply from auth, it's keeping the connection's file descriptor open in its process. Flooding Dovecot with valid passwords for invalid users could make master process run out of fds, which isn't good. But no-one should know the password for those users so maybe this isn't an issue.
I'm not really sure which one to implement. The second idea could have positive effect in general, making authentication somewhat faster when passdb and userdb lookups are done close to each others. It'd also make step 5 happen instantly because there's no need to do userdb lookup at that point anymore. But it'd take more memory and might have some other negative side effects that I can't think of now. Hmm..
It is very late at night (1am) and my memory of the code is fuzzy, but would it be easy at stage 2 to add a filter for user root to fail at that stage just as if user/pass fails? ie:
if (user=="root") auth_fail(); ... passdb lookup ...
If I am talking bollox then in my dozy state I agree that the second method sounds better in theory. I'll read this again in the morning and think harder :)
Regards Andrew
Andrew Hutchings (A-Wing) - Linux Guru Netserve Consultants - http://www.domaincity.co.uk/ A-Wing Internet Services - http://www.a-wing.co.uk/ Random quote 187: Our OS who art in CPU, UNIX be thy name. Thy programs run, thy syscalls done, in kernel as it is in user! - Olli Vinberg