1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.directory.server.core.authz;
21
22
23 import org.apache.directory.shared.ldap.exception.LdapNoPermissionException;
24 import org.apache.directory.shared.ldap.name.LdapDN;
25 import org.apache.directory.server.core.integ.CiRunner;
26 import org.apache.directory.server.core.integ.annotations.Factory;
27 import org.apache.directory.server.core.DirectoryService;
28 import org.junit.runner.RunWith;
29
30 import javax.naming.NamingException;
31 import javax.naming.NamingEnumeration;
32 import javax.naming.Name;
33 import javax.naming.directory.Attribute;
34 import javax.naming.directory.Attributes;
35 import javax.naming.directory.BasicAttribute;
36 import javax.naming.directory.BasicAttributes;
37 import javax.naming.directory.DirContext;
38 import javax.naming.directory.ModificationItem;
39
40 import java.util.List;
41 import java.util.ArrayList;
42
43 import static org.junit.Assert.assertTrue;
44 import static org.junit.Assert.assertFalse;
45 import org.junit.Test;
46
47 import static org.apache.directory.server.core.authz.AutzIntegUtils.createUser;
48 import static org.apache.directory.server.core.authz.AutzIntegUtils.getContextAs;
49 import static org.apache.directory.server.core.authz.AutzIntegUtils.getContextAsAdmin;
50 import static org.apache.directory.server.core.authz.AutzIntegUtils.createAccessControlSubentry;
51 import static org.apache.directory.server.core.authz.AutzIntegUtils.addUserToGroup;
52 import static org.apache.directory.server.core.authz.AutzIntegUtils.deleteAccessControlSubentry;
53 import static org.apache.directory.server.core.authz.AutzIntegUtils.createGroup;
54 import static org.apache.directory.server.core.authz.AutzIntegUtils.changePresciptiveACI;
55
56
57 /**
58 * Tests whether or not authorization around entry modify operations work properly.
59 *
60 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
61 * @version $Rev: 691179 $
62 */
63 @RunWith ( CiRunner.class )
64 @Factory ( AutzIntegUtils.ServiceFactory.class )
65 public class ModifyAuthorizationIT
66 {
67 public static DirectoryService service;
68
69
70 /**
71 * Checks if an attribute of a simple entry (an organizationalUnit) with an RDN
72 * relative to ou=system can be modified by a specific non-admin user. If a
73 * permission exception is encountered it is caught and false is returned,
74 * otherwise true is returned. The entry is deleted after being created just in case
75 * subsequent calls to this method are made in the same test case: the admin account
76 * is used to add and delete this test entry so permissions to add and delete are not
77 * required to test the modify operation by the user.
78 *
79 * @param uid the unique identifier for the user (presumed to exist under ou=users,ou=system)
80 * @param password the password of this user
81 * @param entryRdn the relative DN, relative to ou=system where entry is created
82 * for modification test
83 * @param mods the modifications to make to the entry
84 * @return true if the modifications can be made by the user at the specified location,
85 * false otherwise.
86 * @throws javax.naming.NamingException if there are problems conducting the test
87 */
88 public boolean checkCanModifyAs( String uid, String password, String entryRdn, ModificationItem[] mods )
89 throws Exception
90 {
91 // create the entry with the telephoneNumber attribute to modify
92 Attributes testEntry = new BasicAttributes( "ou", "testou", true );
93 Attribute objectClass = new BasicAttribute( "objectClass" );
94 testEntry.put( objectClass );
95 objectClass.add( "top" );
96 objectClass.add( "organizationalUnit" );
97 testEntry.put( "telephoneNumber", "867-5309" ); // jenny don't change your number
98
99 DirContext adminContext = getContextAsAdmin();
100
101 //noinspection EmptyCatchBlock
102 try
103 {
104 // create the entry as admin
105 LdapDN userName = new LdapDN( "uid=" + uid + ",ou=users,ou=system" );
106 adminContext.createSubcontext( entryRdn, testEntry );
107
108 // modify the entry as the user
109 DirContext userContext = getContextAs( userName, password );
110 userContext.modifyAttributes( entryRdn, mods );
111
112 return true;
113 }
114 catch ( LdapNoPermissionException e )
115 {
116 }
117 finally
118 {
119 // let's clean up
120 adminContext.destroySubcontext( entryRdn );
121 }
122
123 return false;
124 }
125
126
127 /**
128 * Checks if an attribute of a simple entry (an organizationalUnit) with an RDN
129 * relative to ou=system can be modified by a specific non-admin user. If a
130 * permission exception is encountered it is caught and false is returned,
131 * otherwise true is returned. The entry is deleted after being created just in case
132 * subsequent calls to this method are made in the same test case: the admin account
133 * is used to add and delete this test entry so permissions to add and delete are not
134 * required to test the modify operation by the user.
135 *
136 * @param uid the unique identifier for the user (presumed to exist under ou=users,ou=system)
137 * @param password the password of this user
138 * @param entryRdn the relative DN, relative to ou=system where entry is created
139 * for modification test
140 * @param mods the attributes to modify in the entry
141 * @param modOp the modification operation to use for all attributes
142 * @return true if the modifications can be made by the user at the specified location,
143 * false otherwise.
144 * @throws javax.naming.NamingException if there are problems conducting the test
145 */
146 public boolean checkCanModifyAs( String uid, String password, String entryRdn, int modOp, Attributes mods )
147 throws Exception
148 {
149 // create the entry with the telephoneNumber attribute to modify
150 Attributes testEntry = new BasicAttributes( "ou", "testou", true );
151 Attribute objectClass = new BasicAttribute( "objectClass" );
152 testEntry.put( objectClass );
153 objectClass.add( "top" );
154 objectClass.add( "organizationalUnit" );
155 testEntry.put( "telephoneNumber", "867-5309" ); // jenny don't change your number
156
157 DirContext adminContext = getContextAsAdmin();
158
159 try
160 {
161 // create the entry as admin
162 LdapDN userName = new LdapDN( "uid=" + uid + ",ou=users,ou=system" );
163 adminContext.createSubcontext( entryRdn, testEntry );
164
165 // modify the entry as the user
166 DirContext userContext = getContextAs( userName, password );
167 userContext.modifyAttributes( entryRdn, modOp, mods );
168
169 return true;
170 }
171 catch ( LdapNoPermissionException e )
172 {
173 return false;
174 }
175 finally
176 {
177 // let's clean up
178 adminContext.destroySubcontext( entryRdn );
179 }
180 }
181
182
183 /**
184 * Checks if a user can modify an attribute of their own entry. Users are
185 * presumed to reside under ou=users,ou=system. If a permission exception is
186 * encountered it is caught and false is returned, otherwise true is returned.
187 *
188 * @param uid the unique identifier for the user (presumed to exist under ou=users,ou=system)
189 * @param password the password of this user
190 * @param mods the attributes to modify in the entry
191 * @param modOp the modification operation to use for all attributes
192 * @return true if the modifications can be made by the user his/her own entry,
193 * false otherwise.
194 * @throws javax.naming.NamingException if there are problems conducting the test
195 */
196 public boolean checkCanSelfModify( String uid, String password, int modOp, Attributes mods ) throws Exception
197 {
198 try
199 {
200 // modify the entry as the user
201 Name userEntry = new LdapDN( "uid=" + uid + ",ou=users,ou=system" );
202 DirContext userContext = getContextAs( userEntry, password, userEntry.toString() );
203 userContext.modifyAttributes( "", modOp, mods );
204 return true;
205 }
206 catch ( LdapNoPermissionException e )
207 {
208 return false;
209 }
210 }
211
212
213 /**
214 * Checks if a user can modify an attribute of their own entry. Users are
215 * presumed to reside under ou=users,ou=system. If a permission exception is
216 * encountered it is caught and false is returned, otherwise true is returned.
217 *
218 * @param uid the unique identifier for the user (presumed to exist under ou=users,ou=system)
219 * @param password the password of this user
220 * @param mods the attributes to modify in the entry
221 * @return true if the modifications can be made by the user his/her own entry,
222 * false otherwise.
223 * @throws javax.naming.NamingException if there are problems conducting the test
224 */
225 public boolean checkCanSelfModify( String uid, String password, ModificationItem[] mods ) throws Exception
226 {
227 try
228 {
229 // modify the entry as the user
230 Name userEntry = new LdapDN( "uid=" + uid + ",ou=users,ou=system" );
231 DirContext userContext = getContextAs( userEntry, password, userEntry.toString() );
232 userContext.modifyAttributes( "", mods );
233 return true;
234 }
235 catch ( LdapNoPermissionException e )
236 {
237 return false;
238 }
239 }
240
241
242 /**
243 * Converts a set of attributes and a modification operation type into a MoficationItem array.
244 *
245 * @param modOp the modification operation to perform
246 * @param changes the modifications to the attribute
247 * @return the array of modification items represting the changes
248 * @throws NamingException if there are problems accessing attributes
249 */
250 private ModificationItem[] toItems( int modOp, Attributes changes ) throws NamingException
251 {
252 List<ModificationItem> mods = new ArrayList<ModificationItem>();
253 NamingEnumeration<? extends Attribute> list = changes.getAll();
254 while ( list.hasMore() )
255 {
256 Attribute attr = list.next();
257 mods.add( new ModificationItem( modOp, attr ) );
258 }
259 ModificationItem[] modArray = new ModificationItem[mods.size()];
260 return mods.toArray( modArray );
261 }
262
263
264 @Test
265 public void testSelfModification() throws Exception
266 {
267 // ----------------------------------------------------------------------------------
268 // Modify with Attribute Addition
269 // ----------------------------------------------------------------------------------
270
271 // create the non-admin user
272 createUser( "billyd", "billyd" );
273
274 // create the password modification
275 ModificationItem[] mods = toItems( DirContext.REPLACE_ATTRIBUTE, new BasicAttributes( "userPassword",
276 "williams", true ) );
277
278 // try a modify operation which should fail without any ACI
279 assertFalse( checkCanSelfModify( "billyd", "billyd", mods ) );
280
281 // Gives grantModify, and grantRead perm to all users in the Administrators group for
282 // entries and all attribute types and values
283 createAccessControlSubentry( "selfModifyUserPassword", "{ " + "identificationTag \"addAci\", "
284 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
285 + "userClasses { thisEntry }, " + "userPermissions { "
286 + "{ protectedItems {entry}, grantsAndDenials { grantModify, grantBrowse, grantRead } }, "
287 + "{ protectedItems {allAttributeValues {userPassword}}, grantsAndDenials { grantAdd, grantRemove } } "
288 + "} } }" );
289
290 // try a modify operation which should succeed with ACI
291 assertTrue( checkCanSelfModify( "billyd", "billyd", mods ) );
292 deleteAccessControlSubentry( "selfModifyUserPassword" );
293 }
294
295
296 /**
297 * Checks to make sure group membership based userClass works for modify operations.
298 *
299 * @throws javax.naming.NamingException if the test encounters an error
300 */
301 @Test
302 public void testGrantModifyByTestGroup() throws Exception
303 {
304 // ----------------------------------------------------------------------------------
305 // Modify with Attribute Addition
306 // ----------------------------------------------------------------------------------
307
308 // create the add modifications
309 ModificationItem[] mods = toItems( DirContext.ADD_ATTRIBUTE, new BasicAttributes( "registeredAddress",
310 "100 Park Ave.", true ) );
311
312 // create the non-admin user
313 createUser( "billyd", "billyd" );
314
315 createGroup( "TestGroup" );
316
317 // try a modify operation which should fail without any ACI
318 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
319
320 // Gives grantModify, and grantRead perm to all users in the TestGroup group for
321 // entries and all attribute types and values
322 createAccessControlSubentry( "administratorModifyAdd", "{ " + "identificationTag \"addAci\", "
323 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
324 + "userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + "userPermissions { "
325 + "{ protectedItems {entry}, grantsAndDenials { grantModify, grantBrowse } }, "
326 + "{ protectedItems {attributeType {registeredAddress}, allAttributeValues {registeredAddress}}, grantsAndDenials { grantAdd } } " + "} } }" );
327
328 // see if we can now add that test entry which we could not before
329 // add op should still fail since billd is not in the admin group
330 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
331
332 // now add billyd to the TestGroup group and try again
333 addUserToGroup( "billyd", "TestGroup" );
334
335 // try a modify operation which should succeed with ACI and group membership change
336 assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
337 deleteAccessControlSubentry( "administratorModifyAdd" );
338
339 // ----------------------------------------------------------------------------------
340 // Modify with Attribute Removal
341 // ----------------------------------------------------------------------------------
342
343 // now let's test to see if we can perform a modify with a delete op
344 mods = toItems( DirContext.REMOVE_ATTRIBUTE, new BasicAttributes( "telephoneNumber", "867-5309", true ) );
345
346 // make sure we cannot remove the telephone number from the test entry
347 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
348
349 // Gives grantModify, and grantRead perm to all users in the TestGroup group for
350 // entries and all attribute types and values
351 createAccessControlSubentry( "administratorModifyRemove", "{ " + "identificationTag \"addAci\", "
352 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
353 + "userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + "userPermissions { "
354 + "{ protectedItems {entry}, grantsAndDenials { grantModify, grantBrowse } }, "
355 + "{ protectedItems {attributeType {telephoneNumber}, allAttributeValues {telephoneNumber}}, grantsAndDenials { grantRemove } } " + "} } }" );
356
357 // try a modify operation which should succeed with ACI and group membership change
358 assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
359 deleteAccessControlSubentry( "administratorModifyRemove" );
360
361 // ----------------------------------------------------------------------------------
362 // Modify with Attribute Replace (requires both grantRemove and grantAdd on attrs)
363 // ----------------------------------------------------------------------------------
364
365 // now let's test to see if we can perform a modify with a delete op
366 mods = toItems( DirContext.REPLACE_ATTRIBUTE, new BasicAttributes( "telephoneNumber", "867-5309", true ) );
367
368 // make sure we cannot remove the telephone number from the test entry
369 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
370
371 // Gives grantModify, and grantRead perm to all users in the TestGroup group for
372 // entries and all attribute types and values
373 createAccessControlSubentry( "administratorModifyReplace", "{ " + "identificationTag \"addAci\", "
374 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
375 + "userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + "userPermissions { "
376 + "{ protectedItems {entry}, grantsAndDenials { grantModify, grantBrowse } }, "
377 + "{ protectedItems {attributeType {registeredAddress}, allAttributeValues {telephoneNumber}}, grantsAndDenials { grantAdd, grantRemove } } "
378 + "} } }" );
379
380 // try a modify operation which should succeed with ACI and group membership change
381 assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
382 deleteAccessControlSubentry( "administratorModifyReplace" );
383
384 /* =================================================================================
385 * DO IT ALL OVER AGAIN BUT USE THE OTHER MODIFY METHOD
386 * ================================================================================= */
387
388 // ----------------------------------------------------------------------------------
389 // Modify with Attribute Addition
390 // ----------------------------------------------------------------------------------
391 // create the add modifications
392 Attributes changes = new BasicAttributes( "registeredAddress", "100 Park Ave.", true );
393
394 // try a modify operation which should fail without any ACI
395 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", DirContext.ADD_ATTRIBUTE, changes ) );
396
397 // Gives grantModify, and grantRead perm to all users in the TestGroup group for
398 // entries and all attribute types and values
399 createAccessControlSubentry( "administratorModifyAdd", "{ " + "identificationTag \"addAci\", "
400 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
401 + "userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + "userPermissions { "
402 + "{ protectedItems {entry}, grantsAndDenials { grantModify, grantBrowse } }, "
403 + "{ protectedItems {attributeType {registeredAddress}, allAttributeValues {registeredAddress}}, grantsAndDenials { grantAdd } } " + "} } }" );
404
405 // try a modify operation which should succeed with ACI and group membership change
406 assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", DirContext.ADD_ATTRIBUTE, changes ) );
407 deleteAccessControlSubentry( "administratorModifyAdd" );
408
409 // ----------------------------------------------------------------------------------
410 // Modify with Attribute Removal
411 // ----------------------------------------------------------------------------------
412
413 // now let's test to see if we can perform a modify with a delete op
414 changes = new BasicAttributes( "telephoneNumber", "867-5309", true );
415
416 // make sure we cannot remove the telephone number from the test entry
417 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", DirContext.REMOVE_ATTRIBUTE, changes ) );
418
419 // Gives grantModify, and grantRead perm to all users in the TestGroup group for
420 // entries and all attribute types and values
421 createAccessControlSubentry( "administratorModifyRemove", "{ " + "identificationTag \"addAci\", "
422 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
423 + "userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + "userPermissions { "
424 + "{ protectedItems {entry}, grantsAndDenials { grantModify, grantBrowse } }, "
425 + "{ protectedItems {attributeType {telephoneNumber}, allAttributeValues {telephoneNumber}}, grantsAndDenials { grantRemove } } " + "} } }" );
426
427 // try a modify operation which should succeed with ACI and group membership change
428 assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", DirContext.REMOVE_ATTRIBUTE, changes ) );
429 deleteAccessControlSubentry( "administratorModifyRemove" );
430
431 // ----------------------------------------------------------------------------------
432 // Modify with Attribute Replace (requires both grantRemove and grantAdd on attrs)
433 // ----------------------------------------------------------------------------------
434
435 // now let's test to see if we can perform a modify with a delete op
436 changes = new BasicAttributes( "telephoneNumber", "867-5309", true );
437
438 // make sure we cannot remove the telephone number from the test entry
439 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", DirContext.REPLACE_ATTRIBUTE, changes ) );
440
441 // Gives grantModify, and grantRead perm to all users in the TestGroup group for
442 // entries and all attribute types and values
443 createAccessControlSubentry( "administratorModifyReplace", "{ " + "identificationTag \"addAci\", "
444 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
445 + "userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + "userPermissions { "
446 + "{ protectedItems {entry}, grantsAndDenials { grantModify, grantBrowse } }, "
447 + "{ protectedItems {attributeType {registeredAddress}, allAttributeValues {telephoneNumber}}, grantsAndDenials { grantAdd, grantRemove } } "
448 + "} } }" );
449
450 // try a modify operation which should succeed with ACI and group membership change
451 assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", DirContext.REPLACE_ATTRIBUTE, changes ) );
452 deleteAccessControlSubentry( "administratorModifyReplace" );
453 }
454
455
456 // /**
457 // * Checks to make sure name based userClass works for modify operations.
458 // *
459 // * @throws javax.naming.NamingException if the test encounters an error
460 // */
461 // public void testGrantModifyByName() throws NamingException
462 // {
463 // // create the non-admin user
464 // createUser( "billyd", "billyd" );
465 //
466 // // try an modify operation which should fail without any ACI
467 // assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
468 //
469 // // now add a subentry that enables user billyd to modify an entry below ou=system
470 // createAccessControlSubentry( "billydAdd", "{ " +
471 // "identificationTag \"addAci\", " +
472 // "precedence 14, " +
473 // "authenticationLevel none, " +
474 // "itemOrUserFirst userFirst: { " +
475 // "userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " +
476 // "userPermissions { { " +
477 // "protectedItems {entry, allUserAttributeTypesAndValues}, " +
478 // "grantsAndDenials { grantModify, grantRead, grantBrowse } } } } }" );
479 //
480 // // should work now that billyd is authorized by name
481 // assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
482 // }
483 //
484 //
485 // /**
486 // * Checks to make sure subtree based userClass works for modify operations.
487 // *
488 // * @throws javax.naming.NamingException if the test encounters an error
489 // */
490 // public void testGrantModifyBySubtree() throws NamingException
491 // {
492 // // create the non-admin user
493 // createUser( "billyd", "billyd" );
494 //
495 // // try a modify operation which should fail without any ACI
496 // assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
497 //
498 // // now add a subentry that enables user billyd to modify an entry below ou=system
499 // createAccessControlSubentry( "billyAddBySubtree", "{ " +
500 // "identificationTag \"addAci\", " +
501 // "precedence 14, " +
502 // "authenticationLevel none, " +
503 // "itemOrUserFirst userFirst: { " +
504 // "userClasses { subtree { { base \"ou=users,ou=system\" } } }, " +
505 // "userPermissions { { " +
506 // "protectedItems {entry, allUserAttributeTypesAndValues}, " +
507 // "grantsAndDenials { grantModify, grantRead, grantBrowse } } } } }" );
508 //
509 // // should work now that billyd is authorized by the subtree userClass
510 // assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
511 // }
512 //
513 //
514 // /**
515 // * Checks to make sure <b>allUsers</b> userClass works for modify operations.
516 // *
517 // * @throws javax.naming.NamingException if the test encounters an error
518 // */
519 // public void testGrantModifyAllUsers() throws NamingException
520 // {
521 // // create the non-admin user
522 // createUser( "billyd", "billyd" );
523 //
524 // // try an add operation which should fail without any ACI
525 // assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
526 //
527 // // now add a subentry that enables anyone to add an entry below ou=system
528 // createAccessControlSubentry( "anybodyAdd", "{ " +
529 // "identificationTag \"addAci\", " +
530 // "precedence 14, " +
531 // "authenticationLevel none, " +
532 // "itemOrUserFirst userFirst: { " +
533 // "userClasses { allUsers }, " +
534 // "userPermissions { { " +
535 // "protectedItems {entry, allUserAttributeTypesAndValues}, " +
536 // "grantsAndDenials { grantModify, grantRead, grantBrowse } } } } }" );
537 //
538 // // see if we can now modify that test entry's number which we could not before
539 // // should work with billyd now that all users are authorized
540 // assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", "867-5309" ) );
541 // }
542
543
544 @Test
545 public void testPresciptiveACIModification() throws Exception
546 {
547
548 ModificationItem[] mods = toItems( DirContext.ADD_ATTRIBUTE,
549 new BasicAttributes( "registeredAddress", "100 Park Ave.", true ) );
550
551 createUser( "billyd", "billyd" );
552
553 createAccessControlSubentry( "modifyACI", "{ " + "identificationTag \"modifyAci\", "
554 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
555 + "userClasses { allUsers }, " + "userPermissions { "
556 + "{ protectedItems {entry, allUserAttributeTypesAndValues}, grantsAndDenials { grantModify, grantBrowse, grantAdd, grantRemove } } } } }" );
557
558 assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
559
560 mods = toItems( DirContext.REPLACE_ATTRIBUTE,
561 new BasicAttributes( "registeredAddress", "200 Park Ave.", true ) );
562
563 changePresciptiveACI( "modifyACI", "{ " + "identificationTag \"modifyAci\", "
564 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
565 + "userClasses { allUsers }, " + "userPermissions { "
566 + "{ protectedItems {entry, allUserAttributeTypesAndValues}, grantsAndDenials { denyModify } } } } }" );
567
568 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
569
570 deleteAccessControlSubentry( "modifyACI" );
571
572 }
573
574
575 @Test
576 public void testMaxValueCountProtectedItem() throws Exception
577 {
578 createUser( "billyd", "billyd" );
579 createAccessControlSubentry( "mvcACI",
580 " {" +
581 " identificationTag \"mvcACI\"," +
582 " precedence 10," +
583 " authenticationLevel simple," +
584 " itemOrUserFirst userFirst:" +
585 " {" +
586 " userClasses { allUsers }," +
587 " userPermissions" +
588 " {" +
589 " {" +
590 " protectedItems { entry }," +
591 " grantsAndDenials { grantModify, grantBrowse }" +
592 " }" +
593 " ," +
594 " {" +
595 " protectedItems" +
596 " {" +
597 " attributeType { description }," +
598 " allAttributeValues { description }," +
599 " maxValueCount" +
600 " {" +
601 " { type description, maxCount 1 }" +
602 " }" +
603 " }" +
604 " ," +
605 " grantsAndDenials" +
606 " {" +
607 " grantRemove," +
608 " grantAdd" +
609 " }" +
610 " }" +
611 " }" +
612 " }" +
613 " }" );
614
615 ModificationItem[] mods = toItems( DirContext.ADD_ATTRIBUTE,
616 new BasicAttributes( "description", "description 1", true ) );
617
618 assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
619
620 Attributes attrs = new BasicAttributes( true );
621 Attribute attr = new BasicAttribute( "description" );
622 attr.add( "description 1" );
623 attr.add( "description 2" );
624 attrs.put( attr );
625 mods = toItems( DirContext.ADD_ATTRIBUTE, attrs );
626
627 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
628
629 mods = toItems( DirContext.REPLACE_ATTRIBUTE, attrs );
630
631 assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
632 }
633 }