Make OS-default CA certificate file to be requested explicitely

This simplifies logics for the user, especially if he uses both
fingerprint and certificate validation: it is hard to maintain
the compatibility with the prior behaviour and to avoid getting
default CA bundle to be disabled when fingerprint verification
is requested.

See
  http://thread.gmane.org/gmane.mail.imap.offlineimap.general/6695
for discussion about this change.

Default CA bundle is requested via 'sslcertfile = OS-DEFAULT'.

I had also enforced all cases where explicitely-requested CA bundles
are non-existent to be hard errors: when users asks us to use CA
bundle (and, thus, certificate validation), but we can't find one,
we must error out rather than happily continue and downgrade to
no validation.

Reported-By: Edd Barrett <edd@theunixzoo.co.uk>
Reviewed-By: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
This commit is contained in:
Eygene Ryabinkin
2015-01-18 10:45:46 +03:00
parent 9b911faa58
commit f69613965f
4 changed files with 86 additions and 27 deletions

View File

@ -25,7 +25,7 @@ from offlineimap.repository.Base import BaseRepository
from offlineimap import folder, imaputil, imapserver, OfflineImapError
from offlineimap.folder.UIDMaps import MappedIMAPFolder
from offlineimap.threadutil import ExitNotifyThread
from offlineimap.utils.distro import get_os_sslcertfile
from offlineimap.utils.distro import get_os_sslcertfile, get_os_sslcertfile_searchpath
class IMAPRepository(BaseRepository):
@ -201,16 +201,44 @@ class IMAPRepository(BaseRepository):
return self.getconf_xform('sslclientkey', xforms, None)
def getsslcacertfile(self):
"""Return the absolute path of the CA certfile to use, if any"""
"""Determines CA bundle.
Returns path to the CA bundle. It is either explicitely specified
or requested via "OS-DEFAULT" value (and we will search known
locations for the current OS and distribution).
If search via "OS-DEFAULT" route yields nothing, we will throw an
exception to make our callers distinguish between not specified
value and non-existent default CA bundle.
It is also an error to specify non-existent file via configuration:
it will error out later, but, perhaps, with less verbose explanation,
so we will also throw an exception. It is consistent with
the above behaviour, so any explicitely-requested configuration
that doesn't result in an existing file will give an exception.
"""
xforms = [os.path.expanduser, os.path.expandvars, os.path.abspath]
cacertfile = self.getconf_xform('sslcacertfile', xforms,
get_os_sslcertfile())
cacertfile = self.getconf_xform('sslcacertfile', xforms, None)
if self.getconf('sslcacertfile', None) == "OS-DEFAULT":
cacertfile = get_os_sslcertfile()
if cacertfile == None:
searchpath = get_os_sslcertfile_searchpath()
if searchpath:
reason = "Default CA bundle was requested, "\
"but no existing locations available. "\
"Tried %s." % (", ".join(searchpath))
else:
reason = "Default CA bundle was requested, "\
"but OfflineIMAP doesn't know any for your "\
"current operating system."
raise OfflineImapError(reason, OfflineImapError.ERROR.REPO)
if cacertfile is None:
return None
if not os.path.isfile(cacertfile):
raise SyntaxWarning("CA certfile for repository '%s' could "
"not be found. No such file: '%s'" \
% (self.name, cacertfile))
reason = "CA certfile for repository '%s' couldn't be found. "\
"No such file: '%s'" % (self.name, cacertfile)
raise OfflineImapError(reason, OfflineImapError.ERROR.REPO)
return cacertfile
def getsslversion(self):