View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.server.core.authz.support;
21  
22  
23  import java.util.Collection;
24  import java.util.Iterator;
25  
26  import javax.naming.directory.SearchControls;
27  
28  import org.apache.directory.api.ldap.aci.ACITuple;
29  import org.apache.directory.api.ldap.aci.ProtectedItem;
30  import org.apache.directory.api.ldap.aci.protectedItem.MaxImmSubItem;
31  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
32  import org.apache.directory.api.ldap.model.entry.Entry;
33  import org.apache.directory.api.ldap.model.exception.LdapException;
34  import org.apache.directory.api.ldap.model.exception.LdapOperationException;
35  import org.apache.directory.api.ldap.model.exception.LdapOtherException;
36  import org.apache.directory.api.ldap.model.filter.ExprNode;
37  import org.apache.directory.api.ldap.model.filter.PresenceNode;
38  import org.apache.directory.api.ldap.model.message.AliasDerefMode;
39  import org.apache.directory.api.ldap.model.name.Dn;
40  import org.apache.directory.api.ldap.model.schema.AttributeType;
41  import org.apache.directory.api.ldap.model.schema.SchemaManager;
42  import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
43  import org.apache.directory.server.core.api.interceptor.context.OperationContext;
44  import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
45  
46  
47  /**
48   * An {@link ACITupleFilter} that discards all tuples that doesn't satisfy
49   * {@link org.apache.directory.api.ldap.aci.protectedItem.MaxImmSubItem} constraint if available. (18.8.3.3, X.501)
50   *
51   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
52   */
53  public class MaxImmSubFilter implements ACITupleFilter
54  {
55      private final ExprNode childrenFilter;
56      private final SearchControls childrenSearchControls;
57  
58  
59      public MaxImmSubFilter( SchemaManager schemaManager )
60      {
61          AttributeType objectClassAt = null;
62  
63          try
64          {
65              objectClassAt = schemaManager.lookupAttributeTypeRegistry( SchemaConstants.OBJECT_CLASS_AT );
66          }
67          catch ( LdapException le )
68          {
69              // Do nothing
70          }
71  
72          childrenFilter = new PresenceNode( objectClassAt );
73          childrenSearchControls = new SearchControls();
74          childrenSearchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
75      }
76  
77  
78      /**
79       * {@inheritDoc}
80       */
81      @Override
82      public Collection<ACITuple> filter( AciContext aciContext, OperationScope scope, Entry userEntry )
83          throws LdapException
84      {
85          ACI_LOG.debug( "Filtering MaxImmSub..." );
86  
87          if ( aciContext.getEntryDn().isRootDse() )
88          {
89              return aciContext.getAciTuples();
90          }
91  
92          if ( aciContext.getAciTuples().isEmpty() )
93          {
94              return aciContext.getAciTuples();
95          }
96  
97          if ( scope != OperationScope.ENTRY )
98          {
99              return aciContext.getAciTuples();
100         }
101 
102         int immSubCount = -1;
103 
104         for ( Iterator<ACITuple> i = aciContext.getAciTuples().iterator(); i.hasNext(); )
105         {
106             ACITuple tuple = i.next();
107 
108             if ( !tuple.isGrant() )
109             {
110                 continue;
111             }
112 
113             for ( ProtectedItem item : tuple.getProtectedItems() )
114             {
115                 if ( item instanceof MaxImmSubItem )
116                 {
117                     if ( immSubCount < 0 )
118                     {
119                         immSubCount = getImmSubCount( aciContext.getOperationContext(), aciContext.getEntryDn() );
120                     }
121 
122                     MaxImmSubItem mis = ( MaxImmSubItem ) item;
123 
124                     if ( immSubCount >= mis.getValue() )
125                     {
126                         i.remove();
127                         break;
128                     }
129                 }
130             }
131         }
132 
133         return aciContext.getAciTuples();
134     }
135 
136 
137     private int getImmSubCount( OperationContext opContext, Dn entryName ) throws LdapException
138     {
139         int cnt = 0;
140         EntryFilteringCursor results = null;
141 
142         try
143         {
144             Dn baseDn = new Dn( opContext.getSession().getDirectoryService().getSchemaManager(),
145                 entryName.getRdn( entryName.size() - 1 ) );
146             SearchOperationContextceptor/context/SearchOperationContext.html#SearchOperationContext">SearchOperationContext searchContext = new SearchOperationContext( opContext.getSession(),
147                 baseDn, childrenFilter, childrenSearchControls );
148             searchContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
149             searchContext.setPartition( opContext.getPartition() );
150             searchContext.setTransaction( opContext.getTransaction() );
151 
152             results = opContext.getSession().getDirectoryService().getPartitionNexus().search( searchContext );
153 
154             try
155             {
156                 while ( results.next() )
157                 {
158                     results.get();
159                     cnt++;
160                 }
161             }
162             catch ( Exception e )
163             {
164                 throw new LdapOtherException( e.getMessage(), e );
165             }
166         }
167         finally
168         {
169             if ( results != null )
170             {
171                 try
172                 {
173                     results.close();
174                 }
175                 catch ( Exception e )
176                 {
177                     throw new LdapOperationException( e.getMessage(), e );
178                 }
179             }
180         }
181 
182         return cnt;
183     }
184 }