changeset 544859c64f78 in /home/hg/repos/python-nbxmpp
details:http://hg.gajim.org/python-nbxmpp?cmd=changeset;node=544859c64f78
description: Add possibility to restrict authentication mechanisms used during
login.
Fixes #20
diffstat:
nbxmpp/auth_nb.py | 36 +++++++++++++++++++++++++++++-------
nbxmpp/client_nb.py | 19 ++++++++++++++++---
2 files changed, 45 insertions(+), 10 deletions(-)
diffs (144 lines):
diff -r c79cbe36a94e -r 544859c64f78 nbxmpp/auth_nb.py
--- a/nbxmpp/auth_nb.py Wed Feb 26 11:22:41 2014 +0100
+++ b/nbxmpp/auth_nb.py Sat Mar 01 20:53:52 2014 +0100
@@ -91,25 +91,35 @@
"""Helper function. Used for SCRAM-SHA-1, SCRAM-SHA-1-PLUS
authentication"""
return dict(s.split('=', 1) for s in chatter.split(','))
+SASL_AUTHENTICATION_MECHANISMS = \
+ set(['ANONYMOUS', 'EXTERNAL', 'GSSAPI', 'SCRAM-SHA-1-PLUS', 'SCRAM-SHA-1',
+ 'DIGEST-MD5', 'PLAIN', 'X-MESSENGER-OAUTH2'])
+
class SASL(PlugIn):
"""
Implements SASL authentication. Can be plugged into NonBlockingClient
to start authentication
"""
- def __init__(self, username, password, on_sasl, channel_binding):
+ def __init__(self, username, password, on_sasl, channel_binding,
+ auth_mechs):
"""
:param username: XMPP username
:param password: XMPP password
:param on_sasl: Callback, will be called after each SASL auth-step.
:param channel_binding: TLS channel binding data, None if the
binding data is not available
+ :param auth_mechs: Set of valid authentication mechanisms.
+ Possible entries are:
+ 'ANONYMOUS', 'EXTERNAL', 'GSSAPI', 'SCRAM-SHA-1-PLUS',
+ 'SCRAM-SHA-1', 'DIGEST-MD5', 'PLAIN', 'X-MESSENGER-OAUTH2'
"""
PlugIn.__init__(self)
self.username = username
self.password = password
self.on_sasl = on_sasl
self.channel_binding = channel_binding
+ self.enabled_auth_mechs = auth_mechs
self.realm = None
def plugin(self, owner):
@@ -146,7 +156,7 @@
Start authentication. Result can be obtained via "SASL.startsasl"
attribute and will be either SASL_SUCCESS or SASL_FAILURE
- Note that successfull auth will take at least two Dispatcher.Process()
+ Note that successful auth will take at least two Dispatcher.Process()
calls.
"""
if self.startsasl:
@@ -169,10 +179,22 @@
self.startsasl='not-supported'
log.info('SASL not supported by server')
return
- self.mecs = []
- for mec in feats.getTag('mechanisms', namespace=NS_SASL).getTags(
- 'mechanism'):
- self.mecs.append(mec.getData())
+
+ self.mecs = set(
+ mec.getData()
+ for mec
+ in feats.getTag('mechanisms',
namespace=NS_SASL).getTags('mechanism')
+ ) & self.enabled_auth_mechs
+
+ # Password based authentication mechanism ordered by strength.
+ # If the server supports a mechanism disable all weaker mechanisms.
+ password_auth_mechs_strength = ('SCRAM-SHA-1-PLUS', 'SCRAM-SHA-1',
+ 'DIGEST-MD5', 'PLAIN', 'X-MESSENGER-OAUTH2')
+ for i in range(0, len(password_auth_mechs_strength)):
+ if password_auth_mechs_strength[i] in self.mecs:
+ for m in password_auth_mechs_strength[i + 1:]:
+ self.mecs.discard(m)
+ break
self._owner.RegisterHandler('challenge', self.SASLHandler,
xmlns=NS_SASL)
@@ -508,7 +530,7 @@
class NonBlockingNonSASL(PlugIn):
"""
- Implements old Non-SASL (JEP-0078) authentication used in jabberd1.4 and
+ Implements old Non-SASL (XEP-0078) authentication used in jabberd1.4 and
transport authentication
"""
diff -r c79cbe36a94e -r 544859c64f78 nbxmpp/client_nb.py
--- a/nbxmpp/client_nb.py Wed Feb 26 11:22:41 2014 +0100
+++ b/nbxmpp/client_nb.py Sat Mar 01 20:53:52 2014 +0100
@@ -23,6 +23,7 @@
import socket
import transports_nb, dispatcher_nb, auth_nb, roster_nb, protocol, bosh
from protocol import NS_TLS
+from nbxmpp.auth_nb import SASL_AUTHENTICATION_MECHANISMS
import logging
log = logging.getLogger('nbxmpp.client_nb')
@@ -472,7 +473,8 @@
### follows code for authentication, resource bind, session and roster download
###############################################################################
- def auth(self, user, password, resource='', sasl=True, on_auth=None):
+ def auth(self, user, password, resource='', sasl=True, on_auth=None,
+ auth_mechs=None):
"""
Authenticate connnection and bind resource. If resource is not provided
random one or library name used
@@ -483,6 +485,11 @@
:param sasl: Boolean indicating if SASL shall be used. (default: True)
:param on_auth: Callback, called after auth. On auth failure, argument
is None.
+ :param auth_mechs: Set of valid authentification mechanisms. If None
all
+ authentification mechanisms will be allowed. Possible entries
are:
+ 'ANONYMOUS', 'EXTERNAL', 'GSSAPI', 'SCRAM-SHA-1-PLUS',
+ 'SCRAM-SHA-1', 'DIGEST-MD5', 'PLAIN', 'X-MESSENGER-OAUTH2',
+ 'XEP-0078'
"""
self._User, self._Password = user, password
self._Resource, self._sasl = resource, sasl
@@ -494,6 +501,10 @@
assert (self._channel_binding != None)
except NotImplementedError:
pass
+ if auth_mechs == None:
+ self._auth_mechs = SASL_AUTHENTICATION_MECHANISMS |
set(['XEP-0078'])
+ else:
+ self._auth_mechs = auth_mechs
self.on_auth = on_auth
self._on_doc_attrs()
return
@@ -525,10 +536,12 @@
"""
if self._sasl:
auth_nb.SASL.get_instance(self._User, self._Password,
- self._on_start_sasl, self._channel_binding).PlugIn(self)
+ self._on_start_sasl, self._channel_binding,
+ self._auth_mechs).PlugIn(self)
if not hasattr(self, 'SASL'):
return
- if not self._sasl or self.SASL.startsasl == 'not-supported':
+ if ('XEP-0078' in self._auth_mechs
+ and (not self._sasl or self.SASL.startsasl == 'not-supported')):
if not self._Resource:
self._Resource = 'xmpppy'
auth_nb.NonBlockingNonSASL.get_instance(self._User, self._Password,
_______________________________________________
Commits mailing list
[email protected]
http://lists.gajim.org/cgi-bin/listinfo/commits