Thanks a lot for your answers! Unfortunately I didn't have a chance to sit down and implement the thing yet, but after looking through the Dovecot code I have some additional questions. Please see inline below.
On Fri, Sep 27, 2013 at 10:13 PM, Timo Sirainen <t...@iki.fi> wrote: > On 26.9.2013, at 10.01, Nicolay Vizovitin <vizovi...@gmail.com> wrote: > > > I'm about to start developing authentication/password-scheme module for > > Dovecot. So I would like to get some advice before actually committing to > > doing things in particular way. Hope somebody will be able to help me :) > > > > For the record, I am currently targeting latest stable Dovecot version > > 2.2.5. > > > > I have an SQL DB with mail users' authentication data. Passwords are > stored > > either encrypted via system crypt(3) or ciphered with some custom > algorithm > > (think something symmetrical like AES, so passwords can be decrypted into > > plain form). I want to use this DB as both userdb and passdb backend. The > > issue, of course, is with ciphered passwords support. > > > > 1) Is it feasible to just implement a new password scheme for ciphered > > passwords support and still use stock passdb driver in Dovecot for SQL DB > > access? > > Plugins can implement new password schemes. > http://dovecot.org/patches/password-scheme-lmpass.c is an example, > although I'm not sure if it compiles with v2.2. > > > So that passwords in this scheme would be treated as PLAIN (in a > > sense that both cleartext and shared secret authentication methods would > > work). > > You could do that in a slightly ugly way by setting > password_generate=plain_generate(), so password_scheme_is_alias() returns > TRUE for that. > OK, I figured I had to use something like that. However, after looking through the code I don't think it'll work with shared-secret authentication mechanisms. Looking at struct password_scheme definition: int (*password_verify)(const char *plaintext, const char *user, const unsigned char *raw_password, size_t size, const char **error_r); void (*password_generate)(const char *plaintext, const char *user, const unsigned char **raw_password_r, size_t *size_r); password_generate would have to be equal to plain_generate(). So I'm left with password_verify, but its signature implies that it is called only when plaintext password is available from client, which is not the case with shared-secret mechanisms. A simple question to verify my hypothesis: would PLAIN-TRUNC password scheme work with CRAM-MD5 authentication? My understanding of CRAM-MD5 and what PLAIN-TRUNC does tells me it cannot work even in theory. Something tells me that I rather need a new password encoding than just a password scheme. Yet there is no way to extend password encodings, as far as I can tell (at least from looking at password_decode()). So I guess I can't use new password scheme to solve my problem without patching Dovecot, can I? > > 2) Provided I implement custom password scheme for ciphered passwords, > what > > is the best way to be capable to perform authentication against both > > ciphered and encrypted passwords? Ciphered and encrypted passwords are > > stored in different fields of SQL table (one of them is NULL when the > other > > one is set). > > a) Do I define two passdb clauses with their own default_pass_scheme > > (equal to my new scheme or CRYPT for encrypted passwords) and use > fallback > > to effectively check both of them? > > b) Do I modify SQL query so that it prefixes existing password with > > correct scheme (I'm not sure this will be easy enough to do)? > > By "ciphered" I understand you mean encrypted, and by "encrypted" you mean > hashed.. Scheme prefix would work, mysql and postgresql have complex enough > string manipulation functions to make this possible I think. > Well, yes, I meant exactly that. :) > > 3) Is it mandatory to provide password generation routine for custom > > password scheme? When it will be used? > > doveadm pw command would use it for example. But as mentioned, you should > set it to plain_generate. > > > 4) Maybe it's better to just implement a plugin that serves as both > userdb > > and passdb driver (in other words a kind of generic authentication > module)? > > What are advantages and disadvantages of each method - custom password > > scheme + stock SQL driver VS. custom userdb and passdb driver? > Fortunately, > > I already have all the required credentials lookup and verification code. > > So in any case the question is only in figuring out suitable Dovecot APIs > > and integrating the existing code. > > Implementing yet another sql passdb sounds like quite a lot of work. > I guess it is. But I'd rather trade more work now for more maintainability later (if implementing passdb would help). I don't really want to patch Dovecot as future changes may render the patch incompatible. I could invest some time into the patch provided there is a chance it would get merged into upstream. Otherwise I'd rather use my existing code for accessing SQL DB and password verification/lookup and integrate it into passdb code. BTW, is there anything else passdb/userdb plugin can do other than its direct responsibilities and returning extra userdb fields? In other words, are there any (theoretical) advantages to implementing passdb instead of password scheme? > > 7) Somewhat unrelated question: what is the best way to test IMAP (and > > maybe POP3 as well) server performance and compare it to another server? > > I'm interested in both login performance (the part I will influence) and > > performance with many mails in mailbox. I heard imaptest is suitable for > > this task. Are there any recipes or example testing scenarios you might > > share? ;) > > There are only bad non-realistic benchmarks available currently. With > imaptest you can easily test the login performance though: > > imaptest user=test%d.%d - select=0 clients=100 > > Thanks, will try it out later. -- Best regards, Nick