[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