diff --git a/head/ChangeLog b/head/ChangeLog index ed40238..57fc458 100644 --- a/head/ChangeLog +++ b/head/ChangeLog @@ -1,3 +1,30 @@ +2002-07-04 15:36 jgoerzen + + * debian/changelog: Updated with tunnel feature + +2002-07-04 15:31 jgoerzen + + * offlineimap/imapserver.py: Another tunnel fix + +2002-07-04 15:30 jgoerzen + + * offlineimap.conf, offlineimap.py, offlineimap/imaplib.py, + offlineimap/imapserver.py: Updated with preliminary tunnel support + +2002-07-04 14:47 jgoerzen + + * offlineimap.py, debian/changelog, offlineimap/version.py: Added + support for remotepassfile and bumped versions + +2002-07-04 14:44 jgoerzen + + * offlineimap.conf: Added some more examples as well as + remotepassfile. + +2002-07-04 11:59 jgoerzen + + * ChangeLog: Updated after 2.0.1 + 2002-07-04 11:58 jgoerzen * offlineimap.py, debian/changelog, offlineimap/version.py: Updated diff --git a/head/debian/changelog b/head/debian/changelog index a0e522e..02ca232 100644 --- a/head/debian/changelog +++ b/head/debian/changelog @@ -1,6 +1,7 @@ offlineimap (2.0.2) unstable; urgency=low * Added support for remotepassfile. Closes: #151943. + * Added support for preauth tunnels. -- John Goerzen Thu, 4 Jul 2002 14:46:23 -0500 diff --git a/head/offlineimap.conf b/head/offlineimap.conf index deb82df..a18f582 100644 --- a/head/offlineimap.conf +++ b/head/offlineimap.conf @@ -106,6 +106,17 @@ remoteuser = username # file, which is referenced by the remotefile option. Example: # # remotepassfile = ~/Password.IMAP.Account1 +# +# 4. With a preauth tunnel. With this method, you invoke an external +# program that is guaranteed *NOT* to ask for a password, but rather +# to read from stdin and write to stdout an IMAP procotol stream +# that begins life in the PREAUTH state. When you use a tunnel, +# you do NOT specify a user or password (if you do, they'll be +# ignored.) Instead, you specify a preauthtunnel, as this +# example illustrates for Courier IMAP on Debian: +# +# preauthtunnel = ssh -q imaphost '/usr/bin/imapd ./Maildir' +# # Specify local repository. Your IMAP folders will be synchronized # to maildirs created under this path. OfflineIMAP will create the diff --git a/head/offlineimap.py b/head/offlineimap.py index fa83eda..247ee5a 100644 --- a/head/offlineimap.py +++ b/head/offlineimap.py @@ -48,6 +48,7 @@ server = None remoterepos = None localrepos = None passwords = {} +tunnels = {} threadutil.initInstanceLimit("ACCOUNTLIMIT", config.getint("general", "maxsyncaccounts")) @@ -56,7 +57,9 @@ threadutil.initInstanceLimit("ACCOUNTLIMIT", config.getint("general", # asking for passwords simultaneously. for account in accounts: - if config.has_option(account, "remotepass"): + if config.has_option(account, "preauthtunnel"): + tunnels[account] = config.get(account, "preauthtunnel") + elif config.has_option(account, "remotepass"): passwords[account] = config.get(account, "remotepass") elif config.has_option(account, "remotepassfile"): passfile = os.path.expanduser(config.get(account, "remotepassfile")) @@ -90,11 +93,17 @@ def syncaccount(accountname, *args): if config.has_option(accountname, "remoteport"): port = config.getint(accountname, "remoteport") ssl = config.getboolean(accountname, "ssl") + usetunnel = config.has_option(accountname, "preauthtunnel") + server = None # Connect to the remote server. - server = imapserver.IMAPServer(user, passwords[accountname], - host, port, ssl, - config.getint(accountname, "maxconnections")) + if usetunnel: + server = imapserver.IMAPServer(tunnel = tunnels[accountname], + maxconnections = config.getint(accountname, "maxconnections")) + else: + server = imapserver.IMAPServer(user, passwords[accountname], + host, port, ssl, + config.getint(accountname, "maxconnections")) remoterepos = repository.IMAP.IMAPRepository(config, accountname, server) # Connect to the Maildirs. diff --git a/head/offlineimap/imaplib.py b/head/offlineimap/imaplib.py index 2672eb1..dfaf5fa 100644 --- a/head/offlineimap/imaplib.py +++ b/head/offlineimap/imaplib.py @@ -17,10 +17,11 @@ Public functions: Internaldate2tuple # GET/SETACL contributed by Anthony Baxter April 2001. # IMAP4_SSL contributed by Tino Lange March 2002. # GET/SETQUOTA contributed by Andreas Zeidler June 2002. +# IMAP4_Tunnel contributed by John Goerzen July 2002 __version__ = "2.52" -import binascii, re, socket, time, random, sys +import binascii, re, socket, time, random, sys, os __all__ = ["IMAP4", "Internaldate2tuple", "Int2AP", "ParseFlags", "Time2Internaldate"] @@ -1020,7 +1021,37 @@ class IMAP4: i = 0 n -= 1 +class IMAP4_Tunnel(IMAP4): + """IMAP4 client class over a tunnel + Instantiate with: IMAP4_Tunnel(tunnelcmd) + + tunnelcmd -- shell command to generate the tunnel. + The result will be in PREAUTH stage.""" + + def __init__(self, tunnelcmd): + IMAP4.__init__(self, tunnelcmd) + + def open(self, host, port): + """The tunnelcmd comes in on host!""" + self.outfd, self.infd = os.popen2(host, "t", 0) + + def read(self, size): + retval = '' + while len(retval) < size: + retval += self.infd.read(size - len(retval)) + return retval + + def readline(self): + return self.infd.readline() + + def send(self, data): + self.outfd.write(data) + + def shutdown(self): + self.infd.close() + self.outfd.close() + class IMAP4_SSL(IMAP4): diff --git a/head/offlineimap/imapserver.py b/head/offlineimap/imapserver.py index 7e787cc..f8ced64 100644 --- a/head/offlineimap/imapserver.py +++ b/head/offlineimap/imapserver.py @@ -41,13 +41,15 @@ class UsefulIMAPMixIn: class UsefulIMAP4(UsefulIMAPMixIn, imaplib.IMAP4): pass class UsefulIMAP4_SSL(UsefulIMAPMixIn, imaplib.IMAP4_SSL): pass +class UsefulIMAP4_Tunnel(UsefulIMAPMixIn, imaplib.IMAP4_Tunnel): pass class IMAPServer: - def __init__(self, username, password, hostname, port = None, ssl = 1, - maxconnections = 1): + def __init__(self, username = None, password = None, hostname = None, + port = None, ssl = 1, maxconnections = 1, tunnel = None): self.username = username self.password = password self.hostname = hostname + self.tunnel = tunnel self.port = port self.usessl = ssl self.delim = None @@ -102,12 +104,15 @@ class IMAPServer: self.connectionlock.release() # Release until need to modify data # Generate a new connection. - if self.usessl: + if self.tunnel: + imapobj = UsefulIMAP4_Tunnel(self.tunnel) + elif self.usessl: imapobj = UsefulIMAP4_SSL(self.hostname, self.port) else: imapobj = UsefulIMAP4(self.hostname, self.port) - - imapobj.login(self.username, self.password) + + if not self.tunnel: + imapobj.login(self.username, self.password) if self.delim == None: self.delim, self.root = \