001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.server.core.authz.support;
021
022
023 import java.util.Collection;
024 import java.util.Iterator;
025 import java.util.Set;
026
027 import org.apache.directory.server.core.interceptor.context.OperationContext;
028 import org.apache.directory.server.core.subtree.SubtreeEvaluator;
029 import org.apache.directory.server.i18n.I18n;
030 import org.apache.directory.shared.ldap.aci.ACITuple;
031 import org.apache.directory.shared.ldap.aci.MicroOperation;
032 import org.apache.directory.shared.ldap.aci.UserClass;
033 import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
034 import org.apache.directory.shared.ldap.entry.ServerEntry;
035 import org.apache.directory.shared.ldap.entry.Value;
036 import org.apache.directory.shared.ldap.exception.LdapException;
037 import org.apache.directory.shared.ldap.name.DN;
038 import org.apache.directory.shared.ldap.schema.SchemaManager;
039 import org.apache.directory.shared.ldap.subtree.SubtreeSpecification;
040
041
042 /**
043 * An {@link ACITupleFilter} that discards all tuples whose {@link UserClass}es
044 * are not related with the current user. (18.8.3.1, X.501)
045 *
046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
047 * @version $Rev: 928938 $, $Date: 2010-03-30 02:25:42 +0300 (Tue, 30 Mar 2010) $
048 */
049 public class RelatedUserClassFilter implements ACITupleFilter
050 {
051 private static final DN ROOTDSE_NAME = DN.EMPTY_DN;
052
053 private final SubtreeEvaluator subtreeEvaluator;
054
055
056 public RelatedUserClassFilter(SubtreeEvaluator subtreeEvaluator)
057 {
058 this.subtreeEvaluator = subtreeEvaluator;
059 }
060
061
062 public Collection<ACITuple> filter(
063 SchemaManager schemaManager,
064 Collection<ACITuple> tuples,
065 OperationScope scope,
066 OperationContext opContext,
067 Collection<DN> userGroupNames,
068 DN userName,
069 ServerEntry userEntry,
070 AuthenticationLevel authenticationLevel,
071 DN entryName,
072 String attrId,
073 Value<?> attrValue,
074 ServerEntry entry,
075 Collection<MicroOperation> microOperations,
076 ServerEntry entryView )
077 throws LdapException
078 {
079 if ( tuples.size() == 0 )
080 {
081 return tuples;
082 }
083
084 for ( Iterator<ACITuple> ii = tuples.iterator(); ii.hasNext(); )
085 {
086 ACITuple tuple = ii.next();
087
088 if ( tuple.isGrant() )
089 {
090 if ( !isRelated( userGroupNames,
091 userName,
092 userEntry,
093 entryName,
094 tuple.getUserClasses() )
095 || authenticationLevel.compareTo( tuple.getAuthenticationLevel() ) < 0 )
096 {
097 ii.remove();
098 }
099 }
100 else
101 // Denials
102 {
103 if ( !isRelated( userGroupNames,
104 userName,
105 userEntry,
106 entryName,
107 tuple.getUserClasses() )
108 && authenticationLevel.compareTo( tuple.getAuthenticationLevel() ) >= 0 )
109 {
110 ii.remove();
111 }
112 }
113 }
114
115 return tuples;
116 }
117
118
119 private boolean isRelated( Collection<DN> userGroupNames, DN userName, ServerEntry userEntry,
120 DN entryName, Collection<UserClass> userClasses ) throws LdapException
121 {
122 for ( UserClass userClass : userClasses )
123 {
124 if ( userClass == UserClass.ALL_USERS )
125 {
126 return true;
127 }
128 else if ( userClass == UserClass.THIS_ENTRY )
129 {
130 if ( userName.equals( entryName ) )
131 {
132 return true;
133 }
134 }
135 else if ( userClass == UserClass.PARENT_OF_ENTRY )
136 {
137 if ( entryName.isChildOf( userName ) )
138 {
139 return true;
140 }
141 }
142 else if ( userClass instanceof UserClass.Name )
143 {
144 UserClass.Name nameUserClass = ( UserClass.Name ) userClass;
145 if ( nameUserClass.getNames().contains( userName ) )
146 {
147 return true;
148 }
149 }
150 else if ( userClass instanceof UserClass.UserGroup )
151 {
152 UserClass.UserGroup userGroupUserClass = ( UserClass.UserGroup ) userClass;
153
154 for ( DN userGroupName : userGroupNames )
155 {
156 Set<DN> dns = userGroupUserClass.getNames();
157
158 if ( userGroupName != null )
159 {
160 for ( DN dn : dns )
161 {
162 if ( userGroupName.getNormName().equals( dn.getNormName() ) )
163 {
164 return true;
165 }
166 }
167 }
168 }
169 }
170 else if ( userClass instanceof UserClass.Subtree )
171 {
172 UserClass.Subtree subtree = ( UserClass.Subtree ) userClass;
173 if ( matchUserClassSubtree( userName, userEntry, subtree ) )
174 {
175 return true;
176 }
177 }
178 else
179 {
180 throw new InternalError( I18n.err( I18n.ERR_233, userClass.getClass().getName() ) );
181 }
182 }
183
184 return false;
185 }
186
187
188 private boolean matchUserClassSubtree( DN userName, ServerEntry userEntry, UserClass.Subtree subtree )
189 throws LdapException
190 {
191 for ( SubtreeSpecification subtreeSpec : subtree.getSubtreeSpecifications() )
192 {
193 if ( subtreeEvaluator.evaluate( subtreeSpec, ROOTDSE_NAME, userName, userEntry ) )
194 {
195 return true;
196 }
197 }
198
199 return false;
200 }
201 }