diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java index 0ec8eca..cfca80e 100644 --- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java +++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java @@ -124,6 +124,7 @@ public class DefaultSecurityManager implements JackrabbitSecurityManager { */ private final Map acProviders = new HashMap(); + /** * the AccessControlProviderFactory */ @@ -143,6 +144,8 @@ public class DefaultSecurityManager implements JackrabbitSecurityManager { * factory for login-context {@see Repository#login()) */ private AuthContextProvider authContextProvider; + + private boolean anonymousAccessToSecurityWorkspace = true; //------------------------------------------< JackrabbitSecurityManager >--- /** @@ -203,7 +206,8 @@ public class DefaultSecurityManager implements JackrabbitSecurityManager { createSystemUsers(systemUserManager, this.systemSession, adminId, anonymousId); // init default ac-provider-factory - acProviderFactory = new AccessControlProviderFactoryImpl(); + acProviderFactory = new AccessControlProviderFactoryImpl(anonymousId, + anonymousAccessToSecurityWorkspace); acProviderFactory.init(this.systemSession); // create the workspace access manager @@ -416,6 +420,10 @@ public class DefaultSecurityManager implements JackrabbitSecurityManager { return getAuthContextProvider().getAuthContext(creds, subject, systemSession, getPrincipalProviderRegistry(), adminId, anonymousId); } + + public void setAnonymousAccessToSecurityWorkspace(boolean anonymousAccessToSecurityWorkspace) { + this.anonymousAccessToSecurityWorkspace = anonymousAccessToSecurityWorkspace; + } //----------------------------------------------------------< protected >--- /** diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java index d7442e3..97359e9 100644 --- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java +++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java @@ -30,6 +30,7 @@ import org.apache.jackrabbit.core.NodeImpl; import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.id.ItemId; import org.apache.jackrabbit.core.nodetype.NodeTypeImpl; +import org.apache.jackrabbit.core.security.AnonymousPrincipal; import org.apache.jackrabbit.core.security.SystemPrincipal; import org.apache.jackrabbit.core.security.principal.AdminPrincipal; import org.apache.jackrabbit.spi.Name; @@ -53,6 +54,12 @@ public abstract class AbstractAccessControlProvider implements AccessControlProv * previously installed AC content. */ public static final String PARAM_OMIT_DEFAULT_PERMISSIONS = "omit-default-permission"; + + /** + * Constant for the name of the configuration option "anonymousId". + * The option is a flag indicating the name of the anonymous user id. + */ + public static final String PARAM_ANONYMOUS_ID = "anonymousId"; /** * the system session this provider has been created for. @@ -63,12 +70,11 @@ public abstract class AbstractAccessControlProvider implements AccessControlProv protected int privAll; protected int privRead; + + protected String anonymousId; private boolean initialized; - protected AbstractAccessControlProvider() { - } - /** * Throws IllegalStateException if the provider has not * been initialized or has been closed. @@ -200,6 +206,20 @@ public abstract class AbstractAccessControlProvider implements AccessControlProv return false; } + /** + * @see AccessControlUtils#isAnonymous(Set) + */ + public boolean isAnonymous(Set principals) { + for (Principal p : principals) { + if (p instanceof AnonymousPrincipal) { + return true; + } else if (p.getName().equals(anonymousId)) { + return true; + } + } + return false; + } + //----------------------------------------------< AccessControlProvider >--- /** * Tests if the given systemSession is a SessionImpl and @@ -224,6 +244,10 @@ public abstract class AbstractAccessControlProvider implements AccessControlProv privAll = PrivilegeRegistry.getBits(new Privilege[] {session.getAccessControlManager().privilegeFromName(Privilege.JCR_ALL)}); privRead = PrivilegeRegistry.getBits(new Privilege[] {session.getAccessControlManager().privilegeFromName(Privilege.JCR_READ)}); + if (configuration.containsKey(PARAM_ANONYMOUS_ID)) { + anonymousId = (String) configuration.get(PARAM_ANONYMOUS_ID); + } + initialized = true; } diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProviderFactoryImpl.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProviderFactoryImpl.java index 82fb6de..144e461 100644 --- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProviderFactoryImpl.java +++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProviderFactoryImpl.java @@ -35,6 +35,16 @@ import java.util.Map; */ public class AccessControlProviderFactoryImpl implements AccessControlProviderFactory { + @Deprecated + public AccessControlProviderFactoryImpl() { + this(null, true); + } + + public AccessControlProviderFactoryImpl(String anonymousId, boolean anonymousAccessToSecurityWorkspace) { + this.anonymousId = anonymousId; + this.anonymousAccessToSecurityWorkspace = anonymousAccessToSecurityWorkspace; + } + /** * the default logger */ @@ -45,6 +55,9 @@ public class AccessControlProviderFactoryImpl implements AccessControlProviderFa */ private String secWorkspaceName; private String defaultWorkspaceName; + + private boolean anonymousAccessToSecurityWorkspace; + private String anonymousId; //---------------------------------------< AccessControlProviderFactory >--- /** @@ -82,12 +95,12 @@ public class AccessControlProviderFactoryImpl implements AccessControlProviderFa // UserAccessControlProvider is designed to work with an extra // workspace storing user and groups. therefore avoid returning // this ac provider for the default workspace. - prov = new UserAccessControlProvider(); + prov = new UserAccessControlProvider(anonymousAccessToSecurityWorkspace); } else { prov = new ACLProvider(); } log.debug("Default provider for workspace " + workspaceName + " = " + prov.getClass().getName()); - props = Collections.emptyMap(); + props = Collections.singletonMap("anonymousId", anonymousId); } prov.init(systemSession, props); diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlUtils.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlUtils.java index ac5fe65..2949f54 100644 --- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlUtils.java +++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlUtils.java @@ -63,6 +63,16 @@ public interface AccessControlUtils { boolean isAdminOrSystem(Set principals); /** + * Test if the specified set of principals contains the anonymous + * principal + * + * @param principals A set of principals. + * @return true if the specified set of principals contains + * the anonymous principal + */ + boolean isAnonymous(Set principals); + + /** * Test if if the specified set of principals will have read-only permissions * only. False otherwise (or if it cannot be determined from the principal * set only). diff --git a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java index 889099d..0fc966c 100644 --- a/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java +++ b/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java @@ -101,13 +101,24 @@ public class UserAccessControlProvider extends AbstractAccessControlProvider private String groupAdminGroupPath; private String administratorsGroupPath; private boolean membersInProperty; + + private boolean anonymousAccess; /** * */ + @Deprecated public UserAccessControlProvider() { - policy = new NamedAccessControlPolicyImpl("userPolicy"); + this(true); } + + /** + * + */ + public UserAccessControlProvider(boolean anonymousAccess) { + policy = new NamedAccessControlPolicyImpl("userPolicy"); + this.anonymousAccess = anonymousAccess; + } //-------------------------------------------------< AccessControlUtils >--- /** @@ -205,6 +216,10 @@ public class UserAccessControlProvider extends AbstractAccessControlProvider if (isAdminOrSystem(principals)) { return getAdminPermissions(); } else { + if (!anonymousAccess && isAnonymous(principals)) { + return CompiledPermissions.NO_PERMISSION; + } + // determined the 'user' present in the given set of principals. ItemBasedPrincipal userPrincipal = getUserPrincipal(principals); NodeImpl userNode = getUserNode(userPrincipal); @@ -223,6 +238,9 @@ public class UserAccessControlProvider extends AbstractAccessControlProvider */ public boolean canAccessRoot(Set principals) throws RepositoryException { checkInitialized(); + if (!anonymousAccess && isAnonymous(principals)) { + return false; + } return true; } diff --git a/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AnonUserAccessControlProviderTest.java b/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AnonUserAccessControlProviderTest.java new file mode 100644 index 0000000..01338a4 --- /dev/null +++ b/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AnonUserAccessControlProviderTest.java @@ -0,0 +1,66 @@ +/* + * 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.security.user; + +import java.io.File; + +import javax.jcr.LoginException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.AccessControlPolicy; +import javax.jcr.security.AccessControlPolicyIterator; +import javax.jcr.security.Privilege; + +import junit.framework.TestCase; + +import org.apache.jackrabbit.core.TransientRepository; + +public class AnonUserAccessControlProviderTest extends TestCase { + private TransientRepository repository; + + @Override + protected void setUp() throws Exception { + repository = new TransientRepository(new File("src/test/resources/repository-security.xml"), new File( + "target/repository")); + } + + @Override + protected void tearDown() throws Exception { + repository.shutdown(); + } + + public void test() throws RepositoryException { + Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), "security"); + + AccessControlManager acm = session.getAccessControlManager(); + + Privilege[] privledges = acm.getPrivileges("/"); + assertEquals(1, privledges.length); + assertEquals("jcr:all", privledges[0].getName()); + session.logout(); + + try { + session = repository.login("security"); + fail("Should not be able to log into the security workspace as the anonymous user"); + } catch (LoginException e) { + } + + session.logout(); + } +} diff --git a/jackrabbit-core/src/test/resources/repository-security.xml b/jackrabbit-core/src/test/resources/repository-security.xml new file mode 100644 index 0000000..bc67acb --- /dev/null +++ b/jackrabbit-core/src/test/resources/repository-security.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +