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    
026    import javax.naming.NamingException;
027    import javax.naming.directory.Attribute;
028    
029    import org.apache.directory.server.core.event.Evaluator;
030    import org.apache.directory.server.core.interceptor.context.OperationContext;
031    import org.apache.directory.server.core.subtree.RefinementEvaluator;
032    import org.apache.directory.server.i18n.I18n;
033    import org.apache.directory.shared.ldap.aci.ACITuple;
034    import org.apache.directory.shared.ldap.aci.MicroOperation;
035    import org.apache.directory.shared.ldap.aci.ProtectedItem;
036    import org.apache.directory.shared.ldap.aci.ProtectedItem.MaxValueCountItem;
037    import org.apache.directory.shared.ldap.aci.ProtectedItem.RestrictedByItem;
038    import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
039    import org.apache.directory.shared.ldap.constants.SchemaConstants;
040    import org.apache.directory.shared.ldap.entry.EntryAttribute;
041    import org.apache.directory.shared.ldap.entry.ServerEntry;
042    import org.apache.directory.shared.ldap.entry.Value;
043    import org.apache.directory.shared.ldap.exception.LdapException;
044    import org.apache.directory.shared.ldap.name.DN;
045    import org.apache.directory.shared.ldap.schema.AttributeType;
046    import org.apache.directory.shared.ldap.schema.SchemaManager;
047    import org.apache.directory.shared.ldap.schema.registries.OidRegistry;
048    import org.apache.directory.shared.ldap.util.AttributeUtils;
049    
050    
051    /**
052     * An {@link ACITupleFilter} that discards all tuples whose {@link ProtectedItem}s
053     * are not related with the operation. (18.8.3.2, X.501)
054     *
055     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
056     * @version $Rev: 927146 $, $Date: 2010-03-24 19:39:54 +0100 (Wed, 24 Mar 2010) $
057     */
058    public class RelatedProtectedItemFilter implements ACITupleFilter
059    {
060        private final RefinementEvaluator refinementEvaluator;
061        private final Evaluator entryEvaluator;
062        private final SchemaManager schemaManager;
063    
064    
065        public RelatedProtectedItemFilter( RefinementEvaluator refinementEvaluator, Evaluator entryEvaluator, 
066            OidRegistry oidRegistry, SchemaManager schemaManager )
067        {
068            this.refinementEvaluator = refinementEvaluator;
069            this.entryEvaluator = entryEvaluator;
070            this.schemaManager = schemaManager;
071        }
072    
073    
074        public Collection<ACITuple> filter( 
075                SchemaManager schemaManager, 
076                Collection<ACITuple> tuples, 
077                OperationScope scope, 
078                OperationContext opContext,
079                Collection<DN> userGroupNames, 
080                DN userName, 
081                ServerEntry userEntry,
082                AuthenticationLevel authenticationLevel, 
083                DN entryName, 
084                String attrId,
085                Value<?> attrValue, 
086                ServerEntry entry, 
087                Collection<MicroOperation> microOperations,
088                ServerEntry entryView )
089            throws LdapException, NamingException
090        {
091            if ( tuples.size() == 0 )
092            {
093                return tuples;
094            }
095    
096            for ( Iterator<ACITuple> i = tuples.iterator(); i.hasNext(); )
097            {
098                ACITuple tuple = i.next();
099                
100                if ( !isRelated( tuple, scope, userName, entryName, attrId, attrValue, entry ) )
101                {
102                    i.remove();
103                }
104            }
105    
106            return tuples;
107        }
108    
109    
110        private boolean isRelated( ACITuple tuple, OperationScope scope, DN userName, DN entryName, String attrId,
111                                   Value<?> attrValue, ServerEntry entry ) throws LdapException, NamingException, InternalError
112        {
113            String oid = null;
114            
115            if ( attrId != null )
116            {
117                oid = schemaManager.getAttributeTypeRegistry().getOidByName( attrId );
118            }
119            
120            for ( ProtectedItem item : tuple.getProtectedItems() )
121            {
122                if ( item == ProtectedItem.ENTRY )
123                {
124                    if ( scope == OperationScope.ENTRY )
125                    {
126                        return true;
127                    }
128                }
129                else if ( item == ProtectedItem.ALL_USER_ATTRIBUTE_TYPES )
130                {
131                    if ( scope != OperationScope.ATTRIBUTE_TYPE && scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
132                    {
133                        continue;
134                    }
135    
136                    return true;
137                }
138                else if ( item == ProtectedItem.ALL_USER_ATTRIBUTE_TYPES_AND_VALUES )
139                {
140                    if ( scope != OperationScope.ATTRIBUTE_TYPE && scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
141                    {
142                        continue;
143                    }
144    
145                    return true;
146                }
147                else if ( item instanceof ProtectedItem.AllAttributeValues )
148                {
149                    if ( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
150                    {
151                        continue;
152                    }
153    
154                    ProtectedItem.AllAttributeValues aav = ( ProtectedItem.AllAttributeValues ) item;
155    
156                    for ( Iterator<String> j = aav.iterator(); j.hasNext(); )
157                    {
158                        if ( oid.equals( schemaManager.getAttributeTypeRegistry().getOidByName( j.next() ) ) )
159                        {
160                            return true;
161                        }
162                    }
163                }
164                else if ( item instanceof ProtectedItem.AttributeType )
165                {
166                    if ( scope != OperationScope.ATTRIBUTE_TYPE )
167                    {
168                        continue;
169                    }
170    
171                    ProtectedItem.AttributeType at = ( ProtectedItem.AttributeType ) item;
172                    
173                    for ( Iterator<String> j = at.iterator(); j.hasNext(); )
174                    {
175                        if ( oid.equals( schemaManager.getAttributeTypeRegistry().getOidByName( j.next() ) ) )
176                        {
177                            return true;
178                        }
179                    }
180                }
181                else if ( item instanceof ProtectedItem.AttributeValue )
182                {
183                    if ( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
184                    {
185                        continue;
186                    }
187    
188                    ProtectedItem.AttributeValue av = ( ProtectedItem.AttributeValue ) item;
189                    for ( Iterator<Attribute> j = av.iterator(); j.hasNext(); )
190                    {
191                        Attribute attr = j.next();
192                        String attrOid = schemaManager.getAttributeTypeRegistry().getOidByName( attr.getID() );
193                        AttributeType attrType = schemaManager.lookupAttributeTypeRegistry( attrOid );
194                        
195                        if ( oid.equals( attrOid ) && AttributeUtils.containsValue( attr, attrValue, attrType ) )
196                        {
197                            return true;
198                        }
199                    }
200                }
201                else if ( item instanceof ProtectedItem.Classes )
202                {
203                    ProtectedItem.Classes c = ( ProtectedItem.Classes ) item;
204                    if ( refinementEvaluator.evaluate( c.getClasses(), entry.get( SchemaConstants.OBJECT_CLASS_AT ) ) )
205                    {
206                        return true;
207                    }
208                }
209                else if ( item instanceof ProtectedItem.MaxImmSub )
210                {
211                    return true;
212                }
213                else if ( item instanceof ProtectedItem.MaxValueCount )
214                {
215                    if ( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
216                    {
217                        continue;
218                    }
219    
220                    ProtectedItem.MaxValueCount mvc = ( ProtectedItem.MaxValueCount ) item;
221                    for ( Iterator<MaxValueCountItem> j = mvc.iterator(); j.hasNext(); )
222                    {
223                        MaxValueCountItem mvcItem = j.next();
224                        
225                        if ( oid.equals( schemaManager.getAttributeTypeRegistry().getOidByName( mvcItem.getAttributeType() ) ) )
226                        {
227                            return true;
228                        }
229                    }
230                }
231                else if ( item instanceof ProtectedItem.RangeOfValues )
232                {
233                    ProtectedItem.RangeOfValues rov = ( ProtectedItem.RangeOfValues ) item;
234                    
235                    if ( entryEvaluator.evaluate( rov.getFilter(), entryName.getNormName(), entry ) )
236                    {
237                        return true;
238                    }
239                }
240                else if ( item instanceof ProtectedItem.RestrictedBy )
241                {
242                    if ( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
243                    {
244                        continue;
245                    }
246    
247                    ProtectedItem.RestrictedBy rb = ( ProtectedItem.RestrictedBy ) item;
248                    for ( Iterator<RestrictedByItem> j = rb.iterator(); j.hasNext(); )
249                    {
250                        RestrictedByItem rbItem = j.next();
251                        if ( oid.equals( schemaManager.getAttributeTypeRegistry().getOidByName( rbItem.getAttributeType() ) ) )
252                        {
253                            return true;
254                        }
255                    }
256                }
257                else if ( item instanceof ProtectedItem.SelfValue )
258                {
259                    if ( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE && scope != OperationScope.ATTRIBUTE_TYPE )
260                    {
261                        continue;
262                    }
263    
264                    ProtectedItem.SelfValue sv = ( ProtectedItem.SelfValue ) item;
265                    for ( Iterator<String> j = sv.iterator(); j.hasNext(); )
266                    {
267                        String svItem = j.next();
268                        
269                        if ( oid.equals( schemaManager.getAttributeTypeRegistry().getOidByName( svItem ) ) )
270                        {
271                            EntryAttribute attr = entry.get( oid );
272                            
273                            if ( ( attr != null ) && 
274                                 ( ( attr.contains( userName.getNormName() ) || 
275                                   ( attr.contains( userName.getName() ) ) ) ) )
276                            {
277                                return true;
278                            }
279                        }
280                    }
281                }
282                else
283                {
284                    throw new InternalError( I18n.err( I18n.ERR_232, item.getClass().getName() ) );
285                }
286            }
287    
288            return false;
289        }
290    }