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 static org.opends.messages.AccessControlMessages.*; 032 import static org.opends.server.authorization.dseecompat.Aci.*; 033 import java.util.HashSet; 034 import java.util.regex.Pattern; 035 import org.opends.server.core.DirectoryServer; 036 import org.opends.server.types.AttributeType; 037 038 /** 039 * A class representing an ACI's targetattr keyword. 040 */ 041 public class TargetAttr { 042 /* 043 * Enumeration representing the targetattr operator. 044 */ 045 private EnumTargetOperator operator = EnumTargetOperator.EQUALITY; 046 047 /* 048 * Flags that is set if all user attributes pattern seen "*". 049 */ 050 private boolean allUserAttributes = false ; 051 052 /* 053 * Flags that is set if all operational attributes pattern seen "+". 054 */ 055 private boolean allOpAttributes = false ; 056 057 /* 058 * HashSet of the attribute types parsed by the constructor. 059 */ 060 private HashSet<AttributeType> attributes = new HashSet<AttributeType>(); 061 062 /** 063 * HashSet of the operational attribute types parsed by the constructor. 064 */ 065 private HashSet<AttributeType> opAttributes = new HashSet<AttributeType>(); 066 067 /* 068 * Regular expression that matches one or more ATTR_NAME's separated by 069 * the "||" token. 070 */ 071 private static final String attrListRegex = ZERO_OR_MORE_WHITESPACE + 072 ATTR_NAME + ZERO_OR_MORE_WHITESPACE + "(" + 073 LOGICAL_OR + ZERO_OR_MORE_WHITESPACE + ATTR_NAME + 074 ZERO_OR_MORE_WHITESPACE + ")*"; 075 076 /** 077 * Constructor creating a class representing a targetattr keyword of an ACI. 078 * @param operator The operation enumeration of the targetattr 079 * expression (=, !=). 080 * @param attrString A string representing the attributes specified in 081 * the targetattr expression (ie, dn || +). 082 * @throws AciException If the attrs string is invalid. 083 */ 084 private TargetAttr(EnumTargetOperator operator, String attrString) 085 throws AciException { 086 this.operator = operator; 087 if (attrString != null) { 088 if (Pattern.matches(ALL_USER_ATTRS_WILD_CARD, attrString) ) 089 allUserAttributes = true ; 090 else if (Pattern.matches(ALL_OP_ATTRS_WILD_CARD, attrString) ) 091 allOpAttributes = true ; 092 else { 093 if (Pattern.matches(ZERO_OR_MORE_WHITESPACE, attrString)){ 094 allUserAttributes = false; 095 allOpAttributes=false; 096 } else { 097 if (Pattern.matches(attrListRegex, attrString)) { 098 // Remove the spaces in the attr string and 099 // split the list. 100 Pattern separatorPattern = 101 Pattern.compile(LOGICAL_OR); 102 attrString= 103 attrString.replaceAll(ZERO_OR_MORE_WHITESPACE, ""); 104 String[] attributeArray= 105 separatorPattern.split(attrString); 106 //Add each element of array to appropriate HashSet 107 //after conversion to AttributeType. 108 arrayToAttributeTypes(attributeArray, attrString); 109 } else { 110 Message message = 111 WARN_ACI_SYNTAX_INVALID_TARGETATTRKEYWORD_EXPRESSION. 112 get(attrString); 113 throw new AciException(message); 114 } 115 } 116 } 117 } 118 } 119 120 121 /** 122 * Converts each element of an array of attribute strings 123 * to attribute types and adds them to either the user attributes HashSet or 124 * the operational attributes HashSet. Also, scan for the shorthand tokens 125 * "*" for all user attributes and "+" for all operational attributes. 126 * 127 * @param attributeArray The array of attribute type strings. 128 * @param attrStr String used in error message if an Aci Exception 129 * is thrown. 130 * @throws AciException If the one of the attribute checks fails. 131 */ 132 private void arrayToAttributeTypes(String[] attributeArray, String attrStr) 133 throws AciException { 134 for (int i=0, n=attributeArray.length; i < n; i++) { 135 String attribute=attributeArray[i].toLowerCase(); 136 if(attribute.equals("*")) { 137 if(!allUserAttributes) 138 allUserAttributes=true; 139 else { 140 Message message = 141 WARN_ACI_TARGETATTR_INVALID_ATTR_TOKEN.get(attrStr); 142 throw new AciException(message); 143 } 144 } else if(attribute.equals("+")) { 145 if(!allOpAttributes) 146 allOpAttributes=true; 147 else { 148 Message message = 149 WARN_ACI_TARGETATTR_INVALID_ATTR_TOKEN.get(attrStr); 150 throw new AciException(message); 151 } 152 } else { 153 AttributeType attributeType; 154 if((attributeType = 155 DirectoryServer.getAttributeType(attribute)) == null) 156 attributeType = 157 DirectoryServer.getDefaultAttributeType(attribute); 158 if(attributeType.isOperational()) 159 opAttributes.add(attributeType); 160 else 161 attributes.add(attributeType); 162 } 163 } 164 } 165 166 /** 167 * Returns the operator enumeration of the targetattr expression. 168 * @return The operator enumeration. 169 */ 170 public EnumTargetOperator getOperator() { 171 return operator; 172 } 173 174 /** 175 * This flag is set if the parsing code saw: 176 * targetattr="*" or targetattr != "*". 177 * @return True if all attributes was seen. 178 */ 179 public boolean isAllUserAttributes() { 180 return allUserAttributes; 181 } 182 183 184 /** 185 * This flag is set if the parsing code saw: 186 * targetattr="+" or targetattr != "+". 187 * @return True if all attributes was seen. 188 */ 189 public boolean isAllOpAttributes() { 190 return allOpAttributes; 191 } 192 193 /** 194 * Return array holding each attribute type to be evaluated 195 * in the expression. 196 * @return Array holding each attribute types. 197 */ 198 public HashSet<AttributeType> getAttributes() { 199 return attributes; 200 } 201 202 /** 203 * Return array holding operational attribute types to be evaluated 204 * in the expression. 205 * @return Array holding attribute types. 206 */ 207 public HashSet<AttributeType> getOpAttributes() { 208 return opAttributes; 209 } 210 211 /** 212 * Decodes an targetattr expression string into a targetattr class suitable 213 * for evaluation. 214 * @param operator The operator enumeration of the expression. 215 * @param expr The expression string to be decoded. 216 * @return A TargetAttr suitable to evaluate this ACI's targetattrs. 217 * @throws AciException If the expression string is invalid. 218 */ 219 public static TargetAttr decode(EnumTargetOperator operator, String expr) 220 throws AciException { 221 return new TargetAttr(operator, expr); 222 } 223 224 /** 225 * Performs test to see if the specified is applicable to the specified 226 * TargetAttr. First a check if the TargetAttr parsing code saw an 227 * expression like: 228 * 229 * (targetattrs="+ || *), (targetattrs != "* || +) 230 * 231 * where both shorthand tokens where parsed. IF so then the attribute type 232 * matches automatically (or not matches if NOT_EQUALITY). 233 * 234 * If there isn't a match, then the method evalAttrType is called to further 235 * evaluate the attribute type and targetAttr combination. 236 * 237 * 238 * @param a The attribute type to evaluate. 239 * @param targetAttr The ACI's TargetAttr class to evaluate against. 240 * @return The boolean result of the above tests and application 241 * TargetAttr's operator value applied to the test result. 242 */ 243 244 public static boolean isApplicable(AttributeType a, 245 TargetAttr targetAttr) { 246 boolean ret; 247 if(targetAttr.isAllUserAttributes() && targetAttr.isAllOpAttributes()) { 248 ret = 249 !targetAttr.getOperator().equals(EnumTargetOperator.NOT_EQUALITY); 250 } else 251 ret=evalAttrType(a, targetAttr); 252 253 return ret; 254 } 255 256 /** 257 * First check is to see if the attribute type is operational. If so then 258 * a match is true if the allOpAttributes boolean is true or if the 259 * attribute type is found in the operational attributes HashSet. 260 * Both results can be negated if the expression operator is NOT_EQUALITY). 261 * 262 * Second check is similar to above, except the user attributes boolean 263 * and HashSet is examined. 264 * 265 * 266 * @param a The attribute type to evaluate. 267 * @param targetAttr The targetAttr to apply to the attribute type. 268 * @return True if the attribute type is applicable to the targetAttr. 269 */ 270 private static 271 boolean evalAttrType(AttributeType a, TargetAttr targetAttr) { 272 boolean ret=false; 273 if(a.isOperational()) { 274 if(targetAttr.isAllOpAttributes() || 275 targetAttr.opAttributes.contains(a)) 276 ret=true; 277 if(targetAttr.isAllOpAttributes() || 278 !targetAttr.opAttributes.isEmpty()) { 279 if(targetAttr.getOperator(). 280 equals(EnumTargetOperator.NOT_EQUALITY)) 281 ret=!ret; 282 } 283 } else { 284 if(targetAttr.isAllUserAttributes() || 285 targetAttr.attributes.contains(a)) 286 ret=true; 287 if(targetAttr.isAllUserAttributes() || 288 !targetAttr.attributes.isEmpty()) { 289 if(targetAttr.getOperator(). 290 equals(EnumTargetOperator.NOT_EQUALITY)) 291 ret=!ret; 292 } 293 } 294 return ret; 295 } 296 }