Commit 4b16e1dd authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

use UnrestrictedMethod's super user instead of ad-hoc SUPER_USER. Squashed commit of the following:

commit 2ba8fb59b67cda4a35bda5ee809ac0dd6af40d84
Author: Kazuhiko Shiozaki <kazuhiko@nexedi.com>
Date:   Fri Jun 1 23:26:30 2012 +0200

    if the activity is called by super user, it should be invoked with the same permission as UnrestrictedMethod.

commit f63c2e8625934d0a5a056e933f4c7215098bfa1b
Author: Kazuhiko Shiozaki <kazuhiko@nexedi.com>
Date:   Fri Jun 1 15:58:41 2012 +0200

    use UnrestrictedMethod's super user instead of ad-hoc SUPER_USER.

commit 965460b092967bc3ada3ee7268e1f942fc770efd
Author: Kazuhiko Shiozaki <kazuhiko@nexedi.com>
Date:   Fri Jun 1 15:57:45 2012 +0200

    security query for super user should be simply empty.

commit 6d519b78f52f1a631d6663ee5594ae92a0730cc3
Author: Kazuhiko Shiozaki <kazuhiko@nexedi.com>
Date:   Fri Jun 1 15:37:33 2012 +0200

    support both ERP5Security's SUPER_USER and UnrestrictedMethod's super user.

commit 21431518b821a5e2756caad5393fc746bed79d36
Author: Kazuhiko Shiozaki <kazuhiko@nexedi.com>
Date:   Fri Jun 1 15:32:45 2012 +0200

    make sure that SUPER_USER can access the object explicitly, that can be required with erp5_web.

commit 63279ac74cbb40e520da36571927bfdee5af5e05
Author: Kazuhiko Shiozaki <kazuhiko@nexedi.com>
Date:   Fri Jun 1 15:27:00 2012 +0200

    use UnrestrictedMethod instead of ad-hoc SUPER_USER, still keeping SUPER_USER for compatibility.
parent c8fdf112
...@@ -44,6 +44,7 @@ from AccessControl.SecurityManagement import newSecurityManager ...@@ -44,6 +44,7 @@ from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager from AccessControl.SecurityManagement import noSecurityManager
from AccessControl.SecurityManagement import setSecurityManager from AccessControl.SecurityManagement import setSecurityManager
from AccessControl.SecurityManagement import getSecurityManager from AccessControl.SecurityManagement import getSecurityManager
from AccessControl.User import system as system_user
from Products.CMFCore.utils import UniqueObject, _getAuthenticatedUser from Products.CMFCore.utils import UniqueObject, _getAuthenticatedUser
from Products.ERP5Type.Globals import InitializeClass, DTMLFile from Products.ERP5Type.Globals import InitializeClass, DTMLFile
from Acquisition import aq_base, aq_inner, aq_parent from Acquisition import aq_base, aq_inner, aq_parent
...@@ -51,6 +52,8 @@ from ActivityBuffer import ActivityBuffer ...@@ -51,6 +52,8 @@ from ActivityBuffer import ActivityBuffer
from ActivityRuntimeEnvironment import BaseMessage from ActivityRuntimeEnvironment import BaseMessage
from zExceptions import ExceptionFormatter from zExceptions import ExceptionFormatter
from BTrees.OIBTree import OIBTree from BTrees.OIBTree import OIBTree
from Zope2 import app
from Products.ERP5Type.UnrestrictedMethod import PrivilegedUser
try: try:
from Products import iHotfix from Products import iHotfix
...@@ -248,6 +251,16 @@ class Message(BaseMessage): ...@@ -248,6 +251,16 @@ class Message(BaseMessage):
if user is None: if user is None:
uf = activity_tool.getPortalObject().aq_parent.acl_users uf = activity_tool.getPortalObject().aq_parent.acl_users
user = uf.getUserById(user_name) user = uf.getUserById(user_name)
if user is None and user_name == system_user.getUserName():
# The following logic comes from unrestricted_apply()
# implementation in ERP5Type.UnrestrictedMethod.
try:
# XXX is it better to get roles from the parent (i.e. portal)?
uf = user.aq_inner.aq_parent
except AttributeError:
uf = app().acl_users
role_list = uf.valid_roles()
user = PrivilegedUser(user_name, None, role_list, ()).__of__(uf)
if user is not None: if user is not None:
user = user.__of__(uf) user = user.__of__(uf)
newSecurityManager(None, user) newSecurityManager(None, user)
......
...@@ -32,10 +32,11 @@ from DateTime import DateTime ...@@ -32,10 +32,11 @@ from DateTime import DateTime
from AccessControl import ClassSecurityInfo, Unauthorized from AccessControl import ClassSecurityInfo, Unauthorized
from AccessControl.SecurityManagement import getSecurityManager, \ from AccessControl.SecurityManagement import getSecurityManager, \
setSecurityManager, newSecurityManager setSecurityManager, newSecurityManager
from AccessControl.User import nobody
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Security.ERP5UserManager import SUPER_USER from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ERP5.mixin.periodicity import PeriodicityMixin from Products.ERP5.mixin.periodicity import PeriodicityMixin
class Alarm(XMLObject, PeriodicityMixin): class Alarm(XMLObject, PeriodicityMixin):
...@@ -118,11 +119,10 @@ class Alarm(XMLObject, PeriodicityMixin): ...@@ -118,11 +119,10 @@ class Alarm(XMLObject, PeriodicityMixin):
if not checkPermission(Permissions.ManagePortal, self): if not checkPermission(Permissions.ManagePortal, self):
raise Unauthorized('fixing problems or activating a disabled alarm is not allowed') raise Unauthorized('fixing problems or activating a disabled alarm is not allowed')
# Switch to the superuser temporarily, so that the behavior would not # Use UnrestrictedMethod, so that the behavior would not
# change even if this method is invoked by random users. # change even if this method is invoked by random users.
sm = getSecurityManager() @UnrestrictedMethod
newSecurityManager(None, portal_membership.getMemberById(SUPER_USER)) def _activeSense():
try:
# Set the next date at which this method should be invoked # Set the next date at which this method should be invoked
self.setNextAlarmDate() self.setNextAlarmDate()
...@@ -158,6 +158,13 @@ class Alarm(XMLObject, PeriodicityMixin): ...@@ -158,6 +158,13 @@ class Alarm(XMLObject, PeriodicityMixin):
getattr(self.activate(tag=tag), method_id)() getattr(self.activate(tag=tag), method_id)()
if self.isAlarmNotificationMode(): if self.isAlarmNotificationMode():
self.activate(after_tag=tag).notify(include_active=True, params=params) self.activate(after_tag=tag).notify(include_active=True, params=params)
# switch to nobody temporarily so that unrestricted _activeSense
# is already invoked by system user.
sm = getSecurityManager()
newSecurityManager(None, nobody)
try:
_activeSense()
finally: finally:
# Restore the original user. # Restore the original user.
setSecurityManager(sm) setSecurityManager(sm)
......
...@@ -31,6 +31,7 @@ from Products.ZSQLCatalog.ZSQLCatalog import ZCatalog ...@@ -31,6 +31,7 @@ from Products.ZSQLCatalog.ZSQLCatalog import ZCatalog
from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from AccessControl import ClassSecurityInfo, getSecurityManager from AccessControl import ClassSecurityInfo, getSecurityManager
from AccessControl.User import system as system_user
from Products.CMFCore.utils import UniqueObject, _getAuthenticatedUser, getToolByName from Products.CMFCore.utils import UniqueObject, _getAuthenticatedUser, getToolByName
from Products.ERP5Type.Globals import InitializeClass, DTMLFile from Products.ERP5Type.Globals import InitializeClass, DTMLFile
from Acquisition import aq_base, aq_inner, aq_parent, ImplicitAcquisitionWrapper from Acquisition import aq_base, aq_inner, aq_parent, ImplicitAcquisitionWrapper
...@@ -391,7 +392,7 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): ...@@ -391,7 +392,7 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
""" """
user = _getAuthenticatedUser(self) user = _getAuthenticatedUser(self)
user_str = str(user) user_str = str(user)
user_is_superuser = (user_str == SUPER_USER) user_is_superuser = (user == system_user) or (user_str == SUPER_USER)
allowedRolesAndUsers = self._listAllowedRolesAndUsers(user) allowedRolesAndUsers = self._listAllowedRolesAndUsers(user)
role_column_dict = {} role_column_dict = {}
local_role_column_dict = {} local_role_column_dict = {}
...@@ -508,6 +509,12 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): ...@@ -508,6 +509,12 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
values. The query takes into account the fact that some roles are values. The query takes into account the fact that some roles are
catalogued with columns. catalogued with columns.
""" """
user = _getAuthenticatedUser(self)
user_str = str(user)
user_is_superuser = (user == system_user) or (user_str == SUPER_USER)
if user_is_superuser:
# We need no security check for super user.
return query
original_query = query original_query = query
security_uid_list, role_column_dict, local_role_column_dict = \ security_uid_list, role_column_dict, local_role_column_dict = \
self.getSecurityUidListAndRoleColumnDict( self.getSecurityUidListAndRoleColumnDict(
......
...@@ -26,6 +26,7 @@ from Products.PluggableAuthService.interfaces.plugins import IGroupsPlugin ...@@ -26,6 +26,7 @@ from Products.PluggableAuthService.interfaces.plugins import IGroupsPlugin
from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Cache import CachingMethod
from Products.ERP5Type.ERP5Type \ from Products.ERP5Type.ERP5Type \
import ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT import ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.PluggableAuthService.PropertiedUser import PropertiedUser from Products.PluggableAuthService.PropertiedUser import PropertiedUser
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
...@@ -86,17 +87,13 @@ class ERP5GroupManager(BasePlugin): ...@@ -86,17 +87,13 @@ class ERP5GroupManager(BasePlugin):
if principal.getId() == SUPER_USER: if principal.getId() == SUPER_USER:
return () return ()
@UnrestrictedMethod
def _getGroupsForPrincipal(user_name, path): def _getGroupsForPrincipal(user_name, path):
security_category_dict = {} # key is the base_category_list, security_category_dict = {} # key is the base_category_list,
# value is the list of fetched categories # value is the list of fetched categories
security_group_list = [] security_group_list = []
security_definition_list = () security_definition_list = ()
# because we aren't logged in, we have to create our own
# SecurityManager to be able to access the Catalog
sm = getSecurityManager()
if sm.getUser().getId() != SUPER_USER:
newSecurityManager(self, self.getUser(SUPER_USER))
try: try:
# To get the complete list of groups, we try to call the # To get the complete list of groups, we try to call the
# ERP5Type_getSecurityCategoryMapping which should return a list # ERP5Type_getSecurityCategoryMapping which should return a list
...@@ -180,7 +177,7 @@ class ERP5GroupManager(BasePlugin): ...@@ -180,7 +177,7 @@ class ERP5GroupManager(BasePlugin):
generator_name, generator_name,
error = sys.exc_info()) error = sys.exc_info())
finally: finally:
setSecurityManager(sm) pass
return tuple(security_group_list) return tuple(security_group_list)
if not NO_CACHE_MODE: if not NO_CACHE_MODE:
......
...@@ -48,6 +48,7 @@ from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin ...@@ -48,6 +48,7 @@ from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
from Products.PluggableAuthService.plugins.CookieAuthHelper import CookieAuthHelper from Products.PluggableAuthService.plugins.CookieAuthHelper import CookieAuthHelper
from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Cache import CachingMethod
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ERP5Security.ERP5UserManager import ERP5UserManager,\ from Products.ERP5Security.ERP5UserManager import ERP5UserManager,\
SUPER_USER,\ SUPER_USER,\
_AuthenticationFailure _AuthenticationFailure
...@@ -327,6 +328,7 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper): ...@@ -327,6 +328,7 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper):
return None return None
#Function to allow cache #Function to allow cache
@UnrestrictedMethod
def _authenticateCredentials(login): def _authenticateCredentials(login):
if not login: if not login:
return None return None
...@@ -337,10 +339,7 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper): ...@@ -337,10 +339,7 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper):
raise _AuthenticationFailure() raise _AuthenticationFailure()
user = user_list[0] user = user_list[0]
#We need to be super_user if True:
sm = getSecurityManager()
if sm.getUser().getId() != SUPER_USER:
newSecurityManager(self, self.getUser(SUPER_USER))
try: try:
# get assignment list # get assignment list
assignment_list = [x for x in user.contentValues(portal_type="Assignment") \ assignment_list = [x for x in user.contentValues(portal_type="Assignment") \
...@@ -361,7 +360,7 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper): ...@@ -361,7 +360,7 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper):
if len(valid_assignment_list) > 0: if len(valid_assignment_list) > 0:
return (login, login) return (login, login)
finally: finally:
setSecurityManager(sm) pass
raise _AuthenticationFailure() raise _AuthenticationFailure()
......
...@@ -26,6 +26,7 @@ from Products.PluggableAuthService.interfaces.plugins import IUserFactoryPlugin ...@@ -26,6 +26,7 @@ from Products.PluggableAuthService.interfaces.plugins import IUserFactoryPlugin
from Products.PluggableAuthService.PropertiedUser import PropertiedUser from Products.PluggableAuthService.PropertiedUser import PropertiedUser
from Products.PluggableAuthService.PropertiedUser import \ from Products.PluggableAuthService.PropertiedUser import \
_what_not_even_god_should_do _what_not_even_god_should_do
from Products.ERP5Security.ERP5UserManager import SUPER_USER
manage_addERP5UserFactoryForm = PageTemplateFile( manage_addERP5UserFactoryForm = PageTemplateFile(
'www/ERP5Security_addERP5UserFactory', globals(), 'www/ERP5Security_addERP5UserFactory', globals(),
...@@ -101,6 +102,10 @@ class ERP5User(PropertiedUser): ...@@ -101,6 +102,10 @@ class ERP5User(PropertiedUser):
As for getRolesInContext, we take into account _getAcquireLocalRoles for As for getRolesInContext, we take into account _getAcquireLocalRoles for
ERP5. ERP5.
""" """
if self.getUserName() == SUPER_USER:
# super user is allowed to accesss any object
return 1
if object_roles is _what_not_even_god_should_do: if object_roles is _what_not_even_god_should_do:
return 0 return 0
......
...@@ -28,6 +28,7 @@ from Products.PluggableAuthService.utils import classImplements ...@@ -28,6 +28,7 @@ from Products.PluggableAuthService.utils import classImplements
from Products.PluggableAuthService.interfaces.plugins import IAuthenticationPlugin from Products.PluggableAuthService.interfaces.plugins import IAuthenticationPlugin
from Products.PluggableAuthService.interfaces.plugins import IUserEnumerationPlugin from Products.PluggableAuthService.interfaces.plugins import IUserEnumerationPlugin
from Products.ERP5Type.Cache import CachingMethod, transactional_cached from Products.ERP5Type.Cache import CachingMethod, transactional_cached
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
import sys import sys
from DateTime import DateTime from DateTime import DateTime
...@@ -126,6 +127,7 @@ class ERP5UserManager(BasePlugin): ...@@ -126,6 +127,7 @@ class ERP5UserManager(BasePlugin):
if login == SUPER_USER: if login == SUPER_USER:
return None return None
@UnrestrictedMethod
def _authenticateCredentials(login, password, path, def _authenticateCredentials(login, password, path,
ignore_password=False): ignore_password=False):
if not login or not (password or ignore_password): if not login or not (password or ignore_password):
...@@ -138,9 +140,6 @@ class ERP5UserManager(BasePlugin): ...@@ -138,9 +140,6 @@ class ERP5UserManager(BasePlugin):
user = user_list[0] user = user_list[0]
sm = getSecurityManager()
if sm.getUser().getId() != SUPER_USER:
newSecurityManager(self, self.getUser(SUPER_USER))
try: try:
# get assignment # get assignment
assignment_list = [x for x in user.contentValues(portal_type="Assignment") if x.getValidationState() == "open"] assignment_list = [x for x in user.contentValues(portal_type="Assignment") if x.getValidationState() == "open"]
...@@ -161,7 +160,7 @@ class ERP5UserManager(BasePlugin): ...@@ -161,7 +160,7 @@ class ERP5UserManager(BasePlugin):
.getValidationState() != 'deleted': #user.getCareerRole() == 'internal': .getValidationState() != 'deleted': #user.getCareerRole() == 'internal':
return login, login # use same for user_id and login return login, login # use same for user_id and login
finally: finally:
setSecurityManager(sm) pass
raise _AuthenticationFailure() raise _AuthenticationFailure()
_authenticateCredentials = CachingMethod(_authenticateCredentials, _authenticateCredentials = CachingMethod(_authenticateCredentials,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment