mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

dugan
02.02.2007 2d0aba220afc66dcb50fcd2639df306a25f639ea
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
 
package org.opends.server.authorization.dseecompat;
 
import static org.opends.server.messages.AciMessages.*;
import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import java.util.HashSet;
import java.util.regex.Pattern;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.AttributeType;
 
/**
 * A class representing an ACI's targetattr keyword.
 */
public class TargetAttr {
    /*
     * Enumeration representing the targetattr operator.
     */
    private EnumTargetOperator operator = EnumTargetOperator.EQUALITY;
 
    /*
     * Flags that is set if all attributes pattern seen "*".
     */
    private boolean allAttributes = false ;
 
    /*
     * HashSet of the attribute types parsed by the constructor.
     */
    private HashSet<AttributeType> attributes = new HashSet<AttributeType>();
 
  /**
   * HashSet of the operational attribute types parsed by the constructor.
   */
  private HashSet<AttributeType> opAttributes = new HashSet<AttributeType>();
 
    /*
     * Regular expression that matches one or more ATTR_NAME's separated by
     * the "||" token.
     */
    private static final String attrListRegex  =  ZERO_OR_MORE_WHITESPACE +
           ATTR_NAME + ZERO_OR_MORE_WHITESPACE + "(" +
            LOGICAL_OR + ZERO_OR_MORE_WHITESPACE + ATTR_NAME +
            ZERO_OR_MORE_WHITESPACE + ")*";
 
    /**
     * Constructor creating a class representing a targetattr keyword of an ACI.
     * @param operator The operation enumeration of the targetattr
     * expression (=, !=).
     * @param attrString A string representing the attributes specified in
     * the targetattr expression (ie, dn || cn).
     * @throws AciException If the attrs string is invalid.
     */
    private TargetAttr(EnumTargetOperator operator, String attrString)
    throws AciException {
        this.operator = operator;
        if (attrString != null) {
            if (Pattern.matches(ALL_ATTRS_WILD_CARD, attrString) ){
                allAttributes = true ;
            } else {
                if (Pattern.matches(ZERO_OR_MORE_WHITESPACE, attrString)){
                    allAttributes = false;
                } else {
                    if (Pattern.matches(attrListRegex, attrString)) {
                        // Remove the spaces in the attr string and
                        // split the list.
                        Pattern separatorPattern =
                            Pattern.compile(LOGICAL_OR);
                        attrString=
                         attrString.replaceAll(ZERO_OR_MORE_WHITESPACE, "");
                        String[] attributeArray=
                             separatorPattern.split(attrString);
                        //Add each element of array to attributes HashSet
                        //after converting it to AttributeType.
                        arrayToAttributeTypes(attributeArray);
                       //Must be either all operational attrs or all user attrs,
                       //but not both.
                        if(!opAttributes.isEmpty() && !attributes.isEmpty()) {
                            int msgID =
                             MSGID_ACI_TARGETATTR_INVALID_OP_USER_ATTR;
                            String message = getMessage(msgID, attrString);
                            throw new AciException(msgID, message);
                        }
                        //Inequality not allowed with operational attrs.
                        if(!opAttributes.isEmpty() &&
                            operator.equals(EnumTargetOperator.NOT_EQUALITY)) {
                            int msgID =
                               MSGID_ACI_TARGATTR_INVALID_OP_ATTR_INEQUALITY;
                            String message = getMessage(msgID, attrString);
                            throw new AciException(msgID, message);
                        }
                    } else {
                      int msgID =
                         MSGID_ACI_SYNTAX_INVALID_TARGETATTRKEYWORD_EXPRESSION;
                      String message = getMessage(msgID, attrString);
                      throw new AciException(msgID, message);
                    }
                }
            }
        }
    }
 
    /**
     * Converts each element of an array of attribute type strings
     * to attribute types and adds them to either the attributes HashSet or
     * the operational attributes HashSet if they are operational.
     * @param attributeArray The array of attribute type strings.
     */
    private void arrayToAttributeTypes(String[] attributeArray) {
        for (int i=0, n=attributeArray.length; i < n; i++) {
            String attribute=attributeArray[i].toLowerCase();
            AttributeType attributeType;
            if((attributeType =
                    DirectoryServer.getAttributeType(attribute)) == null)
                attributeType =
                        DirectoryServer.getDefaultAttributeType(attribute);
          if(attributeType.isOperational())
           opAttributes.add(attributeType);
          else
            attributes.add(attributeType);
        }
    }
 
