Fix SASL mechanism selection bug.

ANONYMOUS was being treated as PLAIN, mechanism was being chosen
purely from supported mechanisms, not those provided by the server.

Broke nested handler methods into top-level methods.
This commit is contained in:
Lance Stout 2011-06-29 14:05:27 -07:00
parent 3b1f3fddf0
commit 9ed972ffeb

View file

@ -112,6 +112,23 @@ class ClientXMPP(BaseXMPP):
self.default_ns, self.default_ns,
'jabber:iq:roster')), 'jabber:iq:roster')),
self._handle_roster)) self._handle_roster))
self.register_handler(
Callback('SASL Success',
MatchXPath(sasl.Success.tag_name()),
self._handle_sasl_success,
instream=True,
once=True))
self.register_handler(
Callback('SASL Failure',
MatchXPath(sasl.Failure.tag_name()),
self._handle_sasl_fail,
instream=True,
once=True))
self.register_handler(
Callback('STARTTLS Proceed',
MatchXPath(tls.Proceed.tag_name()),
self._handle_starttls_proceed,
instream=True))
self.register_feature('starttls', self._handle_starttls, self.register_feature('starttls', self._handle_starttls,
restart=True, restart=True,
@ -130,7 +147,7 @@ class ClientXMPP(BaseXMPP):
self._handle_sasl_plain, self._handle_sasl_plain,
priority=1) priority=1)
self.register_sasl_mechanism('ANONYMOUS', self.register_sasl_mechanism('ANONYMOUS',
self._handle_sasl_plain, self._handle_sasl_anonymous,
priority=0) priority=0)
def connect(self, address=tuple(), reattempt=True, use_tls=True): def connect(self, address=tuple(), reattempt=True, use_tls=True):
@ -349,22 +366,9 @@ class ClientXMPP(BaseXMPP):
Arguments: Arguments:
features -- The stream:features element. features -- The stream:features element.
""" """
def tls_proceed(proceed):
"""Restart the XML stream when TLS is accepted."""
log.debug("Starting TLS")
if self.start_tls():
self.features.append('starttls')
raise RestartStream()
if not self.use_tls: if not self.use_tls:
return False return False
elif self.ssl_support: elif self.ssl_support:
self.register_handler(
Callback('STARTTLS Proceed',
MatchXPath(tls.Proceed.tag_name()),
tls_proceed,
instream=True))
self.send(features['starttls'], now=True) self.send(features['starttls'], now=True)
return True return True
else: else:
@ -372,6 +376,13 @@ class ClientXMPP(BaseXMPP):
" to some servers, and has not been found.") " to some servers, and has not been found.")
return False return False
def _handle_starttls_proceed(self, proceed):
"""Restart the XML stream when TLS is accepted."""
log.debug("Starting TLS")
if self.start_tls():
self.features.append('starttls')
raise RestartStream()
def _handle_sasl_auth(self, features): def _handle_sasl_auth(self, features):
""" """
Handle authenticating using SASL. Handle authenticating using SASL.
@ -379,46 +390,32 @@ class ClientXMPP(BaseXMPP):
Arguments: Arguments:
features -- The stream features stanza. features -- The stream features stanza.
""" """
def sasl_success(stanza):
"""SASL authentication succeeded. Restart the stream."""
self.authenticated = True
self.features.append('mechanisms')
raise RestartStream()
def sasl_fail(stanza):
"""SASL authentication failed. Disconnect and shutdown."""
log.info("Authentication failed.")
self.event("failed_auth", direct=True)
self.disconnect()
log.debug("Starting SASL Auth")
return True
self.register_handler(
Callback('SASL Success',
MatchXPath(sasl.Success.tag_name()),
sasl_success,
instream=True,
once=True))
self.register_handler(
Callback('SASL Failure',
MatchXPath(sasl.Failure.tag_name()),
sasl_fail,
instream=True,
once=True))
for priority, mech in self._sasl_mechanism_priorities: for priority, mech in self._sasl_mechanism_priorities:
if mech in self._sasl_mechanism_handlers: if mech in features['mechanisms']:
handler = self._sasl_mechanism_handlers[mech] handler = self._sasl_mechanism_handlers[mech]
if handler(self): if handler(self):
break break
else: else:
log.error("No appropriate login method.") log.error("No appropriate login method.")
self.event("no_auth", direct=True)
self.disconnect() self.disconnect()
return True return True
def _handle_sasl_success(self, stanza):
"""SASL authentication succeeded. Restart the stream."""
self.authenticated = True
self.features.append('mechanisms')
raise RestartStream()
def _handle_sasl_fail(self, stanza):
"""SASL authentication failed. Disconnect and shutdown."""
log.info("Authentication failed.")
self.event("failed_auth", direct=True)
self.disconnect()
log.debug("Starting SASL Auth")
return True
def _handle_sasl_plain(self, xmpp): def _handle_sasl_plain(self, xmpp):
""" """
Attempt to authenticate using SASL PLAIN. Attempt to authenticate using SASL PLAIN.