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.support;
21
22
23 import org.apache.directory.server.core.CoreSession;
24 import org.apache.directory.server.core.DefaultCoreSession;
25 import org.apache.directory.server.core.DefaultDirectoryService;
26 import org.apache.directory.server.core.DirectoryService;
27 import org.apache.directory.server.core.OperationManager;
28 import org.apache.directory.server.core.ReferralHandlingMode;
29 import org.apache.directory.server.core.authn.LdapPrincipal;
30 import org.apache.directory.server.core.changelog.ChangeLog;
31 import org.apache.directory.server.core.cursor.ClosureMonitor;
32 import org.apache.directory.server.core.cursor.Cursor;
33 import org.apache.directory.server.core.cursor.CursorIterator;
34 import org.apache.directory.server.core.entry.ClonedServerEntry;
35 import org.apache.directory.server.core.entry.DefaultServerEntry;
36 import org.apache.directory.server.core.entry.ServerEntry;
37 import org.apache.directory.server.core.event.EventService;
38 import org.apache.directory.server.core.filtering.EntryFilteringCursor;
39 import org.apache.directory.server.core.filtering.BaseEntryFilteringCursor;
40 import org.apache.directory.server.core.interceptor.Interceptor;
41 import org.apache.directory.server.core.interceptor.InterceptorChain;
42 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
43 import org.apache.directory.server.core.interceptor.context.BindOperationContext;
44 import org.apache.directory.server.core.interceptor.context.CompareOperationContext;
45 import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
46 import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
47 import org.apache.directory.server.core.interceptor.context.GetMatchedNameOperationContext;
48 import org.apache.directory.server.core.interceptor.context.GetRootDSEOperationContext;
49 import org.apache.directory.server.core.interceptor.context.GetSuffixOperationContext;
50 import org.apache.directory.server.core.interceptor.context.ListOperationContext;
51 import org.apache.directory.server.core.interceptor.context.ListSuffixOperationContext;
52 import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
53 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
54 import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
55 import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
56 import org.apache.directory.server.core.interceptor.context.OperationContext;
57 import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
58 import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
59 import org.apache.directory.server.core.interceptor.context.UnbindOperationContext;
60 import org.apache.directory.server.core.partition.Partition;
61 import org.apache.directory.server.core.partition.PartitionNexus;
62 import org.apache.directory.server.core.schema.SchemaOperationControl;
63 import org.apache.directory.server.core.schema.SchemaService;
64 import org.apache.directory.server.schema.registries.Registries;
65 import org.apache.directory.shared.ldap.NotImplementedException;
66 import org.apache.directory.shared.ldap.aci.ACITuple;
67 import org.apache.directory.shared.ldap.aci.MicroOperation;
68 import org.apache.directory.shared.ldap.aci.ProtectedItem;
69 import org.apache.directory.shared.ldap.aci.UserClass;
70 import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
71 import org.apache.directory.shared.ldap.entry.Modification;
72 import org.apache.directory.shared.ldap.ldif.LdifEntry;
73 import org.apache.directory.shared.ldap.name.LdapDN;
74
75 import javax.naming.NamingException;
76 import javax.naming.ldap.Control;
77 import javax.naming.ldap.LdapContext;
78 import java.io.File;
79 import java.util.ArrayList;
80 import java.util.Collection;
81 import java.util.Collections;
82 import java.util.HashSet;
83 import java.util.Hashtable;
84 import java.util.Iterator;
85 import java.util.List;
86 import java.util.NoSuchElementException;
87 import java.util.Set;
88
89 import org.junit.Test;
90 import org.junit.BeforeClass;
91 import static org.junit.Assert.assertEquals;
92
93
94
95
96
97
98
99
100 public class MaxImmSubFilterTest
101 {
102 private static final Collection<ACITuple> EMPTY_ACI_TUPLE_COLLECTION = Collections.unmodifiableCollection( new ArrayList<ACITuple>() );
103 private static final Collection<UserClass> EMPTY_USER_CLASS_COLLECTION = Collections.unmodifiableCollection( new ArrayList<UserClass>() );
104 private static final Collection<ProtectedItem> EMPTY_PROTECTED_ITEM_COLLECTION = Collections.unmodifiableCollection( new ArrayList<ProtectedItem>() );
105
106 private static final Set<MicroOperation> EMPTY_MICRO_OPERATION_SET = Collections.unmodifiableSet( new HashSet<MicroOperation>() );
107
108 private static final LdapDN ROOTDSE_NAME = new LdapDN();
109 private static LdapDN ENTRY_NAME;
110 private static Collection<ProtectedItem> PROTECTED_ITEMS = new ArrayList<ProtectedItem>();
111 private static ServerEntry ENTRY;
112
113
114 private static DirectoryService service;
115
116
117 @BeforeClass public static void setup() throws NamingException
118 {
119 service = new DefaultDirectoryService();
120
121 ENTRY_NAME = new LdapDN( "ou=test, ou=system" );
122 PROTECTED_ITEMS.add( new ProtectedItem.MaxImmSub( 2 ) );
123 ENTRY = new DefaultServerEntry( service.getRegistries(), ENTRY_NAME );
124 }
125
126
127 @Test public void testWrongScope() throws Exception
128 {
129 MaxImmSubFilter filter = new MaxImmSubFilter();
130 Collection<ACITuple> tuples = new ArrayList<ACITuple>();
131 tuples.add( new ACITuple( EMPTY_USER_CLASS_COLLECTION, AuthenticationLevel.NONE,
132 EMPTY_PROTECTED_ITEM_COLLECTION, EMPTY_MICRO_OPERATION_SET, true, 0 ) );
133
134 tuples = Collections.unmodifiableCollection( tuples );
135
136 assertEquals( tuples, filter.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE, null, null, null, null,
137 null, ENTRY_NAME, null, null, ENTRY, null, null ) );
138
139 assertEquals( tuples, filter.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, null,
140 null, null, ENTRY_NAME, null, null, ENTRY, null, null ) );
141 }
142
143
144 @Test public void testRootDSE() throws Exception
145 {
146 MaxImmSubFilter filter = new MaxImmSubFilter();
147
148 Collection<ACITuple> tuples = new ArrayList<ACITuple>();
149 tuples.add( new ACITuple( EMPTY_USER_CLASS_COLLECTION, AuthenticationLevel.NONE,
150 EMPTY_PROTECTED_ITEM_COLLECTION, EMPTY_MICRO_OPERATION_SET, true, 0 ) );
151
152 tuples = Collections.unmodifiableCollection( tuples );
153
154 assertEquals( tuples, filter.filter( null, tuples, OperationScope.ENTRY, null, null, null, null, null,
155 ROOTDSE_NAME, null, null, ENTRY, null, null ) );
156 }
157
158
159 @Test public void testZeroTuple() throws Exception
160 {
161 MaxImmSubFilter filter = new MaxImmSubFilter();
162
163 assertEquals( 0, filter.filter( null, EMPTY_ACI_TUPLE_COLLECTION, OperationScope.ENTRY, null, null, null, null, null,
164 ENTRY_NAME, null, null, ENTRY, null, null ).size() );
165 }
166
167
168 @Test public void testDenialTuple() throws Exception
169 {
170 MaxImmSubFilter filter = new MaxImmSubFilter();
171 Collection<ACITuple> tuples = new ArrayList<ACITuple>();
172 tuples.add( new ACITuple( EMPTY_USER_CLASS_COLLECTION, AuthenticationLevel.NONE,
173 PROTECTED_ITEMS, EMPTY_MICRO_OPERATION_SET, false, 0 ) );
174
175 tuples = Collections.unmodifiableCollection( tuples );
176
177 assertEquals( tuples, filter.filter( null, tuples, OperationScope.ENTRY, null, null, null, null, null,
178 ENTRY_NAME, null, null, ENTRY, null, null ) );
179 }
180
181
182 @Test public void testGrantTuple() throws Exception
183 {
184 MaxImmSubFilter filter = new MaxImmSubFilter();
185 Collection<ACITuple> tuples = new ArrayList<ACITuple>();
186 tuples.add( new ACITuple( EMPTY_USER_CLASS_COLLECTION, AuthenticationLevel.NONE,
187 PROTECTED_ITEMS, EMPTY_MICRO_OPERATION_SET, true, 0 ) );
188
189 assertEquals( 1, filter.filter( null, tuples, OperationScope.ENTRY, new MockOperation( 1 ), null, null, null,
190 null, ENTRY_NAME, null, null, ENTRY, null, null ).size() );
191
192 assertEquals( 0, filter.filter( null, tuples, OperationScope.ENTRY, new MockOperation( 3 ), null, null, null,
193 null, ENTRY_NAME, null, null, ENTRY, null, null ).size() );
194 }
195
196
197 class MockOperation implements OperationContext
198 {
199 final int count;
200 final CoreSession session;
201
202
203 public MockOperation( int count ) throws Exception
204 {
205 this.count = count;
206 this.session = new DefaultCoreSession( new LdapPrincipal( new LdapDN(), AuthenticationLevel.STRONG ),
207 new MockDirectoryService( count ) );
208 }
209
210
211 public EntryFilteringCursor search( SearchOperationContext opContext )
212 throws NamingException
213 {
214 return new BaseEntryFilteringCursor( new BogusCursor( count ), opContext );
215 }
216
217
218 public EntryFilteringCursor search( SearchOperationContext opContext, Collection<String> bypass ) throws NamingException
219 {
220 return new BaseEntryFilteringCursor( new BogusCursor( count ), opContext );
221 }
222
223
224 public void addRequestControl( Control requestControl )
225 {
226 }
227
228
229 public void addRequestControls( Control[] requestControls )
230 {
231 }
232
233
234 public void addResponseControl( Control responseControl )
235 {
236 }
237
238
239 public Collection<String> getByPassed()
240 {
241 return null;
242 }
243
244
245 public LdapDN getDn()
246 {
247 return null;
248 }
249
250
251 public String getName()
252 {
253 return null;
254 }
255
256
257 public Control getRequestControl( String numericOid )
258 {
259 return null;
260 }
261
262
263 public Control getResponseControl( String numericOid )
264 {
265 return null;
266 }
267
268
269 public int getResponseControlCount()
270 {
271 return 0;
272 }
273
274
275 public Control[] getResponseControls()
276 {
277 return null;
278 }
279
280
281 public CoreSession getSession()
282 {
283 return session;
284 }
285
286
287 public boolean hasBypass()
288 {
289 return false;
290 }
291
292
293 public boolean hasRequestControl( String numericOid )
294 {
295 return false;
296 }
297
298
299 public boolean hasRequestControls()
300 {
301 return false;
302 }
303
304
305 public boolean hasResponseControl( String numericOid )
306 {
307 return false;
308 }
309
310
311 public boolean hasResponseControls()
312 {
313 return false;
314 }
315
316
317 public boolean isBypassed( String interceptorName )
318 {
319 return false;
320 }
321
322
323 public boolean isCollateralOperation()
324 {
325 return false;
326 }
327
328
329 public ClonedServerEntry lookup( LdapDN dn, Collection<String> bypass ) throws Exception
330 {
331 return null;
332 }
333
334
335 public ClonedServerEntry lookup( LookupOperationContext lookupContext ) throws Exception
336 {
337 return null;
338 }
339
340
341 public LookupOperationContext newLookupContext( LdapDN dn )
342 {
343 return null;
344 }
345
346
347 public void setByPassed( Collection<String> byPassed )
348 {
349 }
350
351
352 public void setCollateralOperation( boolean collateralOperation )
353 {
354 }
355
356
357 public void setDn( LdapDN dn )
358 {
359 }
360
361
362 public LdapPrincipal getEffectivePrincipal()
363 {
364 return null;
365 }
366
367
368 public OperationContext getFirstOperation()
369 {
370 return null;
371 }
372
373
374 public OperationContext getLastOperation()
375 {
376 return null;
377 }
378
379
380 public OperationContext getNextOperation()
381 {
382 return null;
383 }
384
385
386 public OperationContext getPreviousOperation()
387 {
388 return null;
389 }
390
391
392 public boolean isFirstOperation()
393 {
394 return false;
395 }
396
397
398 public void add( ServerEntry entry, Collection<String> bypass ) throws Exception
399 {
400 }
401
402
403 public void delete( LdapDN dn, Collection<String> bypass ) throws Exception
404 {
405 }
406
407
408 public void modify( LdapDN dn, List<Modification> mods, Collection<String> bypass ) throws Exception
409 {
410 }
411
412
413 public boolean hasEntry( LdapDN dn, Collection<String> byPass ) throws Exception
414 {
415 return false;
416 }
417
418
419 public ReferralHandlingMode getReferralHandlingMode()
420 {
421 return null;
422 }
423
424
425 public void setReferralHandlingMode( ReferralHandlingMode referralHandlingMode )
426 {
427 }
428
429
430 public ClonedServerEntry getEntry()
431 {
432 return null;
433 }
434
435
436 public void setEntry( ClonedServerEntry entry )
437 {
438 }
439 }
440
441 class MockDirectoryService implements DirectoryService
442 {
443 int count;
444
445
446 public MockDirectoryService( int count )
447 {
448 this.count = count;
449 }
450
451 public Hashtable<String, Object> getEnvironment()
452 {
453 return null;
454 }
455
456
457 public void setEnvironment( Hashtable<String, Object> environment )
458 {
459 }
460
461
462 public long revert( long revision ) throws NamingException
463 {
464 return 0;
465 }
466
467
468 public long revert() throws NamingException
469 {
470 return 0;
471 }
472
473
474 public PartitionNexus getPartitionNexus()
475 {
476 return null;
477 }
478
479
480 public InterceptorChain getInterceptorChain()
481 {
482 return null;
483 }
484
485
486 public void addPartition( Partition partition ) throws NamingException
487 {
488 }
489
490
491 public void removePartition( Partition partition ) throws NamingException
492 {
493 }
494
495
496 public Registries getRegistries()
497 {
498 return null;
499 }
500
501
502 public void setRegistries( Registries registries )
503 {
504 }
505
506
507 public SchemaService getSchemaService()
508 {
509 return null;
510 }
511
512
513 public void setSchemaService( SchemaService schemaService )
514 {
515
516 }
517
518
519 public SchemaOperationControl getSchemaManager()
520 {
521 return null;
522 }
523
524
525 public void setSchemaManager( SchemaOperationControl schemaManager )
526 {
527 }
528
529
530 public void startup() throws NamingException
531 {
532 }
533
534
535 public void shutdown() throws NamingException
536 {
537 }
538
539
540 public void sync() throws NamingException
541 {
542 }
543
544
545 public boolean isStarted()
546 {
547 return true;
548 }
549
550
551 public LdapContext getJndiContext() throws NamingException
552 {
553 return null;
554 }
555
556
557 public DirectoryService getDirectoryService()
558 {
559 return null;
560 }
561
562
563 public void setInstanceId( String instanceId )
564 {
565
566 }
567
568
569 public String getInstanceId()
570 {
571 return null;
572 }
573
574
575 public Set<? extends Partition> getPartitions()
576 {
577 return null;
578 }
579
580
581 public void setPartitions( Set<? extends Partition> partitions )
582 {
583 }
584
585
586 public boolean isAccessControlEnabled()
587 {
588 return false;
589 }
590
591
592 public void setAccessControlEnabled( boolean accessControlEnabled )
593 {
594 }
595
596
597 public boolean isAllowAnonymousAccess()
598 {
599 return false;
600 }
601
602
603 public void setAllowAnonymousAccess( boolean enableAnonymousAccess )
604 {
605
606 }
607
608
609 public List<Interceptor> getInterceptors()
610 {
611 return null;
612 }
613
614
615 public void setInterceptors( List<Interceptor> interceptors )
616 {
617
618 }
619
620
621 public List<LdifEntry> getTestEntries()
622 {
623 return null;
624 }
625
626
627 public void setTestEntries( List<? extends LdifEntry> testEntries )
628 {
629 }
630
631
632 public File getWorkingDirectory()
633 {
634 return null;
635 }
636
637
638 public void setWorkingDirectory( File workingDirectory )
639 {
640 }
641
642
643 public void validate()
644 {
645 }
646
647
648 public void setShutdownHookEnabled( boolean shutdownHookEnabled )
649 {
650
651 }
652
653
654 public boolean isShutdownHookEnabled()
655 {
656 return false;
657 }
658
659
660 public void setExitVmOnShutdown( boolean exitVmOnShutdown )
661 {
662
663 }
664
665
666 public boolean isExitVmOnShutdown()
667 {
668 return false;
669 }
670
671
672 public void setMaxSizeLimit( int maxSizeLimit )
673 {
674
675 }
676
677
678 public int getMaxSizeLimit()
679 {
680 return 0;
681 }
682
683
684 public void setMaxTimeLimit( int maxTimeLimit )
685 {
686
687 }
688
689
690 public int getMaxTimeLimit()
691 {
692 return 0;
693 }
694
695
696 public void setSystemPartition( Partition systemPartition )
697 {
698
699 }
700
701
702 public Partition getSystemPartition()
703 {
704 return null;
705 }
706
707
708 public boolean isDenormalizeOpAttrsEnabled()
709 {
710 return false;
711 }
712
713
714 public void setDenormalizeOpAttrsEnabled( boolean denormalizeOpAttrsEnabled )
715 {
716
717 }
718
719 public void setChangeLog( ChangeLog changeLog )
720 {
721
722 }
723
724 public ChangeLog getChangeLog()
725 {
726 return null;
727 }
728
729
730 public ServerEntry newEntry( LdapDN dn ) throws NamingException
731 {
732 return null;
733 }
734
735 public ServerEntry newEntry( String ldif, String dn )
736 {
737 return null;
738 }
739
740
741 public OperationManager getOperationManager()
742 {
743 return new MockOperationManager( count );
744 }
745
746
747 public CoreSession getSession() throws Exception
748 {
749 return null;
750 }
751
752
753 public CoreSession getSession( LdapPrincipal principal ) throws Exception
754 {
755 return null;
756 }
757
758
759 public CoreSession getSession( LdapDN principalDn, byte[] credentials ) throws Exception
760 {
761 return null;
762 }
763
764
765 public CoreSession getSession( LdapDN principalDn, byte[] credentials, String saslMechanism, String saslAuthId )
766 throws Exception
767 {
768 return null;
769 }
770
771 public CoreSession getAdminSession() throws Exception
772 {
773 return null;
774 }
775
776 public EventService getEventService()
777 {
778 return null;
779 }
780
781 public void setEventService( EventService eventService )
782 {
783 }
784 }
785
786
787 class MockOperationManager implements OperationManager
788 {
789 int count;
790
791 public MockOperationManager( int count )
792 {
793 this.count = count;
794 }
795
796 public void add( AddOperationContext opContext ) throws Exception
797 {
798 }
799
800
801 public void bind( BindOperationContext opContext ) throws Exception
802 {
803 }
804
805
806 public boolean compare( CompareOperationContext opContext ) throws Exception
807 {
808 return false;
809 }
810
811
812 public void delete( DeleteOperationContext opContext ) throws Exception
813 {
814 }
815
816 public LdapDN getMatchedName( GetMatchedNameOperationContext opContext ) throws Exception
817 {
818 return null;
819 }
820
821 public ClonedServerEntry getRootDSE( GetRootDSEOperationContext opContext ) throws Exception
822 {
823 return null;
824 }
825
826 public LdapDN getSuffix( GetSuffixOperationContext opContext ) throws Exception
827 {
828 return null;
829 }
830
831 public boolean hasEntry( EntryOperationContext opContext ) throws Exception
832 {
833 return false;
834 }
835
836 public EntryFilteringCursor list( ListOperationContext opContext ) throws Exception
837 {
838 return null;
839 }
840
841 public Iterator<String> listSuffixes( ListSuffixOperationContext opContext ) throws Exception
842 {
843 return null;
844 }
845
846 public ClonedServerEntry lookup( LookupOperationContext opContext ) throws Exception
847 {
848 return null;
849 }
850
851 public void modify( ModifyOperationContext opContext ) throws Exception
852 {
853 }
854
855 public void move( MoveOperationContext opContext ) throws Exception
856 {
857 }
858
859 public void moveAndRename( MoveAndRenameOperationContext opContext ) throws Exception
860 {
861 }
862
863 public void rename( RenameOperationContext opContext ) throws Exception
864 {
865 }
866
867 public EntryFilteringCursor search( SearchOperationContext opContext ) throws Exception
868 {
869 return new BaseEntryFilteringCursor( new BogusCursor( count ), opContext );
870 }
871
872
873 public void unbind( UnbindOperationContext opContext ) throws Exception
874 {
875 }
876 }
877
878
879 class BogusCursor implements Cursor<ServerEntry>
880 {
881 final int count;
882 int ii;
883
884
885 public BogusCursor(int count)
886 {
887 this.count = count;
888 }
889
890
891 public boolean available()
892 {
893 return ii < count;
894 }
895
896
897 public void close() throws NamingException
898 {
899 ii = count;
900 }
901
902
903 public boolean hasMoreElements()
904 {
905 return ii < count;
906 }
907
908
909 public Object nextElement()
910 {
911 if ( ii >= count )
912 {
913 throw new NoSuchElementException();
914 }
915
916 ii++;
917
918 return new Object();
919 }
920
921
922 public void after( ServerEntry element ) throws Exception
923 {
924 }
925
926
927 public void afterLast() throws Exception
928 {
929 }
930
931
932 public void before( ServerEntry element ) throws Exception
933 {
934 throw new NotImplementedException();
935 }
936
937
938 public void beforeFirst() throws Exception
939 {
940 ii = -1;
941 }
942
943
944 public boolean first() throws Exception
945 {
946 ii = 0;
947 return ii < count;
948 }
949
950
951 public ServerEntry get() throws Exception
952 {
953 return new DefaultServerEntry( service.getRegistries() );
954 }
955
956
957 public boolean isClosed() throws Exception
958 {
959 return false;
960 }
961
962
963 public boolean isElementReused()
964 {
965 return false;
966 }
967
968
969 public boolean last() throws Exception
970 {
971 ii = count;
972 return true;
973 }
974
975
976 public boolean next()
977 {
978 if ( ii >= count )
979 {
980 return false;
981 }
982
983 ii++;
984
985 return true;
986 }
987
988
989 public boolean previous() throws Exception
990 {
991 if ( ii < 0 )
992 {
993 return false;
994 }
995
996 ii--;
997 return true;
998 }
999
1000
1001 public Iterator<ServerEntry> iterator()
1002 {
1003 return new CursorIterator<ServerEntry>( this );
1004 }
1005
1006
1007 public void close( Exception reason ) throws Exception
1008 {
1009 }
1010
1011
1012 public void setClosureMonitor( ClosureMonitor monitor )
1013 {
1014 }
1015 }
1016 }