From 968d5520dab5ac5188cc0070cd3acc492bfd023f Mon Sep 17 00:00:00 2001 From: Steve Purcell Date: Fri, 3 May 2013 14:56:20 +0100 Subject: [PATCH] Allow transport-type tunnels to the IMAP servers It's nice to set up an ssh tunnel command which forwards an IMAP tcp port inside an encrypted session, e.g. with ssh's "-W" flag. In this case the tunnelled connection still requires authentication inside IMAP session, because this is transport-only tunnel that substitutes normal TCP/SSL connection. New directive, 'transporttunnel' was added: it specifies the command that will create the tunnel. Only one type of tunnel must be specified for a single repository: we can't have both preauthenticated and transport-type tunnels, they won't chain together. From: Steve Purcell Signed-off-by: Eygene Ryabinkin --- Changelog.rst | 2 ++ offlineimap.conf | 23 +++++++++++++++++++++++ offlineimap/imapserver.py | 25 ++++++++++++++++++++----- offlineimap/repository/IMAP.py | 3 +++ 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Changelog.rst b/Changelog.rst index 5a17b90..8fe9e04 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -17,6 +17,8 @@ WIP (add new stuff for the next release) * Allow mbnames output to be sorted by a custom sort key by specifying a 'sort_keyfunc' function in the [mbnames] section of the config. * Support SASL PLAIN authentication method. (Andreas Mack) +* Support transport-only tunnels that requre full IMAP authentication. + (Steve Purcell) OfflineIMAP v6.5.5-rc1 (2012-09-05) =================================== diff --git a/offlineimap.conf b/offlineimap.conf index 9aba014..b72d84a 100644 --- a/offlineimap.conf +++ b/offlineimap.conf @@ -365,6 +365,8 @@ remoteuser = username # # remote_identity = authzuser +########## Passwords + # There are six ways to specify the password for the IMAP server: # # 1. No password at all specified in the config file. @@ -408,6 +410,27 @@ remoteuser = username ########## Advanced settings +# Tunnels. There are two types: +# +# - preauth: they teleport your connection to the remote system +# and you don't need to authenticate yourself there; the sole +# fact that you succeeded to get the tunnel running is enough. +# This tunnel type was explained above in the 'Passwords' section. +# +# - transport: the just provide the transport (probably encrypted) +# to the IMAP server, but you still need to authenticate at the +# IMAP server. +# +# Tunnels are currently working only with IMAP servers and their +# derivatives (currently, GMail). Additionally, for GMail accounts +# preauth tunnel settings are ignored: we don't believe that there +# are ways to preauthenticate at Google mail system IMAP servers. +# +# You must choose at most one tunnel type, be wise M'Lord. +# +# preauthtunnel = ssh -q imaphost '/usr/bin/imapd ./Maildir' +# transporttunnel = openssl s_client -host myimap -port 993 -quiet + # Some IMAP servers need a "reference" which often refers to the "folder # root". This is most commonly needed with UW IMAP, where you might # need to specify the directory in which your mail is stored. The diff --git a/offlineimap/imapserver.py b/offlineimap/imapserver.py index f6d7c27..2d9a1b1 100644 --- a/offlineimap/imapserver.py +++ b/offlineimap/imapserver.py @@ -52,14 +52,28 @@ class IMAPServer: self.ui = getglobalui() self.repos = repos self.config = repos.getconfig() - self.tunnel = repos.getpreauthtunnel() - self.usessl = repos.getssl() - self.username = None if self.tunnel else repos.getuser() + + self.preauth_tunnel = repos.getpreauthtunnel() + self.transport_tunnel = repos.gettransporttunnel() + if self.preauth_tunnel and self.transport_tunnel: + raise OfflineImapError('%s: ' % repos + \ + 'you must enable precisely one ' + 'type of tunnel (preauth or transport), ' + 'not both', OfflineImapError.ERROR.REPO) + self.tunnel = \ + self.preauth_tunnel if self.preauth_tunnel \ + else self.transport_tunnel + + self.username = \ + None if self.preauth_tunnel else repos.getuser() self.user_identity = repos.get_remote_identity() self.password = None self.passworderror = None self.goodpassword = None - self.hostname = None if self.tunnel else repos.gethost() + + self.usessl = repos.getssl() + self.hostname = \ + None if self.preauth_tunnel else repos.gethost() self.port = repos.getport() if self.port == None: self.port = 993 if self.usessl else 143 @@ -69,6 +83,7 @@ class IMAPServer: self.sslversion = repos.getsslversion() if self.sslcacertfile is None: self.verifycert = None # disable cert verification + self.delim = None self.root = None self.maxconnections = repos.getmaxconnections() @@ -356,7 +371,7 @@ class IMAPServer: imapobj = imaplibutil.WrappedIMAP4(self.hostname, self.port, timeout=socket.getdefaulttimeout()) - if not self.tunnel: + if not self.preauth_tunnel: try: self._authn_helper(imapobj) self.goodpassword = self.password diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index ab466b6..35190c0 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -200,6 +200,9 @@ class IMAPRepository(BaseRepository): def getpreauthtunnel(self): return self.getconf('preauthtunnel', None) + def gettransporttunnel(self): + return self.getconf('transporttunnel', None) + def getreference(self): return self.getconf('reference', '') -- 1.8.1.3