[Dovecot] checkpassword migration script in Python

Dan Udey dan at communicate.com
Wed Sep 3 09:33:24 EEST 2008


Hey all,

First post to the list, so here goes, hope I don't break any rules (I  
didn't see any rules about not being overly verbose)

I spent a long time looking for anything that would help me migrate  
from our old IMAP server to our new one without a lot of client-side  
fuss, multiple e-mail accounts, and so on. I find that a lot of our  
users get confused by having two 'inboxes' in Outlook (one local,  
unused, and one IMAP), so I figured the easier I could make it, the  
better.

I figured there must be some way to do what I was looking for, but I  
couldn't find it, so I hacked up a little something to do the job. As  
the saying goes, it's nasty, brutish, and short, but in my tests it's  
done everything I needed it to.



The problem: Our old mail system is hosted by another company,  
outsourced before I was hired, so I don't have access to the old user/ 
passwd database, nor to their e-mail store; thus, I cannot do a clean,  
simple migration by upgrading in-place as I have done on other servers.



The solution IMAP authentication proxying. The idea is that I don't  
need to know the password, because the user's mail client knows the  
password, so all I need is for it to tell me, and then I can create  
their user. That is what this script is for.



To use, set up your authentication backend (passdb) first, and then  
after that section, add a 'passdb checkpassword' section containing  
this script. Thus, the following will happen.

1. Valid users who log into your system will be authenticated as you  
would expect.
2. Users who could not be authenticated will fall through to the  
checkpassword section
3. Checkpassword will look for the user in the password database; if  
they exist, it is assumed that it is a valid user, but incorrect  
password, and checkpassword fails the user as well.
4. If the user is not currently in the database, it will initiate an  
IMAP4 connection to the remote host specified. If it succeeds in  
logging in to the remote host, then we assume that the user is a valid  
user and can be migrated to the local server. They are added to the  
database, along with their password. It then **fails the user's login  
regardless**
5. It /logs the username and password into the database/ so that  
another process can use that information to migrate their e-mail over  
to the new server (not yet implemented).
6. If the IMAP connection fails, the login is failed as well, and  
dovecot continues as normal until it has exhausted all other passdb  
backends.

Interested? A few things to note about the script:

1. It's a brutal hack. Really, ugly stuff. However, it gets the job  
done, if your system is similar enough to mine.
2. It only works on MySQL. I only use MySQL in our system, so there's  
no point for me to add other DBs, nor any way to test.
3. It doesn't support remote servers using SSL. Our current system  
doesn't use it, so again, it's hard to test.
4. It does not currently migrate mailboxes. I'm working on this (see  
below).
5. If your schema is at all different from mine, you will likely have  
to rewrite all of the SQL. There's not much I can do about this.
6. If your backend database doesn't use MySQL, you're largely boned.  
Exception: rewrite add_user() to do whatever you need to do to add  
users to your system.
7. The script will **ALWAYS RETURN A FAILED LOGIN TO DOVECOT**. This  
is because there are too many variables on every configuration, and  
writing code for all of them is absurd. This way, the user's first  
login will always fail, and their second login will always succeed. If  
you want to avoid this, place your normal passdb authentication **both  
before and after this checkpassword section**. That way, it will check  
once, fail, pass to checkpassword, and then check again, success.

TODO:
1. Make it not ugly. Break more junk off into functions (e.g. IMAP  
verification)
2. Send the user an e-mail ('Welcome to the server, sorry your mail is  
gone, we'll fix that soon')
3. Spawn another process to run imapsync in the background to migrate  
the user's old mailboxes over. This would be very site-dependent, as  
there are a lot of variables. It might be best done as a cronjob that  
polls the database every however often (1 minute? 2 minutes?) or a  
daemon that sits in the background watching the db for changes, or  
even accepting the data directly.
4. Stop being so verbose in my first postings to mailing lists.
5. Lots of other things.

URLS

Blah blah blah where's the code. Here you go.

Pretty syntax-highlighted version for browsing before you download, in  
case I'm an evil hacker:
	http://cdslash.net/temp/python/checkpassword.py
Ugly monochrome version for downloading so you don't get line numbers  
in your junk:
	http://cdslash.net/temp/python/checkpassword.raw


Questions, comments? I probably won't be on the list very long, so if  
you want to ask something or have a suggestion, feel free to let me  
know by e-mail at the address listed in the file's license  
notification. Alternately, find me on Freenode, occasionally in  
#dovecot or always in #macosx, as Darien, or some variant thereof.

PS: The code is licensed under a boilerplate MIT license lifted from  
the OSI license page. If you want it under a different license, let me  
know. ;)

Thanks,
Dan


More information about the dovecot mailing list