Use a set to track negotiated features.

Added guards to prevent renegotiating STARTTLS or SASL in cases where
servers don't behave properly.
This commit is contained in:
Lance Stout 2011-07-02 22:30:34 -07:00
parent fba235a801
commit b898b14b77
5 changed files with 18 additions and 5 deletions

View file

@ -83,7 +83,7 @@ class ClientXMPP(BaseXMPP):
"xmlns='%s'" % self.default_ns) "xmlns='%s'" % self.default_ns)
self.stream_footer = "</stream:stream>" self.stream_footer = "</stream:stream>"
self.features = [] self.features = set()
self._stream_feature_handlers = {} self._stream_feature_handlers = {}
self._stream_feature_order = [] self._stream_feature_order = []
@ -273,7 +273,7 @@ class ClientXMPP(BaseXMPP):
self.sessionstarted = False self.sessionstarted = False
self.bound = False self.bound = False
self.bindfail = False self.bindfail = False
self.features = [] self.features = set()
def session_timeout(): def session_timeout():
if not self.session_started_event.isSet(): if not self.session_started_event.isSet():

View file

@ -53,6 +53,8 @@ class feature_bind(base_plugin):
self.xmpp.set_jid(response['bind']['jid']) self.xmpp.set_jid(response['bind']['jid'])
self.xmpp.bound = True self.xmpp.bound = True
self.features.add('bind')
log.info("Node set to: %s" % self.xmpp.boundjid.full) log.info("Node set to: %s" % self.xmpp.boundjid.full)
if 'session' not in features['features']: if 'session' not in features['features']:

View file

@ -90,6 +90,11 @@ class feature_mechanisms(base_plugin):
Arguments: Arguments:
features -- The stream features stanza. features -- The stream features stanza.
""" """
if 'mechanisms' in self.xmpp.features:
# SASL authentication has already succeeded, but the
# server has incorrectly offered it again.
return False
for priority, mech in self._mechanism_priorities: for priority, mech in self._mechanism_priorities:
if mech in features['mechanisms']: if mech in features['mechanisms']:
log.debug('Attempt to use SASL %s' % mech) log.debug('Attempt to use SASL %s' % mech)
@ -105,7 +110,7 @@ class feature_mechanisms(base_plugin):
def _handle_success(self, stanza): def _handle_success(self, stanza):
"""SASL authentication succeeded. Restart the stream.""" """SASL authentication succeeded. Restart the stream."""
self.xmpp.authenticated = True self.xmpp.authenticated = True
self.xmpp.features.append('mechanisms') self.xmpp.features.add('mechanisms')
raise RestartStream() raise RestartStream()
def _handle_fail(self, stanza): def _handle_fail(self, stanza):

View file

@ -48,6 +48,8 @@ class feature_session(base_plugin):
iq.enable('session') iq.enable('session')
response = iq.send(now=True) response = iq.send(now=True)
self.xmpp.features.add('session')
log.debug("Established Session") log.debug("Established Session")
self.xmpp.sessionstarted = True self.xmpp.sessionstarted = True
self.xmpp.session_started_event.set() self.xmpp.session_started_event.set()

View file

@ -48,7 +48,11 @@ class feature_starttls(base_plugin):
Arguments: Arguments:
features -- The stream:features element. features -- The stream:features element.
""" """
if not self.xmpp.use_tls: if 'starttls' in self.xmpp.features:
# We have already negotiated TLS, but the server is
# offering it again, against spec.
return False
elif not self.xmpp.use_tls:
return False return False
elif self.xmpp.ssl_support: elif self.xmpp.ssl_support:
self.xmpp.send(features['starttls'], now=True) self.xmpp.send(features['starttls'], now=True)
@ -62,5 +66,5 @@ class feature_starttls(base_plugin):
"""Restart the XML stream when TLS is accepted.""" """Restart the XML stream when TLS is accepted."""
log.debug("Starting TLS") log.debug("Starting TLS")
if self.xmpp.start_tls(): if self.xmpp.start_tls():
self.xmpp.features.append('starttls') self.xmpp.features.add('starttls')
raise RestartStream() raise RestartStream()