From 6a25f1930c28d452709ba60511af74a30effcaa8 Mon Sep 17 00:00:00 2001 From: "Herton R. Krzesinski" Date: Thu, 9 Apr 2020 18:07:34 -0300 Subject: [PATCH] Fix stale gss api authentication security context Inside __authn_gssapi function, the else clause is never executed because the return statement in the try section, which means if there is an error and a reconnect is tried, the authentication will now fail with due the stale self.gss_vc value. For example, offlineimap will be stuck after any socket error and unable to reconnect, even if I have a valid kerberos ticket: ======================================================================== abort: command: FETCH => socket error: - Too many read 0 command: FETCH => socket error: - Too many read 0 GSSAPI authentication failed: AUTHENTICATE command error: BAD ['AUTHENTICATE aborted']. Data: BLMC2 AUTHENTICATE GSSAPI Enter password for user 'XXX': ======================================================================== You can verify this try..finally behaviour with this slightly modified example that I copied from python documentation: >>> def divide(x, y): ... try: ... result = x / y ... return 1 ... except ZeroDivisionError: ... print("division by zero!") ... else: ... print("result is", result) ... finally: ... print("executing finally clause") ... >>> divide(2, 1) executing finally clause 1 >>> The else section is never executed with a return inside try. To fix the issue here, instead of relying on else clause, just clear gss_vc always inside finally, and we don't need to handle any exception to set self.gssapi, it can be left False by default and just set to True after authentication is done. I'm running with this fix and now offlineimap doesn't stop requiring manual intervention, and succesfully re-authenticate after errors while fetching data. Signed-off-by: Herton R. Krzesinski Signed-off-by: Nicolas Sebrecht --- offlineimap/imapserver.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/offlineimap/imapserver.py b/offlineimap/imapserver.py index 600ce65..6d12736 100644 --- a/offlineimap/imapserver.py +++ b/offlineimap/imapserver.py @@ -356,16 +356,13 @@ class IMAPServer(object): return False self.connectionlock.acquire() + self.gssapi = False try: imapobj.authenticate('GSSAPI', self.__gsshandler) - return True - except imapobj.error as e: - self.gssapi = False - raise - else: self.gssapi = True - self.gss_vc = None + return True finally: + self.gss_vc = None self.connectionlock.release() def __authn_cram_md5(self, imapobj):