/*
|
* 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;
|
}
|
}
|