Adapt the code to work with the new imaplib2
imaplib renamed self.sslobj to self.sock and our overriden open() functions were failing for that reason when updating imaplib2 to v2.28. It turns out that all of our custom initializations are being done by stock imaplib2 now anyway, so there is no need to override them anymore. This lets us simplify the code we have to worry about. Move the verifycert() function to the imapserver.py file, it is now a callback function that is being handed to imaplib from there, so it makes sense to also define it in our imapserver function... (this also lets us easily make use of the verifycert function in the starttls case in the future) TODO: we need to examine if and why we still need to override the select() function, it is the only reason why we still wrap the IMAP4 classes. Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de> Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:

committed by
Nicolas Sebrecht

parent
1c0c19ad86
commit
3a91e296f0
@ -24,10 +24,11 @@ import offlineimap.accounts
|
||||
import hmac
|
||||
import socket
|
||||
import base64
|
||||
import time
|
||||
|
||||
from socket import gaierror
|
||||
try:
|
||||
from ssl import SSLError
|
||||
from ssl import SSLError, cert_time_to_seconds
|
||||
except ImportError:
|
||||
# Protect against python<2.6, use dummy and won't get SSL errors.
|
||||
SSLError = None
|
||||
@ -204,9 +205,12 @@ class IMAPServer:
|
||||
self.ui.connecting(self.hostname, self.port)
|
||||
imapobj = imaplibutil.WrappedIMAP4_SSL(self.hostname,
|
||||
self.port,
|
||||
self.sslclientkey, self.sslclientcert,
|
||||
self.sslclientkey,
|
||||
self.sslclientcert,
|
||||
self.sslcacertfile,
|
||||
self.verifycert,
|
||||
timeout=socket.getdefaulttimeout(),
|
||||
cacertfile = self.sslcacertfile)
|
||||
)
|
||||
else:
|
||||
self.ui.connecting(self.hostname, self.port)
|
||||
imapobj = imaplibutil.WrappedIMAP4(self.hostname, self.port,
|
||||
@ -403,6 +407,47 @@ class IMAPServer:
|
||||
|
||||
self.ui.debug('imap', 'keepalive: bottom of loop')
|
||||
|
||||
|
||||
def verifycert(self, cert, hostname):
|
||||
'''Verify that cert (in socket.getpeercert() format) matches hostname.
|
||||
CRLs are not handled.
|
||||
|
||||
Returns error message if any problems are found and None on success.
|
||||
'''
|
||||
errstr = "CA Cert verifying failed: "
|
||||
if not cert:
|
||||
return ('%s no certificate received' % errstr)
|
||||
dnsname = hostname.lower()
|
||||
certnames = []
|
||||
|
||||
# cert expired?
|
||||
notafter = cert.get('notAfter')
|
||||
if notafter:
|
||||
if time.time() >= cert_time_to_seconds(notafter):
|
||||
return '%s certificate expired %s' % (errstr, notafter)
|
||||
|
||||
# First read commonName
|
||||
for s in cert.get('subject', []):
|
||||
key, value = s[0]
|
||||
if key == 'commonName':
|
||||
certnames.append(value.lower())
|
||||
if len(certnames) == 0:
|
||||
return ('%s no commonName found in certificate' % errstr)
|
||||
|
||||
# Then read subjectAltName
|
||||
for key, value in cert.get('subjectAltName', []):
|
||||
if key == 'DNS':
|
||||
certnames.append(value.lower())
|
||||
|
||||
# And finally try to match hostname with one of these names
|
||||
for certname in certnames:
|
||||
if (certname == dnsname or
|
||||
'.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]):
|
||||
return None
|
||||
|
||||
return ('%s no matching domain name found in certificate' % errstr)
|
||||
|
||||
|
||||
class IdleThread(object):
|
||||
def __init__(self, parent, folder=None):
|
||||
self.parent = parent
|
||||
|
Reference in New Issue
Block a user