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

Reply via email to