@@ -26,14 +26,15 @@ def __init__(self, **config):
2626 raise ValueError ('sasl_kerberos_service_name or sasl_kerberos_name required for GSSAPI sasl configuration' )
2727 self ._is_done = False
2828 self ._is_authenticated = False
29+ self .gssapi_name = None
2930 if config .get ('sasl_kerberos_name' , None ) is not None :
3031 self .auth_id = str (config ['sasl_kerberos_name' ])
32+ if isinstance (config ['sasl_kerberos_name' ], gssapi .Name ):
33+ self .gssapi_name = config ['sasl_kerberos_name' ]
3134 else :
3235 kerberos_domain_name = config .get ('sasl_kerberos_domain_name' , '' ) or config .get ('host' , '' )
3336 self .auth_id = config ['sasl_kerberos_service_name' ] + '@' + kerberos_domain_name
34- if isinstance (config .get ('sasl_kerberos_name' , None ), gssapi .Name ):
35- self .gssapi_name = config ['sasl_kerberos_name' ]
36- else :
37+ if self .gssapi_name is None :
3738 self .gssapi_name = gssapi .Name (self .auth_id , name_type = gssapi .NameType .hostbased_service ).canonicalize (gssapi .MechType .kerberos )
3839 self ._client_ctx = gssapi .SecurityContext (name = self .gssapi_name , usage = 'initiate' )
3940 self ._next_token = self ._client_ctx .step (None )
@@ -43,9 +44,8 @@ def auth_bytes(self):
4344 # so mark is_done after the final auth_bytes are provided
4445 # in practice we'll still receive a response when using SaslAuthenticate
4546 # but not when using the prior unframed approach.
46- if self ._client_ctx . complete :
47+ if self ._is_authenticated :
4748 self ._is_done = True
48- self ._is_authenticated = True
4949 return self ._next_token or b''
5050
5151 def receive (self , auth_bytes ):
@@ -74,6 +74,13 @@ def receive(self, auth_bytes):
7474 ]
7575 # add authorization identity to the response, and GSS-wrap
7676 self ._next_token = self ._client_ctx .wrap (b'' .join (message_parts ), False ).message
77+ # We need to identify the last token in auth_bytes();
78+ # we can't rely on client_ctx.complete because it becomes True after generating
79+ # the second-to-last token (after calling .step(auth_bytes) for the final time)
80+ # We could introduce an additional state variable (i.e., self._final_token),
81+ # but instead we just set _is_authenticated. Since the plugin interface does
82+ # not read is_authenticated() until after is_done() is True, this should be fine.
83+ self ._is_authenticated = True
7784
7885 def is_done (self ):
7986 return self ._is_done
0 commit comments