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 */ 020package org.apache.directory.server.core.authz.support; 021 022 023import java.util.Collection; 024import java.util.Iterator; 025import java.util.Set; 026 027import org.apache.directory.api.ldap.aci.ACITuple; 028import org.apache.directory.api.ldap.aci.UserClass; 029import org.apache.directory.api.ldap.model.entry.Entry; 030import org.apache.directory.api.ldap.model.exception.LdapException; 031import org.apache.directory.api.ldap.model.name.Dn; 032import org.apache.directory.api.ldap.model.subtree.SubtreeSpecification; 033import org.apache.directory.server.core.api.subtree.SubtreeEvaluator; 034import org.apache.directory.server.i18n.I18n; 035 036 037/** 038 * An {@link ACITupleFilter} that discards all tuples whose {@link UserClass}es 039 * are not related with the current user. (18.8.3.1, X.501) 040 * 041 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 042 */ 043public class RelatedUserClassFilter implements ACITupleFilter 044{ 045 private final SubtreeEvaluator subtreeEvaluator; 046 047 048 public RelatedUserClassFilter( SubtreeEvaluator subtreeEvaluator ) 049 { 050 this.subtreeEvaluator = subtreeEvaluator; 051 } 052 053 054 /** 055 * {@inheritDoc} 056 */ 057 @Override 058 public Collection<ACITuple> filter( AciContext aciContext, OperationScope scope, Entry userEntry ) 059 throws LdapException 060 { 061 if ( aciContext.getAciTuples().isEmpty() ) 062 { 063 return aciContext.getAciTuples(); 064 } 065 066 for ( Iterator<ACITuple> ii = aciContext.getAciTuples().iterator(); ii.hasNext(); ) 067 { 068 ACITuple tuple = ii.next(); 069 070 if ( tuple.isGrant() ) 071 { 072 if ( !isRelated( aciContext.getUserGroupNames(), 073 aciContext.getUserDn(), 074 userEntry, 075 aciContext.getEntryDn(), 076 tuple.getUserClasses() ) 077 || aciContext.getAuthenticationLevel().compareTo( tuple.getAuthenticationLevel() ) < 0 ) 078 { 079 ii.remove(); 080 } 081 } 082 else 083 // Denials 084 { 085 if ( !isRelated( aciContext.getUserGroupNames(), 086 aciContext.getUserDn(), 087 userEntry, 088 aciContext.getEntryDn(), 089 tuple.getUserClasses() ) 090 && aciContext.getAuthenticationLevel().compareTo( tuple.getAuthenticationLevel() ) >= 0 ) 091 { 092 ii.remove(); 093 } 094 } 095 } 096 097 return aciContext.getAciTuples(); 098 } 099 100 101 private boolean isRelated( Collection<String> userGroupNames, Dn userName, Entry userEntry, 102 Dn entryName, Collection<UserClass> userClasses ) throws LdapException 103 { 104 for ( UserClass userClass : userClasses ) 105 { 106 if ( userClass == UserClass.ALL_USERS ) 107 { 108 return true; 109 } 110 else if ( userClass == UserClass.THIS_ENTRY ) 111 { 112 if ( userName.equals( entryName ) ) 113 { 114 return true; 115 } 116 } 117 else if ( userClass == UserClass.PARENT_OF_ENTRY ) 118 { 119 if ( entryName.isDescendantOf( userName ) ) 120 { 121 return true; 122 } 123 } 124 else if ( userClass instanceof UserClass.Name ) 125 { 126 UserClass.Name nameUserClass = ( UserClass.Name ) userClass; 127 128 if ( ( userName != null ) && nameUserClass.getNames().contains( userName.getNormName() ) ) 129 { 130 return true; 131 } 132 } 133 else if ( userClass instanceof UserClass.UserGroup ) 134 { 135 UserClass.UserGroup userGroupUserClass = ( UserClass.UserGroup ) userClass; 136 137 for ( String userGroupName : userGroupNames ) 138 { 139 Set<String> dns = userGroupUserClass.getNames(); 140 141 if ( userGroupName != null ) 142 { 143 for ( String dn : dns ) 144 { 145 if ( userGroupName.equals( dn ) ) 146 { 147 return true; 148 } 149 } 150 } 151 } 152 } 153 else if ( userClass instanceof UserClass.Subtree ) 154 { 155 UserClass.Subtree subtree = ( UserClass.Subtree ) userClass; 156 if ( matchUserClassSubtree( userName, userEntry, subtree ) ) 157 { 158 return true; 159 } 160 } 161 else 162 { 163 throw new InternalError( I18n.err( I18n.ERR_233, userClass.getClass().getName() ) ); 164 } 165 } 166 167 return false; 168 } 169 170 171 private boolean matchUserClassSubtree( Dn userName, Entry userEntry, UserClass.Subtree subtree ) 172 throws LdapException 173 { 174 for ( SubtreeSpecification subtreeSpec : subtree.getSubtreeSpecifications() ) 175 { 176 if ( subtreeEvaluator.evaluate( subtreeSpec, Dn.ROOT_DSE, userName, userEntry ) ) 177 { 178 return true; 179 } 180 } 181 182 return false; 183 } 184}