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

coulbeck
15.50.2007 f3186148daf2a3fead3fdf20e92b7cb14464f74a
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
/*
 * 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 org.opends.server.types.*;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.Group;
import org.opends.server.api.ConnectionSecurityProvider;
import org.opends.server.core.AddOperation;
import org.opends.server.core.Operation;
import org.opends.server.extensions.TLSConnectionSecurityProvider;
import java.net.InetAddress;
import java.util.LinkedList;
 
/**
 *  The AciContainer class contains all of the needed information to perform
 *  both target match and evaluate an ACI. Target matching is the process
 *  of testing if an ACI is applicable to an operation, and evaluation is
 *  the actual access evaluation of the ACI.
 */
public abstract class AciContainer
implements AciTargetMatchContext, AciEvalContext {
 
    /*
     * The allow and deny lists.
     */
    private LinkedList<Aci> denyList, allowList;
 
    /*
     * The attribute type in the resource entry currently being evaluated.
     */
    private AttributeType attributeType;
 
    /*
     * The attribute type value in the resource entry currently being
     * evaluated.
     */
    private AttributeValue attributeValue;
 
    /*
     * True if this is the first attribute type in the resource entry being
     * evaluated.
     */
    private boolean isFirst = false;
 
    /*
     * True if an entry test rule was seen during target matching of an ACI
     * entry. A entry test rule is an ACI with targetattrs target keyword.
     */
    private boolean isEntryTestRule = false;
 
    /*
     * True if the evaluation of an ACI is from the deny list.
     */
    private boolean isDenyEval;
 
    /*
     * True if the evaluation is a result of an LDAP add operation.
     */
    private boolean isAddOp=false;
 
    /*
     * The rights to use in the evaluation of the LDAP operation.
     */
    private int rights;
 
    /*
     * The entry being evaluated (resource entry).
     */
    private Entry resourceEntry;
 
    /*
     * The client connection information.
     */
    private ClientConnection clientConnection;
 
    /*
     * The operation being evaluated.
     */
    private Operation operation;
 
    /*
     * True if a targattrfilters match was found.
     */
    private boolean targAttrFiltersMatch=false;
 
    /**
     * This constructor is used by all currently supported LDAP operations.
     *
     * @param operation The Operation object being evaluated and target
     * matching.
     * @param rights The rights array to use in evaluation and target matching.
     * @param entry The current entry being evaluated and target matched.
     */
    protected AciContainer(Operation operation, int rights, Entry entry) {
      this.resourceEntry=entry;
      this.operation=operation;
      this.clientConnection=operation.getClientConnection();
      if(operation instanceof AddOperation)
          this.isAddOp=true;
      this.rights = rights;
    }
 
    /**
     * The list of deny ACIs. These are all of the applicable
     * ACIs that have a deny permission. Note that an ACI can
     * be on both allow and deny list if it has multiple
     * permission-bind rule pairs.
     *
     * @param denys The list of deny ACIs.
     */
    public void setDenyList(LinkedList<Aci> denys) {
        denyList=denys;
    }
 
    /**
     * The list of allow ACIs. These are all of the applicable
     * ACIs that have an allow permission.
     *
     * @param allows  The list of allow ACIs.
     */
    public void setAllowList(LinkedList<Aci> allows) {
        allowList=allows;
    }
 
    /**
     * Return the current attribute type being evaluated.
     * @return  Attribute type being evaluated.
     */
    public AttributeType getCurrentAttributeType() {
        return attributeType;
    }
 
    /**
     * Return the current attribute type value being evaluated.
     * @return Attribute type value being evaluated.
     */
    public AttributeValue getCurrentAttributeValue() {
        return attributeValue;
    }
 
    /**
     * Set the attribute type to be evaluated.
     * @param type The attribute type to evaluate.
     */
    public void setCurrentAttributeType(AttributeType type) {
        attributeType=type;
    }
 
    /**
     * Set the attribute type value to be evaluated.
     * @param value The attribute type value to evaluate.
     */
    public void setCurrentAttributeValue(AttributeValue value) {
        attributeValue=value;
    }
 
    /**
     * Check is this the first attribute being evaluated in an entry.
     * @return  True if it is the first attribute.
     */
    public boolean isFirstAttribute() {
        return isFirst;
    }
 
    /**
     * Set if this is the first attribute in the entry.
     * @param val True if this is the first attribute being evaluated in the
     * entry.
     */
    public void setIsFirstAttribute(boolean val) {
        isFirst=val;
    }
 
    /**
     * Check if an entry test rule was seen during target evaluation.
     * @return True if an entry test rule was seen.
     */
    public boolean hasEntryTestRule() {
        return isEntryTestRule;
    }
 
    /**
     * Used to set if an entry test rule was seen during target evaluation.
     * @param val Set to true if an entry test rule was seen.
     */
    public void setEntryTestRule(boolean val) {
        isEntryTestRule=val;
    }
 
    /**
     * Get the entry being evaluated (known as the resource entry).
     * @return  The entry being evaluated.
     */
    public Entry getResourceEntry() {
        return resourceEntry;
    }
 
    /**
     * Get the entry that corresponds to the client DN.
     * @return The client entry.
     */
    public Entry getClientEntry() {
      return operation.getAuthorizationEntry();
    }
 
    /**
     * Get the deny list of ACIs.
     * @return The deny ACI list.
     */
    public LinkedList<Aci> getDenyList() {
        return denyList;
     }
 
    /**
     * Get the allow list of ACIs.
     * @return The allow ACI list.
     */
    public LinkedList<Aci> getAllowList() {
       return allowList;
    }
 
    /**
     * Check is this is a deny ACI evaluation.
     * @return  True if the evaluation is using an ACI from
     * deny list.
     */
    public boolean isDenyEval() {
        return isDenyEval;
    }
 
    /**
     * Check is this operation bound anonymously.
     * @return  True if the authentication is anonymous.
     */
    public boolean isAnonymousUser() {
        return !clientConnection.getAuthenticationInfo().isAuthenticated();
    }
 
    /**
     * Set the deny evaluation flag.
     * @param val True if this evaluation is a deny ACI.
     */
    public void setDenyEval(boolean val) {
        isDenyEval = val;
    }
 
    /**
     * Returns the client authorization DN known as the client DN.
     * @return  The client's authorization DN.
     */
    public DN getClientDN() {
      return operation.getAuthorizationDN();
    }
 
    /**
     * Get the DN of the entry being evaluated.
     * @return The DN of the entry.
     */
    public DN getResourceDN() {
        return resourceEntry.getDN();
    }
 
    /**
     * Checks if the container's rights has the specified rights.
     * @param  rights The rights to check for.
     * @return True if the container's rights has the specified rights.
     */
    public boolean hasRights(int rights) {
       return (this.rights & rights) != 0;
    }
 
    /**
     * Return the rights set for this container's LDAP operation.
     * @return  The rights set for the container's LDAP operation.
     */
    public int getRights() {
        return this.rights;
    }
 
    /**
     * Sets the rights for this container to the specified rights.
     * @param rights The rights to set the container's rights to.
     */
    public void setRights(int rights) {
         this.rights=rights;
    }
 
    /**
     * Gets the hostname of the remote client.
     * @return  Cannonical hostname of remote client.
     */
    public String getHostName() {
        return clientConnection.getRemoteAddress().getCanonicalHostName();
    }
 
    /**
     * Gets the remote client's address information.
     * @return  Remote client's address.
     */
    public InetAddress getRemoteAddress() {
        return clientConnection.getRemoteAddress();
    }
 
    /**
     * Return true if the current operation is a LDAP add operation.
     * @return True if this is an add operation.
     */
    public boolean isAddOperation() {
        return isAddOp;
    }
 
    /**
     * Set to true  if the ACI had a targattrfilter rule that matched.
     * @param v  The value to use.
     */
    public void setTargAttrFiltersMatch(boolean v) {
        this.targAttrFiltersMatch=v;
    }
 
    /**
     * Return the value of the targAttrFiltersMatch variable. This is set to
     * true if the ACI had a targattrfilter rule that matched.
     * @return  True if the ACI had a targattrfilter rule that matched.
     */
    public boolean getTargAttrFiltersMatch() {
        return targAttrFiltersMatch;
    }
 
    /**
     * {@inheritDoc}
     */
    public EnumEvalResult hasAuthenticationMethod(EnumAuthMethod authMethod,
                                                  String saslMech) {
      EnumEvalResult matched=EnumEvalResult.FALSE;
 
      if(authMethod==EnumAuthMethod.AUTHMETHOD_NONE) {
        /**
         * None actually means any, in that we don't care what method was used.
         * This doesn't seem very intuitive or useful, but that's the way it is.
         */
        matched = EnumEvalResult.TRUE;
      } else {
        /*
         * Some kind of authentication is required.
         */
        AuthenticationInfo authInfo=clientConnection.getAuthenticationInfo();
        if(authInfo.isAuthenticated()) {
          if(authMethod==EnumAuthMethod.AUTHMETHOD_SIMPLE) {
            if(authInfo.hasAuthenticationType(AuthenticationType.SIMPLE)) {
              matched = EnumEvalResult.TRUE;
            }
          } else if(authMethod == EnumAuthMethod.AUTHMETHOD_SSL) {
            /*
             * This means authentication using a certificate over TLS.
             *
             * We check the following:
             * - SASL EXTERNAL has been used, and
             * - TLS is the security provider, and
             * - The client provided a certificate.
             */
            if (authInfo.hasAuthenticationType(AuthenticationType.SASL) &&
                 authInfo.hasSASLMechanism(saslMech)) {
              ConnectionSecurityProvider provider =
                    clientConnection.getConnectionSecurityProvider();
              if (provider instanceof TLSConnectionSecurityProvider) {
                TLSConnectionSecurityProvider tlsProvider =
                      (TLSConnectionSecurityProvider) provider;
                 if (tlsProvider.getClientCertificateChain() != null) {
                   matched = EnumEvalResult.TRUE;
                 }
              }
            }
          } else {
            // A particular SASL mechanism.
            if (authInfo.hasAuthenticationType(AuthenticationType.SASL) &&
                 authInfo.hasSASLMechanism(saslMech)) {
              matched = EnumEvalResult.TRUE;
            }
          }
        }
      }
      return matched;
    }
 
    /**
     * Convenience method that checks if the the clientDN is a member of the
     * specified group.
     * @param group The group to check membership in.
     * @return True if the clientDN is a member of the specified group.
     */
    public boolean isMemberOf(Group group) {
        boolean ret;
        try {
           ret=clientConnection.isMemberOf(group, operation);
        } catch (DirectoryException ex) {
            ret=false;
        }
        return  ret;
    }
}