    /**
     * Returns the operator enumeration of the targetattr expression.
     * @return The operator enumeration.
     */
    public EnumTargetOperator getOperator() {
        return operator;
    }
 
    /**
     * This flag is set if the parsing code saw:
     * targetattr="*" or targetattr != "*".
     * @return True if all attributes was seen.
     */
    public boolean isAllAttributes() {
        return allAttributes;
    }
 
    /**
     * Return array holding each attribute type to be evaluated
     * in the expression.
     * @return Array holding each attribute types.
     */
    public HashSet<AttributeType> getAttributes() {
        return attributes;
    }
 
  /**
   * Return array holding  operational attribute types to be evaluated
   * in the expression.
   * @return  Array holding attribute types.
   */
  public HashSet<AttributeType> getOpAttributes() {
        return opAttributes;
    }
 
    /**
     * Decodes an targetattr expression string into a targetattr class suitable
     * for evaluation.
     * @param operator The operator enumeration of the expression.
     * @param expr The expression string to be decoded.
     * @return A TargetAttr suitable to evaluate this ACI's targetattrs.
     * @throws AciException If the expression string is invalid.
     */
    public static TargetAttr decode(EnumTargetOperator operator, String expr)
            throws AciException  {
        return new TargetAttr(operator, expr);
    }
 
    /**
     * Perform two checks to see if a specified attribute type is applicable.
     * First, check the targetAttr's isAllAttributes() boolean. The
     * isAllAttributes boolean is set true when the string:
     *
     *       targetattrs="*"
     *
     * is  seen when an ACI is parsed.  This boolean only applies to
     * non-operational attribute types. If the attribute type being evaluated
     * and the isAllAttributes is true, then the evaluation will return false
     * because operational attributes must be explicity defined.
     *
     * If the isAllAttributes boolean is true (and the attribute is
     * non-operational), the second check is skipped and the TargetAttr's
     * operator is checked to see if the method should return false
     * (NOT_EQUALITY) instead of true.
     *
     * If the isAllAttributes boolean is false, then the attribute type is
     * checked to see if it is operational. If it is, then the operational
     * HashSet is searched to see if it contains the operational attribute
     * type. If it is found then true is returned, else false is returned
     * if it isn't found. The NOT_EQUALITY operator is invalid for operational
     * attribute types and is not checked.
     *
     * If the attribute is not operational,  then the TargeAttr's user
     * attribute type HashSet is searched to see if it contains the
     * specified attribute type. That result could be negated depending
     * on if the TargetAttr's operator is NOT_EQUALITY.
     *
     * @param a The attribute type to evaluate.
     * @param targetAttr The ACI's TargetAttr class to evaluate against.
     * @return The boolean result of the above tests and application
     * TargetAttr's operator value applied to the test result.
     */
    public static boolean isApplicable(AttributeType a,
                                       TargetAttr targetAttr) {
      boolean ret;
      if(targetAttr.isAllAttributes()) {
        //If it is an operational attribute, then access is denied for all
        //attributes wild-card. Operational attributes must be
        // explicitly defined and cannot be negated.
        if(a.isOperational()) {
          ret=false;
        } else
          ret =
             !targetAttr.getOperator().equals(EnumTargetOperator.NOT_EQUALITY);
      }  else {
        ret=false;
          HashSet<AttributeType> attributes=targetAttr.getAttributes();
          HashSet<AttributeType> opAttributes=targetAttr.getOpAttributes();
           //Check if the attribute is operational, if so check the
           //operation HashSet.
           if(a.isOperational()) {
             if(opAttributes.contains(a))
               ret=true;
         } else {
            if(attributes.contains(a))
              ret=true;
            if(targetAttr.getOperator().equals(EnumTargetOperator.NOT_EQUALITY))
              ret = !ret;
          }
       }
      return ret;
    }
}