1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.authz;
18
19
20 import org.apache.ldap.server.AbstractTestCase;
21 import org.apache.ldap.server.partition.DirectoryPartitionNexus;
22 import org.apache.ldap.server.subtree.SubentryService;
23 import org.apache.ldap.common.name.LdapName;
24
25 import javax.naming.directory.*;
26 import javax.naming.NamingException;
27 import javax.naming.Name;
28 import java.util.Hashtable;
29
30
31 /***
32 * A base class used for authorization tests. It has some extra utility methods
33 * added to it which are required by all authorization tests. Note that we use
34 * the admin test case otherwise failures will result without browse permission
35 * when setting up the test case for non-admin users. Anyway we do not use the
36 * context created for the non-admin user since it is anonymous, we get our own
37 * contexts.
38 *
39 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
40 * @version $Rev$
41 */
42 public abstract class AbstractAuthorizationTest extends AbstractTestCase
43 {
44 /***
45 * Creates an abstract authorization test case which enables the
46 * authorization subsystem of the server.
47 */
48 public AbstractAuthorizationTest()
49 {
50 super( DirectoryPartitionNexus.ADMIN_PRINCIPAL, "secret" );
51 super.configuration.setAccessControlEnabled( true );
52 }
53
54
55
56
57
58
59
60 /***
61 * Gets a context at ou=system as the admin user.
62 *
63 * @return the admin context at ou=system
64 * @throws NamingException if there are problems creating the context
65 */
66 public DirContext getContextAsAdmin() throws NamingException
67 {
68 return getContextAsAdmin( DirectoryPartitionNexus.SYSTEM_PARTITION_SUFFIX );
69 }
70
71
72 /***
73 * Gets a context at some dn within the directory as the admin user.
74 * Should be a dn of an entry under ou=system since no other partitions
75 * are enabled.
76 *
77 * @param dn the DN of the context to get
78 * @return the context for the DN as the admin user
79 * @throws NamingException if is a problem initializing or getting the context
80 */
81 public DirContext getContextAsAdmin( String dn ) throws NamingException
82 {
83 Hashtable env = ( Hashtable ) sysRoot.getEnvironment().clone();
84 env.put( DirContext.PROVIDER_URL, dn );
85 env.put( DirContext.SECURITY_AUTHENTICATION, "simple" );
86 env.put( DirContext.SECURITY_PRINCIPAL, DirectoryPartitionNexus.ADMIN_PRINCIPAL );
87 env.put( DirContext.SECURITY_CREDENTIALS, "secret" );
88 return new InitialDirContext( env );
89 }
90
91
92 /***
93 * Creates a group using the groupOfUniqueNames objectClass under the
94 * ou=groups,ou=sytem container with an initial member.
95 *
96 * @param cn the common name of the group used as the RDN attribute
97 * @param firstMemberDn the DN of the first member of this group
98 * @return the distinguished name of the group entry
99 * @throws NamingException if there are problems creating the new group like
100 * it exists already
101 */
102 public Name createGroup( String cn, String firstMemberDn ) throws NamingException
103 {
104 DirContext adminCtx = getContextAsAdmin();
105 Attributes group = new BasicAttributes( "cn", cn, true );
106 Attribute objectClass = new BasicAttribute( "objectClass" );
107 group.put( objectClass );
108 objectClass.add( "top" );
109 objectClass.add( "groupOfUniqueNames" );
110 group.put( "uniqueMember", firstMemberDn );
111 adminCtx.createSubcontext( "cn="+cn+",ou=groups", group );
112 return new LdapName( "cn="+cn+",ou=groups,ou=system" );
113 }
114
115
116 /***
117 * Deletes a user with a specific UID under ou=users,ou=system.
118 *
119 * @param uid the RDN value for the user to delete
120 * @throws NamingException if there are problems removing the user
121 * i.e. user does not exist
122 */
123 public void deleteUser( String uid ) throws NamingException
124 {
125 DirContext adminCtx = getContextAsAdmin();
126 adminCtx.destroySubcontext( "uid="+uid+",ou=users" );
127 }
128
129
130 /***
131 * Creates a simple user as an inetOrgPerson under the ou=users,ou=system
132 * container. The user's RDN attribute is the uid argument. This argument
133 * is also used as the value of the two MUST attributes: sn and cn.
134 *
135 * @param uid the value of the RDN attriubte (uid), the sn and cn attributes
136 * @param password the password to use to create the user
137 * @return the dn of the newly created user entry
138 * @throws NamingException if there are problems creating the user entry
139 */
140 public Name createUser( String uid, String password ) throws NamingException
141 {
142 DirContext adminCtx = getContextAsAdmin();
143 Attributes user = new BasicAttributes( "uid", uid, true );
144 user.put( "userPassword", password );
145 Attribute objectClass = new BasicAttribute( "objectClass" );
146 user.put( objectClass );
147 objectClass.add( "top" );
148 objectClass.add( "person" );
149 objectClass.add( "organizationalPerson" );
150 objectClass.add( "inetOrgPerson" );
151 user.put( "sn", uid );
152 user.put( "cn", uid );
153 adminCtx.createSubcontext( "uid="+uid+",ou=users", user );
154 return new LdapName( "uid="+uid+",ou=users,ou=system" );
155 }
156
157
158 /***
159 * Adds an existing user under ou=users,ou=system to an existing group under the
160 * ou=groups,ou=system container.
161 *
162 * @param userUid the uid of the user to add to the group
163 * @param groupCn the cn of the group to add the user to
164 * @throws NamingException if the group does not exist
165 */
166 public void addUserToGroup( String userUid, String groupCn ) throws NamingException
167 {
168 DirContext adminCtx = getContextAsAdmin();
169 Attributes changes = new BasicAttributes( "uniqueMember",
170 "uid="+userUid+",ou=users,ou=system", true );
171 adminCtx.modifyAttributes( "cn="+groupCn+",ou=groups",
172 DirContext.ADD_ATTRIBUTE, changes );
173 }
174
175
176 /***
177 * Removes a user from a group.
178 *
179 * @param userUid the RDN attribute value of the user to remove from the group
180 * @param groupCn the RDN attribute value of the group to have user removed from
181 * @throws NamingException if there are problems accessing the group
182 */
183 public void removeUserFromGroup( String userUid, String groupCn ) throws NamingException
184 {
185 DirContext adminCtx = getContextAsAdmin();
186 Attributes changes = new BasicAttributes( "uniqueMember",
187 "uid="+userUid+",ou=users,ou=system", true );
188 adminCtx.modifyAttributes( "cn="+groupCn+",ou=groups",
189 DirContext.REMOVE_ATTRIBUTE, changes );
190 }
191
192
193 /***
194 * Gets the context at ou=system as a specific user.
195 *
196 * @param user the DN of the user to get the context as
197 * @param password the password of the user
198 * @return the context as the user
199 * @throws NamingException if the user does not exist or authx fails
200 */
201 public DirContext getContextAs( Name user, String password ) throws NamingException
202 {
203 return getContextAs( user, password, DirectoryPartitionNexus.SYSTEM_PARTITION_SUFFIX );
204 }
205
206
207 /***
208 * Gets the context at any DN under ou=system as a specific user.
209 *
210 * @param user the DN of the user to get the context as
211 * @param password the password of the user
212 * @param dn the distinguished name of the entry to get the context for
213 * @return the context representing the entry at the dn as a specific user
214 * @throws NamingException if the does not exist or authx fails
215 */
216 public DirContext getContextAs( Name user, String password, String dn ) throws NamingException
217 {
218 Hashtable env = ( Hashtable ) sysRoot.getEnvironment().clone();
219 env.put( DirContext.PROVIDER_URL, dn );
220 env.put( DirContext.SECURITY_AUTHENTICATION, "simple" );
221 env.put( DirContext.SECURITY_PRINCIPAL, user.toString() );
222 env.put( DirContext.SECURITY_CREDENTIALS, password );
223 return new InitialDirContext( env );
224 }
225
226
227 public void deleteAccessControlSubentry( String cn ) throws NamingException
228 {
229 DirContext adminCtx = getContextAsAdmin();
230 adminCtx.destroySubcontext( "cn=" + cn );
231 }
232
233
234 /***
235 * Creates an access control subentry under ou=system whose subtree covers
236 * the entire naming context.
237 *
238 * @param cn the common name and rdn for the subentry
239 * @param aciItem the prescriptive ACI attribute value
240 * @throws NamingException if there is a problem creating the subentry
241 */
242 public void createAccessControlSubentry( String cn, String aciItem ) throws NamingException
243 {
244 createAccessControlSubentry( cn, "{}", aciItem );
245 }
246
247
248 /***
249 * Creates an access control subentry under ou=system whose subtree covers
250 * the entire naming context.
251 *
252 * @param cn the common name and rdn for the subentry
253 * @param subtree the subtreeSpecification for the subentry
254 * @param aciItem the prescriptive ACI attribute value
255 * @throws NamingException if there is a problem creating the subentry
256 */
257 public void createAccessControlSubentry( String cn, String subtree, String aciItem ) throws NamingException
258 {
259 DirContext adminCtx = getContextAsAdmin();
260
261
262 Attributes ap = adminCtx.getAttributes( "", new String[] { "administrativeRole" } );
263 Attribute administrativeRole = ap.get( "administrativeRole" );
264 if ( administrativeRole == null || ! administrativeRole.contains( SubentryService.AC_AREA ) )
265 {
266 Attributes changes = new BasicAttributes( "administrativeRole", SubentryService.AC_AREA, true );
267 adminCtx.modifyAttributes( "", DirContext.ADD_ATTRIBUTE, changes );
268 }
269
270
271 Attributes subentry = new BasicAttributes( "cn", cn, true );
272 Attribute objectClass = new BasicAttribute( "objectClass" );
273 subentry.put( objectClass );
274 objectClass.add( "top" );
275 objectClass.add( "subentry" );
276 objectClass.add( "accessControlSubentry" );
277 subentry.put( "subtreeSpecification", subtree );
278 subentry.put( "prescriptiveACI", aciItem );
279 adminCtx.createSubcontext( "cn=" + cn, subentry );
280 }
281
282
283 /***
284 * Adds and entryACI attribute to an entry specified by a relative name
285 * with respect to ou=system
286 *
287 * @param rdn a name relative to ou=system
288 * @param aciItem the entryACI attribute value
289 * @throws NamingException if there is a problem adding the attribute
290 */
291 public void addEntryACI( Name rdn, String aciItem ) throws NamingException
292 {
293 DirContext adminCtx = getContextAsAdmin();
294
295
296 Attributes changes = new BasicAttributes( "entryACI", aciItem, true );
297 adminCtx.modifyAttributes( rdn, DirContext.ADD_ATTRIBUTE, changes );
298 }
299
300
301 /***
302 * Adds and subentryACI attribute to ou=system
303 *
304 * @param aciItem the subentryACI attribute value
305 * @throws NamingException if there is a problem adding the attribute
306 */
307 public void addSubentryACI( String aciItem ) throws NamingException
308 {
309 DirContext adminCtx = getContextAsAdmin();
310
311
312 Attributes changes = new BasicAttributes( "subentryACI", aciItem, true );
313 adminCtx.modifyAttributes( "", DirContext.ADD_ATTRIBUTE, changes );
314 }
315 }