| /* |
| * 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.directory.server.core.authz; |
| |
| |
| import org.apache.directory.server.constants.ServerDNConstants; |
| import org.apache.directory.server.core.DefaultDirectoryService; |
| import org.apache.directory.server.core.DirectoryService; |
| import org.apache.directory.server.core.integ.DirectoryServiceFactory; |
| import static org.apache.directory.server.core.integ.IntegrationUtils.getSystemContext; |
| import org.apache.directory.server.core.subtree.SubentryInterceptor; |
| import org.apache.directory.shared.ldap.constants.SchemaConstants; |
| import org.apache.directory.shared.ldap.message.AttributeImpl; |
| import org.apache.directory.shared.ldap.message.AttributesImpl; |
| import org.apache.directory.shared.ldap.name.LdapDN; |
| |
| import javax.naming.Name; |
| import javax.naming.NamingException; |
| import javax.naming.directory.Attribute; |
| import javax.naming.directory.Attributes; |
| import javax.naming.directory.DirContext; |
| import javax.naming.directory.InitialDirContext; |
| import javax.naming.ldap.LdapContext; |
| import java.util.Hashtable; |
| |
| |
| /** |
| * Some extra utility methods added to it which are required by all |
| * authorization tests. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| * @version $Rev$ |
| */ |
| public class AutzIntegUtils |
| { |
| public static DirectoryService service; |
| |
| |
| public static class ServiceFactory implements DirectoryServiceFactory |
| { |
| public DirectoryService newInstance() |
| { |
| DefaultDirectoryService service = new DefaultDirectoryService(); |
| service.setAccessControlEnabled( true ); |
| service.getChangeLog().setEnabled( true ); |
| AutzIntegUtils.service = service; |
| return service; |
| } |
| } |
| |
| |
| public static class DefaultServiceFactory implements DirectoryServiceFactory |
| { |
| public DirectoryService newInstance() |
| { |
| DefaultDirectoryService service = new DefaultDirectoryService(); |
| service.setAccessControlEnabled( false ); |
| service.getChangeLog().setEnabled( true ); |
| AutzIntegUtils.service = service; |
| return service; |
| } |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| // Utility methods used by subclasses |
| // ----------------------------------------------------------------------- |
| |
| /** |
| * Gets a context at ou=system as the admin user. |
| * |
| * @return the admin context at ou=system |
| * @throws NamingException if there are problems creating the context |
| */ |
| public static DirContext getContextAsAdmin() throws NamingException |
| { |
| return getSystemContext( service ); |
| } |
| |
| |
| /** |
| * Gets a context at some dn within the directory as the admin user. |
| * Should be a dn of an entry under ou=system since no other partitions |
| * are enabled. |
| * |
| * @param dn the DN of the context to get |
| * @return the context for the DN as the admin user |
| * @throws NamingException if is a problem initializing or getting the context |
| */ |
| @SuppressWarnings("unchecked") |
| public static DirContext getContextAsAdmin( String dn ) throws NamingException |
| { |
| LdapContext sysRoot = getSystemContext( service ); |
| Hashtable<String,Object> env = ( Hashtable<String,Object> ) sysRoot.getEnvironment().clone(); |
| env.put( DirContext.PROVIDER_URL, dn ); |
| env.put( DirContext.SECURITY_AUTHENTICATION, "simple" ); |
| env.put( DirContext.SECURITY_PRINCIPAL, "uid=admin, ou=system" ); |
| env.put( DirContext.SECURITY_CREDENTIALS, "secret" ); |
| env.put( DirContext.INITIAL_CONTEXT_FACTORY, "org.apache.directory.server.core.jndi.CoreContextFactory" ); |
| env.put( DirectoryService.JNDI_KEY, service ); |
| return new InitialDirContext( env ); |
| } |
| |
| |
| /** |
| * Creates a group using the groupOfUniqueNames objectClass under the |
| * ou=groups,ou=sytem container with an initial member. |
| * |
| * @param cn the common name of the group used as the RDN attribute |
| * @param firstMemberDn the DN of the first member of this group |
| * @return the distinguished name of the group entry |
| * @throws NamingException if there are problems creating the new group like |
| * it exists already |
| */ |
| public static Name createGroup( String cn, String firstMemberDn ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| Attributes group = new AttributesImpl( "cn", cn, true ); |
| Attribute objectClass = new AttributeImpl( "objectClass" ); |
| group.put( objectClass ); |
| objectClass.add( "top" ); |
| objectClass.add( "groupOfUniqueNames" ); |
| group.put( "uniqueMember", firstMemberDn ); |
| adminCtx.createSubcontext( "cn=" + cn + ",ou=groups", group ); |
| return new LdapDN( "cn=" + cn + ",ou=groups,ou=system" ); |
| } |
| |
| |
| /** |
| * Deletes a user with a specific UID under ou=users,ou=system. |
| * |
| * @param uid the RDN value for the user to delete |
| * @throws NamingException if there are problems removing the user |
| * i.e. user does not exist |
| */ |
| public static void deleteUser( String uid ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| adminCtx.destroySubcontext( "uid=" + uid + ",ou=users" ); |
| } |
| |
| |
| /** |
| * Creates a simple user as an inetOrgPerson under the ou=users,ou=system |
| * container. The user's RDN attribute is the uid argument. This argument |
| * is also used as the value of the two MUST attributes: sn and cn. |
| * |
| * @param uid the value of the RDN attriubte (uid), the sn and cn attributes |
| * @param password the password to use to create the user |
| * @return the dn of the newly created user entry |
| * @throws NamingException if there are problems creating the user entry |
| */ |
| public static Name createUser( String uid, String password ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| Attributes user = new AttributesImpl( "uid", uid, true ); |
| user.put( "userPassword", password ); |
| Attribute objectClass = new AttributeImpl( "objectClass" ); |
| user.put( objectClass ); |
| objectClass.add( "top" ); |
| objectClass.add( "person" ); |
| objectClass.add( "organizationalPerson" ); |
| objectClass.add( "inetOrgPerson" ); |
| user.put( "sn", uid ); |
| user.put( "cn", uid ); |
| adminCtx.createSubcontext( "uid=" + uid + ",ou=users", user ); |
| return new LdapDN( "uid=" + uid + ",ou=users,ou=system" ); |
| } |
| |
| |
| /** |
| * Creates a simple groupOfUniqueNames under the ou=groups,ou=system |
| * container. The admin user is always a member of this newly created |
| * group. |
| * |
| * @param groupName the name of the cgroup to create |
| * @return the DN of the group as a Name object |
| * @throws NamingException if the group cannot be created |
| */ |
| public static Name createGroup( String groupName ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| Attributes group = new AttributesImpl( true ); |
| Attribute objectClass = new AttributeImpl( "objectClass" ); |
| group.put( objectClass ); |
| objectClass.add( "top" ); |
| objectClass.add( "groupOfUniqueNames" ); |
| |
| // TODO might be ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED |
| group.put( "uniqueMember", "uid=admin, ou=system" ); |
| adminCtx.createSubcontext( "cn=" + groupName + ",ou=groups", group ); |
| return new LdapDN( "cn=" + groupName + ",ou=groups,ou=system" ); |
| } |
| |
| |
| /** |
| * Adds an existing user under ou=users,ou=system to an existing group under the |
| * ou=groups,ou=system container. |
| * |
| * @param userUid the uid of the user to add to the group |
| * @param groupCn the cn of the group to add the user to |
| * @throws NamingException if the group does not exist |
| */ |
| public static void addUserToGroup( String userUid, String groupCn ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| Attributes changes = new AttributesImpl( "uniqueMember", "uid=" + userUid + ",ou=users,ou=system", true ); |
| adminCtx.modifyAttributes( "cn=" + groupCn + ",ou=groups", DirContext.ADD_ATTRIBUTE, changes ); |
| } |
| |
| |
| /** |
| * Removes a user from a group. |
| * |
| * @param userUid the RDN attribute value of the user to remove from the group |
| * @param groupCn the RDN attribute value of the group to have user removed from |
| * @throws NamingException if there are problems accessing the group |
| */ |
| public static void removeUserFromGroup( String userUid, String groupCn ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| Attributes changes = new AttributesImpl( "uniqueMember", "uid=" + userUid + ",ou=users,ou=system", true ); |
| adminCtx.modifyAttributes( "cn=" + groupCn + ",ou=groups", DirContext.REMOVE_ATTRIBUTE, changes ); |
| } |
| |
| |
| /** |
| * Gets the context at ou=system as a specific user. |
| * |
| * @param user the DN of the user to get the context as |
| * @param password the password of the user |
| * @return the context as the user |
| * @throws NamingException if the user does not exist or authx fails |
| */ |
| public static DirContext getContextAs( Name user, String password ) throws NamingException |
| { |
| return getContextAs( user, password, ServerDNConstants.SYSTEM_DN ); |
| } |
| |
| |
| /** |
| * Gets the context at any DN under ou=system as a specific user. |
| * |
| * @param user the DN of the user to get the context as |
| * @param password the password of the user |
| * @param dn the distinguished name of the entry to get the context for |
| * @return the context representing the entry at the dn as a specific user |
| * @throws NamingException if the does not exist or authx fails |
| */ |
| @SuppressWarnings("unchecked") |
| public static DirContext getContextAs( Name user, String password, String dn ) throws NamingException |
| { |
| LdapContext sysRoot = getSystemContext( service ); |
| Hashtable<String,Object> env = ( Hashtable<String,Object> ) sysRoot.getEnvironment().clone(); |
| env.put( DirContext.PROVIDER_URL, dn ); |
| env.put( DirContext.SECURITY_AUTHENTICATION, "simple" ); |
| env.put( DirContext.SECURITY_PRINCIPAL, user.toString() ); |
| env.put( DirContext.SECURITY_CREDENTIALS, password ); |
| env.put( DirContext.INITIAL_CONTEXT_FACTORY, "org.apache.directory.server.core.jndi.CoreContextFactory" ); |
| env.put( DirectoryService.JNDI_KEY, service ); |
| return new InitialDirContext( env ); |
| } |
| |
| |
| public static void deleteAccessControlSubentry( String cn ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| adminCtx.destroySubcontext( "cn=" + cn ); |
| } |
| |
| |
| /** |
| * Creates an access control subentry under ou=system whose subtree covers |
| * the entire naming context. |
| * |
| * @param cn the common name and rdn for the subentry |
| * @param aciItem the prescriptive ACI attribute value |
| * @throws NamingException if there is a problem creating the subentry |
| */ |
| public static void createAccessControlSubentry( String cn, String aciItem ) throws NamingException |
| { |
| createAccessControlSubentry( cn, "{}", aciItem ); |
| } |
| |
| |
| /** |
| * Creates an access control subentry under ou=system whose subtree covers |
| * the entire naming context. |
| * |
| * @param cn the common name and rdn for the subentry |
| * @param subtree the subtreeSpecification for the subentry |
| * @param aciItem the prescriptive ACI attribute value |
| * @throws NamingException if there is a problem creating the subentry |
| */ |
| public static void createAccessControlSubentry( String cn, String subtree, String aciItem ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| |
| // modify ou=system to be an AP for an A/C AA if it is not already |
| Attributes ap = adminCtx.getAttributes( "", new String[] |
| { "administrativeRole" } ); |
| Attribute administrativeRole = ap.get( "administrativeRole" ); |
| if ( administrativeRole == null || !administrativeRole.contains( SubentryInterceptor.AC_AREA ) ) |
| { |
| Attributes changes = new AttributesImpl( "administrativeRole", SubentryInterceptor.AC_AREA, true ); |
| adminCtx.modifyAttributes( "", DirContext.ADD_ATTRIBUTE, changes ); |
| } |
| |
| // now add the A/C subentry below ou=system |
| Attributes subentry = new AttributesImpl( "cn", cn, true ); |
| Attribute objectClass = new AttributeImpl( "objectClass" ); |
| subentry.put( objectClass ); |
| objectClass.add( "top" ); |
| objectClass.add( SchemaConstants.SUBENTRY_OC ); |
| objectClass.add( "accessControlSubentry" ); |
| subentry.put( "subtreeSpecification", subtree ); |
| subentry.put( "prescriptiveACI", aciItem ); |
| adminCtx.createSubcontext( "cn=" + cn, subentry ); |
| } |
| |
| |
| /** |
| * Adds and entryACI attribute to an entry specified by a relative name |
| * with respect to ou=system |
| * |
| * @param rdn a name relative to ou=system |
| * @param aciItem the entryACI attribute value |
| * @throws NamingException if there is a problem adding the attribute |
| */ |
| public static void addEntryACI( Name rdn, String aciItem ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| |
| // modify the entry relative to ou=system to include the aciItem |
| Attributes changes = new AttributesImpl( "entryACI", aciItem, true ); |
| adminCtx.modifyAttributes( rdn, DirContext.ADD_ATTRIBUTE, changes ); |
| } |
| |
| |
| /** |
| * Adds and subentryACI attribute to ou=system |
| * |
| * @param aciItem the subentryACI attribute value |
| * @throws NamingException if there is a problem adding the attribute |
| */ |
| public static void addSubentryACI( String aciItem ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| |
| // modify the entry relative to ou=system to include the aciItem |
| Attributes changes = new AttributesImpl( "subentryACI", aciItem, true ); |
| adminCtx.modifyAttributes( "", DirContext.ADD_ATTRIBUTE, changes ); |
| } |
| |
| |
| /** |
| * Replaces values of an prescriptiveACI attribute of a subentry subordinate |
| * to ou=system. |
| * |
| * @param cn the common name of the aci subentry |
| * @param aciItem the new value for the ACI item |
| * @throws NamingException if the modify fails |
| */ |
| public static void changePresciptiveACI( String cn, String aciItem ) throws NamingException |
| { |
| DirContext adminCtx = getContextAsAdmin(); |
| Attributes changes = new AttributesImpl( "prescriptiveACI", aciItem ); |
| adminCtx.modifyAttributes( "cn=" + cn, DirContext.REPLACE_ATTRIBUTE, changes ); |
| } |
| } |