You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2008/03/19 14:57:11 UTC
svn commit: r638834 [2/14] - in /jackrabbit/trunk:
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/principal/
jackr...
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,479 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import org.apache.jackrabbit.core.config.AccessManagerConfig;
+import org.apache.jackrabbit.core.config.BeanConfig;
+import org.apache.jackrabbit.core.config.LoginModuleConfig;
+import org.apache.jackrabbit.core.config.SecurityConfig;
+import org.apache.jackrabbit.core.config.WorkspaceConfig;
+import org.apache.jackrabbit.core.config.WorkspaceSecurityConfig;
+import org.apache.jackrabbit.core.security.AMContext;
+import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.security.JackrabbitSecurityManager;
+import org.apache.jackrabbit.core.security.SecurityConstants;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.core.security.authentication.AuthContext;
+import org.apache.jackrabbit.core.security.authentication.AuthContextProvider;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProviderFactory;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProviderFactoryImpl;
+import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlException;
+import org.apache.jackrabbit.core.security.principal.DefaultPrincipalProvider;
+import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
+import org.apache.jackrabbit.core.security.principal.PrincipalManagerImpl;
+import org.apache.jackrabbit.core.security.principal.PrincipalProvider;
+import org.apache.jackrabbit.core.security.principal.PrincipalProviderRegistry;
+import org.apache.jackrabbit.core.security.principal.ProviderRegistryImpl;
+import org.apache.jackrabbit.core.security.user.UserManagerImpl;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * The security manager acts as central managing class for all security related
+ * operations on a low-level non-protected level. It manages the
+ * <ul>
+ * <li> {@link PrincipalProvider}s
+ * <li> {@link AccessControlProvider}s
+ * <li> {@link WorkspaceAccessManager}
+ * <li> {@link UserManager}
+ * </ul>
+ */
+public class DefaultSecurityManager implements JackrabbitSecurityManager {
+
+ // TODO: should rather be placed in the core.security package. However protected access to SystemSession required to move here.
+ /**
+ * the default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(DefaultSecurityManager.class);
+
+ /**
+ *
+ */
+ private boolean initialized;
+
+ /**
+ * the repository implementation
+ */
+ private RepositoryImpl repository;
+
+ /**
+ * session on the system workspace.
+ */
+ private SystemSession securitySession;
+
+ /**
+ * System user manager. Implementation needed here for the DefaultPrincipalProvider.
+ */
+ private UserManager systemUserManager;
+
+ /**
+ * System Sessions PrincipalMangager used for internal access to Principals
+ */
+ private PrincipalManager systemPrincipalManager;
+
+ /**
+ * The user id of the administrator. The value is retrieved from
+ * configuration. If the config entry is missing a default id is used (see
+ * {@link SecurityConstants#ADMIN_ID}).
+ *
+ */
+ private String adminId;
+
+ /**
+ * Contains the access control providers per workspace.
+ * key = name of the workspace,
+ * value = {@link AccessControlProvider}
+ */
+ private final Map acProviders = new HashMap();
+
+ /**
+ * the AccessControlProviderFactory
+ */
+ private AccessControlProviderFactory acProviderFactory;
+
+ /**
+ * the configured WorkspaceAccessManager
+ */
+ private WorkspaceAccessManager workspaceAccessManager;
+
+ /**
+ * the principal provider registry
+ */
+ private PrincipalProviderRegistry principalProviderRegistry;
+
+ /**
+ * factory for login-context {@see Repository#login())
+ */
+ private AuthContextProvider authContextProvider;
+
+ //------------------------------------------< JackrabbitSecurityManager >---
+ /**
+ * @see JackrabbitSecurityManager#init(Repository, Session)
+ */
+ public synchronized void init(Repository repository, Session systemSession) throws RepositoryException {
+ if (initialized) {
+ throw new IllegalStateException("already initialized");
+ }
+ if (!(repository instanceof RepositoryImpl)) {
+ throw new RepositoryException("RepositoryImpl expected");
+ }
+ if (!(systemSession instanceof SystemSession)) {
+ throw new RepositoryException("SystemSession expected");
+ }
+
+ securitySession = (SystemSession) systemSession;
+ this.repository = (RepositoryImpl) repository;
+
+ SecurityConfig config = this.repository.getConfig().getSecurityConfig();
+ LoginModuleConfig loginModConf = config.getLoginModuleConfig();
+
+ // build AuthContextProvider based on appName + optional LoginModuleConfig
+ authContextProvider = new AuthContextProvider(config.getAppName(), loginModConf);
+ if (authContextProvider.isJAAS()) {
+ log.info("init: use JAAS login-configuration for " + config.getAppName());
+ } else if (authContextProvider.isLocal()) {
+ log.info("init: use Repository Login-Configuration for " + config.getAppName());
+ } else {
+ String msg = "Neither JAAS nor RepositoryConfig contained a valid Configuriation for " + config.getAppName();
+ log.error(msg);
+ throw new RepositoryException(msg);
+ }
+
+ Properties[] moduleConfig = authContextProvider.getModuleConfig();
+
+ // retrieve default-ids (admin and anomymous) from login-module-configuration.
+ String anonymousId = null;
+ for (int i = 0; i < moduleConfig.length; i++) {
+ if (moduleConfig[i].containsKey(LoginModuleConfig.PARAM_ADMIN_ID)) {
+ adminId = moduleConfig[i].getProperty(LoginModuleConfig.PARAM_ADMIN_ID);
+ }
+ if (moduleConfig[i].containsKey(LoginModuleConfig.PARAM_ANONYMOUS_ID)) {
+ anonymousId = moduleConfig[i].getProperty(LoginModuleConfig.PARAM_ANONYMOUS_ID, null);
+ }
+ }
+ // fallback:
+ if (adminId == null) {
+ log.debug("No adminID defined in LoginModule/JAAS config -> using default.");
+ adminId = SecurityConstants.ADMIN_ID;
+ }
+ if (anonymousId == null) {
+ log.debug("No anonymousID defined in LoginModule/JAAS config -> anonymous not defined..");
+ }
+
+ // create the system userManager and make sure the system-users exist.
+ systemUserManager = new UserManagerImpl(securitySession, adminId);
+ createSystemUsers(adminId, anonymousId);
+
+ // init default ac-provider-factory
+ acProviderFactory = new AccessControlProviderFactoryImpl();
+ acProviderFactory.init(this);
+
+ // create the evalutor for workspace access
+ workspaceAccessManager = createWorkspaceAccessManager();
+
+ // initialize principa-provider registry
+ // 1) create default
+ PrincipalProvider defaultPP = new DefaultPrincipalProvider(securitySession, (UserManagerImpl) systemUserManager);
+ defaultPP.init(new Properties());
+ // 2) create registry instance
+ principalProviderRegistry = new ProviderRegistryImpl(defaultPP);
+ // 3) register all configured principal providers.
+ for (int i = 0; i < moduleConfig.length; i++) {
+ principalProviderRegistry.registerProvider(moduleConfig[i]);
+ }
+
+ // create the principal manager for the security workspace
+ systemPrincipalManager = new PrincipalManagerImpl(securitySession, principalProviderRegistry.getProviders());
+
+ initialized = true;
+ }
+
+ /**
+ * @see JackrabbitSecurityManager#dispose(String)
+ */
+ public void dispose(String workspaceName) {
+ checkInitialized();
+ synchronized (acProviders) {
+ AccessControlProvider prov = (AccessControlProvider) acProviders.remove(workspaceName);
+ if (prov != null) {
+ prov.close();
+ }
+ }
+ }
+
+ /**
+ * @see JackrabbitSecurityManager#close()
+ */
+ public void close() {
+ checkInitialized();
+ synchronized (acProviders) {
+ Iterator itr = acProviders.values().iterator();
+ while (itr.hasNext()) {
+ ((AccessControlProvider) itr.next()).close();
+ }
+ acProviders.clear();
+ }
+ }
+
+ /**
+ * @see JackrabbitSecurityManager#getSecurityConfig()
+ */
+ public SecurityConfig getSecurityConfig() throws RepositoryException {
+ return repository.getConfig().getSecurityConfig();
+ }
+
+ /**
+ * @see JackrabbitSecurityManager#getAccessManager(Session,AMContext)
+ */
+ public AccessManager getAccessManager(Session session, AMContext amContext) throws RepositoryException {
+ checkInitialized();
+ AccessManagerConfig amConfig = getSecurityConfig().getAccessManagerConfig();
+ try {
+ String wspName = session.getWorkspace().getName();
+ AccessControlProvider pp = getAccessControlProvider(wspName);
+
+ AccessManager accessMgr = (AccessManager) amConfig.newInstance();
+ accessMgr.init(amContext, pp, workspaceAccessManager);
+ return accessMgr;
+ } catch (AccessDeniedException ade) {
+ // re-throw
+ throw ade;
+ } catch (Exception e) {
+ // wrap in RepositoryException
+ String msg = "Failed to instantiate AccessManager (" + amConfig.getClassName() + ")";
+ e.printStackTrace();
+ log.error(msg, e);
+ throw new RepositoryException(msg, e);
+ }
+ }
+
+ /**
+ * @see JackrabbitSecurityManager#getPrincipalManager(Session)
+ */
+ public synchronized PrincipalManager getPrincipalManager(Session session)
+ throws RepositoryException {
+ checkInitialized();
+ if (session == securitySession) {
+ return systemPrincipalManager;
+ } else if (session instanceof SessionImpl) {
+ SessionImpl sImpl = (SessionImpl) session;
+ return new PrincipalManagerImpl(sImpl, principalProviderRegistry.getProviders());
+ } else {
+ throw new RepositoryException("Internal error: SessionImpl expected.");
+ }
+ }
+
+ /**
+ * @see JackrabbitSecurityManager#getUserManager(Session)
+ */
+ public UserManager getUserManager(Session session) throws RepositoryException {
+ checkInitialized();
+ if (session == securitySession) {
+ return systemUserManager;
+ } else if (session instanceof SessionImpl) {
+ String workspaceName = securitySession.getWorkspace().getName();
+ try {
+ SessionImpl sImpl = (SessionImpl) session;
+ SessionImpl s = (SessionImpl) sImpl.createSession(workspaceName);
+ return new UserManagerImpl(s, adminId);
+ } catch (NoSuchWorkspaceException e) {
+ throw new AccessControlException("Cannot build UserManager for " + session.getUserID(), e);
+ }
+ } else {
+ throw new RepositoryException("Internal error: SessionImpl expected.");
+ }
+ }
+
+ /**
+ * Creates an AuthContext for the given {@link Credentials} and
+ * {@link Subject}.<br>
+ * This includes selection of applicatoin specific LoginModules and
+ * initalization with credentials and Session to System-Workspace
+ *
+ * @return an {@link AuthContext} for the given Credentials, Subject
+ * @throws RepositoryException in other exceptional repository states
+ */
+ public AuthContext getAuthContext(Credentials creds, Subject subject)
+ throws RepositoryException {
+ checkInitialized();
+ return authContextProvider.getAuthContext(creds, subject, securitySession, principalProviderRegistry);
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * @param wspName
+ * @return The <code>WorkspaceSecurityConfig</code> for the given workspace
+ * name or <code>null</code>.
+ */
+ private WorkspaceSecurityConfig getWorkspaceSecurityConfig(String wspName) {
+ WorkspaceConfig conf = repository.getConfig().getWorkspaceConfig(wspName);
+ if (conf == null) {
+ return null;
+ } else {
+ return conf.getSecurityConfig();
+ }
+ }
+
+ /**
+ * Returns the access control provider for the specified
+ * <code>workspaceName</code>.
+ *
+ * @param workspaceName
+ * @return access control provider
+ * @throws NoSuchWorkspaceException If no workspace with 'workspaceName' exists.
+ * @throws RepositoryException
+ */
+ private AccessControlProvider getAccessControlProvider(String workspaceName)
+ throws NoSuchWorkspaceException, RepositoryException {
+
+ synchronized (acProviders) {
+ AccessControlProvider provider = (AccessControlProvider) acProviders.get(workspaceName);
+ if (provider == null) {
+ SystemSession systemSession = repository.getSystemSession(workspaceName);
+ provider = acProviderFactory.createProvider(systemSession, getWorkspaceSecurityConfig(workspaceName));
+ acProviders.put(workspaceName, provider);
+ }
+ return provider;
+ }
+ }
+
+ /**
+ * @return the WorkspaceAccessManager responsible for the repository.
+ */
+ private WorkspaceAccessManager createWorkspaceAccessManager() throws RepositoryException {
+ WorkspaceAccessManager wspAccess;
+ BeanConfig config = repository.getConfig().getSecurityConfig().getSecurityManagerConfig().getWorkspaceAccessConfig();
+ if (config != null) {
+ wspAccess = (WorkspaceAccessManager) config.newInstance();
+ } else {
+ // fallback -> the default implementation
+ log.debug("No WorkspaceAccessManager configured; using default.");
+ wspAccess = new WorkspaceAccessManagerImpl();
+ }
+ wspAccess.init(this);
+ return wspAccess;
+ }
+
+ /**
+ * Make sure the 'administrators' group exists and the user with the
+ * configured (or default) adminID is member of this user-group.
+ *
+ * @param adminId
+ * @param anonymousId
+ * @throws RepositoryException
+ */
+ private void createSystemUsers(String adminId,
+ String anonymousId) throws RepositoryException {
+ Principal pr = new PrincipalImpl(SecurityConstants.ADMINISTRATORS_NAME);
+ Group admins = (Group) systemUserManager.getAuthorizable(pr);
+ if (admins == null) {
+ admins = systemUserManager.createGroup(new PrincipalImpl(SecurityConstants.ADMINISTRATORS_NAME));
+ log.debug("...created administrators group with name '"+SecurityConstants.ADMINISTRATORS_NAME+"'");
+ }
+
+ if (adminId != null) {
+ Authorizable admin = systemUserManager.getAuthorizable(adminId);
+ if (admin == null) {
+ Credentials creds = new SimpleCredentials(adminId, adminId.toCharArray());
+ admin = systemUserManager.createUser(adminId, creds, new PrincipalImpl(adminId));
+ log.info("...created admin-user with id \'" + adminId + "\' ...");
+ admins.addMember(admin);
+ log.info("...added admin \'" + adminId + "\' as member of the administrators group.");
+ }
+ }
+
+ if (anonymousId != null) {
+ Authorizable anonymous = systemUserManager.getAuthorizable(anonymousId);
+ if (anonymous == null) {
+ Credentials creds = new SimpleCredentials(anonymousId, new char[0]);
+ systemUserManager.createUser(anonymousId, creds, new PrincipalImpl(anonymousId));
+ log.info("...created anonymous-user with id \'" + anonymousId + "\' ...");
+ }
+ }
+ }
+
+ private void checkInitialized() {
+ if (!initialized) {
+ throw new IllegalStateException("Not initialized");
+ }
+ }
+
+ //------------------------------------------------------< inner classes >---
+ /**
+ * <code>WorkspaceAccessManager</code> that upon {@link #grants(Set principals, String)}
+ * evaluates if access to the root node of a workspace with the specified
+ * name is granted.
+ */
+ private class WorkspaceAccessManagerImpl implements SecurityConstants, WorkspaceAccessManager {
+
+ private final Path rootPath = PathFactoryImpl.getInstance().getRootPath();
+
+ //-----------------------------------------< WorkspaceAccessManager >---
+ /**
+ * {@inheritDoc}
+ */
+ public void init(JackrabbitSecurityManager securityManager) throws RepositoryException {
+ // nothing to do here.
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws RepositoryException {
+ // nothing to do here.
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean grants(Set principals, String workspaceName) throws RepositoryException {
+ try {
+ // TODO: improve
+ AccessControlProvider prov = getAccessControlProvider(workspaceName);
+ CompiledPermissions cp = prov.compilePermissions(principals);
+ return cp.grants(rootPath, Permission.READ);
+ } catch (NoSuchWorkspaceException e) {
+ // no such workspace -> return false.
+ return false;
+ }
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java Wed Mar 19 06:56:13 2008
@@ -25,9 +25,9 @@
import org.apache.jackrabbit.core.nodetype.PropDef;
import org.apache.jackrabbit.core.nodetype.PropertyDefinitionImpl;
import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.security.authorization.Permission;
import org.apache.jackrabbit.core.state.ItemState;
import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.ItemStateListener;
import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.core.state.PropertyState;
import org.apache.jackrabbit.core.state.SessionItemStateManager;
@@ -465,13 +465,34 @@
ItemState itemState = (ItemState) dirtyIter.next();
if (itemState.getStatus() != ItemState.STATUS_NEW) {
- // transient item is not 'new', therefore it has to be 'modified'
-
+ /* transient item is not 'new', therefore it has to be 'modified'
+ detect the effective set of modification:
+ - child additions -> add_node perm on the child
+ - property additions, modifications or removals -> set_property permission
+ note: removed items are checked later on.
+ */
// check WRITE permission
- ItemId id = itemState.getId();
- if (!accessMgr.isGranted(id, AccessManager.WRITE)) {
- String msg = itemMgr.safeGetJCRPath(id)
- + ": not allowed to modify item";
+ Path path = stateMgr.getHierarchyMgr().getPath(itemState.getId());
+ boolean isGranted = true;
+ if (itemState.isNode()) {
+ // modified node state -> check possible modifications
+ NodeState nState = (NodeState) itemState;
+ for (Iterator it = nState.getAddedChildNodeEntries().iterator();
+ it.hasNext() && isGranted;) {
+ Name nodeName = ((NodeState.ChildNodeEntry) it.next()).getName();
+ isGranted = accessMgr.isGranted(path, nodeName, Permission.ADD_NODE);
+ }
+ for (Iterator it = nState.getAddedPropertyNames().iterator();
+ it.hasNext() && isGranted;) {
+ Name propName = (Name) it.next();
+ isGranted = accessMgr.isGranted(path, propName, Permission.SET_PROPERTY);
+ }
+ } else {
+ isGranted = accessMgr.isGranted(path, Permission.SET_PROPERTY);
+ }
+
+ if (!isGranted) {
+ String msg = itemMgr.safeGetJCRPath(path) + ": not allowed to modify item";
log.debug(msg);
throw new AccessDeniedException(msg);
}
@@ -640,10 +661,11 @@
// walk through list of removed transient items and check REMOVE permission
while (removedIter.hasNext()) {
ItemState itemState = (ItemState) removedIter.next();
- ItemId id = itemState.getId();
+ Path path = stateMgr.getAtticAwareHierarchyMgr().getPath(itemState.getId());
// check REMOVE permission
- if (!accessMgr.isGranted(id, AccessManager.REMOVE)) {
- String msg = itemMgr.safeGetJCRPath(id)
+ int permission = (itemState.isNode()) ? Permission.REMOVE_NODE : Permission.REMOVE_PROPERTY;
+ if (!accessMgr.isGranted(path, permission)) {
+ String msg = itemMgr.safeGetJCRPath(path)
+ ": not allowed to remove item";
log.debug(msg);
throw new AccessDeniedException(msg);
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java Wed Mar 19 06:56:13 2008
@@ -195,7 +195,7 @@
throws ItemNotFoundException, AccessDeniedException,
RepositoryException {
// check privileges
- if (!session.getAccessManager().isGranted(id, AccessManager.READ)) {
+ if (!canRead(id)) {
// clear cache
ItemImpl item = retrieveItem(id);
if (item != null) {
@@ -217,6 +217,10 @@
}
}
+ private boolean canRead(ItemId id) throws RepositoryException {
+ return session.getAccessManager().isGranted(id, AccessManager.READ);
+ }
+
//--------------------------------------------------< item access methods >
/**
* Checks whether an item exists at the specified path.
@@ -293,7 +297,7 @@
}
// check privileges
- if (!session.getAccessManager().isGranted(id, AccessManager.READ)) {
+ if (!canRead(id)) {
// clear cache
evictItem(id);
// item exists but the session has not been granted read access
@@ -397,7 +401,7 @@
if (item == null) {
// not yet in cache, need to create instance:
// check privileges
- if (!session.getAccessManager().isGranted(id, AccessManager.READ)) {
+ if (!canRead(id)) {
throw new AccessDeniedException("cannot read item " + id);
}
// create instance of item
@@ -448,8 +452,7 @@
if (item == null) {
// not yet in cache, need to create instance:
// only check privileges if state is not new
- if (state.getStatus() != ItemState.STATUS_NEW
- && !session.getAccessManager().isGranted(id, AccessManager.READ)) {
+ if (state.getStatus() != ItemState.STATUS_NEW && !canRead(id)) {
throw new AccessDeniedException("cannot read item " + id);
}
// create instance of item
@@ -482,7 +485,7 @@
while (iter.hasNext()) {
NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
// check read access
- if (session.getAccessManager().isGranted(entry.getId(), AccessManager.READ)) {
+ if (canRead(entry.getId())) {
return true;
}
}
@@ -514,7 +517,7 @@
while (iter.hasNext()) {
NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
// check read access
- if (session.getAccessManager().isGranted(entry.getId(), AccessManager.READ)) {
+ if (canRead(entry.getId())) {
childIds.add(entry.getId());
}
}
@@ -546,7 +549,7 @@
while (iter.hasNext()) {
Name propName = (Name) iter.next();
// check read access
- if (session.getAccessManager().isGranted(new PropertyId(parentId, propName), AccessManager.READ)) {
+ if (canRead(new PropertyId(parentId, propName))) {
return true;
}
}
@@ -580,7 +583,7 @@
Name propName = (Name) iter.next();
PropertyId id = new PropertyId(parentId, propName);
// check read access
- if (session.getAccessManager().isGranted(id, AccessManager.READ)) {
+ if (canRead(id)) {
childIds.add(id);
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Wed Mar 19 06:56:13 2008
@@ -33,9 +33,9 @@
import org.apache.jackrabbit.core.config.ClusterConfig;
import org.apache.jackrabbit.core.config.DataStoreConfig;
import org.apache.jackrabbit.core.config.FileSystemConfig;
-import org.apache.jackrabbit.core.config.LoginModuleConfig;
import org.apache.jackrabbit.core.config.PersistenceManagerConfig;
import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.config.SecurityManagerConfig;
import org.apache.jackrabbit.core.config.VersioningConfig;
import org.apache.jackrabbit.core.config.WorkspaceConfig;
import org.apache.jackrabbit.core.data.DataStore;
@@ -52,24 +52,37 @@
import org.apache.jackrabbit.core.observation.ObservationDispatcher;
import org.apache.jackrabbit.core.persistence.PMContext;
import org.apache.jackrabbit.core.persistence.PersistenceManager;
-import org.apache.jackrabbit.core.security.AuthContext;
+import org.apache.jackrabbit.core.security.JackrabbitSecurityManager;
+import org.apache.jackrabbit.core.security.authentication.AuthContext;
import org.apache.jackrabbit.core.state.CacheManager;
import org.apache.jackrabbit.core.state.ChangeLog;
+import org.apache.jackrabbit.core.state.ISMLocking;
import org.apache.jackrabbit.core.state.ItemStateCacheFactory;
import org.apache.jackrabbit.core.state.ItemStateException;
import org.apache.jackrabbit.core.state.ManagedMLRUItemStateCacheFactory;
import org.apache.jackrabbit.core.state.SharedItemStateManager;
-import org.apache.jackrabbit.core.state.ISMLocking;
import org.apache.jackrabbit.core.util.RepositoryLock;
import org.apache.jackrabbit.core.value.InternalValue;
import org.apache.jackrabbit.core.version.VersionManager;
import org.apache.jackrabbit.core.version.VersionManagerImpl;
-import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+import javax.security.auth.Subject;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -86,19 +99,6 @@
import java.util.Properties;
import java.util.Set;
-import javax.jcr.AccessDeniedException;
-import javax.jcr.Credentials;
-import javax.jcr.LoginException;
-import javax.jcr.NamespaceRegistry;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.observation.EventListener;
-import javax.jcr.observation.ObservationManager;
-import javax.security.auth.Subject;
-
/**
* A <code>RepositoryImpl</code> ...
*/
@@ -150,6 +150,11 @@
private final VirtualNodeTypeStateManager virtNTMgr;
/**
+ * Security manager
+ */
+ private JackrabbitSecurityManager securityMgr;
+
+ /**
* Search manager for the jcr:system tree. May be <code>null</code> if
* none is configured.
*/
@@ -376,6 +381,36 @@
}
/**
+ * Returns the {@link org.apache.jackrabbit.core.security.JackrabbitSecurityManager SecurityManager}
+ * of this <code>Repository</code>
+ *
+ * @return the security manager
+ * @throws RepositoryException if an error occurs.
+ */
+ protected synchronized JackrabbitSecurityManager getSecurityManager()
+ throws RepositoryException {
+
+ if (securityMgr == null) {
+ SecurityManagerConfig smc = getConfig().getSecurityConfig().getSecurityManagerConfig();
+
+ String workspaceName = smc.getWorkspaceName();
+ if (workspaceName == null) {
+ workspaceName = getConfig().getDefaultWorkspaceName();
+ }
+ SystemSession securitySession = getSystemSession(workspaceName);
+ // mark system session as 'active' for that the system workspace does
+ // not get disposed by workspace-janitor
+ onSessionCreated(securitySession);
+
+ securityMgr = (JackrabbitSecurityManager) smc.newInstance();
+ securityMgr.init(this, securitySession);
+
+ log.info("SecurityManager = " + securityMgr.getClass());
+ }
+ return securityMgr;
+ }
+
+ /**
* Creates the version manager.
*
* @param vConfig the versioning config
@@ -412,8 +447,13 @@
*/
protected void initStartupWorkspaces() throws RepositoryException {
String wspName = repConfig.getDefaultWorkspaceName();
+ String secWspName = repConfig.getSecurityConfig().getSecurityManagerConfig().getWorkspaceName();
try {
initWorkspace((WorkspaceInfo) wspInfos.get(wspName));
+ if(secWspName != null && !wspInfos.containsKey(secWspName)) {
+ createWorkspace(secWspName);
+ log.info("created system workspace: {}", secWspName);
+ }
} catch (RepositoryException e) {
// if default workspace failed to initialize, shutdown again
log.error("Failed to initialize workspace '" + wspName + "'", e);
@@ -578,7 +618,7 @@
/**
* todo implement 'System' workspace
* FIXME
- * - the should be one 'System' workspace per repository
+ * - there should be one 'System' workspace per repository
* - the 'System' workspace should have the /jcr:system node
* - versions, version history and node types should be reflected in
* this system workspace as content under /jcr:system
@@ -939,6 +979,57 @@
}
}
+ /**
+ * Tries to add Principals to a given subject:
+ * First Access the Subject from the current AccessControlContext,
+ * If Subject is found the LoginContext is evoked for it, in order
+ * to possibly allow for extension of preauthenticated Subject.<br>
+ * In contrast to a login with Credentials, a Session is created, even if the
+ * Authentication failed.<br>
+ * If the {@link Subject} is marked to be unmodificable or if the
+ * authentication of the the Subject failed Session is build for unchanged
+ * Subject.
+ *
+ * @param workspaceName must not be null
+ * @return if a Subject is exsting null else
+ * @throws RepositoryException
+ * @throws AccessDeniedException
+ */
+ private Session extendAuthentication(String workspaceName)
+ throws RepositoryException, AccessDeniedException {
+
+ Subject subject = null;
+ try {
+ AccessControlContext acc = AccessController.getContext();
+ subject = Subject.getSubject(acc);
+ } catch (SecurityException e) {
+ log.warn("Can't check for preauthentication. Reason:", e.getMessage());
+ }
+ if (subject == null) {
+ log.debug("No preauthenticated subject found -> return null.");
+ return null;
+ }
+
+ Session s;
+ if (subject.isReadOnly()) {
+ log.debug("Preauthenticated Subject is read-only -> create Session");
+ s = createSession(subject, workspaceName);
+ } else {
+ log.debug("Found preauthenticated Subject, try to extend authentication");
+ // login either using JAAS or custom LoginModule
+ AuthContext authCtx = getSecurityManager().getAuthContext(null, subject);
+ try {
+ authCtx.login();
+ s = createSession(authCtx, workspaceName);
+ } catch (javax.security.auth.login.LoginException e) {
+ // subject could not be extended
+ log.debug("Preauthentication could not be extended");
+ s = createSession(subject, workspaceName);
+ }
+ }
+ return s;
+ }
+
//-------------------------------------------------< JackrabbitRepository >
/**
@@ -975,6 +1066,10 @@
clusterNode.stop();
}
+ if (securityMgr != null) {
+ securityMgr.close();
+ }
+
// close active user sessions
// (copy sessions to array to avoid ConcurrentModificationException;
// manually copy entries rather than calling ReferenceMap#toArray() in
@@ -1236,30 +1331,24 @@
getWorkspaceInfo(workspaceName);
if (credentials == null) {
- // null credentials, obtain the identity of the already-authenticated
+ // try to obtain the identity of the already authenticated
// subject from access control context
- AccessControlContext acc = AccessController.getContext();
- Subject subject = Subject.getSubject(acc);
- if (subject != null) {
- return createSession(subject, workspaceName);
+ Session session = extendAuthentication(workspaceName);
+ if (session != null) {
+ // sucessful extended authentication
+ return session;
+ } else {
+ log.debug("Attempt to login without Credentials and Subject -> try login with null credentials.");
}
}
- // login either using JAAS or our own LoginModule
- AuthContext authCtx;
- LoginModuleConfig lmc = repConfig.getLoginModuleConfig();
- if (lmc == null) {
- authCtx = new AuthContext.JAAS(repConfig.getAppName(), credentials);
- } else {
- authCtx = new AuthContext.Local(
- lmc.getLoginModule(), lmc.getParameters(), credentials);
- }
+ // not preauthenticated -> try login with credentials
+ AuthContext authCtx = getSecurityManager().getAuthContext(credentials, new Subject());
authCtx.login();
-
// create session
return createSession(authCtx, workspaceName);
+
} catch (SecurityException se) {
- throw new LoginException(
- "Unable to access authentication information", se);
+ throw new LoginException("Unable to access authentication information", se);
} catch (javax.security.auth.login.LoginException le) {
throw new LoginException(le.getMessage(), le);
} catch (AccessDeniedException ade) {
@@ -1873,6 +1962,12 @@
searchMgr.close();
searchMgr = null;
}
+
+ // deregister
+ if (securityMgr != null) {
+ securityMgr.dispose(getName());
+ }
+
// close system session
if (systemSession != null) {
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
+import org.apache.jackrabbit.core.nodetype.NodeDefinitionImpl;
+import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.security.user.UserManagerImpl;
+import org.apache.jackrabbit.core.security.authorization.acl.ACLEditor;
+
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.Property;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.version.VersionException;
+import javax.jcr.lock.LockException;
+
+/**
+ * <code>SecurityItemModifier</code>: An abstract helper class to allow classes
+ * of the security API residing outside of the core package to modify and remove
+ * protected items for security. The protected item definitions are required in
+ * order not to have security relevant content being changed through common
+ * item operations but forcing the usage of the security API. The latter asserts
+ * that implementation specific constraints are not violated.
+ */
+public abstract class SecurityItemModifier {
+
+ private static Logger log = LoggerFactory.getLogger(SecurityItemModifier.class);
+
+ protected SecurityItemModifier() {
+ Class cl = getClass();
+ if (!(cl.equals(UserManagerImpl.class) ||
+ cl.equals(ACLEditor.class) ||
+ cl.getSuperclass().equals(ACLEditor.class))) {
+ throw new IllegalArgumentException("Only UserManagerImpl and ACLEditor may extend from the SecurityItemModifier");
+ }
+ }
+
+ protected NodeImpl addSecurityNode(NodeImpl parentImpl, Name name, Name ntName) throws RepositoryException, PathNotFoundException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
+ synchronized (parentImpl) {
+ // validation: make sure Node is not locked or checked-in.
+ parentImpl.checkSetProperty();
+
+ NodeTypeImpl nodeType = parentImpl.session.getNodeTypeManager().getNodeType(ntName);
+ NodeDefinitionImpl def = parentImpl.getApplicableChildNodeDefinition(name, ntName);
+
+ // check for name collisions
+ // TODO: improve. copied from NodeImpl
+ NodeState thisState = (NodeState) parentImpl.getItemState();
+ NodeState.ChildNodeEntry cne = thisState.getChildNodeEntry(name, 1);
+ if (cne != null) {
+ // there's already a child node entry with that name;
+ // check same-name sibling setting of new node
+ if (!def.allowsSameNameSiblings()) {
+ throw new ItemExistsException();
+ }
+ // check same-name sibling setting of existing node
+ NodeId newId = cne.getId();
+ NodeImpl n = (NodeImpl) parentImpl.session.getItemManager().getItem(newId);
+ if (!n.getDefinition().allowsSameNameSiblings()) {
+ throw new ItemExistsException();
+ }
+ }
+
+ return parentImpl.createChildNode(name, def, nodeType, null);
+ }
+ }
+
+ protected Property setSecurityProperty(NodeImpl parentImpl, Name name, Value value) throws RepositoryException, PathNotFoundException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
+ synchronized (parentImpl) {
+ // validation: make sure Node is not locked or checked-in.
+ parentImpl.checkSetProperty();
+ InternalValue intVs = InternalValue.create(value, parentImpl.session.getNamePathResolver());
+ return parentImpl.internalSetProperty(name, intVs);
+ }
+ }
+
+ protected Property setSecurityProperty(NodeImpl parentImpl, Name name, Value[] values) throws RepositoryException, PathNotFoundException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
+ synchronized (parentImpl) {
+ // validation: make sure Node is not locked or checked-in.
+ parentImpl.checkSetProperty();
+ InternalValue[] intVs = new InternalValue[values.length];
+ for (int i = 0; i < values.length; i++) {
+ intVs[i] = InternalValue.create(values[i], parentImpl.session.getNamePathResolver());
+ }
+ return parentImpl.internalSetProperty(name, intVs);
+ }
+ }
+
+ protected void removeSecurityItem(ItemImpl itemImpl) throws LockException, VersionException, AccessDeniedException, ItemNotFoundException, RepositoryException {
+ NodeImpl n = (itemImpl.isNode()) ? (NodeImpl) itemImpl : (NodeImpl) itemImpl.getParent();
+ synchronized (n) {
+ // validation: make sure Node is not locked or checked-in.
+ n.checkSetProperty();
+ itemImpl.internalRemove(true);
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Wed Mar 19 06:56:13 2008
@@ -20,7 +20,6 @@
import org.apache.commons.collections.map.ReferenceMap;
import org.apache.jackrabbit.commons.AbstractSession;
import org.apache.jackrabbit.core.RepositoryImpl.WorkspaceInfo;
-import org.apache.jackrabbit.core.config.AccessManagerConfig;
import org.apache.jackrabbit.core.config.WorkspaceConfig;
import org.apache.jackrabbit.core.data.GarbageCollector;
import org.apache.jackrabbit.core.lock.LockManager;
@@ -31,8 +30,13 @@
import org.apache.jackrabbit.core.persistence.PersistenceManager;
import org.apache.jackrabbit.core.security.AMContext;
import org.apache.jackrabbit.core.security.AccessManager;
-import org.apache.jackrabbit.core.security.AuthContext;
import org.apache.jackrabbit.core.security.SecurityConstants;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.core.security.authentication.AuthContext;
+import org.apache.jackrabbit.core.security.jsr283.security.AccessControlManager;
import org.apache.jackrabbit.core.state.ItemStateException;
import org.apache.jackrabbit.core.state.LocalItemStateManager;
import org.apache.jackrabbit.core.state.NodeState;
@@ -80,8 +84,8 @@
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.ValueFactory;
import javax.jcr.Workspace;
-import javax.jcr.lock.Lock;
import javax.jcr.lock.LockException;
+import javax.jcr.lock.Lock;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.observation.EventListener;
@@ -91,7 +95,6 @@
import java.io.File;
import java.io.PrintStream;
import java.security.AccessControlException;
-import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -99,21 +102,34 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.Arrays;
/**
* A <code>SessionImpl</code> ...
*/
public class SessionImpl extends AbstractSession
- implements NamePathResolver, Dumpable {
+ implements JackrabbitSession, NamePathResolver, Dumpable {
private static Logger log = LoggerFactory.getLogger(SessionImpl.class);
/**
- * prededfined action constants in checkPermission
+ * TODO deprecate as soon as present with Session interface (JSR 283)
*/
public static final String READ_ACTION = "read";
+
+ /**
+ * TODO deprecate as soon as present with Session interface (JSR 283)
+ */
public static final String REMOVE_ACTION = "remove";
+
+ /**
+ * TODO deprecate as soon as present with Session interface (JSR 283)
+ */
public static final String ADD_NODE_ACTION = "add_node";
+
+ /**
+ * TODO deprecate as soon as present with Session interface (JSR 283)
+ */
public static final String SET_PROPERTY_ACTION = "set_property";
/**
@@ -208,6 +224,16 @@
protected ValueFactory valueFactory;
/**
+ * Principal Manager
+ */
+ private PrincipalManager principalManager;
+
+ /**
+ * User Manager
+ */
+ private UserManager userManager;
+
+ /**
* Protected constructor.
*
* @param rep
@@ -240,17 +266,26 @@
throws AccessDeniedException, RepositoryException {
alive = true;
this.rep = rep;
- Set principals = subject.getPrincipals();
- if (principals.isEmpty()) {
- String msg = "unable to instantiate Session: no principals found";
- log.error(msg);
- throw new RepositoryException(msg);
- } else {
- // use 1st principal in case there are more that one
- Principal principal = (Principal) principals.iterator().next();
- userId = principal.getName();
- }
this.subject = subject;
+
+ /*
+ Retrieve userID from the subject.
+ Since the subject may contain multiple principals and the principal
+ name must not be equals to the UserID by definition, the proper way
+ is to check for known credentials the provide the correct userID.
+ The specification explicitely defines the UserID to be related to
+ the credentials and allows 'null' values in case the credentials do
+ not reveal a userID.
+ TODO: eval alternative approach via UserManager
+ */
+ String uid = null;
+ Iterator creds = subject.getPublicCredentials(SimpleCredentials.class).iterator();
+ if (creds.hasNext()) {
+ SimpleCredentials sc = (SimpleCredentials) creds.next();
+ uid = sc.getUserID();
+ }
+ userId = uid;
+
nsMappings = new LocalNamespaceMappings(rep.getNamespaceRegistry());
namePathResolver = new DefaultNamePathResolver(nsMappings, true);
ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), rep.getNamespaceRegistry(), getNamespaceResolver(), getNamePathResolver(), rep.getDataStore());
@@ -323,27 +358,15 @@
protected AccessManager createAccessManager(Subject subject,
HierarchyManager hierMgr)
throws AccessDeniedException, RepositoryException {
- AccessManagerConfig amConfig = rep.getConfig().getAccessManagerConfig();
- try {
-
- AMContext ctx = new AMContext(new File(rep.getConfig().getHomeDir()),
- rep.getFileSystem(),
- subject,
- hierMgr,
- rep.getNamespaceRegistry(),
- wsp.getName());
- AccessManager accessMgr = (AccessManager) amConfig.newInstance();
- accessMgr.init(ctx);
- return accessMgr;
- } catch (AccessDeniedException ade) {
- // re-throw
- throw ade;
- } catch (Exception e) {
- // wrap in RepositoryException
- String msg = "failed to instantiate AccessManager implementation: " + amConfig.getClassName();
- log.error(msg, e);
- throw new RepositoryException(msg, e);
- }
+ String wspName = getWorkspace().getName();
+ AMContext ctx = new AMContext(new File(rep.getConfig().getHomeDir()),
+ rep.getFileSystem(),
+ this,
+ getSubject(),
+ getItemStateManager().getAtticAwareHierarchyMgr(),
+ getNamePathResolver(),
+ wspName);
+ return rep.getSecurityManager().getAccessManager(this, ctx);
}
/**
@@ -365,11 +388,39 @@
*
* @return the <code>Subject</code> associated with this session
*/
- protected Subject getSubject() {
+ public Subject getSubject() {
return subject;
}
/**
+ * Creates a new session with the same subject as this sessions but to a
+ * different workspace. The returned session is a newly logged in session,
+ * with the same subject but a different workspace. Even if the given
+ * workspace is the same as this sessions one, the implementation must
+ * return a new session object.
+ *
+ * @param workspaceName name of the workspace to acquire a session for.
+ * @return A session to the requested workspace for the same authenticated
+ * subject.
+ * @throws AccessDeniedException in case the current Subject is not allowed
+ * to access the requested Workspace
+ * @throws NoSuchWorkspaceException If the named workspace does not exist.
+ * @throws RepositoryException in any other exceptional state
+ */
+ public Session createSession(String workspaceName)
+ throws AccessDeniedException, NoSuchWorkspaceException, RepositoryException {
+
+ if (workspaceName == null) {
+ workspaceName = rep.getConfig().getDefaultWorkspaceName();
+ }
+ if (loginContext!=null) {
+ return rep.createSession(loginContext, workspaceName);
+ } else {
+ return rep.createSession(getSubject(), workspaceName);
+ }
+ }
+
+ /**
* Returns the <code>AccessManager</code> associated with this session.
*
* @return the <code>AccessManager</code> associated with this session
@@ -649,134 +700,35 @@
return namePathResolver.getQPath(path);
}
- //--------------------------------------------------------------< Session >
+ //----------------------------------------------------< JackrabbitSession >
/**
- * {@inheritDoc}
+ * @see JackrabbitSession#getPrincipalManager()
*/
- public void checkPermission(String absPath, String actions)
- throws AccessControlException, RepositoryException {
- // check sanity of this session
- sanityCheck();
-
- // build the set of actions to be checked
- String[] strings = actions.split(",");
- HashSet set = new HashSet();
- for (int i = 0; i < strings.length; i++) {
- set.add(strings[i]);
- }
-
- Path targetPath;
- try {
- targetPath = getQPath(absPath).getNormalizedPath();
- } catch (NameException e) {
- String msg = "invalid path: " + absPath;
- log.debug(msg, e);
- throw new RepositoryException(msg, e);
- }
- if (!targetPath.isAbsolute()) {
- throw new RepositoryException("not an absolute path: " + absPath);
- }
-
- ItemId targetId = null;
-
- /**
- * "read" action:
- * requires READ permission on target item
- */
- if (set.contains(READ_ACTION)) {
- try {
- targetId = hierMgr.resolvePath(targetPath);
- if (targetId == null) {
- // target does not exist, throw exception
- throw new AccessControlException(READ_ACTION);
- }
- accessMgr.checkPermission(targetId, AccessManager.READ);
- } catch (AccessDeniedException re) {
- // otherwise the RepositoryException catch clause will
- // log a warn message, which is not appropriate in this case.
- throw new AccessControlException(READ_ACTION);
- }
- }
-
- Path parentPath = null;
- ItemId parentId = null;
-
- /**
- * "add_node" action:
- * requires WRITE permission on parent item
- */
- if (set.contains(ADD_NODE_ACTION)) {
- try {
- parentPath = targetPath.getAncestor(1);
- parentId = hierMgr.resolveNodePath(parentPath);
- if (parentId == null) {
- // parent does not exist (i.e. / was specified), throw exception
- throw new AccessControlException(ADD_NODE_ACTION);
- }
- accessMgr.checkPermission(parentId, AccessManager.WRITE);
- } catch (AccessDeniedException re) {
- // otherwise the RepositoryException catch clause will
- // log a warn message, which is not appropriate in this case.
- throw new AccessControlException(ADD_NODE_ACTION);
- }
+ public PrincipalManager getPrincipalManager() throws RepositoryException, AccessDeniedException {
+ if (principalManager == null) {
+ principalManager = rep.getSecurityManager().getPrincipalManager(this);
}
+ return principalManager;
+ }
- /**
- * "remove" action:
- * requires REMOVE permission on target item
- */
- if (set.contains(REMOVE_ACTION)) {
- try {
- if (targetId == null) {
- targetId = hierMgr.resolvePath(targetPath);
- if (targetId == null) {
- // parent does not exist, throw exception
- throw new AccessControlException(REMOVE_ACTION);
- }
- }
- accessMgr.checkPermission(targetId, AccessManager.REMOVE);
- } catch (AccessDeniedException re) {
- // otherwise the RepositoryException catch clause will
- // log a warn message, which is not appropriate in this case.
- throw new AccessControlException(REMOVE_ACTION);
- }
+ /**
+ * @see JackrabbitSession#getUserManager()
+ */
+ public UserManager getUserManager() throws AccessDeniedException, RepositoryException {
+ if (userManager == null) {
+ userManager = rep.getSecurityManager().getUserManager(this);
}
+ return userManager;
+ }
- /**
- * "set_property" action:
- * requires WRITE permission on parent item if property is going to be
- * added or WRITE permission on target item if property is going to be
- * modified
- */
- if (set.contains(SET_PROPERTY_ACTION)) {
- try {
- if (targetId == null) {
- targetId = hierMgr.resolvePath(targetPath);
- if (targetId == null) {
- // property does not exist yet,
- // check WRITE permission on parent
- if (parentPath == null) {
- parentPath = targetPath.getAncestor(1);
- }
- if (parentId == null) {
- parentId = hierMgr.resolveNodePath(parentPath);
- if (parentId == null) {
- // parent does not exist, throw exception
- throw new AccessControlException(SET_PROPERTY_ACTION);
- }
- }
- accessMgr.checkPermission(parentId, AccessManager.WRITE);
- } else {
- // property does already exist,
- // check WRITE permission on target
- accessMgr.checkPermission(targetId, AccessManager.WRITE);
- }
- }
- } catch (AccessDeniedException re) {
- // otherwise the RepositoryException catch clause will
- // log a warn message, which is not appropriate in this case.
- throw new AccessControlException(SET_PROPERTY_ACTION);
- }
+ //--------------------------------------------------------------< Session >
+ /**
+ * {@inheritDoc}
+ */
+ public void checkPermission(String absPath, String actions)
+ throws AccessControlException, RepositoryException {
+ if (!hasPermission(absPath, actions)) {
+ throw new AccessControlException(actions);
}
}
@@ -1391,7 +1343,7 @@
* absolute path.
* @since JCR 2.0
*/
- boolean propertyExists(String absPath) throws RepositoryException {
+ public boolean propertyExists(String absPath) throws RepositoryException {
// check sanity of this session
sanityCheck();
@@ -1405,6 +1357,69 @@
String msg = "invalid path:" + absPath;
log.debug(msg);
throw new RepositoryException(msg, e);
+ }
+ }
+
+ /**
+ * @see Session#hasPermission(String, String)
+ * @since 2.0
+ */
+ public boolean hasPermission(String absPath, String actions) throws RepositoryException {
+ // check sanity of this session
+ sanityCheck();
+ Path path = getQPath(absPath).getNormalizedPath();
+ // test if path is absolute
+ if (!path.isAbsolute()) {
+ throw new RepositoryException("Absolute path expected. Was:" + absPath);
+ }
+
+ Set s = new HashSet(Arrays.asList(actions.split(",")));
+ int permissions = 0;
+ if (s.remove(SessionImpl.READ_ACTION)) {
+ permissions |= Permission.READ;
+ }
+ if (s.remove(SessionImpl.ADD_NODE_ACTION)) {
+ permissions |= Permission.ADD_NODE;
+ }
+ if (s.remove(SessionImpl.SET_PROPERTY_ACTION)) {
+ permissions |= Permission.SET_PROPERTY;
+ }
+ if (s.remove(SessionImpl.REMOVE_ACTION)) {
+ if (nodeExists(absPath)) {
+ permissions |= (propertyExists(absPath)) ?
+ (Permission.REMOVE_NODE | Permission.REMOVE_PROPERTY) :
+ Permission.REMOVE_NODE;
+ } else if (propertyExists(absPath)) {
+ permissions |= Permission.REMOVE_PROPERTY;
+ } else {
+ // item does exist -> check both permissions
+ permissions = Permission.REMOVE_NODE | Permission.REMOVE_PROPERTY;
+ }
+ }
+ if (!s.isEmpty()) {
+ StringBuffer sb = new StringBuffer();
+ for (Iterator it = s.iterator(); it.hasNext();) {
+ sb.append(it.next());
+ }
+ throw new IllegalArgumentException("Unknown actions: " + sb.toString());
+ }
+ try {
+ return getAccessManager().isGranted(path, permissions);
+ } catch (AccessDeniedException e) {
+ return false;
+ }
+ }
+
+ /**
+ * @see Session#getAccessControlManager()
+ * @since 2.0
+ */
+ public AccessControlManager getAccessControlManager()
+ throws UnsupportedRepositoryOperationException, RepositoryException {
+ if (accessMgr instanceof AccessControlManager) {
+ return (AccessControlManager) accessMgr;
+ } else {
+ throw new UnsupportedRepositoryOperationException("Access control discovery is not supported.");
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java Wed Mar 19 06:56:13 2008
@@ -20,6 +20,10 @@
import org.apache.jackrabbit.core.security.AMContext;
import org.apache.jackrabbit.core.security.AccessManager;
import org.apache.jackrabbit.core.security.SystemPrincipal;
+import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.Name;
import javax.jcr.AccessDeniedException;
import javax.jcr.ItemNotFoundException;
@@ -84,7 +88,6 @@
* correctly
*/
return new SystemAccessManager();
- //return super.createAccessManager(subject, hierMgr);
}
//--------------------------------------------------------< inner classes >
@@ -105,6 +108,10 @@
// nop
}
+ public void init(AMContext context, AccessControlProvider acProvider, WorkspaceAccessManager wspAccessMgr) throws AccessDeniedException, Exception {
+ // nop
+ }
+
/**
* {@inheritDoc}
*/
@@ -134,6 +141,26 @@
*/
public boolean isGranted(ItemId id, int permissions)
throws ItemNotFoundException, RepositoryException {
+ // allow everything
+ return true;
+ }
+
+ /**
+ * Always returns true.
+ *
+ * @see AccessManager#isGranted(Path, int)
+ */
+ public boolean isGranted(Path absPath, int permissions) throws RepositoryException {
+ // allow everything
+ return true;
+ }
+
+ /**
+ * Always returns true.
+ *
+ * @see AccessManager#isGranted(Path, Name, int)
+ */
+ public boolean isGranted(Path parentPath, Name childName, int permissions) throws ItemNotFoundException, RepositoryException {
// allow everything
return true;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java Wed Mar 19 06:56:13 2008
@@ -20,7 +20,7 @@
import org.apache.jackrabbit.core.lock.LockManager;
import org.apache.jackrabbit.core.lock.LockManagerImpl;
import org.apache.jackrabbit.core.lock.XALockManager;
-import org.apache.jackrabbit.core.security.AuthContext;
+import org.apache.jackrabbit.core.security.authentication.AuthContext;
import org.apache.jackrabbit.core.state.SharedItemStateManager;
import org.apache.jackrabbit.core.state.XAItemStateManager;
import org.apache.jackrabbit.core.version.VersionManager;
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/AccessManagerConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/AccessManagerConfig.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/AccessManagerConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/AccessManagerConfig.java Wed Mar 19 06:56:13 2008
@@ -23,7 +23,7 @@
* This class is currently only used to assign a static type to
* more generic bean configuration information.
*
- * @see RepositoryConfig#getAccessManagerConfig()
+ * @see SecurityConfig#getAccessManagerConfig()
*/
public class AccessManagerConfig extends BeanConfig {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/LoginModuleConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/LoginModuleConfig.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/LoginModuleConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/LoginModuleConfig.java Wed Mar 19 06:56:13 2008
@@ -29,6 +29,23 @@
*/
public class LoginModuleConfig extends BeanConfig {
+ public static final String PARAM_ANONYMOUS_ID = "anonymousId";
+ public static final String PARAM_ADMIN_ID = "adminId";
+
+ /**
+ * Name of the default user id to be used upon Repository.login with
+ * <code>null</code> credentials. Optional parameter in the LoginModule
+ * configuration.
+ */
+ public static final String PARAM_DEFAULT_USERID = "defaultUserId";
+
+ /**
+ * Property-Key for the fully qualified class name of the implementation of
+ * {@link org.apache.jackrabbit.core.security.principal.PrincipalProvider}
+ * to be used with the LoginModule.
+ */
+ public static final String PARAM_PRINCIPAL_PROVIDER_CLASS = "principalprovider";
+
/**
* Creates an access manager configuration object from the
* given bean configuration.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java Wed Mar 19 06:56:13 2008
@@ -634,6 +634,7 @@
* JAAS app-entry configuration.
*
* @return repository name
+ * @deprecated Use {@link SecurityConfig#getAppName()} instead.
*/
public String getAppName() {
return sec.getAppName();
@@ -643,6 +644,7 @@
* Returns the repository access manager configuration.
*
* @return access manager configuration
+ * @deprecated Use {@link SecurityConfig#getAccessManagerConfig()} instead.
*/
public AccessManagerConfig getAccessManagerConfig() {
return sec.getAccessManagerConfig();
@@ -653,6 +655,7 @@
*
* @return login module configuration, or <code>null</code> if standard
* JAAS mechanism should be used.
+ * @deprecated Use {@link SecurityConfig#getLoginModuleConfig()} instead.
*/
public LoginModuleConfig getLoginModuleConfig() {
return sec.getLoginModuleConfig();
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java Wed Mar 19 06:56:13 2008
@@ -16,14 +16,14 @@
*/
package org.apache.jackrabbit.core.config;
-import java.io.File;
-import java.util.Properties;
-
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
+import java.io.File;
+import java.util.Properties;
+
/**
* Configuration parser. This class is used to parse the repository and
* workspace configuration files.
@@ -55,12 +55,21 @@
/** Name of the security configuration element. */
public static final String SECURITY_ELEMENT = "Security";
+ /** Name of the security manager configuration element. */
+ public static final String SECURITY_MANAGER_ELEMENT = "SecurityManager";
+
/** Name of the access manager configuration element. */
public static final String ACCESS_MANAGER_ELEMENT = "AccessManager";
/** Name of the login module configuration element. */
public static final String LOGIN_MODULE_ELEMENT = "LoginModule";
+ /**
+ * Name of the optional WorkspaceAccessManager element defining which
+ * implementation of WorkspaceAccessManager to be used.
+ */
+ private static final String WORKSPACE_ACCESS_ELEMENT = "WorkspaceAccessManager";
+
/** Name of the general workspace configuration element. */
public static final String WORKSPACES_ELEMENT = "Workspaces";
@@ -95,6 +104,9 @@
/** Name of the application name configuration attribute. */
public static final String APP_NAME_ATTRIBUTE = "appName";
+ /** Name of the workspace conaining security data. */
+ public static final String WSP_NAME_ATTRIBUTE = "workspaceName";
+
/** Name of the root path configuration attribute. */
public static final String ROOT_PATH_ATTRIBUTE = "rootPath";
@@ -124,6 +136,15 @@
/** Default synchronization delay, in milliseconds. */
public static final String DEFAULT_SYNC_DELAY = "5000";
+ /** Name of the workspace specific security configuration element */
+ private static final String WSP_SECURITY_ELEMENT = "WorkspaceSecurity";
+
+ /**
+ * Name of the optional AccessControlProvider element defining which
+ * implementation of AccessControlProvider should be used.
+ */
+ private static final String AC_PROVIDER_ELEMENT = "AccessControlProvider";
+
/**
* Creates a new configuration parser with the given parser variables.
*
@@ -140,6 +161,7 @@
* <Repository>
* <FileSystem ...>
* <Security appName="...">
+ * <SecurityManager ...>
* <AccessManager ...>
* <LoginModule ... (optional)>
* </Security>
@@ -236,13 +258,15 @@
* uses the following format:
* <pre>
* <Security appName="...">
+ * <SecurityManager ...>
* <AccessManager ...>
* <LoginModule ... (optional)>
* </Security>
* </pre>
* <p/>
- * Both the <code>AccessManager</code> and <code>LoginModule</code>
- * elements are {@link #parseBeanConfig(Element,String) bean configuration}
+ * The <code>SecurityManager</code>, the <code>AccessManager</code>
+ * and <code>LoginModule</code> are all
+ * {@link #parseBeanConfig(Element,String) bean configuration}
* elements.
* <p/>
* The login module is an optional feature of repository configuration.
@@ -254,9 +278,35 @@
public SecurityConfig parseSecurityConfig(Element security)
throws ConfigurationException {
String appName = getAttribute(security, APP_NAME_ATTRIBUTE);
+
+ SecurityManagerConfig smc = parseSecurityManagerConfig(security);
AccessManagerConfig amc = parseAccessManagerConfig(security);
LoginModuleConfig lmc = parseLoginModuleConfig(security);
- return new SecurityConfig(appName, amc, lmc);
+
+ return new SecurityConfig(appName, smc, amc, lmc);
+ }
+
+ /**
+ * Parses the security manager configuration.
+ *
+ * @param security the <security> element.
+ * @return the security manager configuration.
+ * @throws ConfigurationException if the configuration is broken
+ */
+ public SecurityManagerConfig parseSecurityManagerConfig(Element security)
+ throws ConfigurationException {
+
+ BeanConfig bc = parseBeanConfig(security, SECURITY_MANAGER_ELEMENT);
+
+ Element smElement = getElement(security, SECURITY_MANAGER_ELEMENT);
+ String wspAttr = getAttribute(smElement, WSP_NAME_ATTRIBUTE, null);
+
+ BeanConfig wac = null;
+ Element element = getElement(smElement, WORKSPACE_ACCESS_ELEMENT, false);
+ if (element != null) {
+ wac = parseBeanConfig(smElement, WORKSPACE_ACCESS_ELEMENT);
+ }
+ return new SecurityManagerConfig(bc, wspAttr, wac);
}
/**
@@ -300,6 +350,8 @@
* <PersistenceManager ...>
* <SearchIndex ...>
* <ISMLocking ...>
+ * <WorkspaceSecurity ...>
+ * <ISMLocking ...>
* </Workspace>
* </pre>
* <p>
@@ -337,6 +389,7 @@
* @throws ConfigurationException if the configuration is broken
* @see #parseBeanConfig(Element, String)
* @see #parseSearchConfig(Element)
+ * @see #parseWorkspaceSecurityConfig(Element)
*/
public WorkspaceConfig parseWorkspaceConfig(InputSource xml)
throws ConfigurationException {
@@ -371,7 +424,10 @@
// Item state manager locking configuration (optional)
ISMLockingConfig ismLockingConfig = tmpParser.parseISMLockingConfig(root);
- return new WorkspaceConfig(home, name, clustered, fsc, pmc, sc, ismLockingConfig);
+ // workspace specific security configuration
+ WorkspaceSecurityConfig workspaceSecurityConfig = tmpParser.parseWorkspaceSecurityConfig(root);
+
+ return new WorkspaceConfig(home, name, clustered, fsc, pmc, sc, ismLockingConfig, workspaceSecurityConfig);
}
/**
@@ -430,6 +486,34 @@
return null;
}
+
+ /**
+ * Read the WorkspaceSecurity Element of Workspace's configuration. It uses
+ * the following format:
+ * <pre>
+ * <WorkspaceSecurity>
+ * <AccessControlProvider class="..." (optional)>
+ * </WorkspaceSecurity>
+ * </pre>
+ *
+ * @param parent Workspace-Root-Element
+ * @return
+ * @throws ConfigurationException
+ */
+ public WorkspaceSecurityConfig parseWorkspaceSecurityConfig(Element parent)
+ throws ConfigurationException {
+
+ BeanConfig factConf = null;
+ Element element = getElement(parent, WSP_SECURITY_ELEMENT, false);
+ if (element != null) {
+ Element provFact = getElement(element, AC_PROVIDER_ELEMENT, false);
+ if (provFact !=null ) {
+ factConf = parseBeanConfig(element, AC_PROVIDER_ELEMENT);
+ }
+ }
+ return new WorkspaceSecurityConfig(factConf);
+ }
+
/**
* Parses ism locking configuration. ism locking configuration uses the
* following format:
@@ -587,7 +671,7 @@
* <code>DataStore</code> is a {@link #parseBeanConfig(Element,String) bean configuration}
* element.
*
- * @param cluster parent cluster element
+ * @param parent cluster element
* @return journal configuration, or <code>null</code>
* @throws ConfigurationException if the configuration is broken
*/
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityConfig.java?rev=638834&r1=638833&r2=638834&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityConfig.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityConfig.java Wed Mar 19 06:56:13 2008
@@ -28,6 +28,11 @@
private final String name;
/**
+ * Repository security manager configuration;
+ */
+ private final SecurityManagerConfig smc;
+
+ /**
* Repository access manager configuration;
*/
private final AccessManagerConfig amc;
@@ -41,12 +46,16 @@
* Creates a new security configuration.
*
* @param name repository name for a JAAS app-entry configuration
+ * @param smc security manager configuration
* @param amc access manager configuration
* @param lmc login module configuration (can be <code>null</code>)
*/
public SecurityConfig(
- String name, AccessManagerConfig amc, LoginModuleConfig lmc) {
+ String name,
+ SecurityManagerConfig smc,
+ AccessManagerConfig amc, LoginModuleConfig lmc) {
this.name = name;
+ this.smc = smc;
this.amc = amc;
this.lmc = lmc;
}
@@ -59,6 +68,15 @@
*/
public String getAppName() {
return name;
+ }
+
+ /**
+ * Returns the repository security manager configuration.
+ *
+ * @return access manager configuration
+ */
+ public SecurityManagerConfig getSecurityManagerConfig() {
+ return smc;
}
/**
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java?rev=638834&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java Wed Mar 19 06:56:13 2008
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.config;
+
+/**
+ * Security manager configuration. This bean configuration class
+ * is used to create configured security manager objects.
+ * <p>
+ * This class is currently only used to assign a static type to
+ * more generic bean configuration information.
+ *
+ * @see SecurityConfig#getSecurityManagerConfig()
+ */
+public class SecurityManagerConfig extends BeanConfig {
+
+ private final String workspaceName;
+ private final BeanConfig workspaceAccessConfig;
+
+ /**
+ * Creates an security manager configuration object from the
+ * given bean configuration.
+ *
+ * @param config bean configuration
+ */
+ public SecurityManagerConfig(BeanConfig config, String workspaceName,
+ BeanConfig workspaceAccessConfig) {
+ super(config);
+ this.workspaceName = workspaceName;
+ this.workspaceAccessConfig = workspaceAccessConfig;
+ }
+
+ /**
+ * Returns the name of the 'workspaceName' attribute or <code>null</code>
+ * if the SecurityManager does not require an extra workspace.
+ *
+ * @return
+ */
+ public String getWorkspaceName() {
+ return workspaceName;
+ }
+
+ /**
+ * @return the configuration for the <code>WorkspaceAccessManager</code>.
+ * May be <code>null</code> if the configuration entry is missing (i.e.
+ * the system default should be used).
+ */
+ public BeanConfig getWorkspaceAccessConfig() {
+ return workspaceAccessConfig;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/SecurityManagerConfig.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url