Port to python-gssapi from pykerberos
python-gssapi has a visible, active upstream and a more pleasant interface. python-gssapi is present in most distributions, while pykerberos is slated for removal from Fedora/RHEL/CentOS. Github-ref: https://github.com/OfflineIMAP/offlineimap/pull/529 Tested-by: Robbie Harwood <rharwood@redhat.com> Signed-off-by: Robbie Harwood <rharwood@redhat.com> Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
c8847ccff9
commit
88724949fa
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
import hmac
|
import hmac
|
||||||
import socket
|
import socket
|
||||||
import base64
|
|
||||||
import json
|
import json
|
||||||
import urllib
|
import urllib
|
||||||
import time
|
import time
|
||||||
@ -36,13 +35,10 @@ from offlineimap.ui import getglobalui
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# do we have a recent pykerberos?
|
import gssapi
|
||||||
have_gss = False
|
have_gss = True
|
||||||
import kerberos
|
|
||||||
if 'authGSSClientWrap' in dir(kerberos):
|
|
||||||
have_gss = True
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
have_gss = False
|
||||||
|
|
||||||
|
|
||||||
class IMAPServer(object):
|
class IMAPServer(object):
|
||||||
@ -55,9 +51,6 @@ class IMAPServer(object):
|
|||||||
delim The server's folder delimiter. Only valid after acquireconnection()
|
delim The server's folder delimiter. Only valid after acquireconnection()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
GSS_STATE_STEP = 0
|
|
||||||
GSS_STATE_WRAP = 1
|
|
||||||
|
|
||||||
def __init__(self, repos):
|
def __init__(self, repos):
|
||||||
""":repos: a IMAPRepository instance."""
|
""":repos: a IMAPRepository instance."""
|
||||||
|
|
||||||
@ -127,7 +120,6 @@ class IMAPServer(object):
|
|||||||
self.connectionlock = Lock()
|
self.connectionlock = Lock()
|
||||||
self.reference = repos.getreference()
|
self.reference = repos.getreference()
|
||||||
self.idlefolders = repos.getidlefolders()
|
self.idlefolders = repos.getidlefolders()
|
||||||
self.gss_step = self.GSS_STATE_STEP
|
|
||||||
self.gss_vc = None
|
self.gss_vc = None
|
||||||
self.gssapi = False
|
self.gssapi = False
|
||||||
|
|
||||||
@ -267,32 +259,34 @@ class IMAPServer(object):
|
|||||||
self.ui.debug('imap', 'xoauth2handler: returning "%s"'% auth_string)
|
self.ui.debug('imap', 'xoauth2handler: returning "%s"'% auth_string)
|
||||||
return auth_string
|
return auth_string
|
||||||
|
|
||||||
def __gssauth(self, response):
|
# Perform the next step handling a GSSAPI connection.
|
||||||
data = base64.b64encode(response)
|
# Client sends first, so token will be ignored if there is no context.
|
||||||
|
def __gsshandler(self, token):
|
||||||
|
if token == "":
|
||||||
|
token = None
|
||||||
try:
|
try:
|
||||||
if self.gss_step == self.GSS_STATE_STEP:
|
if not self.gss_vc:
|
||||||
if not self.gss_vc:
|
name = gssapi.Name('imap@' + self.hostname,
|
||||||
rc, self.gss_vc = kerberos.authGSSClientInit(
|
gssapi.NameType.hostbased_service)
|
||||||
'imap@' + self.hostname)
|
self.gss_vc = gssapi.SecurityContext(usage="initiate",
|
||||||
response = kerberos.authGSSClientResponse(self.gss_vc)
|
name=name)
|
||||||
rc = kerberos.authGSSClientStep(self.gss_vc, data)
|
|
||||||
if rc != kerberos.AUTH_GSS_CONTINUE:
|
|
||||||
self.gss_step = self.GSS_STATE_WRAP
|
|
||||||
elif self.gss_step == self.GSS_STATE_WRAP:
|
|
||||||
rc = kerberos.authGSSClientUnwrap(self.gss_vc, data)
|
|
||||||
response = kerberos.authGSSClientResponse(self.gss_vc)
|
|
||||||
rc = kerberos.authGSSClientWrap(
|
|
||||||
self.gss_vc, response, self.username)
|
|
||||||
response = kerberos.authGSSClientResponse(self.gss_vc)
|
|
||||||
except kerberos.GSSError as err:
|
|
||||||
# Kerberos errored out on us, respond with None to cancel the
|
|
||||||
# authentication
|
|
||||||
self.ui.debug('imap', '%s: %s'% (err[0][0], err[1][0]))
|
|
||||||
return None
|
|
||||||
|
|
||||||
if not response:
|
if not self.gss_vc.complete:
|
||||||
response = ''
|
response = self.gss_vc.step(token)
|
||||||
return base64.b64decode(response)
|
return response if response else ""
|
||||||
|
|
||||||
|
# Don't bother checking qop because we're over a TLS channel
|
||||||
|
# already. But hey, if some server started encrypting tomorrow,
|
||||||
|
# we'd be ready since krb5 always requests integrity and
|
||||||
|
# confidentiality support.
|
||||||
|
response = self.gss_vc.unwrap(token)
|
||||||
|
response = self.gss_vc.wrap(response.message, response.encrypted)
|
||||||
|
return response.message if response.message else ""
|
||||||
|
except gssapi.exceptions.GSSError as err:
|
||||||
|
# GSSAPI errored out on us; respond with None to cancel the
|
||||||
|
# authentication
|
||||||
|
self.ui.debug('imap', err.gen_message())
|
||||||
|
return None
|
||||||
|
|
||||||
def __start_tls(self, imapobj):
|
def __start_tls(self, imapobj):
|
||||||
if 'STARTTLS' in imapobj.capabilities and not self.usessl:
|
if 'STARTTLS' in imapobj.capabilities and not self.usessl:
|
||||||
@ -327,16 +321,14 @@ class IMAPServer(object):
|
|||||||
|
|
||||||
self.connectionlock.acquire()
|
self.connectionlock.acquire()
|
||||||
try:
|
try:
|
||||||
imapobj.authenticate('GSSAPI', self.__gssauth)
|
imapobj.authenticate('GSSAPI', self.__gsshandler)
|
||||||
return True
|
return True
|
||||||
except imapobj.error as e:
|
except imapobj.error as e:
|
||||||
self.gssapi = False
|
self.gssapi = False
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
self.gssapi = True
|
self.gssapi = True
|
||||||
kerberos.authGSSClientClean(self.gss_vc)
|
|
||||||
self.gss_vc = None
|
self.gss_vc = None
|
||||||
self.gss_step = self.GSS_STATE_STEP
|
|
||||||
finally:
|
finally:
|
||||||
self.connectionlock.release()
|
self.connectionlock.release()
|
||||||
|
|
||||||
@ -680,8 +672,7 @@ class IMAPServer(object):
|
|||||||
self.assignedconnections = []
|
self.assignedconnections = []
|
||||||
self.availableconnections = []
|
self.availableconnections = []
|
||||||
self.lastowner = {}
|
self.lastowner = {}
|
||||||
# reset kerberos state
|
# reset GSSAPI state
|
||||||
self.gss_step = self.GSS_STATE_STEP
|
|
||||||
self.gss_vc = None
|
self.gss_vc = None
|
||||||
self.gssapi = False
|
self.gssapi = False
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user