[Checkins] SVN: Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/ User masquerading. Adapted from a patch against PAS 1.0.4.

Stefan H. Holek stefan at epy.co.at
Fri Feb 27 16:16:44 EST 2009


Log message for revision 97359:
  User masquerading. Adapted from a patch against PAS 1.0.4.
  
  Logging in as AUTHUSER/ROLEUSER (e.g. 'admin/jdoe') authenticates
  against AUTHUSER but returns ROLEUSER. As a security precaution,
  AUTHUSER must have the Manager role. Note: AUTHUSER and ROLEUSER
  must live in the same user folder.
  

Changed:
  U   Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/PluggableAuthService.py
  U   Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/PropertiedUser.py
  U   Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/utils.py

-=-
Modified: Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/PluggableAuthService.py
===================================================================
--- Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/PluggableAuthService.py	2009-02-27 18:28:35 UTC (rev 97358)
+++ Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/PluggableAuthService.py	2009-02-27 21:16:43 UTC (rev 97359)
@@ -86,6 +86,8 @@
 from utils import createViewName
 from utils import createKeywords
 from utils import classImplements
+from utils import splitmasq
+from utils import joinmasq
 
 security = ModuleSecurityInfo(
     'Products.PluggableAuthService.PluggableAuthService' )
@@ -241,6 +243,10 @@
 
             user = self._findUser(plugins, user_id, login, request=request)
 
+            # Masquerading may reset the user
+            if user is None:
+                continue
+
             if aq_base( user ) is emergency_user:
 
                 if is_top:
@@ -597,14 +603,29 @@
                     for authenticator_id, auth in authenticators:
 
                         try:
+                            # Masquerading: Authenticate auth_user
+                            login = credentials.get('login', '')
+                            auth_user_id, role_user_id = splitmasq( login )
+                            if role_user_id is not None:
+                                credentials['login'] = auth_user_id
+
                             uid_and_info = auth.authenticateCredentials(
                                 credentials )
 
+                            # Masquerading: Restore credentials before continue
+                            if role_user_id is not None:
+                                credentials['login'] = login
+
                             if uid_and_info is None:
                                 continue
 
                             user_id, info = uid_and_info
 
+                            # Masquerading: Decorate id and login with masquerading info
+                            if role_user_id is not None:
+                                user_id = joinmasq( user_id, role_user_id )
+                                info = joinmasq( info, role_user_id )
+
                         except _SWALLOWABLE_PLUGIN_EXCEPTIONS:
                             msg = 'AuthenticationPlugin %s error' % ( 
                                     authenticator_id, )
@@ -712,6 +733,32 @@
         if user_id == self._emergency_user.getUserName():
             return self._emergency_user
 
+        # Masquerading: Lookup role_user
+        saved_id = user_id
+
+        auth_user_id, role_user_id = splitmasq( user_id )
+        if role_user_id is not None:
+            user_id = role_user_id
+
+        auth_user_login, role_user_login = splitmasq( name )
+        if role_user_login is not None:
+            name = role_user_login
+
+        # Masquerading: Check if auth_user is eligible for masquerading
+        if role_user_id is not None:
+            rolemakers = plugins.listPlugins( IRolesPlugin )
+            auth_user = PropertiedUser( auth_user_id, auth_user_id )
+            auth_user_roles = []
+            for rolemaker_id, rolemaker in rolemakers:
+                roles = rolemaker.getRolesForPrincipal( auth_user, request )
+                if roles:
+                    auth_user_roles.extend(roles)
+            if 'Manager' in auth_user_roles:
+                logger.info('Masquerading allowed: %s' % (saved_id,))
+            else:
+                logger.warn('Masquerading denied: %s' % (saved_id,))
+                return None
+
         # See if the user can be retrieved from the cache
         view_name = createViewName('_findUser', user_id)
         keywords = createKeywords(user_id=user_id, name=name)
@@ -765,6 +812,15 @@
             # plugin enumerators.
             return None
 
+        # Masquerading: Lookup role_user
+        auth_user_id, role_user_id = splitmasq( user_id )
+        if role_user_id is not None:
+            user_id = role_user_id
+
+        auth_user_login, role_user_login = splitmasq( login )
+        if role_user_login is not None:
+            login = role_user_login
+
         criteria = {'exact_match': True}
 
         if user_id is not None:

Modified: Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/PropertiedUser.py
===================================================================
--- Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/PropertiedUser.py	2009-02-27 18:28:35 UTC (rev 97358)
+++ Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/PropertiedUser.py	2009-02-27 21:16:43 UTC (rev 97359)
@@ -27,6 +27,8 @@
 from Products.PluggableAuthService.interfaces.propertysheets \
     import IPropertySheet
 
+from Products.PluggableAuthService.utils import splitmasq
+
 class PropertiedUser( BasicUser ):
 
     """ User objects which manage propertysheets, obtained from decorators.
@@ -97,6 +99,12 @@
           no other extension mechanism. :(
         """
         user_id = self.getId()
+
+        # Masquerading: Return role_user roles
+        auth_user_id, role_user_id = splitmasq( user_id )
+        if role_user_id is not None:
+            user_id = role_user_id
+
         # [ x.getId() for x in self.getGroups() ]
         group_ids = self.getGroups()
 
@@ -187,6 +195,12 @@
         # we can incur only the overhead required to find a match.
         inner_obj = aq_inner( object )
         user_id = self.getId()
+
+        # Masquerading: Check role_user roles
+        auth_user_id, role_user_id = splitmasq( user_id )
+        if role_user_id is not None:
+            user_id = role_user_id
+
         # [ x.getId() for x in self.getGroups() ]
         group_ids = self.getGroups()
 

Modified: Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/utils.py
===================================================================
--- Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/utils.py	2009-02-27 18:28:35 UTC (rev 97358)
+++ Products.PluggableAuthService/branches/shh-15-masquerading/Products/PluggableAuthService/utils.py	2009-02-27 21:16:43 UTC (rev 97359)
@@ -210,3 +210,19 @@
 
     return {'keywords': keywords.hexdigest()}
 
+#
+#   Masquerading helpers
+#
+_MASQ = '/'
+
+def splitmasq( user_id ):
+    if user_id is not None:
+        if user_id.find(_MASQ) > 0:
+            return user_id.split(_MASQ, 1)
+    return user_id, None
+
+def joinmasq( auth_user_id, role_user_id ):
+    if None in (auth_user_id, role_user_id):
+        return auth_user_id
+    return _MASQ.join((auth_user_id, role_user_id))
+



More information about the Checkins mailing list