001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 028 package org.opends.server.authorization.dseecompat; 029 import org.opends.messages.Message; 030 031 import org.opends.server.types.AttributeType; 032 import org.opends.server.types.SearchFilter; 033 import org.opends.server.types.DirectoryException; 034 import org.opends.server.core.DirectoryServer; 035 import static org.opends.messages.AccessControlMessages.*; 036 import static org.opends.server.authorization.dseecompat.Aci.*; 037 import java.util.regex.Pattern; 038 import java.util.regex.Matcher; 039 import java.util.LinkedHashMap; 040 041 /** 042 * The TargAttrFilterList class represents an targattrfilters list. A 043 * targattrfilters list looks like: 044 * 045 * "Op=attr1:F1 [(&& attr2:F2)*] 046 */ 047 public class TargAttrFilterList { 048 049 /* 050 * The mask coresponding to the operation of this list (add or del). 051 */ 052 private int mask=0; 053 054 /* 055 * ListHashMap keyed by the attribute type and mapping to the corresponding 056 * search filter. LinkedHashMap is used so everything is in order. 057 */ 058 private LinkedHashMap<AttributeType, SearchFilter> attrFilterList; 059 060 /* 061 * Regular expression group count. 062 */ 063 private static int expectedGroupCount=2; 064 065 /* 066 * Regular expression attribute group position. 067 */ 068 private static int attributePos=1; 069 070 /* 071 * Regular expression filter group position. 072 */ 073 private static int filterPos=2; 074 075 /* 076 * Regular expression used to match a filter list including the strange 077 * "and" token used to join the multiple attribute type filter pairs. 078 */ 079 private static final String filterListSeperator = 080 ZERO_OR_MORE_WHITESPACE + "&&" + ZERO_OR_MORE_WHITESPACE; 081 082 /* 083 * Regular expression used to match an attribute filter pair. 084 */ 085 private static final String attributeFilter= 086 ATTR_NAME + ZERO_OR_MORE_WHITESPACE + ":{1}" + 087 ZERO_OR_MORE_WHITESPACE + "(\\({1}.*\\){1})"; 088 089 /** 090 * Construct a class representing an targattrfilters filter list. 091 * @param mask The mask representing the operation. 092 * @param attrFilterList The list map containing the attribute type 093 * filter mappings. 094 */ 095 public TargAttrFilterList(int mask, 096 LinkedHashMap<AttributeType, SearchFilter> attrFilterList) { 097 this.mask=mask; 098 this.attrFilterList=attrFilterList; 099 } 100 101 /** 102 * Decode an TargAttrFilterList from the specified expression string. 103 * @param mask The mask representing the operation. 104 * @param expression The expression string to decode. 105 * @return A TargAttrFilterList class representing the targattrfilters 106 * filter list. 107 * @throws AciException If the expression string contains errors. 108 */ 109 public static TargAttrFilterList decode(int mask, String expression) 110 throws AciException { 111 LinkedHashMap<AttributeType, SearchFilter> attrFilterList = 112 new LinkedHashMap<AttributeType, SearchFilter>(); 113 String[] subExpressions=expression.split(filterListSeperator, -1); 114 //Iterate over each sub-expression, parse and add them to the list 115 //if there are no errors. 116 for(String subs : subExpressions) { 117 Pattern pattern=Pattern.compile(attributeFilter); 118 Matcher matcher=pattern.matcher(subs); 119 //Match the attribute:filter pair part of the expression 120 if(!matcher.find() || matcher.groupCount() != expectedGroupCount) { 121 Message message = 122 WARN_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LIST_FORMAT. 123 get(expression); 124 throw new AciException(message); 125 } 126 String attributeName=matcher.group(attributePos).toLowerCase(); 127 //Strip off any options, so it will match the filter option 128 //handling. 129 int semicolon = attributeName.indexOf(';'); 130 if (semicolon != -1) 131 attributeName=attributeName.substring(0, semicolon); 132 String filterString=matcher.group(filterPos); 133 AttributeType attributeType; 134 if((attributeType = 135 DirectoryServer.getAttributeType(attributeName)) == null) 136 attributeType = 137 DirectoryServer.getDefaultAttributeType(attributeName); 138 SearchFilter filter; 139 //Check if it is a valid filter and add it to the list map if ok. 140 try { 141 filter = SearchFilter.createFilterFromString(filterString); 142 attrFilterList.put(attributeType, filter); 143 } catch (DirectoryException ex) { 144 Message er=ex.getMessageObject(); 145 Message message = 146 WARN_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LISTS_FILTER. 147 get(filterString, er); 148 throw new AciException(message); 149 } 150 //Verify the filter components. This check assures that each 151 //attribute type in the filter matches the provided attribute 152 //type. 153 verifyFilterComponents(filter, attributeType); 154 } 155 return new TargAttrFilterList(mask, attrFilterList); 156 } 157 158 /** 159 * Verify the filter component attribute types by assuring that each 160 * attribute type in the filter matches the specified attribute type. 161 * @param filter The filter to verify. 162 * @param type The attribute type to use in the verification. 163 * @throws AciException If the filter contains an attribute type not 164 * specified. 165 */ 166 private static void verifyFilterComponents(SearchFilter filter, 167 AttributeType type) 168 throws AciException { 169 switch (filter.getFilterType()) { 170 case AND: 171 case OR: { 172 for (SearchFilter f : filter.getFilterComponents()) { 173 verifyFilterComponents(f, type); 174 } 175 break; 176 } 177 case NOT: { 178 SearchFilter f = filter.getNotComponent(); 179 verifyFilterComponents(f, type); 180 break; 181 } 182 default: { 183 AttributeType attrType=filter.getAttributeType(); 184 if(!attrType.equals(type)) { 185 Message message = 186 WARN_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LISTS_ATTR_FILTER. 187 get(filter.toString()); 188 throw new AciException(message); 189 } 190 } 191 } 192 } 193 194 /** 195 * Return the mask of this TargAttrFilterList. 196 * @return The mask value. 197 */ 198 public int getMask() { 199 return this.mask; 200 } 201 202 /** 203 * Check if the mask value of this TargAttrFilterList class contains the 204 * specified mask value. 205 * @param mask The mask to check for. 206 * @return True if the mask matches the specified value. 207 */ 208 public boolean hasMask(int mask) { 209 return (this.mask & mask) != 0; 210 } 211 212 /** 213 * Return the list map holding the attribute type to filter mappings. 214 * @return The list map. 215 */ 216 public 217 LinkedHashMap<AttributeType, SearchFilter> getAttributeTypeFilterList() { 218 return attrFilterList; 219 } 220 }