1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.authz;
21
22
23 import static org.apache.directory.server.core.authz.AutzIntegUtils.addEntryACI;
24 import static org.apache.directory.server.core.authz.AutzIntegUtils.addPrescriptiveACI;
25 import static org.apache.directory.server.core.authz.AutzIntegUtils.addSubentryACI;
26 import static org.apache.directory.server.core.authz.AutzIntegUtils.addUserToGroup;
27 import static org.apache.directory.server.core.authz.AutzIntegUtils.createAccessControlSubentry;
28 import static org.apache.directory.server.core.authz.AutzIntegUtils.createUser;
29 import static org.apache.directory.server.core.authz.AutzIntegUtils.deleteAccessControlSubentry;
30 import static org.apache.directory.server.core.authz.AutzIntegUtils.getContextAs;
31 import static org.apache.directory.server.core.integ.IntegrationUtils.getSystemContext;
32 import static org.junit.Assert.assertEquals;
33 import static org.junit.Assert.assertFalse;
34 import static org.junit.Assert.assertNotNull;
35 import static org.junit.Assert.assertNull;
36 import static org.junit.Assert.assertTrue;
37 import static org.junit.Assert.fail;
38
39 import java.util.HashMap;
40 import java.util.Map;
41
42 import javax.naming.Name;
43 import javax.naming.NamingEnumeration;
44 import javax.naming.NamingException;
45 import javax.naming.directory.Attribute;
46 import javax.naming.directory.Attributes;
47 import javax.naming.directory.BasicAttribute;
48 import javax.naming.directory.BasicAttributes;
49 import javax.naming.directory.DirContext;
50 import javax.naming.directory.SearchControls;
51 import javax.naming.directory.SearchResult;
52 import javax.naming.ldap.LdapContext;
53
54 import org.apache.directory.server.core.DirectoryService;
55 import org.apache.directory.server.core.integ.CiRunner;
56 import org.apache.directory.server.core.integ.annotations.Factory;
57 import org.apache.directory.shared.ldap.exception.LdapNameNotFoundException;
58 import org.apache.directory.shared.ldap.exception.LdapNoPermissionException;
59 import org.apache.directory.shared.ldap.name.LdapDN;
60 import org.junit.Test;
61 import org.junit.runner.RunWith;
62
63
64
65
66
67
68
69
70
71 @RunWith ( CiRunner.class )
72 @Factory ( AutzIntegUtils.ServiceFactory.class )
73 public class SearchAuthorizationIT
74 {
75 public static DirectoryService service;
76
77
78
79
80
81
82
83 private Map<String, SearchResult> results = new HashMap<String, SearchResult>();
84
85
86
87
88
89
90
91
92
93 private Attributes[] getTestNodes( final int count )
94 {
95 Attributes[] attributes = new Attributes[count];
96 for ( int ii = 0; ii < count; ii++ )
97 {
98 attributes[ii] = new BasicAttributes( true );
99 Attribute oc = new BasicAttribute( "objectClass" );
100 oc.add( "top" );
101 oc.add( "organizationalUnit" );
102 attributes[ii].put( oc );
103 Attribute ou = new BasicAttribute( "ou" );
104 ou.add( String.valueOf( ii ) );
105 ou.add( "testEntry" );
106 attributes[ii].put( ou );
107 attributes[ii].put( "telephoneNumber", String.valueOf( count ) );
108 }
109
110 return attributes;
111 }
112
113
114 private void recursivelyAddSearchData( Name parent, Attributes[] children, final int sizeLimit, int[] count )
115 throws Exception
116 {
117 Name[] childRdns = new Name[children.length];
118 for ( int ii = 0; ii < children.length && count[0] < sizeLimit; ii++ )
119 {
120 Name childRdn = new LdapDN();
121 childRdn.addAll( parent );
122 childRdn.add( "ou=" + ii );
123 childRdns[ii] = childRdn;
124 getSystemContext( service ).createSubcontext( childRdn, children[ii] );
125 count[0]++;
126 }
127
128 if ( count[0] >= sizeLimit )
129 {
130 return;
131 }
132
133 for ( int ii = 0; ii < children.length && count[0] < sizeLimit; ii++ )
134 {
135 recursivelyAddSearchData( childRdns[ii], children, sizeLimit, count );
136 }
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 private Name addSearchData( Name parent, int branchingFactor, int sizelimit ) throws Exception
153 {
154 parent = ( Name ) parent.clone();
155 parent.add( "ou=tests" );
156 getSystemContext( service ).createSubcontext( parent, getTestNodes( 1 )[0] );
157 recursivelyAddSearchData( parent, getTestNodes( branchingFactor ), sizelimit, new int[]
158 { 1 } );
159 return parent;
160 }
161
162
163
164
165
166
167
168
169 private void recursivelyDelete( Name rdn ) throws Exception
170 {
171 LdapContext sysRoot = getSystemContext( service );
172 NamingEnumeration<SearchResult> results = sysRoot.search( rdn, "(objectClass=*)", new SearchControls() );
173
174 while ( results.hasMore() )
175 {
176 SearchResult result = results.next();
177 Name childRdn = new LdapDN( result.getName() );
178 childRdn.remove( 0 );
179 recursivelyDelete( childRdn );
180 }
181 sysRoot.destroySubcontext( rdn );
182 }
183
184
185
186
187
188
189
190
191
192
193
194 private boolean checkCanSearchAs( String uid, String password ) throws Exception
195 {
196 return checkCanSearchAs( uid, password, "(objectClass=*)", null, 3 );
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211 private boolean checkCanSearchAs( String uid, String password, int resultSetSz ) throws Exception
212 {
213 return checkCanSearchAs( uid, password, "(objectClass=*)", null, resultSetSz );
214 }
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229 private boolean checkCanSearchAs( String uid, String password, SearchControls cons, int resultSetSz )
230 throws Exception
231 {
232 return checkCanSearchAs( uid, password, "(objectClass=*)", cons, resultSetSz );
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 private boolean checkCanSearchAs( String uid, String password, String filter, SearchControls cons, int resultSetSz )
249 throws Exception
250 {
251 if ( cons == null )
252 {
253 cons = new SearchControls();
254 }
255
256 Name base = addSearchData( new LdapDN(), 3, 10 );
257 Name userDn = new LdapDN( "uid=" + uid + ",ou=users,ou=system" );
258 try
259 {
260 results.clear();
261 DirContext userCtx = getContextAs( userDn, password );
262 NamingEnumeration<SearchResult> list = userCtx.search( base, filter, cons );
263 int counter = 0;
264
265 while ( list.hasMore() )
266 {
267 SearchResult result = list.next();
268 results.put( result.getName(), result );
269 counter++;
270 }
271 return counter == resultSetSz;
272 }
273 catch ( LdapNoPermissionException e )
274 {
275 return false;
276 }
277 finally
278 {
279 recursivelyDelete( base );
280 }
281 }
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297 private boolean checkSearchAsWithEntryACI( String uid, String password, SearchControls cons, Name rdn, String aci,
298 int resultSetSz ) throws Exception
299 {
300 if ( cons == null )
301 {
302 cons = new SearchControls();
303 }
304
305 Name base = addSearchData( new LdapDN(), 3, 10 );
306 addEntryACI( rdn, aci );
307 Name userDn = new LdapDN( "uid=" + uid + ",ou=users,ou=system" );
308 try
309 {
310 results.clear();
311 DirContext userCtx = getContextAs( userDn, password );
312 NamingEnumeration<SearchResult> list = userCtx.search( base, "(objectClass=*)", cons );
313 int counter = 0;
314
315 while ( list.hasMore() )
316 {
317 SearchResult result = list.next();
318 results.put( result.getName(), result );
319 counter++;
320 }
321 return counter == resultSetSz;
322 }
323 catch ( LdapNoPermissionException e )
324 {
325 return false;
326 }
327 finally
328 {
329 recursivelyDelete( base );
330 }
331 }
332
333
334
335
336
337
338
339
340
341 @Test
342 public void testAddSearchData() throws Exception
343 {
344 LdapContext sysRoot = getSystemContext( service );
345 Name base = addSearchData( new LdapDN(), 3, 10 );
346 SearchControls controls = new SearchControls();
347 controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
348 NamingEnumeration<SearchResult> results = sysRoot.search( base, "(objectClass=*)", controls );
349 int counter = 0;
350
351 while ( results.hasMore() )
352 {
353 results.next();
354 counter++;
355 }
356
357 assertEquals( 10, counter );
358 recursivelyDelete( base );
359
360 try
361 {
362 sysRoot.lookup( base );
363 fail();
364 }
365 catch ( LdapNameNotFoundException e )
366 {
367 }
368 }
369
370
371
372
373
374
375
376
377
378
379
380 @Test
381 public void testGrantAdministrators() throws Exception
382 {
383
384 createUser( "billyd", "billyd" );
385
386
387 assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
388
389
390
391 createAccessControlSubentry( "searchAdmin", "{ " + "identificationTag \"searchAci\", " + "precedence 14, "
392 + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
393 + "userClasses { userGroup { \"cn=Administrators,ou=groups,ou=system\" } }, " + "userPermissions { { "
394 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
395 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
396
397
398
399 assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
400
401
402 addUserToGroup( "billyd", "Administrators" );
403
404
405 assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
406 }
407
408
409
410
411
412
413
414 @Test
415 public void testGrantSearchByName() throws Exception
416 {
417
418 createUser( "billyd", "billyd" );
419
420
421 assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
422
423
424 createAccessControlSubentry( "billydSearch", "{ " + "identificationTag \"searchAci\", " + "precedence 14, "
425 + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
426 + "userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " + "userPermissions { { "
427 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
428 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
429
430
431 assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
432 }
433
434
435
436
437
438
439
440
441 @Test
442 public void testGrantSearchByNameUserDnCase() throws Exception
443 {
444
445 createUser( "billyd", "billyd" );
446
447
448 assertFalse( checkCanSearchAs( "BillyD", "billyd" ) );
449
450
451 createAccessControlSubentry( "billydSearch", "{ " + "identificationTag \"searchAci\", " + "precedence 14, "
452 + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
453 + "userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " + "userPermissions { { "
454 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
455 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
456
457
458 assertTrue( checkCanSearchAs( "BillyD", "billyd" ) );
459 }
460
461
462
463
464
465
466
467 @Test
468 public void testGrantSearchBySubtree() throws Exception
469 {
470
471 createUser( "billyd", "billyd" );
472
473
474 assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
475
476
477 createAccessControlSubentry( "billySearchBySubtree", "{ " + "identificationTag \"searchAci\", "
478 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
479 + "userClasses { subtree { { base \"ou=users,ou=system\" } } }, " + "userPermissions { { "
480 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
481 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
482
483
484 assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
485 }
486
487
488
489
490
491
492
493 @Test
494 public void testGrantSearchAllUsers() throws Exception
495 {
496
497 createUser( "billyd", "billyd" );
498
499
500 assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
501
502
503 createAccessControlSubentry( "anybodySearch", "{ " + "identificationTag \"searchAci\", " + "precedence 14, "
504 + "authenticationLevel none, " + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, "
505 + "userPermissions { { " + "protectedItems {entry, allUserAttributeTypesAndValues}, "
506 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
507
508
509
510 assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
511 }
512
513
514
515
516
517
518
519
520
521
522
523
524 @Test
525 public void testSelectiveGrantsAllUsers() throws Exception
526 {
527
528 createUser( "billyd", "billyd" );
529
530
531 SearchControls cons = new SearchControls();
532 cons.setSearchScope( SearchControls.SUBTREE_SCOPE );
533 assertFalse( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
534
535
536
537 createAccessControlSubentry( "anybodySearch", "{ maximum 2 }", "{ " + "identificationTag \"searchAci\", "
538 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
539 + "userClasses { allUsers }, " + "userPermissions { { "
540 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
541 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
542
543
544
545 assertTrue( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
546 }
547
548
549
550
551
552
553
554
555 @Test
556 public void testHidingAttributes() throws Exception
557 {
558
559 createUser( "billyd", "billyd" );
560
561
562 SearchControls cons = new SearchControls();
563 cons.setSearchScope( SearchControls.SUBTREE_SCOPE );
564 assertFalse( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
565
566
567
568
569 createAccessControlSubentry( "excluseTelephoneNumber", "{ maximum 2 }", "{ "
570 + "identificationTag \"searchAci\", " + "precedence 14, " + "authenticationLevel none, "
571 + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, " + "userPermissions { { "
572 + "protectedItems {entry, allAttributeValues { ou, objectClass } }, "
573 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
574
575
576 assertTrue( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
577
578
579 for ( SearchResult result : results.values() )
580 {
581 assertNull( result.getAttributes().get( "telephoneNumber" ) );
582 }
583
584
585 deleteAccessControlSubentry( "excluseTelephoneNumber" );
586
587
588
589
590 createAccessControlSubentry( "includeAllAttributeTypesAndValues", "{ maximum 2 }", "{ "
591 + "identificationTag \"searchAci\", " + "precedence 14, " + "authenticationLevel none, "
592 + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, " + "userPermissions { { "
593 + "protectedItems {entry, allUserAttributeTypesAndValues }, "
594 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
595
596
597 assertTrue( checkCanSearchAs( "billyd", "billyd", cons, 4 ) );
598
599
600 for ( SearchResult result : results.values() )
601 {
602 assertNotNull( result.getAttributes().get( "telephoneNumber" ) );
603 }
604 }
605
606
607
608
609
610
611
612
613 @Test
614 public void testHidingAttributeValues() throws Exception
615 {
616
617 createUser( "billyd", "billyd" );
618
619
620 assertFalse( checkCanSearchAs( "billyd", "billyd", 3 ) );
621
622
623
624
625 createAccessControlSubentry(
626 "excluseOUValue",
627 "{ maximum 2 }",
628 "{ "
629 + "identificationTag \"searchAci\", "
630 + "precedence 14, "
631 + "authenticationLevel none, "
632 + "itemOrUserFirst userFirst: { "
633 + "userClasses { allUsers }, "
634 + "userPermissions { { "
635 + "protectedItems {entry, attributeType { ou }, allAttributeValues { objectClass }, attributeValue { ou=0, ou=1, ou=2 } }, "
636 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
637
638
639 assertTrue( checkCanSearchAs( "billyd", "billyd", 3 ) );
640
641
642 for ( SearchResult result : results.values() )
643 {
644 assertFalse( result.getAttributes().get( "ou" ).contains( "testEntry" ) );
645 }
646
647
648 deleteAccessControlSubentry( "excluseOUValue" );
649
650
651
652
653 createAccessControlSubentry( "includeAllAttributeTypesAndValues", "{ maximum 2 }", "{ "
654 + "identificationTag \"searchAci\", " + "precedence 14, " + "authenticationLevel none, "
655 + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, " + "userPermissions { { "
656 + "protectedItems {entry, allUserAttributeTypesAndValues }, "
657 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
658
659
660 assertTrue( checkCanSearchAs( "billyd", "billyd", 3 ) );
661
662
663 for ( SearchResult result : results.values() )
664 {
665 assertTrue( result.getAttributes().get( "ou" ).contains( "testEntry" ) );
666 }
667 }
668
669
670
671
672
673
674
675
676
677 @Test
678 public void testPerscriptiveGrantWithEntryDenial() throws Exception
679 {
680
681 createUser( "billyd", "billyd" );
682
683
684 String aci = "{ " + "identificationTag \"denyAci\", " + "precedence 14, " + "authenticationLevel none, "
685 + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, " + "userPermissions { { "
686 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
687 + "grantsAndDenials { denyRead, denyReturnDN, denyBrowse } } } } }";
688
689
690 SearchControls cons = new SearchControls();
691 cons.setSearchScope( SearchControls.SUBTREE_SCOPE );
692 LdapDN rdn = new LdapDN( "ou=tests" );
693 assertFalse( checkSearchAsWithEntryACI( "billyd", "billyd", cons, rdn, aci, 9 ) );
694
695
696 createAccessControlSubentry( "anybodySearch", "{ " + "identificationTag \"searchAci\", " + "precedence 14, "
697 + "authenticationLevel none, " + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, "
698 + "userPermissions { { " + "protectedItems {entry, allUserAttributeTypesAndValues}, "
699 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
700
701
702
703
704 assertTrue( checkSearchAsWithEntryACI( "billyd", "billyd", cons, rdn, aci, 9 ) );
705 assertNull( results.get( "ou=tests,ou=system" ) );
706
707
708 assertTrue( checkCanSearchAs( "billyd", "billyd", cons, 10 ) );
709 assertNotNull( results.get( "ou=tests,ou=system" ) );
710 }
711
712
713
714
715
716
717
718
719
720
721 @Test
722 public void testPerscriptiveGrantWithEntryDenialWithPrecidence() throws Exception
723 {
724
725 createUser( "billyd", "billyd" );
726
727
728 String aci = "{ " + "identificationTag \"denyAci\", " + "precedence 14, " + "authenticationLevel none, "
729 + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, " + "userPermissions { { "
730 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
731 + "grantsAndDenials { denyRead, denyReturnDN, denyBrowse } } } } }";
732
733
734 SearchControls cons = new SearchControls();
735 cons.setSearchScope( SearchControls.SUBTREE_SCOPE );
736 LdapDN rdn = new LdapDN( "ou=tests" );
737 assertFalse( checkSearchAsWithEntryACI( "billyd", "billyd", cons, rdn, aci, 9 ) );
738
739
740 createAccessControlSubentry( "anybodySearch", "{ " + "identificationTag \"searchAci\", " + "precedence 15, "
741 + "authenticationLevel none, " + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, "
742 + "userPermissions { { " + "protectedItems {entry, allUserAttributeTypesAndValues}, "
743 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
744
745
746
747
748
749
750 assertTrue( checkSearchAsWithEntryACI( "billyd", "billyd", cons, rdn, aci, 10 ) );
751 assertNotNull( results.get( "ou=tests,ou=system" ) );
752
753
754
755 aci = "{ " + "identificationTag \"denyAci\", " + "precedence 16, " + "authenticationLevel none, "
756 + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, " + "userPermissions { { "
757 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
758 + "grantsAndDenials { denyRead, denyReturnDN, denyBrowse } } } } }";
759
760
761
762
763
764
765 assertTrue( checkSearchAsWithEntryACI( "billyd", "billyd", cons, rdn, aci, 9 ) );
766 assertNull( results.get( "ou=tests,ou=system" ) );
767 }
768
769
770
771
772
773
774
775
776
777
778
779 private SearchResult checkCanSearhSubentryAs( String uid, String password, Name rdn ) throws Exception
780 {
781 DirContext userCtx = getContextAs( new LdapDN( "uid=" + uid + ",ou=users,ou=system" ), password );
782 SearchControls cons = new SearchControls();
783 cons.setSearchScope( SearchControls.OBJECT_SCOPE );
784 SearchResult result = null;
785 NamingEnumeration<SearchResult> list = null;
786
787
788 try
789 {
790 list = userCtx.search( rdn, "(objectClass=*)", cons );
791 if ( list.hasMore() )
792 {
793 result = list.next();
794 list.close();
795 return result;
796 }
797 }
798 catch ( LdapNoPermissionException e )
799 {
800 return null;
801 }
802 finally
803 {
804 if ( list != null )
805 {
806 list.close();
807 }
808 }
809
810 return result;
811 }
812
813
814 @Test
815 public void testSubentryAccess() throws Exception
816 {
817
818 createUser( "billyd", "billyd" );
819
820
821 createAccessControlSubentry( "anybodySearch", "{ " + "identificationTag \"searchAci\", " + "precedence 14, "
822 + "authenticationLevel none, " + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, "
823 + "userPermissions { { " + "protectedItems {entry, allUserAttributeTypesAndValues}, "
824 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
825
826
827 assertNotNull( checkCanSearhSubentryAs( "billyd", "billyd", new LdapDN( "cn=anybodySearch" ) ) );
828
829
830 addSubentryACI( "{ " + "identificationTag \"searchAci\", " + "precedence 14, " + "authenticationLevel none, "
831 + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, " + "userPermissions { { "
832 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
833 + "grantsAndDenials { denyRead, denyReturnDN, denyBrowse } } } } }" );
834
835
836 assertNull( checkCanSearhSubentryAs( "billyd", "billyd", new LdapDN( "cn=anybodySearch" ) ) );
837 }
838
839
840 @Test
841 public void testGetMatchedName() throws Exception
842 {
843
844 createUser( "billyd", "billyd" );
845
846
847
848 createAccessControlSubentry( "selectiveDiscloseOnError", "{ specificExclusions { chopBefore:\"ou=groups\" } }",
849 "{ " + "identificationTag \"searchAci\", " + "precedence 14, " + "authenticationLevel none, "
850 + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, " + "userPermissions { { "
851 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
852 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse, grantDiscloseOnError } } } } }" );
853
854
855 DirContext userCtx = getContextAs( new LdapDN( "uid=billyd,ou=users,ou=system" ), "billyd" );
856 try
857 {
858 userCtx.lookup( "cn=blah,ou=groups" );
859 }
860 catch ( NamingException e )
861 {
862 Name matched = e.getResolvedName();
863
864
865 assertEquals( matched.toString(), "ou=system" );
866 }
867
868
869 deleteAccessControlSubentry( "selectiveDiscloseOnError" );
870 createAccessControlSubentry( "selectiveDiscloseOnError", "{ " + "identificationTag \"searchAci\", "
871 + "precedence 14, " + "authenticationLevel none, " + "itemOrUserFirst userFirst: { "
872 + "userClasses { allUsers }, " + "userPermissions { { "
873 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
874 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse, grantDiscloseOnError } } } } }" );
875
876
877 try
878 {
879 userCtx.lookup( "cn=blah,ou=groups" );
880 }
881 catch ( NamingException e )
882 {
883 Name matched = e.getResolvedName();
884
885
886 assertEquals( matched.toString(), "ou=groups,ou=system" );
887 }
888 }
889
890 @Test
891 public void testUserClassParentOfEntry() throws Exception
892 {
893
894 createUser( "billyd", "billyd" );
895
896
897 DirContext billydCtx = AutzIntegUtils.getContextAsAdmin("uid=billyd,ou=users,ou=system");
898 Attributes phoneBook = new BasicAttributes( "ou", "phoneBook", true );
899 Attribute objectClass = new BasicAttribute( "objectClass" );
900 phoneBook.put( objectClass );
901 objectClass.add( "top" );
902 objectClass.add( "organizationalUnit" );
903 billydCtx.createSubcontext( "ou=phoneBook", phoneBook );
904
905
906 createAccessControlSubentry( "anybodySearchTheirSubordinates", "{ " + "identificationTag \"searchAci\", " + "precedence 14, "
907 + "authenticationLevel none, " + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, "
908 + "userPermissions { { " + "protectedItems {entry, allUserAttributeTypesAndValues}, "
909 + "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
910
911
912 assertNotNull( checkCanSearhSubentryAs( "billyd", "billyd", new LdapDN( "ou=phoneBook,uid=billyd,ou=users" ) ) );
913
914
915 addPrescriptiveACI( "anybodySearchTheirSubordinates", "{ " + "identificationTag \"anybodyDontSearchTheirSubordinates\", " + "precedence 14, " + "authenticationLevel none, "
916 + "itemOrUserFirst userFirst: { " + "userClasses { parentOfEntry }, " + "userPermissions { { "
917 + "protectedItems {entry, allUserAttributeTypesAndValues}, "
918 + "grantsAndDenials { denyRead, denyReturnDN, denyBrowse } } } } }" );
919
920
921 assertNull( checkCanSearhSubentryAs( "billyd", "billyd", new LdapDN( "ou=phoneBook,uid=billyd,ou=users" ) ) );
922 }
923 }