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 javax.naming.directory.SearchControls;
24
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.Iterator;
29
30 import org.apache.directory.server.core.authn.AuthenticationInterceptor;
31 import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
32 import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
33 import org.apache.directory.server.core.entry.ServerEntry;
34 import org.apache.directory.server.core.event.EventInterceptor;
35 import org.apache.directory.server.core.filtering.EntryFilteringCursor;
36 import org.apache.directory.server.core.interceptor.context.OperationContext;
37 import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
38 import org.apache.directory.server.core.normalization.NormalizationInterceptor;
39 import org.apache.directory.server.core.operational.OperationalAttributeInterceptor;
40 import org.apache.directory.server.core.schema.SchemaInterceptor;
41 import org.apache.directory.server.core.subtree.SubentryInterceptor;
42 import org.apache.directory.server.schema.registries.Registries;
43 import org.apache.directory.shared.ldap.aci.ACITuple;
44 import org.apache.directory.shared.ldap.aci.MicroOperation;
45 import org.apache.directory.shared.ldap.aci.ProtectedItem;
46 import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
47 import org.apache.directory.shared.ldap.constants.SchemaConstants;
48 import org.apache.directory.shared.ldap.entry.Value;
49 import org.apache.directory.shared.ldap.filter.ExprNode;
50 import org.apache.directory.shared.ldap.filter.PresenceNode;
51 import org.apache.directory.shared.ldap.message.AliasDerefMode;
52 import org.apache.directory.shared.ldap.name.LdapDN;
53
54
55
56
57
58
59
60
61
62
63 public class MaxImmSubFilter implements ACITupleFilter
64 {
65 private final ExprNode childrenFilter;
66 private final SearchControls childrenSearchControls;
67
68
69 public MaxImmSubFilter()
70 {
71 childrenFilter = new PresenceNode( SchemaConstants.OBJECT_CLASS_AT );
72 childrenSearchControls = new SearchControls();
73 childrenSearchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
74 }
75
76
77 public Collection<ACITuple> filter(
78 Registries registries,
79 Collection<ACITuple> tuples,
80 OperationScope scope,
81 OperationContext opContext,
82 Collection<LdapDN> userGroupNames,
83 LdapDN userName,
84 ServerEntry userEntry,
85 AuthenticationLevel authenticationLevel,
86 LdapDN entryName,
87 String attrId,
88 Value<?> attrValue,
89 ServerEntry entry,
90 Collection<MicroOperation> microOperations,
91 ServerEntry entryView )
92 throws Exception
93 {
94 if ( entryName.size() == 0 )
95 {
96 return tuples;
97 }
98
99 if ( tuples.size() == 0 )
100 {
101 return tuples;
102 }
103
104 if ( scope != OperationScope.ENTRY )
105 {
106 return tuples;
107 }
108
109 int immSubCount = -1;
110
111 for ( Iterator<ACITuple> i = tuples.iterator(); i.hasNext(); )
112 {
113 ACITuple tuple = i.next();
114 if ( !tuple.isGrant() )
115 {
116 continue;
117 }
118
119 for ( ProtectedItem item : tuple.getProtectedItems() )
120 {
121 if ( item instanceof ProtectedItem.MaxImmSub )
122 {
123 if ( immSubCount < 0 )
124 {
125 immSubCount = getImmSubCount( registries, opContext, entryName );
126 }
127
128 ProtectedItem.MaxImmSub mis = ( ProtectedItem.MaxImmSub ) item;
129 if ( immSubCount >= mis.getValue() )
130 {
131 i.remove();
132 break;
133 }
134 }
135 }
136 }
137
138 return tuples;
139 }
140
141 public static final Collection<String> SEARCH_BYPASS;
142 static
143 {
144 Collection<String> c = new HashSet<String>();
145 c.add( NormalizationInterceptor.class.getName() );
146 c.add( AuthenticationInterceptor.class.getName() );
147 c.add( AciAuthorizationInterceptor.class.getName() );
148 c.add( DefaultAuthorizationInterceptor.class.getName() );
149 c.add( OperationalAttributeInterceptor.class.getName() );
150 c.add( SchemaInterceptor.class.getName() );
151 c.add( SubentryInterceptor.class.getName() );
152 c.add( EventInterceptor.class.getName() );
153 SEARCH_BYPASS = Collections.unmodifiableCollection( c );
154 }
155
156
157 private int getImmSubCount( Registries registries, OperationContext opContext, LdapDN entryName ) throws Exception
158 {
159 int cnt = 0;
160 EntryFilteringCursor results = null;
161
162 try
163 {
164 SearchOperationContext searchContext = new SearchOperationContext( opContext.getSession(),
165 ( LdapDN ) entryName.getPrefix( 1 ), AliasDerefMode.DEREF_ALWAYS,
166 childrenFilter, childrenSearchControls );
167 searchContext.setByPassed( SEARCH_BYPASS );
168 results = opContext.getSession().getDirectoryService().getOperationManager().search( searchContext );
169
170 while ( results.next() )
171 {
172 results.get();
173 cnt++;
174 }
175
176 }
177 finally
178 {
179 if ( results != null )
180 {
181 results.close();
182 }
183 }
184
185 return cnt;
186 }
187 }