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.NamingException;
27  
28  import org.apache.directory.server.core.entry.ServerEntry;
29  import org.apache.directory.server.core.interceptor.context.OperationContext;
30  import org.apache.directory.server.core.subtree.SubtreeEvaluator;
31  import org.apache.directory.server.schema.registries.Registries;
32  import org.apache.directory.shared.ldap.aci.ACITuple;
33  import org.apache.directory.shared.ldap.aci.MicroOperation;
34  import org.apache.directory.shared.ldap.aci.UserClass;
35  import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
36  import org.apache.directory.shared.ldap.entry.Value;
37  import org.apache.directory.shared.ldap.name.LdapDN;
38  import org.apache.directory.shared.ldap.subtree.SubtreeSpecification;
39  
40  
41  /**
42   * An {@link ACITupleFilter} that discards all tuples whose {@link UserClass}es
43   * are not related with the current user. (18.8.3.1, X.501)
44   *
45   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
46   * @version $Rev: 690042 $, $Date: 2008-08-29 01:14:21 +0200 (Fr, 29 Aug 2008) $
47   */
48  public class RelatedUserClassFilter implements ACITupleFilter
49  {
50      private static final LdapDN ROOTDSE_NAME = LdapDN.EMPTY_LDAPDN;
51  
52      private final SubtreeEvaluator subtreeEvaluator;
53  
54  
55      public RelatedUserClassFilter(SubtreeEvaluator subtreeEvaluator)
56      {
57          this.subtreeEvaluator = subtreeEvaluator;
58      }
59  
60  
61      public Collection<ACITuple> filter( 
62              Registries registries, 
63              Collection<ACITuple> tuples, 
64              OperationScope scope, 
65              OperationContext opContext,
66              Collection<LdapDN> userGroupNames, 
67              LdapDN userName, 
68              ServerEntry userEntry, 
69              AuthenticationLevel authenticationLevel,
70              LdapDN entryName, 
71              String attrId, 
72              Value<?> attrValue, 
73              ServerEntry entry, 
74              Collection<MicroOperation> microOperations,
75              ServerEntry entryView )
76          throws NamingException
77      {
78          if ( tuples.size() == 0 )
79          {
80              return tuples;
81          }
82  
83          for ( Iterator<ACITuple> ii = tuples.iterator(); ii.hasNext(); )
84          {
85              ACITuple tuple = ii.next();
86              
87              if ( tuple.isGrant() )
88              {
89                  if ( !isRelated( userGroupNames, 
90                                   userName, 
91                                   userEntry, 
92                                   entryName, 
93                                   tuple.getUserClasses() )
94                      || authenticationLevel.compareTo( tuple.getAuthenticationLevel() ) < 0 )
95                  {
96                      ii.remove();
97                  }
98              }
99              else
100             // Denials
101             {
102                 if ( !isRelated( userGroupNames, 
103                                  userName, 
104                                  userEntry, 
105                                  entryName, 
106                                  tuple.getUserClasses() )
107                     && authenticationLevel.compareTo( tuple.getAuthenticationLevel() ) >= 0 )
108                 {
109                     ii.remove();
110                 }
111             }
112         }
113 
114         return tuples;
115     }
116 
117 
118     private boolean isRelated( Collection<LdapDN> userGroupNames, LdapDN userName, ServerEntry userEntry, 
119         LdapDN entryName, Collection<UserClass> userClasses ) throws NamingException
120     {
121         for ( UserClass userClass : userClasses )
122         {
123             if ( userClass == UserClass.ALL_USERS )
124             {
125                 return true;
126             }
127             else if ( userClass == UserClass.THIS_ENTRY )
128             {
129                 if ( userName.equals( entryName ) )
130                 {
131                     return true;
132                 }
133             }
134             else if ( userClass == UserClass.PARENT_OF_ENTRY )
135             {
136                 if ( entryName.startsWith( userName ) )
137                 {
138                     return true;
139                 }
140             }
141             else if ( userClass instanceof UserClass.Name )
142             {
143                 UserClass.Name nameUserClass = ( UserClass.Name ) userClass;
144                 if ( nameUserClass.getNames().contains( userName ) )
145                 {
146                     return true;
147                 }
148             }
149             else if ( userClass instanceof UserClass.UserGroup )
150             {
151                 UserClass.UserGroup userGroupUserClass = ( UserClass.UserGroup ) userClass;
152                 
153                 for ( LdapDN userGroupName : userGroupNames )
154                 {
155                     if ( userGroupName != null && userGroupUserClass.getNames().contains( userGroupName ) )
156                     {
157                         return true;
158                     }
159                 }
160             }
161             else if ( userClass instanceof UserClass.Subtree )
162             {
163                 UserClass.Subtree subtree = ( UserClass.Subtree ) userClass;
164                 if ( matchUserClassSubtree( userName, userEntry, subtree ) )
165                 {
166                     return true;
167                 }
168             }
169             else
170             {
171                 throw new InternalError( "Unexpected userClass: " + userClass.getClass().getName() );
172             }
173         }
174 
175         return false;
176     }
177 
178 
179     private boolean matchUserClassSubtree( LdapDN userName, ServerEntry userEntry, UserClass.Subtree subtree )
180         throws NamingException
181     {
182         for ( SubtreeSpecification subtreeSpec : subtree.getSubtreeSpecifications() )
183         {
184             if ( subtreeEvaluator.evaluate( subtreeSpec, ROOTDSE_NAME, userName, userEntry ) )
185             {
186                 return true;
187             }
188         }
189 
190         return false;
191     }
192 }