1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.ldap.server.authz.support;
20
21 import java.util.*;
22
23 import javax.naming.Name;
24 import javax.naming.NamingException;
25 import javax.naming.directory.Attributes;
26
27 import org.apache.ldap.common.aci.ACIItem;
28 import org.apache.ldap.common.aci.ACITuple;
29 import org.apache.ldap.common.aci.AuthenticationLevel;
30 import org.apache.ldap.common.aci.MicroOperation;
31 import org.apache.ldap.common.exception.LdapNoPermissionException;
32 import org.apache.ldap.server.event.Evaluator;
33 import org.apache.ldap.server.event.ExpressionEvaluator;
34 import org.apache.ldap.server.schema.AttributeTypeRegistry;
35 import org.apache.ldap.server.schema.OidRegistry;
36 import org.apache.ldap.server.subtree.RefinementEvaluator;
37 import org.apache.ldap.server.subtree.RefinementLeafEvaluator;
38 import org.apache.ldap.server.subtree.SubtreeEvaluator;
39 import org.apache.ldap.server.partition.DirectoryPartitionNexusProxy;
40
41
42 /***
43 * An implementation of Access Control Decision Function (18.8, X.501).
44 * <p>
45 * This engine simply filters the collection of tuples using the following
46 * {@link ACITupleFilter}s sequentially:
47 * <ol>
48 * <li>{@link RelatedUserClassFilter}</li>
49 * <li>{@link RelatedProtectedItemFilter}</li>
50 * <li>{@link MaxValueCountFilter}</li>
51 * <li>{@link MaxImmSubFilter}</li>
52 * <li>{@link RestrictedByFilter}</li>
53 * <li>{@link MicroOperationFilter}</li>
54 * <li>{@link HighestPrecedenceFilter}</li>
55 * <li>{@link MostSpecificUserClassFilter}</li>
56 * <li>{@link MostSpecificProtectedItemFilter}</li>
57 * </ol>
58 * <p>
59 * Operation is determined to be permitted if and only if there is at least one
60 * tuple left and all of them grants the access. (18.8.4. X.501)
61 *
62 * @author The Apache Directory Project
63 * @version $Rev: 326083 $, $Date: 2005-10-18 06:59:38 -0400 (Tue, 18 Oct 2005) $
64 */
65 public class ACDFEngine
66 {
67 private final ACITupleFilter[] filters;
68
69 /***
70 * Creates a new instance.
71 *
72 * @param oidRegistry an OID registry to be used by internal components
73 * @param attrTypeRegistry an attribute type registry to be used by internal components
74 *
75 * @throws NamingException if failed to initialize internal components
76 */
77 public ACDFEngine( OidRegistry oidRegistry, AttributeTypeRegistry attrTypeRegistry ) throws NamingException
78 {
79 Evaluator entryEvaluator = new ExpressionEvaluator( oidRegistry, attrTypeRegistry );
80 SubtreeEvaluator subtreeEvaluator = new SubtreeEvaluator( oidRegistry );
81 RefinementEvaluator refinementEvaluator = new RefinementEvaluator(
82 new RefinementLeafEvaluator( oidRegistry ) );
83
84 filters = new ACITupleFilter[] {
85 new RelatedUserClassFilter( subtreeEvaluator ),
86 new RelatedProtectedItemFilter( attrTypeRegistry, refinementEvaluator, entryEvaluator ),
87 new MaxValueCountFilter(),
88 new MaxImmSubFilter(),
89 new RestrictedByFilter(),
90 new MicroOperationFilter(),
91 new HighestPrecedenceFilter(),
92 new MostSpecificUserClassFilter(),
93 new MostSpecificProtectedItemFilter(),
94 };
95 }
96
97 /***
98 * Checks the user with the specified name can access the specified resource
99 * (entry, attribute type, or attribute value) and throws {@link LdapNoPermissionException}
100 * if the user doesn't have any permission to perform the specified grants.
101 *
102 * @param proxy the proxy to the partition nexus
103 * @param userGroupNames the collection of the group DNs the user who is trying to access the resource belongs
104 * @param username the DN of the user who is trying to access the resource
105 * @param entryName the DN of the entry the user is trying to access
106 * @param attrId the attribute type of the attribute the user is trying to access.
107 * <tt>null</tt> if the user is not accessing a specific attribute type.
108 * @param attrValue the attribute value of the attribute the user is trying to access.
109 * <tt>null</tt> if the user is not accessing a specific attribute value.
110 * @param microOperations the {@link MicroOperation}s to perform
111 * @param aciTuples {@link ACITuple}s translated from {@link ACIItem}s in the subtree entries
112 * @throws NamingException if failed to evaluate ACI items
113 */
114 public void checkPermission(
115 DirectoryPartitionNexusProxy proxy,
116 Collection userGroupNames, Name username, AuthenticationLevel authenticationLevel,
117 Name entryName, String attrId, Object attrValue,
118 Collection microOperations, Collection aciTuples, Attributes entry ) throws NamingException
119 {
120 if( !hasPermission(
121 proxy,
122 userGroupNames, username, authenticationLevel,
123 entryName, attrId, attrValue,
124 microOperations, aciTuples, entry ) )
125 {
126 throw new LdapNoPermissionException();
127 }
128 }
129
130
131 public static final Collection USER_LOOKUP_BYPASS;
132 static
133 {
134 Collection c = new HashSet();
135 c.add( "normalizationService" );
136 c.add( "authenticationService" );
137 c.add( "authorizationService" );
138 c.add( "oldAuthorizationService" );
139 c.add( "schemaService" );
140 c.add( "subentryService" );
141 c.add( "operationalAttributeService" );
142 c.add( "eventService" );
143 USER_LOOKUP_BYPASS = Collections.unmodifiableCollection( c );
144 }
145
146
147 /***
148 * Returns <tt>true</tt> if the user with the specified name can access the specified resource
149 * (entry, attribute type, or attribute value) and throws {@link LdapNoPermissionException}
150 * if the user doesn't have any permission to perform the specified grants.
151 *
152 * @param proxy the proxy to the partition nexus
153 * @param userGroupNames the collection of the group DNs the user who is trying to access the resource belongs
154 * @param userName the DN of the user who is trying to access the resource
155 * @param entryName the DN of the entry the user is trying to access
156 * @param attrId the attribute type of the attribute the user is trying to access.
157 * <tt>null</tt> if the user is not accessing a specific attribute type.
158 * @param attrValue the attribute value of the attribute the user is trying to access.
159 * <tt>null</tt> if the user is not accessing a specific attribute value.
160 * @param microOperations the {@link MicroOperation}s to perform
161 * @param aciTuples {@link ACITuple}s translated from {@link ACIItem}s in the subtree entries
162 */
163 public boolean hasPermission(
164 DirectoryPartitionNexusProxy proxy,
165 Collection userGroupNames, Name userName, AuthenticationLevel authenticationLevel,
166 Name entryName, String attrId, Object attrValue,
167 Collection microOperations, Collection aciTuples, Attributes entry ) throws NamingException
168 {
169 if( entryName == null )
170 {
171 throw new NullPointerException( "entryName" );
172 }
173
174 Attributes userEntry = proxy.lookup( userName, USER_LOOKUP_BYPASS );
175
176
177 OperationScope scope;
178 if( attrId == null )
179 {
180 scope = OperationScope.ENTRY;
181 }
182 else if( attrValue == null )
183 {
184 scope = OperationScope.ATTRIBUTE_TYPE;
185 }
186 else
187 {
188 scope = OperationScope.ATTRIBUTE_TYPE_AND_VALUE;
189 }
190
191
192 aciTuples = new ArrayList( aciTuples );
193
194
195 for( int i = 0; i < filters.length; i++ )
196 {
197 ACITupleFilter filter = filters[ i ];
198 aciTuples = filter.filter(
199 aciTuples, scope, proxy,
200 userGroupNames, userName, userEntry, authenticationLevel,
201 entryName, attrId, attrValue, entry, microOperations );
202 }
203
204
205 if( aciTuples.size() == 0 )
206 {
207 return false;
208 }
209
210
211
212 for( Iterator i = aciTuples.iterator(); i.hasNext(); )
213 {
214 ACITuple tuple = ( ACITuple ) i.next();
215 if( !tuple.isGrant() )
216 {
217 return false;
218 }
219 }
220
221 return true;
222 }
223 }